1
2 /******************************************************************************
3 * MODULE : totm.cpp
4 * DESCRIPTION: conversion of TeXmacs trees to the TeXmacs file format
5 * COPYRIGHT : (C) 1999 Joris van der Hoeven
6 *******************************************************************************
7 * This software falls under the GNU general public license version 3 or later.
8 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
9 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
10 ******************************************************************************/
11
12 #include "convert.hpp"
13 #include "drd_std.hpp"
14
15 /******************************************************************************
16 * Conversion of TeXmacs trees to the present TeXmacs string format
17 ******************************************************************************/
18
19 struct tm_writer {
20 string buf; // the resulting string
21 string spc; // "" or " "
22 string tmp; // not yet flushed characters
23 int mode; // normal: 0, verbatim: 1, mathematics: 2
24
25 int tab; // number of tabs after CR
26 int xpos; // current horizontal position in buf
27 bool spc_flag; // true if last printed character was a space or CR
28 bool ret_flag; // true if last printed character was a CR
29
tm_writertm_writer30 tm_writer ():
31 buf (""), spc (""), tmp (""), mode (0),
32 tab (0), xpos (0), spc_flag (true), ret_flag (true) {}
33
34 void cr ();
35 void flush ();
36 void write_space ();
37 void write_return ();
38 void write (string s, bool flag= true, bool encode_space= false);
39 void br (int indent= 0);
40 void tag (string before, string s, string after);
41 void apply (string func, array<tree> args);
42 void write (tree t);
43 };
44
45 void
cr()46 tm_writer::cr () {
47 int i, n= N(buf);
48 for (i=n-1; i>=0; i--)
49 if ((buf[i] != ' ') || ((i>0) && (buf[i-1] == '\\')))
50 break;
51 if (i<n-1) {
52 buf= buf (0, i+1);
53 n = n- N(buf);
54 for (i=0; i<n; i++) buf << "\\ ";
55 }
56 buf << '\n';
57 for (i=0; i<min(tab,20); i++) buf << ' ';
58 xpos= min(tab,20);
59 }
60
61 void
flush()62 tm_writer::flush () {
63 int i, m= N(spc), n= N(tmp);
64 if ((m+n)==0) return;
65 if ((xpos+m+n) < 78) {
66 buf << spc << tmp;
67 xpos += m+n;
68 }
69 else {
70 if (spc == " ") {
71 if (xpos > 40) cr ();
72 else {
73 buf << " ";
74 xpos++;
75 }
76 }
77 if ((xpos+n) < 78) {
78 buf << tmp;
79 xpos += n;
80 }
81 else for (i=0; i<n; ) {
82 if (((i+1) < n) && (tmp[i] == '\\') && (tmp[i+1] == ' ')) {
83 /* not nice when searching text in a .tm file
84 if (xpos >= 76) {
85 buf << "\\";
86 cr ();
87 }
88 */
89 buf << "\\ ";
90 xpos += 2;
91 i += 2;
92 }
93 else {
94 /* not nice when searching text in a .tm file
95 if (xpos >= 77) {
96 buf << "\\";
97 cr ();
98 }
99 */
100 buf << tmp[i];
101 xpos++;
102 i++;
103 }
104 }
105 }
106 spc= "";
107 tmp= "";
108 }
109
110 void
write_space()111 tm_writer::write_space () {
112 if (spc_flag) tmp << "\\ ";
113 else {
114 flush ();
115 spc= " ";
116 }
117 spc_flag= true;
118 ret_flag= false;
119 }
120
121 void
write_return()122 tm_writer::write_return () {
123 if (ret_flag) {
124 buf << "\\;\n";
125 cr ();
126 }
127 else {
128 if ((spc == " ") && (tmp == "")) {
129 spc= "";
130 tmp= "\\ ";
131 }
132 flush ();
133 buf << "\n";
134 cr ();
135 }
136 spc_flag= true;
137 ret_flag= true;
138 }
139
140 void
write(string s,bool flag,bool encode_space)141 tm_writer::write (string s, bool flag, bool encode_space) {
142 if (flag) {
143 int i, n=N(s);
144 for (i=0; i<n; i++) {
145 char c= s[i];
146 if ((c == ' ') && (!encode_space)) write_space ();
147 else {
148 if (c == ' ') tmp << "\\ ";
149 else if (c == '\n') tmp << "\\n";
150 else if (c == '\t') tmp << "\\t";
151 else if (c == '\0') tmp << "\\0";
152 else if (c == '\\') tmp << "\\\\";
153 else if (c == '<') tmp << "\\<";
154 else if (c == '|') tmp << "\\|";
155 else if (c == '>') tmp << "\\>";
156 else if (c == '\34') tmp << c;
157 else if (((unsigned char) c) < ' ') tmp << '\\' << (c+'@');
158 else tmp << c;
159 spc_flag= false;
160 ret_flag= false;
161 }
162 }
163 }
164 else {
165 tmp << s;
166 if (N(s) != 0) {
167 spc_flag= false;
168 ret_flag= false;
169 }
170 }
171 }
172
173 void
br(int indent)174 tm_writer::br (int indent) {
175 int i;
176 flush ();
177 tab += indent;
178 for (i=N(buf)-1; i>=0; i--) {
179 if (buf[i] == '\n') return;
180 if (buf[i] != ' ') {
181 cr ();
182 spc_flag= true;
183 ret_flag= false;
184 return;
185 }
186 }
187 }
188
189 void
tag(string before,string s,string after)190 tm_writer::tag (string before, string s, string after) {
191 write (before, false);
192 write (s);
193 write (after, false);
194 }
195
196 void
apply(string func,array<tree> args)197 tm_writer::apply (string func, array<tree> args) {
198 int i, last, n=N(args);
199 for (i=n-1; i>=0; i--)
200 if (is_document (args[i]) || is_func (args[i], COLLECTION))
201 break;
202 last= i;
203
204 if (last >= 0) {
205 /*
206 tag ("<\\", func, ">");
207 for (i=0; i<n; i++) {
208 if (is_empty (args[i])) br ();
209 else {
210 br (2);
211 write (args[i]);
212 br (-2);
213 }
214 if (i<(n-1)) tag ("<|", func, ">");
215 }
216 tag ("</", func, ">");
217 */
218
219 for (i=0; i<=n; i++) {
220 bool flag=
221 (i<n) && (is_document (args[i]) || is_func (args[i], COLLECTION));
222 if (i==0) { write ("<\\", false); write (func, true, true); }
223 else if (i==last+1) {write ("</", false); write (func, true, true); }
224 else if (is_document (args[i-1]) || is_func (args[i-1], COLLECTION)) {
225 write ("<|", false); write (func, true, true); }
226 if (i==n) {
227 write (">", false);
228 break;
229 }
230
231 if (flag) {
232 write (">", false);
233 br (2);
234 write (args[i]);
235 br (-2);
236 }
237 else {
238 write ("|", false);
239 write (args[i]);
240 }
241 }
242 }
243 else {
244 write ("<", false);
245 write (func, true, true);
246 for (i=0; i<n; i++) {
247 write ("|", false);
248 write (args[i]);
249 }
250 write (">", false);
251 }
252 }
253
254 void
write(tree t)255 tm_writer::write (tree t) {
256 if (is_atomic (t)) {
257 write (t->label);
258 return;
259 }
260
261 int i, n= N(t);
262 switch (L(t)) {
263 case RAW_DATA:
264 {
265 write ("<#", false);
266 string s= as_string (t[0]);
267 for (i=0; i<N(s); i++)
268 write (as_hexadecimal ((unsigned char) s[i], 2), false);
269 write (">", false);
270 break;
271 }
272 case DOCUMENT:
273 spc_flag= true;
274 ret_flag= true;
275 for (i=0; i<n; i++) {
276 write (t[i]);
277 if (i<(n-1)) write_return ();
278 else if (ret_flag) write ("\\;", false);
279 }
280 break;
281 case CONCAT:
282 for (i=0; i<n; i++) write (t[i]);
283 break;
284 case EXPAND:
285 if ((n>=1) && is_atomic (t[0])) {
286 string s= t[0]->label;
287 if (std_contains (s));
288 else if ((N(s)>0) && (!is_iso_alpha (s)));
289 else {
290 apply (s, A(t(1,n)));
291 break;
292 }
293 }
294 apply (as_string (EXPAND), A(t));
295 break;
296 case COLLECTION:
297 tag ("<\\", as_string (COLLECTION), ">");
298 if (n==0) br ();
299 else {
300 br (2);
301 for (i=0; i<n; i++) {
302 write (t[i]);
303 if (i<(n-1)) br ();
304 }
305 br (-2);
306 }
307 tag ("</", as_string (COLLECTION), ">");
308 break;
309 default:
310 apply (as_string (L(t)), A(t));
311 break;
312 }
313 }
314
315 /******************************************************************************
316 * Conversion of TeXmacs trees to TeXmacs strings
317 ******************************************************************************/
318
319 string
tree_to_texmacs(tree t)320 tree_to_texmacs (tree t) {
321 if (!is_snippet (t)) {
322 int i, n= N(t);
323 tree r (t, n);
324 for (i=0; i<n; i++)
325 if (is_compound (t[i], "style", 1)) {
326 tree style= t[i][0];
327 if (is_func (style, TUPLE, 1)) style= style[0];
328 r[i]= copy (t[i]);
329 r[i][0]= style;
330 }
331 else r[i]= t[i];
332 t= r;
333 }
334
335 tm_writer tmw;
336 tmw.write (t);
337 tmw.flush ();
338 return tmw.buf;
339 }
340