Back to index

texmacs  1.0.7.15
verbatim.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : verbatim.cpp
00004 * DESCRIPTION: routines for converting between TeXmacs trees and text
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 "converter.hpp"
00014 #include "vars.hpp"
00015 #include "drd_std.hpp"
00016 #include "analyze.hpp"
00017 
00018 /******************************************************************************
00019 * TeXmacs to verbatim
00020 ******************************************************************************/
00021 
00022 static void print_verbatim (string& buf, tree t, bool wrap);
00023 static string as_verbatim (tree t, bool wrap);
00024 
00025 static void
00026 print_verbatim_arg (string& buf, tree t, bool wrap) {
00027   string s= as_verbatim (t, wrap);
00028   if (tm_string_length (s) <= 1 || is_iso_alpha (s) || is_numeric (s))
00029     print_verbatim (buf, t, wrap);
00030   else {
00031     buf << "(";
00032     print_verbatim (buf, t, wrap);
00033     buf << ")";
00034   }
00035 }
00036 
00037 static int
00038 get_width (string s) {
00039   if (occurs ("\n", s)) return 0;
00040   else return tm_string_length (s);
00041 }
00042 
00043 static void
00044 print_verbatim_table (string& buf, tree t, bool wrap) {
00045   if (N(buf)>0 && buf[N(buf)-1] != '\n') buf << "\n";
00046   int i, nr= N(t), j, nc= 0;
00047   tree tab (TUPLE, nr);
00048   for (i=0; i<nr; i++) {
00049     tree row= t[i];
00050     if (is_func (row, CWITH)) row= row[N(row)-1];
00051     if (!is_func (row, ROW)) tab[i]= tree (TUPLE);
00052     else {
00053       nc= max (nc, N(row));
00054       tab[i]= tree (TUPLE, N(row));
00055       for (j=0; j<N(row); j++)
00056         tab[i][j]= as_verbatim (row[j], wrap);
00057     }
00058   }
00059   array<int> w (nc);
00060   for (j=0; j<nc; j++) w[j]= 0;
00061   for (i=0; i<nr; i++) {
00062     for (j=0; j<N(tab[i]); j++)
00063       w[j]= max (w[j], get_width(tab[i][j]->label));
00064   }
00065   for (i=0; i<nr; i++) {
00066     for (j=0; j<N(tab[i]); j++) {
00067       int spc= w[j] - get_width(tab[i][j]->label) + 1;
00068       buf << tab[i][j]->label;
00069       if (j != N(tab[i]) - 1)
00070        for (int k=0; k<spc; k++) buf << " ";
00071     }
00072     buf << "\n";
00073   }
00074 }
00075 
00076 static void
00077 print_verbatim (string& buf, tree t, bool wrap) {
00078   if (is_atomic (t)) buf << t->label;
00079   else switch (L(t)) {
00080     case SURROUND:
00081       print_verbatim (buf, t[0], wrap);
00082       print_verbatim (buf, t[2], wrap);
00083       print_verbatim (buf, t[1], wrap);
00084       break;
00085     case HSPACE:
00086     case SPACE:
00087     case HTAB:
00088       if (N(buf)>0 && buf[N(buf)-1] != '\n') buf << " ";
00089       break;
00090     case AROUND:
00091     case VAR_AROUND:
00092       print_verbatim (buf, t[0], wrap);
00093       print_verbatim (buf, t[1], wrap);
00094       print_verbatim (buf, t[2], wrap);
00095       break;
00096     case BIG_AROUND:
00097       print_verbatim (buf, t[0], wrap);
00098       print_verbatim (buf, t[1], wrap);
00099       break;
00100     case LEFT:
00101     case MID:
00102     case RIGHT:
00103     case BIG:
00104     case LPRIME:
00105     case RPRIME:
00106       print_verbatim (buf, t[0], wrap);
00107       break;
00108     case RSUB:
00109       buf << "_";
00110       print_verbatim_arg (buf, t[0], wrap);
00111       break;
00112     case RSUP:
00113       buf << "^";
00114       print_verbatim_arg (buf, t[0], wrap);
00115       break;
00116     case FRAC:
00117       print_verbatim_arg (buf, t[0], wrap);
00118       buf << "/";
00119       print_verbatim_arg (buf, t[1], wrap);
00120       break;
00121     case SQRT:
00122       if (N(t) == 1) {
00123         buf << "sqrt(";
00124         print_verbatim (buf, t[0], wrap);
00125         buf << ")";
00126       }
00127       else {
00128         print_verbatim_arg (buf, t[0], wrap);
00129         print_verbatim_arg (buf, tree (RSUP, tree (FRAC, "1", t[1])), wrap);
00130       }
00131       break;
00132     case WIDE:
00133       print_verbatim_arg (buf, t[0], wrap);
00134       print_verbatim (buf, t[1], wrap);
00135       break;
00136     case SYNTAX:
00137       print_verbatim_arg (buf, t[0], wrap);
00138       break;
00139     case TABLE:
00140       print_verbatim_table (buf, t, wrap);
00141       break;
00142     default:
00143       if (is_compound (t, "TeXmacs", 0))
00144         print_verbatim (buf, "TeXmacs", wrap);
00145       else {
00146         int i, n= N(t);
00147         for (i=0; i<n; i++)
00148           if (the_drd->is_accessible_child (t, i)) {
00149             if (is_document (t) && (i>0)) {
00150               if (wrap && N(buf)>0 && buf[N(buf)-1] != '\n') buf << "\n";
00151               buf << "\n";
00152             }
00153             tree w= std_drd->get_env_child (t, i, tree (ATTR));
00154             if (drd_env_read (w, MODE, "text") == "prog" ||
00155                 drd_env_read (w, FONT_FAMILY, "rm") == "tt")
00156               print_verbatim (buf, t[i], false);
00157             else print_verbatim (buf, t[i], wrap);
00158           }
00159       }
00160       break;
00161     }
00162 }
00163 
00164 static string
00165 as_verbatim (tree t, bool wrap) {
00166   if (!is_snippet (t)) {
00167     tree init= extract (t, "initial");
00168     hashmap<string,tree> h (UNINIT, init);
00169     if (h[MODE] == "prog" || h[FONT_FAMILY] == "tt") wrap= false;
00170     t= extract (t, "body");
00171   }
00172   string buf;
00173   print_verbatim (buf, t, wrap);
00174   if (wrap) {
00175     int i= 0, n= N(buf);
00176     while (i<n) {
00177       int pos= i;
00178       while (i<n && buf[i]!='\n') i++;
00179       array<string> a= tm_tokenize (buf (pos, i));
00180       int start= 0;
00181       //cout << "a= " << a << "\n";
00182       //cout << "l= " << N(a) << "\n";
00183       while (N(a)-start > 78) {
00184        //cout << "  start= " << start << "\n";
00185        int mid= start+78;
00186        while (mid>start && a[mid] != " ") mid--;
00187        if (mid <= start) break;
00188        if (mid<N(a)) {
00189          //cout << "  mid= " << mid << "\n";
00190          pos += N(tm_recompose (range (a, start, mid)));
00191          ASSERT (buf[pos] == ' ', "error in space synchronization");
00192          buf[pos]= '\n';
00193          start= mid+1;
00194          pos++;
00195        }
00196        else break;
00197       }
00198       if (i<n) i++;
00199     }
00200   }
00201   return buf;
00202 }
00203 
00204 string
00205 unix_to_dos (string s) {
00206   int i, n= N(s);
00207   string r;
00208   for (i=0; i<n; i++)
00209     if (s[i] == '\n') r << "\r\n";
00210     else r << s[i];
00211   return r;
00212 }
00213 
00214 string
00215 var_cork_to_utf8 (string s) {
00216   string r;
00217   for (int i=0; i<N(s); ) {
00218     int start= i;
00219     while (i<N(s) && s[i] != '\n') i++;
00220     r << cork_to_utf8 (s (start, i));
00221     if (i<N(s)) { r << '\n'; i++; }
00222   }
00223   return r;
00224 }
00225 
00226 string
00227 tree_to_verbatim (tree t, bool wrap, string enc) {
00228   if (enc == "default") enc= "utf-8";
00229   string buf= as_verbatim (t, wrap);
00230   if (enc == "utf-8") buf= var_cork_to_utf8 (buf);
00231   else if (enc == "iso-8859-1") buf= tm_decode (buf);
00232 #ifdef OS_WIN32
00233   return unix_to_dos (buf);
00234 #else
00235   return buf;
00236 #endif
00237 }
00238 
00239 /******************************************************************************
00240 * Verbatim to TeXmacs
00241 ******************************************************************************/
00242 
00243 static string
00244 un_special (string s) {
00245   int i, j;
00246   string r;
00247   for (i=0, j=0; i<N(s); i++, j++)
00248     if (s[i] == '\t') {
00249       do {
00250        r << " "; j++;
00251       } while ((j&7) != 0);
00252       j--;
00253     }
00254     else if ((s[i] == '\b') && (N(r)>0) && (r[N(r)-1]!='\n'))
00255       r->resize (N(r)-1);
00256     else r << s[i];
00257   return r;
00258 }
00259 
00260 static string
00261 encode (string s, string enc) {
00262   if (enc == "utf-8") return utf8_to_cork (s);
00263   else if (enc == "iso-8859-1") return tm_encode (s);
00264   else return s;
00265 }
00266 
00267 tree
00268 verbatim_to_tree (string s, string enc) {
00269   int i, j;
00270   for (i=0; i<N(s); i++)
00271     if (s[i]=='\n') {
00272       tree t (DOCUMENT);
00273       for (i=0, j=0; i<N(s); i++)
00274        if (s[i]=='\n') {
00275          t << encode (un_special (s (j, i)), enc);
00276          j= i+1;
00277        }
00278       t << encode (un_special (s (j, i)), enc);
00279       return t;
00280     }
00281   return encode (un_special (s), enc);
00282 }
00283 
00284 string
00285 dos_to_unix (string s) {
00286   int i, n= N(s);
00287   string r;
00288   for (i=0; i<n; i++)
00289     if (s[i] == '\r' && i+1<n && s[i+1] == '\n') { r << "\n"; i++; }
00290     else r << s[i];
00291   return r;
00292 }
00293 
00294 string
00295 mac_to_unix (string s) {
00296   int i, n= N(s);
00297   string r;
00298   for (i=0; i<n; i++)
00299     if (s[i] == '\r') r << "\n";
00300     else r << s[i];
00301   return r;
00302 }
00303 
00304 tree
00305 verbatim_to_tree (string s, bool wrap, string enc) {
00306   if (enc == "default") enc= "utf-8";
00307   s= mac_to_unix (dos_to_unix (s));
00308   if (wrap) {
00309     string r;
00310     int i, n= N(s);
00311     for (i=0; i<n; ) {
00312       if (s[i] == '\n' || s[i] == ' ' || s[i] == '\t') {
00313        int lf= 0;
00314        while (i<n && (s[i] == '\n' || s[i] == ' ' || s[i] == '\t')) {
00315          if (s[i] == '\n') lf++;
00316          i++;
00317        }
00318        if (lf <= 1) r << " ";
00319        else r << "\n";
00320       }
00321       else r << s[i++];
00322     }
00323     s= r;
00324   }
00325   return verbatim_to_tree (s, enc);
00326 }
00327 
00328 tree
00329 verbatim_document_to_tree (string s, bool wrap, string enc) {
00330   if (enc == "default") enc= "utf-8";
00331   tree t    = verbatim_to_tree (s, wrap, enc);
00332   tree init = tree (COLLECTION,
00333                   tree (ASSOCIATE, LANGUAGE, "verbatim"),
00334                   tree (ASSOCIATE, FONT_FAMILY, "tt"),
00335                   tree (ASSOCIATE, PAR_FIRST, "0cm"));
00336   return tree (DOCUMENT, compound ("body", t), compound ("initial", init));
00337 }