1
2 /******************************************************************************
3 * MODULE : upgradetm.cpp
4 * DESCRIPTION: upgrade old TeXmacs formats
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 "converter.hpp"
14 #include "hashset.hpp"
15 #include "path.hpp"
16 #include "vars.hpp"
17 #include "drd_std.hpp"
18 #include <stdio.h>
19 #include "scheme.hpp"
20 #include "tree_correct.hpp"
21 #include "merge_sort.hpp"
22
23 static bool upgrade_tex_flag= false;
24 double get_magnification (string s);
25
26 /******************************************************************************
27 * Retrieve older operator hashmap
28 ******************************************************************************/
29
30 static void
rename_feature(hashmap<string,int> & H,string old_name,string new_name)31 rename_feature (hashmap<string,int>& H, string old_name, string new_name) {
32 H (old_name)= H [new_name];
33 H->reset (new_name);
34 }
35
36 static void
new_feature(hashmap<string,int> & H,string new_name)37 new_feature (hashmap<string,int>& H, string new_name) {
38 H->reset (new_name);
39 }
40
41 /*static*/ hashmap<string,int>
get_codes(string version)42 get_codes (string version) {
43 hashmap<string,int> H (UNKNOWN);
44 H->join (STD_CODE);
45
46 if (version_inf ("1.0.7.6", version)) return H;
47
48 rename_feature (H, "group", "rigid");
49 rename_feature (H, "postscript", "image");
50
51 if (version_inf ("1.0.6.9", version)) return H;
52
53 rename_feature (H, "frozen", "freeze");
54
55 if (version_inf ("1.0.6.2", version)) return H;
56
57 new_feature (H, "expand-as");
58 new_feature (H, "locus");
59 new_feature (H, "id");
60 new_feature (H, "hard-id");
61 new_feature (H, "link");
62 new_feature (H, "url");
63 new_feature (H, "script");
64
65 if (version_inf ("1.0.4.1", version)) return H;
66
67 new_feature (H, "copy");
68 new_feature (H, "cm-length");
69 new_feature (H, "mm-length");
70 new_feature (H, "in-length");
71 new_feature (H, "pt-length");
72 new_feature (H, "bp-length");
73 new_feature (H, "dd-length");
74 new_feature (H, "pc-length");
75 new_feature (H, "cc-length");
76 new_feature (H, "fs-length");
77 new_feature (H, "fbs-length");
78 new_feature (H, "em-length");
79 new_feature (H, "ln-length");
80 new_feature (H, "sep-length");
81 new_feature (H, "yfrac-length");
82 new_feature (H, "ex-length");
83 new_feature (H, "fn-length");
84 new_feature (H, "fns-length");
85 new_feature (H, "bls-length");
86 new_feature (H, "spc-length");
87 new_feature (H, "xspc-length");
88 new_feature (H, "par-length");
89 new_feature (H, "pag-length");
90 new_feature (H, "tmpt-length");
91 new_feature (H, "px-length");
92 new_feature (H, "tmlen");
93
94 if (version_inf ("1.0.3.12", version)) return H;
95
96 new_feature (H, "unquote*");
97
98 if (version_inf ("1.0.3.4", version)) return H;
99
100 new_feature (H, "for-each");
101 new_feature (H, "quasi");
102 rename_feature (H, "hold", "quasiquote");
103 rename_feature (H, "release", "unquote");
104
105 if (version_inf ("1.0.3.3", version)) return H;
106
107 new_feature (H, "quote-value");
108 new_feature (H, "quote-arg");
109 new_feature (H, "mark");
110 new_feature (H, "use-package");
111 new_feature (H, "style-only");
112 new_feature (H, "style-only*");
113 new_feature (H, "rewrite-inactive");
114 new_feature (H, "inline-tag");
115 new_feature (H, "open-tag");
116 new_feature (H, "middle-tag");
117 new_feature (H, "close-tag");
118
119 if (version_inf ("1.0.2.8", version)) return H;
120
121 rename_feature (H, "raw_data", "raw-data");
122 rename_feature (H, "sub_table", "subtable");
123 rename_feature (H, "drd_props", "drd-props");
124 rename_feature (H, "get_label", "get-label");
125 rename_feature (H, "get_arity", "get-arity");
126 rename_feature (H, "map_args", "map-args");
127 rename_feature (H, "eval_args", "eval-args");
128 rename_feature (H, "find_file", "find-file");
129 rename_feature (H, "is_tuple", "is-tuple");
130 rename_feature (H, "look_up", "look-up");
131 rename_feature (H, "var_if", "if*");
132 rename_feature (H, "var_inactive", "inactive*");
133 rename_feature (H, "var_active", "active*");
134 rename_feature (H, "text_at", "text-at");
135 rename_feature (H, "var_spline", "spline*");
136 rename_feature (H, "old_matrix", "old-matrix");
137 rename_feature (H, "old_table", "old-table");
138 rename_feature (H, "old_mosaic", "old-mosaic");
139 rename_feature (H, "old_mosaic_item", "old-mosaic-item");
140 rename_feature (H, "var_expand", "expand*");
141 rename_feature (H, "hide_expand", "hide-expand");
142
143 rename_feature (H, "with_limits", "with-limits");
144 rename_feature (H, "line_break", "line-break");
145 rename_feature (H, "new_line", "new-line");
146 rename_feature (H, "line_separator", "line-sep");
147 rename_feature (H, "next_line", "next-line");
148 rename_feature (H, "no_line_break", "no-break");
149 rename_feature (H, "no_first_indentation", "no-indent");
150 rename_feature (H, "enable_first_indentation", "yes-indent");
151 rename_feature (H, "no_indentation_after", "no-indent*");
152 rename_feature (H, "enable_indentation_after", "yes-indent*");
153 rename_feature (H, "page_break_before", "page-break*");
154 rename_feature (H, "page_break", "page-break");
155 rename_feature (H, "no_page_break_before", "no-page-break*");
156 rename_feature (H, "no_page_break_after", "no-page-break");
157 rename_feature (H, "new_page_before", "new-page*");
158 rename_feature (H, "new_page", "new-page");
159 rename_feature (H, "new_double_page_before", "new-dpage*");
160 rename_feature (H, "new_double_page", "new-dpage");
161
162 if (version_inf ("1.0.2.5", version)) return H;
163
164 new_feature (H, "compound");
165 new_feature (H, "xmacro");
166 new_feature (H, "get_label");
167 new_feature (H, "get_arity");
168 new_feature (H, "map_args");
169 new_feature (H, "eval_args");
170 new_feature (H, "drd_props");
171
172 if (version_inf ("1.0.2.0", version)) return H;
173
174 new_feature (H, "with_limits");
175 new_feature (H, "line_break");
176 new_feature (H, "new_line");
177 new_feature (H, "line_separator");
178 new_feature (H, "next_line");
179 new_feature (H, "no_line_break");
180 new_feature (H, "no_first_indentation");
181 new_feature (H, "enable_first_indentation");
182 new_feature (H, "no_indentation_after");
183 new_feature (H, "enable_indentation_after");
184 new_feature (H, "page_break_before");
185 new_feature (H, "page_break");
186 new_feature (H, "no_page_break_before");
187 new_feature (H, "no_page_break_after");
188 new_feature (H, "new_page_before");
189 new_feature (H, "new_page");
190 new_feature (H, "new_double_page_before");
191 new_feature (H, "new_double_page");
192
193 if (version_inf ("1.0.1.25", version)) return H;
194
195 new_feature (H, "active");
196 new_feature (H, "var_inactive");
197 new_feature (H, "var_active");
198 new_feature (H, "attr");
199
200 if (version_inf ("1.0.0.20", version)) return H;
201
202 new_feature (H, "text_at");
203
204 if (version_inf ("1.0.0.19", version)) return H;
205
206 new_feature (H, "find_file");
207
208 if (version_inf ("1.0.0.14", version)) return H;
209
210 rename_feature (H, "paragraph", "para");
211
212 if (version_inf ("1.0.0.5", version)) return H;
213
214 new_feature (H, "var_if");
215 new_feature (H, "hide_expand");
216
217 if (version_inf ("1.0.0.2", version)) return H;
218
219 new_feature (H, "superpose");
220 new_feature (H, "spline");
221 new_feature (H, "var_spline");
222 new_feature (H, "cspline");
223 new_feature (H, "fill");
224
225 if (version_inf ("0.3.5.2", version)) return H;
226
227 new_feature (H, "raw_data");
228 new_feature (H, "include");
229
230 if (version_inf ("0.3.5.1", version)) return H;
231
232 new_feature (H, "var_expand");
233
234 if (version_inf ("0.3.4.12", version)) return H;
235
236 new_feature (H, "range");
237 new_feature (H, "is_tuple");
238 new_feature (H, "look_up");
239
240 if (version_inf ("0.3.4.11", version)) return H;
241
242 new_feature (H, "float");
243 new_feature (H, "datoms");
244 new_feature (H, "dlines");
245 new_feature (H, "dpages");
246 new_feature (H, "pageref");
247
248 if (version_inf ("0.3.4.7", version)) return H;
249
250 rename_feature (H, "matrix", "old_matrix");
251 rename_feature (H, "table", "old_table");
252 rename_feature (H, "mosaic", "old_mosaic");
253 rename_feature (H, "mosaic_item", "old_mosaic_item");
254
255 if (version_inf ("0.3.4.6", version)) return H;
256
257 new_feature (H, "tformat");
258 new_feature (H, "twith");
259 new_feature (H, "cwith");
260 new_feature (H, "tmarker");
261 new_feature (H, "row");
262 new_feature (H, "cell");
263 new_feature (H, "sub_table");
264
265 if (version_inf ("0.3.4.0", version)) return H;
266
267 new_feature (H, "tag");
268 new_feature (H, "syntax");
269
270 if (version_inf_eq ("0.3.3.15", version)) return H;
271
272 new_feature (H, "uninit");
273 new_feature (H, "error");
274 new_feature (H, "surround");
275 new_feature (H, "hold");
276 new_feature (H, "release");
277 new_feature (H, "arg");
278
279 if (version_inf_eq ("0.3.3.0", version)) return H;
280
281 new_feature (H, "with");
282 new_feature (H, "macro");
283 new_feature (H, "eval");
284 new_feature (H, "value");
285 new_feature (H, "or");
286 new_feature (H, "xor");
287 new_feature (H, "and");
288 new_feature (H, "not");
289 new_feature (H, "over");
290 new_feature (H, "divide");
291 new_feature (H, "modulo");
292 new_feature (H, "length");
293 new_feature (H, "date");
294 new_feature (H, "equal");
295 new_feature (H, "unequal");
296 new_feature (H, "less");
297 new_feature (H, "lesseq");
298 new_feature (H, "greater");
299 new_feature (H, "greatereq");
300 new_feature (H, "if");
301 new_feature (H, "case");
302 new_feature (H, "for");
303 new_feature (H, "while");
304 new_feature (H, "extern");
305 new_feature (H, "authorize");
306
307 if (version_inf_eq ("0.3.1.8", version)) return H;
308
309 rename_feature (H, "mosaic item", "mosaic_item");
310 rename_feature (H, "<>", "symbol");
311 rename_feature (H, ";", "backup");
312 rename_feature (H, "'", "quote");
313 rename_feature (H, ":=", "assign");
314 rename_feature (H, "\\", "apply");
315 rename_feature (H, "()", "tuple");
316 rename_feature (H, "{,}", "collection");
317 rename_feature (H, "->", "associate");
318 rename_feature (H, "+", "plus");
319 rename_feature (H, "-", "minus");
320 rename_feature (H, "x", "times");
321 rename_feature (H, "*", "merge");
322 rename_feature (H, "nr", "number");
323 H ("style")= H ["()"];
324
325 return H;
326 }
327
328 /******************************************************************************
329 * Old style is_expand predicates
330 ******************************************************************************/
331
332 static bool
is_expand(tree t)333 is_expand (tree t) {
334 return ((L(t) == EXPAND) || (L(t) == VAR_EXPAND) || (L(t) == HIDE_EXPAND));
335 }
336
337 static bool
is_expand(tree t,string s,int n)338 is_expand (tree t, string s, int n) {
339 return is_expand (t) && (N(t) == n+1) && (t[0] == s);
340 }
341
342 /******************************************************************************
343 * Old style conversion from TeXmacs strings to TeXmacs trees
344 ******************************************************************************/
345
346 static tree
string_to_tree(string s,int & pos,hashmap<string,int> codes)347 string_to_tree (string s, int& pos, hashmap<string,int> codes) {
348 string l ("");
349 while ((pos<N(s)) && (s[pos]!='(') && (s[pos]!=',') && (s[pos]!=')')) {
350 if ((s[pos]=='\\') && (pos<N(s)-1)) pos++;
351 l << s[pos++];
352 }
353 tree t (l);
354 tree_label code= (tree_label) codes [l];
355 if ((l == "style") || (code == COLLECTION)) t= tree (code);
356 if ((pos<N(s)) && (s[pos]=='(')) {
357 if (code != UNKNOWN) t= tree (code);
358 else t= tuple (l);
359 do {
360 pos++;
361 t << string_to_tree (s, pos, codes);
362 } while ((pos<N(s)) && (s[pos]==','));
363 if ((pos<N(s)) && (s[pos]==')')) pos++;
364 }
365 return t;
366 }
367
368 static tree
un_paragraph(tree t)369 un_paragraph (tree t) {
370 if (is_atomic (t)) return t;
371 if (is_func (t, PARA, 1)) return t[0];
372 else {
373 int i, n= N(t);
374 tree r (t, n);
375 for (i=0; i<n; i++) r[i]= un_paragraph (t[i]);
376 return r;
377 }
378 }
379
380 /*static*/ tree
string_to_tree(string s,string version)381 string_to_tree (string s, string version) {
382 int pos=0;
383 return un_paragraph (string_to_tree (s, pos, get_codes (version)));
384 }
385
386 /******************************************************************************
387 * Upgrade large delimiters, big operators and primes
388 ******************************************************************************/
389
390 tree
upgrade_textual(tree t,path & mode_stack)391 upgrade_textual (tree t, path& mode_stack) {
392 if (t == "") return t;
393 if (is_atomic (t)) {
394 int i, n= N(t->label);
395 string s;
396 tree r (CONCAT);
397 for (i=0; i<n; ) {
398 if (t->label[i] == '<') {
399 int start= i;
400 for (i++; i<n; i++)
401 if (t->label[i-1] == '>') break;
402 string ss= t->label (start, i);
403 if (t->label[i-1] != '>') ss << '>';
404 if (starts (ss, "<left-")) {
405 if (s != "") r << s; s= "";
406 r << tree (LEFT, ss (6, N(ss)-1));
407 }
408 else if (starts (ss, "<mid-")) {
409 if (s != "") r << s; s= "";
410 r << tree (MID, ss (5, N(ss)-1));
411 }
412 else if (starts (ss, "<right-")) {
413 if (s != "") r << s; s= "";
414 r << tree (RIGHT, ss (7, N(ss)-1));
415 }
416 else if (starts (ss, "<big-")) {
417 if (s != "") r << s; s= "";
418 r << tree (BIG, ss (5, N(ss)-1));
419 }
420 else s << ss;
421 }
422 else if (((t->label[i] == '\'') || (t->label[i] == '`')) &&
423 (!is_nil (mode_stack)) && (mode_stack->item == 1))
424 {
425 int start= i++;
426 while ((i<n) && (t->label[i] == t->label[i-1])) i++;
427 if (s != "") r << s; s= "";
428 tree_label op= t->label[start] == '`'? LPRIME: RPRIME;
429 r << tree (op, t->label (start, i));
430 }
431 else s << t->label[i++];
432 }
433 if (s != "") r << s;
434 if (N(r) == 1) return r[0];
435 return r;
436 }
437 else {
438 int i, n= arity (t);
439 tree r (t, 0);
440 for (i=0; i<n; i++) {
441 tree u= upgrade_textual (t[i], mode_stack);
442 if (is_func (u, SET)) {
443 if (u == tree (SET, "mode", "text")) mode_stack= path (0, mode_stack);
444 if (u == tree (SET, "mode", "math")) mode_stack= path (1, mode_stack);
445 if (u == tree (SET, "mode", "prog")) mode_stack= path (2, mode_stack);
446 }
447 else if (is_func (u, RESET)) {
448 if (u == tree (RESET, "mode"))
449 if (!is_nil (mode_stack))
450 mode_stack= mode_stack->next;
451 }
452 else if (is_func (u, BEGIN, 1)) {
453 if ((u[0] == "equation") ||
454 (u[0] == "equation*") ||
455 (u[0] == "eqnarray*") ||
456 (u[0] == "leqnarray*"))
457 mode_stack= path (1, mode_stack);
458 }
459 else if (is_func (u, END, 1)) {
460 if ((u[0] == "equation") ||
461 (u[0] == "equation*") ||
462 (u[0] == "eqnarray*") ||
463 (u[0] == "leqnarray*"))
464 if (!is_nil (mode_stack))
465 mode_stack= mode_stack->next;
466 }
467 if (is_concat (t) && is_concat (u)) r << A(u);
468 else r << u;
469 }
470 return r;
471 }
472 }
473
474 /******************************************************************************
475 * Upgrade lambda application -> macro expansion and value keyword
476 ******************************************************************************/
477
478 tree
upgrade_apply_expand_value(tree t,hashset<string> H)479 upgrade_apply_expand_value (tree t, hashset<string> H) {
480 if (is_atomic (t)) return t;
481 else {
482 int i, n= arity (t);
483 tree r (t, n);
484 if (is_func (t, APPLY))
485 if ((n >= 1) && is_atomic (t[0]) && H->contains (t[0]->label)) {
486 if (n == 1) r= tree (VALUE, n);
487 else r= tree (EXPAND, n);
488 }
489 for (i=0; i<n; i++)
490 r[i]= upgrade_apply_expand_value (t[i], H);
491 return r;
492 }
493 }
494
495 typedef const char* charp;
496 static charp apply_expand_value_strings[]= {
497 "part", "part*", "chapter", "chapter*", "appendix",
498 "section", "section*", "subsection", "subsection*",
499 "subsubsection", "subsubsection*",
500 "paragraph", "paragraph*", "subparagraph", "subparagraph*",
501 "footnote", "item*", "overline", "underline",
502 "mathord", "mathbin", "mathopen", "mathpunct",
503 "mathop", "mathrel", "mathclose", "mathalpha",
504 "op", "strong", "em", "tt", "name", "samp", "abbr",
505 "dfn", "kbd", "var", "acronym", "person",
506 "menu", "submenu", "subsubmenu", "tmdef", "tmref",
507 "key", "skey", "ckey", "akey", "mkey", "hkey",
508 "include-document", "include-project", "globalize-variable",
509 "localize-variable", "assign-variable",
510 "gb", "cgb", "gbt", "cgbt", "head", "tail", "hm", "tm", "binom",
511 //"ma", "mb", "md", "me", "mf", "mg", "mh", "mi", "mj", "mk",
512 //"mm", "mn", "mu", "mv", "mw", "my", "mz",
513 //"MA", "MB", "MD", "ME", "MF", "MG", "MH", "MI", "MJ", "MK",
514 //"MM", "MN", "MU", "MV", "MW", "MY", "MZ",
515 ""
516 };
517
518 tree
upgrade_apply_expand_value(tree t)519 upgrade_apply_expand_value (tree t) {
520 int i;
521 hashset<string> H;
522 for (i=0; apply_expand_value_strings[i][0] != '\0'; i++)
523 H->insert (apply_expand_value_strings[i]);
524 return upgrade_apply_expand_value (t, H);
525 }
526
527 /******************************************************************************
528 * Subroutines for upgrading set/reset -> with, begin/end -> apply
529 ******************************************************************************/
530
531 static bool
matching(tree open,tree close)532 matching (tree open, tree close) {
533 if (is_func (open, SET, 2))
534 return is_func (close, RESET, 1) && (open[0] == close[0]);
535 if (is_func (open, BEGIN))
536 return is_func (close, END, 1) && (open[0] == close[0]);
537 return false;
538 }
539
540 static tree
with_replace(tree var,tree val,tree body)541 with_replace (tree var, tree val, tree body) {
542 if (is_func (body, WITH)) {
543 int i, n= N(body);
544 tree t= tree (WITH, n+2);
545 t[0]= var;
546 t[1]= val;
547 for (i=0; i<n; i++) t[i+2]= body[i];
548 return t;
549 }
550 else return tree (WITH, var, val, body);
551 }
552
553 static tree
expand_replace(tree begin,tree body)554 expand_replace (tree begin, tree body) {
555 int i, k= N(begin);
556 tree expand (EXPAND, k+1);
557 for (i=0; i<k; i++) expand[i]= begin[i];
558 expand[i]= body;
559 return expand;
560 }
561
562 static void
concat_search(tree t,int & i,tree open="")563 concat_search (tree t, int& i, tree open= "") {
564 bool set_reset= (open == "") || is_func (open, SET) || is_func (open, RESET);
565 bool begin_end= (open == "") || is_func (open, BEGIN) || is_func (open, END);
566 int n= N(t);
567 while (i<n) {
568 if (set_reset && is_func (t[i], SET, 2)) return;
569 if (set_reset && is_func (t[i], RESET, 1)) return;
570 if (begin_end && is_func (t[i], BEGIN)) return;
571 if (begin_end && is_func (t[i], END, 1)) return;
572 i++;
573 }
574 }
575
576 static tree
concat_replace(tree t,int i1,int i2)577 concat_replace (tree t, int i1, int i2) {
578 int i;
579 tree v (CONCAT);
580 for (i=i1+1; i<i2; i++) v << t[i];
581 if (N(v)==0) v= "";
582 else if (N(v)==1) v= v[0];
583 if (is_func (t[i1], SET))
584 return with_replace (t[i1][0], t[i1][1], v);
585 else return expand_replace (t[i1], v);
586 }
587
588 static tree
document_explode(tree t)589 document_explode (tree t) {
590 int i, n= N(t);
591 tree u (t, n);
592 for (i=0; i<n; i++)
593 if (is_concat (t[i])) u[i]= t[i];
594 else u[i]= tree (CONCAT, t[i]);
595 return u;
596 }
597
598 static tree
document_contract(tree t)599 document_contract (tree t) {
600 int i, n= N(t);
601 tree u (t, n);
602 for (i=0; i<n; i++)
603 if (N(t[i]) == 0) u[i]= "";
604 else if (N(t[i]) == 1) u[i]= t[i][0];
605 else u[i]= t[i];
606 return u;
607 }
608
609 static void
document_search(tree t,int & i,int & j,tree open="")610 document_search (tree t, int& i, int& j, tree open= "") {
611 bool set_reset= (open == "") || is_func (open, SET) || is_func (open, RESET);
612 bool begin_end= (open == "") || is_func (open, BEGIN) || is_func (open, END);
613 int n= N(t);
614 while (i<n) {
615 int k= N(t[i]);
616 while (j<k) {
617 if (set_reset && is_func (t[i][j], SET, 2)) return;
618 if (set_reset && is_func (t[i][j], RESET, 1)) return;
619 if (begin_end && is_func (t[i][j], BEGIN)) return;
620 if (begin_end && is_func (t[i][j], END, 1)) return;
621 j++;
622 }
623 i++;
624 j=0;
625 }
626 }
627
628 static void
document_inc(tree doc_t,int & doc_i,int & con_i)629 document_inc (tree doc_t, int& doc_i, int& con_i) {
630 con_i++;
631 if (con_i == N(doc_t[doc_i])) {
632 doc_i++;
633 con_i= 0;
634 }
635 }
636
637 static void
document_inc(tree & doc,tree & con,tree doc_t,int & doc_i,int & con_i)638 document_inc (tree& doc, tree& con, tree doc_t, int& doc_i, int& con_i) {
639 con_i++;
640 if (con_i == N(doc_t[doc_i])) {
641 doc << con;
642 con= tree (CONCAT);
643 doc_i++;
644 con_i= 0;
645 }
646 }
647
648 static void
document_merge(tree & doc,tree & con,tree doc_t,int doc_1,int con_1,int doc_2,int con_2)649 document_merge (tree& doc, tree& con, tree doc_t,
650 int doc_1, int con_1, int doc_2, int con_2)
651 {
652 int doc_i= doc_1, con_i= con_1;
653 while ((doc_i<doc_2) || ((doc_i==doc_2) && (con_i<con_2))) {
654 con << doc_t[doc_i][con_i];
655 document_inc (doc, con, doc_t, doc_i, con_i);
656 }
657 }
658
659 static tree
document_replace(tree doc_t,int doc_1,int con_1,int doc_2,int con_2)660 document_replace (tree doc_t, int doc_1, int con_1, int doc_2, int con_2) {
661 tree doc_b (DOCUMENT), con_b (CONCAT);
662 int doc_i= doc_1, con_i= con_1;
663 document_inc (doc_b, con_b, doc_t, doc_i, con_i);
664 document_merge (doc_b, con_b, doc_t, doc_i, con_i, doc_2, con_2);
665 doc_b << con_b;
666 doc_b= document_contract (doc_b);
667 bool flag= (doc_1!=doc_2) || ((con_1==0) && (con_2==N(doc_t[doc_2])-1));
668 /*
669 if (N(doc_b) != (doc_2-doc_1+1))
670 cout << (doc_2-doc_1+1) << ", " << doc_b << "\n";
671 */
672 if ((!flag) && (N(doc_b)==1)) doc_b= doc_b[0];
673 if (is_func (doc_t[doc_1][con_1], SET))
674 return with_replace (doc_t[doc_1][con_1][0],
675 doc_t[doc_1][con_1][1],
676 doc_b);
677 else return expand_replace (doc_t[doc_1][con_1], doc_b);
678 }
679
680 /******************************************************************************
681 * Upgrade set/reset -> with, begin/end -> apply
682 ******************************************************************************/
683
684 static tree upgrade_set_begin (tree t);
685
686 static tree
upgrade_set_begin_default(tree t)687 upgrade_set_begin_default (tree t) {
688 int i, n= N(t);
689 tree u (t, n);
690 for (i=0; i<n; i++)
691 u[i]= upgrade_set_begin (t[i]);
692 return u;
693 }
694
695 static tree
upgrade_set_begin_concat_once(tree t)696 upgrade_set_begin_concat_once (tree t) {
697 // cout << "in : " << t << "\n";
698 int i=0, n= N(t);
699 tree u (CONCAT);
700 while (i<n) {
701 int i0=i, i1, i2;
702 concat_search (t, i);
703 i1= i;
704 for (i=i0; i<i1; i++) u << t[i];
705 if (i==n) {
706 // cout << " " << i0 << ", " << i1 << "\n";
707 break;
708 }
709 i++;
710 concat_search (t, i, t[i1]);
711 i2= i;
712 // cout << " " << i0 << ", " << i1 << ", " << i2 << "\n";
713 if ((i2<n) && matching (t[i1], t[i2])) {
714 u << concat_replace (t, i1, i2);
715 i= i2+1;
716 }
717 else {
718 i= i1;
719 if (i == i0) u << t[i++];
720 }
721 }
722 // cout << "out: " << u << "\n";
723 // cout << "-------------------------------------------------------------\n";
724 // fflush (stdout);
725 return u;
726 }
727
728 static tree
upgrade_set_begin_concat(tree t)729 upgrade_set_begin_concat (tree t) {
730 tree u= t;
731 do { t= u; u= upgrade_set_begin_concat_once (t); } while (u != t);
732 u= upgrade_set_begin_default (u);
733 if (N(u) == 1) return u[0];
734 return u;
735 }
736
737 static void
upgrade_verbatim_expand(tree & doc,tree & con,tree ins)738 upgrade_verbatim_expand (tree& doc, tree& con, tree ins) {
739 tree& body= ins[N(ins)-1];
740 if (is_document (body) && (N(body)>1)) {
741 int n= N(body);
742 int start=0, end=n;
743 if (body[0] == "") start= 1;
744 if (body[n-1] == "") end= n-1;
745 body= body (start, end);
746 if (start != 0) {
747 doc << con;
748 con= tree (CONCAT);
749 }
750 con << ins;
751 if (end != n) {
752 doc << con;
753 con= tree (CONCAT);
754 }
755 }
756 else con << ins;
757 }
758
759 static void
upgrade_abstract_expand(tree & doc,tree & con,tree ins)760 upgrade_abstract_expand (tree& doc, tree& con, tree ins) {
761 (void) doc;
762 tree& body= ins[N(ins)-1];
763 if (is_document (body) && (N(body) > 1) && (body[0] == ""))
764 body= body (1, N(body));
765 con << ins;
766 }
767
768 static tree
upgrade_set_begin_document_once(tree doc_t)769 upgrade_set_begin_document_once (tree doc_t) {
770 // cout << "in : " << doc_t << "\n";
771 int doc_i=0, con_i=0;
772 tree doc (DOCUMENT), con (CONCAT);
773 while ((doc_i < N(doc_t)) && (con_i < N(doc_t[doc_i]))) {
774 int doc_0= doc_i, con_0= con_i;
775 document_search (doc_t, doc_i, con_i);
776 int doc_1= doc_i, con_1= con_i;
777 // cout << " 0: " << doc_0 << ", " << con_0 << "\n";
778 // cout << " 1: " << doc_1 << ", " << con_1 << "\n";
779 document_merge (doc, con, doc_t, doc_0, con_0, doc_1, con_1);
780 if (doc_i == N(doc_t)) break;
781 document_inc (doc_t, doc_i, con_i);
782 document_search (doc_t, doc_i, con_i, doc_t[doc_1][con_1]);
783 int doc_2= doc_i, con_2= con_i;
784 // cout << " 2: " << doc_2 << ", " << con_2 << "\n";
785 if ((doc_2 < N(doc_t)) &&
786 matching (doc_t[doc_1][con_1], doc_t[doc_2][con_2]))
787 {
788 tree ins= document_replace (doc_t, doc_1, con_1, doc_2, con_2);
789 // cout << "ins: " << ins << "\n";
790 if (is_func (ins, EXPAND, 2)) {
791 if ((ins[0] == "verbatim") || (ins[0] == "code") ||
792 (upgrade_tex_flag && is_verbatim (compound (as_string(ins[0])))))
793 upgrade_verbatim_expand (doc, con, ins);
794 else if (ins[0] == "abstract")
795 upgrade_abstract_expand (doc, con, ins);
796 else con << ins;
797 }
798 else if (is_func (ins, WITH) &&
799 is_func (ins[N(ins)-1], DOCUMENT, 1)) {
800 ins[N(ins)-1]= ins[N(ins)-1][0];
801 con << ins;
802 }
803 else con << ins;
804 document_inc (doc, con, doc_t, doc_i, con_i);
805 }
806 else {
807 doc_i= doc_1; con_i= con_1;
808 if ((doc_i == doc_0) && (con_i == con_0)) {
809 con << doc_t[doc_i][con_i];
810 document_inc (doc, con, doc_t, doc_i, con_i);
811 }
812 }
813 }
814 // cout << "out: " << doc << "\n";
815 // cout << "-------------------------------------------------------------\n";
816 fflush (stdout);
817 return doc;
818 }
819
820 static tree
upgrade_set_begin_document(tree t)821 upgrade_set_begin_document (tree t) {
822 tree u= t;
823 do {
824 t= u;
825 u= document_explode (u);
826 u= upgrade_set_begin_document_once (u);
827 u= document_contract (u);
828 } while (u != t);
829 u= upgrade_set_begin_default (u);
830 return u;
831 }
832
833 static tree
upgrade_set_begin_surround(tree t,tree search,bool & found)834 upgrade_set_begin_surround (tree t, tree search, bool& found) {
835 if (t == search) {
836 found= true;
837 if (upgrade_tex_flag)
838 return tree (DOCUMENT, copy (t));
839 return copy (t);
840 }
841 if (is_func (t, WITH) || is_func (t, EXPAND)) {
842 tree u= copy (t);
843 u[N(u)-1]= upgrade_set_begin_surround (u[N(u)-1], search, found);
844 return u;
845 }
846 if (is_concat (t)) {
847 int i, n= N(t), searching= !found;
848 tree left (CONCAT), middle, right (CONCAT);
849 for (i=0; i<n; i++) {
850 middle= upgrade_set_begin_surround (t[i], search, found);
851 if (searching && found) break;
852 else left << middle;
853 }
854 if (i==n) return copy (t);
855 for (i++; i<n; i++)
856 right << upgrade_set_begin_surround (t[i], search, found);
857 if (N(left) == 0) left= "";
858 else if (N(left) == 1) left= left[0];
859 if (N(right) == 0) right= "";
860 else if (N(right) == 1) right= right[0];
861 return tree (SURROUND, left, right, middle);
862 }
863 return copy (t);
864 }
865
866 static tree
upgrade_env_args(tree t,tree env)867 upgrade_env_args (tree t, tree env) {
868 if (is_atomic (t)) return t;
869 else if (is_func (t, APPLY, 1)) {
870 int i, k= N(env);
871 for (i=0; i<k-2; i++)
872 if (t[0] == env[i])
873 return tree (ARG, t[0]);
874 return t;
875 }
876 else {
877 int i, n= N(t);
878 tree r (t, n);
879 for (i=0; i<n; i++)
880 r[i]= upgrade_env_args (t[i], env);
881 return r;
882 }
883 }
884
885 static tree
upgrade_set_begin_env(tree t)886 upgrade_set_begin_env (tree t) {
887 //cout << "in : " << t << "\n";
888 int i, n= N(t);
889 tree u (MACRO, n);
890 for (i=0; i<n-2; i++)
891 u[i]= upgrade_set_begin (t[i]);
892 string s= "body";
893 for (i=0; i<n-2; i++)
894 if (t[i] == "body") s= "body*";
895 u[n-2]= copy (s);
896
897 tree begin= t[n-2], end= t[n-1], body (CONCAT);
898 if (begin == "") begin= tree (CONCAT);
899 else if (!is_concat (begin)) begin= tree (CONCAT, begin);
900 if (end == "") end= tree (CONCAT);
901 else if (!is_concat (end)) end= tree (CONCAT, end);
902 body << A(begin) << tree (ARG, copy (s)) << A(end);
903 //cout << "mid1: " << body << "\n";
904 body= upgrade_set_begin_concat (body);
905 body= upgrade_env_args (body, t);
906 //cout << "mid2: " << body << "\n";
907 bool found= false;
908 u[n-1]= upgrade_set_begin_surround (body, tree (ARG, s), found);
909 //cout << "out : " << u << "\n";
910 //cout << "-------------------------------------------------------------\n";
911 return u;
912 }
913
914 static tree
upgrade_set_begin(tree t)915 upgrade_set_begin (tree t) {
916 if (is_atomic (t)) return copy (t);
917 else {
918 if (is_concat (t)) return upgrade_set_begin_concat (t);
919 else if (is_document (t)) return upgrade_set_begin_document (t);
920 else if (is_func (t, ENV)) return upgrade_set_begin_env (t);
921 else return upgrade_set_begin_default (t);
922 }
923 }
924
925 static tree
eliminate_set_begin(tree t)926 eliminate_set_begin (tree t) {
927 if (is_atomic (t)) return t;
928 if (is_func (t, SET) || is_func (t, RESET) ||
929 is_func (t, BEGIN) || is_func (t, END) ||
930 is_func (t, ENV)) return "";
931
932 int i, n= N(t);
933 if (is_concat (t)) {
934 tree r (CONCAT);
935 for (i=0; i<n; i++) {
936 tree u= eliminate_set_begin (t[i]);
937 if (u != "") r << u;
938 }
939 if (N(r) == 0) return "";
940 if (N(r) == 1) return r[0];
941 return r;
942 }
943 else {
944 tree r (t, n);
945 for (i=0; i<n; i++)
946 r[i]= eliminate_set_begin (t[i]);
947 return r;
948 }
949 }
950
951 /******************************************************************************
952 * Upgrade surround, indentation after and final routine
953 ******************************************************************************/
954
955 bool
expand_needs_surrounding(string s)956 expand_needs_surrounding (string s) {
957 return
958 (s == "maketitle") || (s == "abstract") ||
959 (s == "theorem") || (s == "proposition") || (s == "lemma") ||
960 (s == "corollary") || (s == "proof") || (s == "axiom") ||
961 (s == "definition") || (s == "notation") || (s == "conjecture") ||
962 (s == "remark") || (s == "note") || (s == "example") ||
963 (s == "exercise") || (s == "warning") ||
964 (s == "convention") || (s == "acknowledgments") ||
965 (s == "code") || (s == "quote") ||
966 (s == "quotation") || (s == "verse") || (s == "center") ||
967 (s == "indent") || (s == "body") || (s == "description") ||
968 starts (s, "itemize") || starts (s, "enumerate");
969 }
970
971 static bool
with_needs_surrounding(string s)972 with_needs_surrounding (string s) {
973 return
974 (s == "paragraph mode") || (s == "paragraph hyphenation") ||
975 (s == "paragraph width") || (s == "left margin") ||
976 (s == "right margin") || (s == "first indentation") ||
977 (s == "last indentation") || (s == "no first indentation") ||
978 (s == "no last indentation") || (s == "interline space") ||
979 (s == "horizontal ink separation") || (s == "line stretch") ||
980 (s == "interparagraph space");
981 }
982
983 static bool
needs_surrounding(tree t)984 needs_surrounding (tree t) {
985 if (is_multi_paragraph (t)) return true;
986 if ((is_func (t, APPLY) || is_func (t, EXPAND)) && is_atomic (t[0])) {
987 if (t[0] == "verbatim") return (N(t)==2) && is_multi_paragraph (t[1]);
988 return expand_needs_surrounding (t[0]->label);
989 }
990 if (is_func (t, WITH)) {
991 int i, n= N(t)-1;
992 for (i=0; i<n; i+=2)
993 if (is_atomic (t[i]) && with_needs_surrounding (t[i]->label))
994 return true;
995 }
996 return false;
997 }
998
999 static bool
needs_transfer(tree t)1000 needs_transfer (tree t) {
1001 return
1002 is_func (t, EXPAND, 2) &&
1003 ((t[0] == "equation") || (t[0] == "equation*") ||
1004 (t[0] == "eqnarray*") || (t[0] == "leqnarray*"));
1005 }
1006
1007 static tree
upgrade_surround(tree t)1008 upgrade_surround (tree t) {
1009 if (upgrade_tex_flag || is_atomic (t)) return t;
1010 int i, n= N(t);
1011 tree r (t, n);
1012 for (i=0; i<n; i++) {
1013 tree u= t[i];
1014 if (is_document (t) && is_concat (u) && (N(u)>1)) {
1015 int j, k= N(u);
1016 for (j=0; j<k; j++)
1017 if (needs_surrounding (u[j])) {
1018 tree before= u (0 , j);
1019 tree after = u (j+1, k);
1020 tree body = upgrade_surround (u[j]);
1021 if (N(before)==0) before= "";
1022 if (N(before)==1) before= before[0];
1023 if (N(after )==0) after = "";
1024 if (N(after )==1) after = after [0];
1025 before= upgrade_surround (before);
1026 after = upgrade_surround (after );
1027 r[i]= tree (SURROUND, before, after, body);
1028 break;
1029 }
1030 else if (needs_transfer (u[j])) {
1031 tree temp= upgrade_surround (u[j][1]);
1032 if (!is_concat (temp)) temp= tree (CONCAT, temp);
1033 tree body= u (0, j);
1034 body << A (temp) << A (u (j+1, k));
1035 r[i]= tree (EXPAND, u[j][0], body);
1036 break;
1037 }
1038 if (j<k) continue;
1039 }
1040 r[i]= upgrade_surround (u);
1041 }
1042 return r;
1043 }
1044
1045 static tree
upgrade_indent(tree t)1046 upgrade_indent (tree t) {
1047 if (is_atomic (t)) return t;
1048 else if (t == tree (ASSIGN, "no first indentation", "true"))
1049 return tree (FORMAT, "no indentation after");
1050 else if (t == tree (ASSIGN, "no first indentation", "false"))
1051 return tree (FORMAT, "enable indentation after");
1052 else {
1053 int i, n= N(t);
1054 tree r (t, n);
1055 for (i=0; i<n; i++)
1056 r[i]= upgrade_indent (t[i]);
1057 return r;
1058 }
1059 }
1060
1061 static tree
upgrade_equations(tree t)1062 upgrade_equations (tree t) {
1063 if (!upgrade_tex_flag || is_atomic (t)) return t;
1064 else if (needs_transfer (t) && !is_document (t[1])) {
1065 t[1]= document (upgrade_equations (t[1]));
1066 return t;
1067 }
1068 else {
1069 int i, n= N(t);
1070 tree r (t, n);
1071 for (i=0; i<n; i++)
1072 r[i]= upgrade_equations (t[i]);
1073 return r;
1074 }
1075 }
1076
1077 static tree
upgrade_new_environments(tree t)1078 upgrade_new_environments (tree t) {
1079 t= upgrade_set_begin (t);
1080 t= eliminate_set_begin (t);
1081 t= upgrade_surround (t);
1082 t= upgrade_indent (t);
1083 t= upgrade_equations (t);
1084 return t;
1085 }
1086
1087 /******************************************************************************
1088 * Upgrade items
1089 ******************************************************************************/
1090
1091 static tree
upgrade_items(tree t)1092 upgrade_items (tree t) {
1093 if (is_atomic (t)) return t;
1094 else if ((t == tree (APPLY, "item")) || (t == tree (VALUE, "item")))
1095 return tree (EXPAND, "item");
1096 else {
1097 int i, n= N(t);
1098 tree r (t, n);
1099 for (i=0; i<n; i++)
1100 r[i]= upgrade_items (t[i]);
1101 return r;
1102 }
1103 }
1104
1105 /******************************************************************************
1106 * Upgrade resize
1107 ******************************************************************************/
1108
1109 static tree
upgrade_resize_arg(tree t,int type)1110 upgrade_resize_arg (tree t, int type) {
1111 if (!is_atomic (t)) return "";
1112 string s= t->label;
1113 if ((s == "same") || (s == "ink")) return "";
1114 if (type == 1) s= "l[" * s;
1115 if (type == 2) s= "b[" * s;
1116 if (type == 3) s= "r]" * s;
1117 if (type == 4) s= "t]" * s;
1118 return s;
1119 }
1120
1121 static tree
upgrade_resize(tree t)1122 upgrade_resize (tree t) {
1123 if (is_atomic (t)) return t;
1124 else if (is_func (t, RESIZE, 6)) {
1125 tree r (RESIZE, t[0]);
1126 int extend= (t[1] == "extend"? 1: 0);
1127 r << upgrade_resize_arg (t[2], 1 * extend)
1128 << upgrade_resize_arg (t[3], 2 * extend)
1129 << upgrade_resize_arg (t[4], 3 * extend)
1130 << upgrade_resize_arg (t[5], 4 * extend);
1131 return r;
1132 }
1133 else {
1134 int i, n= N(t);
1135 tree r (t, n);
1136 for (i=0; i<n; i++)
1137 r[i]= upgrade_resize (t[i]);
1138 return r;
1139 }
1140 }
1141
1142 /******************************************************************************
1143 * Upgrade tables
1144 ******************************************************************************/
1145
1146 static void
handle_mosaic_format(tree & fm,tree t,int i,int j)1147 handle_mosaic_format (tree& fm, tree t, int i, int j) {
1148 string align = as_string (t[1]);
1149 string hspan = as_string (t[2]);
1150 string vspan = as_string (t[3]);
1151 string col = as_string (t[4]);
1152
1153 string halign= "l";
1154 string valign= "B";
1155 if (N(align)>=2) {
1156 switch (align[0]) {
1157 case 'n': valign= "t"; break;
1158 case 'c': valign= "c"; break;
1159 case '0': valign= "B"; break;
1160 case 's': valign= "s"; break;
1161 }
1162 switch (align[1]) {
1163 case 'w': halign= "l"; break;
1164 case '0': halign= "L"; break;
1165 case 'c': halign= "c"; break;
1166 case 'e': halign= "r"; break;
1167 }
1168 }
1169 if ((col == "none") || (col == "")) col= "";
1170 else col= "foreground";
1171
1172 tree w (CWITH);
1173 w << as_string (i+1) << as_string (j+1)
1174 << as_string (i+1) << as_string (j+1);
1175
1176 if (halign != "l") {
1177 tree with= copy (w);
1178 with << "cell halign" << halign;
1179 fm << with;
1180 }
1181 if (valign != "B") {
1182 tree with= copy (w);
1183 with << "cell valign" << valign;
1184 fm << with;
1185 }
1186 if (hspan != "1") {
1187 tree with= copy (w);
1188 with << "cell hspan" << hspan;
1189 fm << with;
1190 }
1191 if (vspan != "1") {
1192 tree with= copy (w);
1193 with << "cell vspan" << vspan;
1194 fm << with;
1195 }
1196 if (col != "") {
1197 tree with= copy (w);
1198 with << "cell background" << col;
1199 fm << with;
1200 }
1201 }
1202
1203
1204 static tree
upgrade_table(tree t)1205 upgrade_table (tree t) {
1206 if (is_atomic (t)) return t;
1207 else if (is_func (t, OLD_MATRIX) ||
1208 is_func (t, OLD_TABLE) ||
1209 is_func (t, OLD_MOSAIC) ||
1210 (is_func (t, TFORMAT) && is_func (t[N(t)-1], OLD_MATRIX)))
1211 {
1212 tree ft (TFORMAT);
1213 if (is_func (t, TFORMAT)) {
1214 ft= t (0, N(t)-1);
1215 t = t [N(t)-1];
1216 }
1217 if (is_func (t, OLD_MOSAIC)) {
1218 tree with (CWITH);
1219 with << "1" << "-1" << "1" << "-1" << "cell mode" << "c";
1220 ft << with;
1221 }
1222
1223 int i, j;
1224 int nr_rows= as_int (t[N(t)-1]);
1225 int nr_cols= as_int (t[N(t)-2]);
1226 tree tt (TABLE, nr_rows);
1227 for (i=0; i<nr_rows; i++) {
1228 tree rt (ROW, nr_cols);
1229 for (j=0; j<nr_cols; j++) {
1230 tree c= upgrade_table (t[i*nr_cols+j]);
1231 if (is_func (c, OLD_MOSAIC_ITEM)) {
1232 handle_mosaic_format (ft, c, i, j);
1233 c= c[0];
1234 }
1235 rt[j]= tree (CELL, c);
1236 }
1237 tt[i]= rt;
1238 }
1239
1240 ft << tt;
1241 tree xt (EXPAND, "tabular*", ft);
1242 if (is_func (t, OLD_TABLE)) xt[0]= "block*";
1243 if (is_func (t, OLD_MOSAIC)) xt[0]= "tabular";
1244 return xt;
1245 }
1246 else {
1247 int i, n= N(t);
1248 tree r (t, n);
1249 for (i=0; i<n; i++)
1250 r[i]= upgrade_table (t[i]);
1251 return r;
1252 }
1253 }
1254
1255 /******************************************************************************
1256 * Upgrade splits
1257 ******************************************************************************/
1258
1259 static tree
upgrade_split(tree t,bool eq=false)1260 upgrade_split (tree t, bool eq= false) {
1261 int i, n= N(t);
1262 if (is_atomic (t)) return t;
1263 else if (is_func (t, SURROUND, 3) && is_func (t[0], SPLIT)) {
1264 tree u= t[2];
1265 if (!is_concat (u)) u= tree (CONCAT, t[0], u);
1266 else u= tree (CONCAT, t[0]) * u;
1267 return tree (SURROUND, "", upgrade_split (t[1]), upgrade_split (u));
1268 }
1269 else if (is_func (t, SURROUND, 3) && is_concat (t[0])) {
1270 tree r (CONCAT);
1271 tree split ("");
1272 for (i=0; i<N(t[0]); i++)
1273 if (is_func (t[0][i], SPLIT)) split= t[0][i];
1274 else r << t[0][i];
1275 tree u= t[2];
1276 if (split != "") {
1277 if (!is_concat (u)) u= tree (CONCAT, split, u);
1278 else u= tree (CONCAT, split) * u;
1279 }
1280 r= tree (SURROUND, upgrade_split (r),
1281 upgrade_split (t[1]), upgrade_split (u));
1282 return r;
1283 }
1284 else if (is_concat (t)) {
1285 tree r (CONCAT);
1286 tree split ("");
1287 int nr_rows=1, nr_cols=1, sep=1;
1288 for (i=0; i<n; i++)
1289 if (is_func (t[i], SPLIT)) split= t[i];
1290 else {
1291 tree u= upgrade_split (t[i]);
1292 if (u == tree (FORMAT, "line separator")) sep++;
1293 if (u == tree (FORMAT, "next line")) {
1294 nr_cols= max (sep, nr_cols);
1295 sep= 1;
1296 nr_rows++;
1297 }
1298 r << u;
1299 }
1300 nr_cols= max (sep, nr_cols);
1301 if (split == "" && nr_cols == 1 && !eq) return r;
1302 else {
1303 int col=0, row=0;
1304 tree T (TABLE, nr_rows);
1305 for (row=0; row<nr_rows; row++) {
1306 tree R (ROW, nr_cols);
1307 for (col=0; col<nr_cols; col++) R[col]= tree (CELL, "");
1308 T[row]= R;
1309 }
1310
1311 tree u (CONCAT);
1312 row= col= 0;
1313 for (i=0; i<N(r); i++)
1314 if ((r[i] == tree (FORMAT, "line separator")) ||
1315 (r[i] == tree (FORMAT, "next line")))
1316 {
1317 if (N(u) == 0) u= "";
1318 else if (N(u) == 1) u= u[0];
1319 T[row][col][0]= u;
1320 u= tree (CONCAT);
1321 if (r[i] == tree (FORMAT, "line separator")) col++;
1322 else {
1323 row++;
1324 col= 0;
1325 }
1326 }
1327 else u << r[i];
1328 if (N(u) == 0) u= "";
1329 else if (N(u) == 1) u= u[0];
1330 T[row][col][0]= u;
1331 r= T;
1332 }
1333
1334 tree tf (TFORMAT);
1335 if (split != "") {
1336 tf << tree (TWITH, "table hyphen", "y")
1337 << tree (TWITH, "table width", "1par")
1338 << tree (TWITH, "table min cols", as_string (N (split)))
1339 << tree (TWITH, "table max cols", as_string (N (split)))
1340 << tree (CWITH, "1", "-1", "1", "1", "cell lsep", "0spc")
1341 << tree (CWITH, "1", "-1", "-1", "-1", "cell rsep", "0spc")
1342 << tree (CWITH, "1", "-1", "1", "-1", "cell bsep", "0sep")
1343 << tree (CWITH, "1", "-1", "1", "-1", "cell tsep", "0sep")
1344 << tree (CWITH, "1", "-1", "1", "1", "cell hyphen", "b")
1345 << tree (CWITH, "1", "-1", "-1", "-1", "cell hyphen", "t");
1346 if (split[0] == "right")
1347 tf << tree (CWITH, "1", "-1", "1", "1", "cell hpart", "1");
1348 if ((split[N(split)-1] == "left") || (split[N(split)-1] == "justify"))
1349 tf << tree (CWITH, "1", "-1", "-1", "-1", "cell hpart", "1");
1350 for (i=0; i<N(split); i++) {
1351 tree with (CWITH);
1352 int j= (i==N(split)-1)? -1: i+1;
1353 with << "1" << "-1" << as_string (j) << as_string (j) << "cell halign";
1354 if (split[i] == "right") with << "r";
1355 else if (split[i] == "center") with << "c";
1356 else with << "l";
1357 tf << with;
1358 }
1359 }
1360 if (r == tree (CONCAT)) r= "";
1361 else if (is_func (r, CONCAT, 1)) r= r[0];
1362 tf << r;
1363 if ((split != "") && is_func (r, TABLE))
1364 return tree (EXPAND, "tabular*", tf);
1365 return tf;
1366 }
1367 else {
1368 tree r (t, n);
1369 if (n == 1 || is_func (t, EXPAND, 2)) {
1370 string s= as_string (L(t));
1371 if (is_func (t, EXPAND, 2) && is_atomic (t[0])) s= t[0]->label;
1372 if (ends (s, "*")) s= s (0, N(s)-1);
1373 if (s == "eqnarray" || s == "align" || s == "multline" ||
1374 s == "gather" || s == "eqsplit") {
1375 tree arg= t[n-1];
1376 if (is_func (arg, DOCUMENT, 1)) arg= arg[0];
1377 if (!is_concat (arg)) arg= tree (CONCAT, arg);
1378 r= copy (t);
1379 r[n-1]= upgrade_split (arg, true);
1380 return r;
1381 }
1382 }
1383 else if (upgrade_tex_flag && (n == 2 || is_func (t, EXPAND, 3))) {
1384 string s= as_string (L(t));
1385 if (is_func (t, EXPAND, 3) && is_atomic (t[0])) s= t[0]->label;
1386 if (ends (s, "*")) s= s (0, N(s)-1);
1387 if (s == "alignat") {
1388 tree arg= t[n-1];
1389 if (is_func (arg, DOCUMENT, 1)) arg= arg[0];
1390 if (!is_concat (arg)) arg= tree (CONCAT, arg);
1391 r= copy (t);
1392 r[n-1]= upgrade_split (arg, true);
1393 return r;
1394 }
1395 }
1396 for (i=0; i<n; i++)
1397 r[i]= upgrade_split (t[i]);
1398 return r;
1399 }
1400 }
1401
1402 /******************************************************************************
1403 * Upgrade projects
1404 ******************************************************************************/
1405
1406 static tree
upgrade_project(tree t)1407 upgrade_project (tree t) {
1408 if (is_atomic (t)) return t;
1409 else if (is_expand (t, "include-document", 1))
1410 return tree (VAR_INCLUDE, t[1]);
1411 else {
1412 int i, n= N(t);
1413 tree r (t, n);
1414 for (i=0; i<n; i++)
1415 r[i]= upgrade_project (t[i]);
1416 return r;
1417 }
1418 }
1419
1420 /******************************************************************************
1421 * Upgrade title
1422 ******************************************************************************/
1423
1424 static tree
upgrade_title(tree t,tree & tit,tree & auth,tree & meta)1425 upgrade_title (tree t, tree& tit, tree& auth, tree& meta) {
1426 if (is_atomic (t)) return t;
1427 else if (is_func (t, APPLY, 2) ||
1428 is_func (t, EXPAND, 2)) {
1429 if (t[0] == "title") {
1430 tit << tree (EXPAND, "title", t[1]); return ""; }
1431 if (t[0] == "author") {
1432 auth << tree (EXPAND, "author", t[1]); return ""; }
1433 if (t[0] == "address") {
1434 auth << tree (EXPAND, "address", t[1]); return ""; }
1435 if (t[0] == "urladdr") {
1436 auth << tree (EXPAND, "title-web", t[1]); return ""; }
1437 if (t[0] == "title-email") {
1438 auth << tree (EXPAND, "title-email", t[1]); return ""; }
1439 if (t[0] == "title-thanks") {
1440 meta << tree (EXPAND, "title-thanks", t[1]); return ""; }
1441 if (t[0] == "keywords") {
1442 meta << tree (EXPAND, "title-keywords", t[1]); return ""; }
1443 if (t[0] == "subjclass") {
1444 meta << tree (EXPAND, "title-ams-class", t[1]); return ""; }
1445 if (t[0] == "classification") {
1446 meta << tree (EXPAND, "title-ams-class", t[1]); return ""; }
1447 }
1448 else if (is_func (t, APPLY, 3) ||
1449 is_func (t, EXPAND, 3)) {
1450 if (t[0] == "subjclass*") {
1451 meta << tree (EXPAND, "title-ams-class", t[2]); return ""; }
1452 }
1453 else if ((t == tree (APPLY, "maketitle")) ||
1454 (t == tree (EXPAND, "maketitle")))
1455 {
1456 tree doc (DOCUMENT);
1457 doc << A (tit);
1458 doc << A (auth);
1459 doc << A (meta);
1460 doc << tree (EXPAND, "title-date", tree (_DATE, ""));
1461 return tree (EXPAND, "make-title", doc);
1462 }
1463
1464 int i, n= N(t);
1465 tree r (t, n);
1466 for (i=0; i<n; i++)
1467 r[i]= upgrade_title (t[i], tit, auth, meta);
1468 return r;
1469 }
1470
1471 static tree
upgrade_title(tree t)1472 upgrade_title (tree t) {
1473 tree tit (DOCUMENT), auth (DOCUMENT), meta (DOCUMENT);
1474 return simplify_correct (upgrade_title (t, tit, auth, meta));
1475 }
1476
1477 /******************************************************************************
1478 * Upgrade cas
1479 ******************************************************************************/
1480
1481 static void
upgrade_cas_search(tree t,tree & style)1482 upgrade_cas_search (tree t, tree& style) {
1483 if (is_atomic (t));
1484 else if (is_expand (t, "session", 3)) {
1485 if (!is_atomic (t[1])) return;
1486 string l= copy (t[1]->label);
1487 if (l == "scheme") return;
1488 if (l == "shell") return;
1489 if (l == "gTybalt") l= "gtybalt";
1490 if (l == "Macaulay2") l= "macaulay2";
1491 int i, n= N(style);
1492 for (i=0; i<n; i++)
1493 if (style[i] == l) return;
1494 style << l;
1495 }
1496 else {
1497 int i, n= N(t);
1498 for (i=0; i<n; i++)
1499 upgrade_cas_search (t[i], style);
1500 }
1501 }
1502
1503 static void
set_document_attribute(tree doc,string attr,tree val)1504 set_document_attribute (tree doc, string attr, tree val) {
1505 int i, n= arity (doc);
1506 for (i=0; i<n; i++)
1507 if ((is_func (doc[i], EXPAND, 2) || is_func (doc[i], APPLY, 2)) &&
1508 (doc[i][0] == attr))
1509 {
1510 doc[i][1]= val;
1511 return;
1512 }
1513 doc << tree (EXPAND, attr, val);
1514 }
1515
1516 static tree
upgrade_cas(tree doc)1517 upgrade_cas (tree doc) {
1518 tree style= copy (extract (doc, "style"));
1519 upgrade_cas_search (doc, style);
1520 doc= copy (doc);
1521 set_document_attribute (doc, "style", style);
1522 return doc;
1523 }
1524
1525 /******************************************************************************
1526 * Upgrade modified symbols
1527 ******************************************************************************/
1528
1529 static bool
is_with(tree t,string var,string val)1530 is_with (tree t, string var, string val) {
1531 return is_func (t, WITH, 3) && (t[0] == var) && (t[1] == val);
1532 }
1533
1534 static bool
is_alpha(tree t)1535 is_alpha (tree t) {
1536 if (is_compound (t)) return false;
1537 string s= t->label;
1538 return (N(s) == 1) && is_alpha (s[0]);
1539 }
1540
1541 static bool
is_alpha_numeric(tree t)1542 is_alpha_numeric (tree t) {
1543 if (is_compound (t)) return false;
1544 string s= t->label;
1545 return (N(s) == 1) && (is_alpha (s[0]) || is_numeric (s[0]));
1546 }
1547
1548 static bool
is_upper(tree t)1549 is_upper (tree t) {
1550 if (is_compound (t)) return false;
1551 string s= t->label;
1552 return (N(s) == 1) && (s[0] >= 'A') && (s[0] <= 'Z');
1553 }
1554
1555 static bool
is_bold(tree t)1556 is_bold (tree t) {
1557 if (is_compound (t)) return false;
1558 if (is_alpha_numeric (t)) return true;
1559 string s= locase_all (t->label);
1560 return
1561 (s == "<alpha>") || (s == "<beta>") || (s == "<gamma>") ||
1562 (s == "<delta>") || (s == "<epsilon>") || (s == "<zeta>") ||
1563 (s == "<eta>") || (s == "<theta>") || (s == "<iota>") ||
1564 (s == "<kappa>") || (s == "<lambda>") || (s == "<mu>") ||
1565 (s == "<nu>") || (s == "<xi>") || (s == "<omicron>") ||
1566 (s == "<pi>") || (s == "<rho>") || (s == "<sigma>") ||
1567 (s == "<tau>") || (s == "<upsilon>") || (s == "<phi>") ||
1568 (s == "<psi>") || (s == "<chi>") || (s == "<omega>") ||
1569 (s == "<varepsilon>") || (s == "<vartheta>") || (s == "<varkappa>") ||
1570 (s == "<varpi>") || (s == "<varrho>") || (s == "<varsigma>") ||
1571 (s == "<varphi>") || (s == "<backepsilon>") || (s == "<mho>") ||
1572 (s == "<Backepsilon>") || (s == "<Mho>") || (s == "<ell>");
1573 }
1574
1575 static tree
upgrade_mod_symbol(string prefix,string s)1576 upgrade_mod_symbol (string prefix, string s) {
1577 if (N(s) == 1) return "<" * prefix * s * ">";
1578 else return "<" * prefix * s (1, N(s)-1) * ">";
1579 }
1580
1581 static tree
upgrade_mod_symbols(tree t)1582 upgrade_mod_symbols (tree t) {
1583 if (is_atomic (t)) return t;
1584 if (is_with (t, "math font series", "bold") && is_bold (t[2]))
1585 return upgrade_mod_symbol ("b-", t[2]->label);
1586 else if (is_with (t, "math font", "cal") && is_upper (t[2]))
1587 return upgrade_mod_symbol ("cal-", t[2]->label);
1588 else if (is_with (t, "math font", "Euler") && is_alpha (t[2]))
1589 return upgrade_mod_symbol ("frak-", t[2]->label);
1590 else if (is_with (t, "math font", "Bbb*") && is_alpha (t[2]))
1591 return upgrade_mod_symbol ("bbb-", t[2]->label);
1592 else if (is_with (t, "math font series", "bold") &&
1593 is_with (t[2], "math font", "cal") && is_upper (t[2][2]))
1594 return upgrade_mod_symbol ("b-cal-", t[2][2]->label);
1595 else if (is_with (t, "math font", "cal") &&
1596 is_with (t[2], "math font series", "bold") && is_upper (t[2][2]))
1597 return upgrade_mod_symbol ("b-cal-", t[2][2]->label);
1598 //else if ((is_func (t, VALUE, 1) || is_func (t, EXPAND, 1) ||
1599 // is_func (t, APPLY, 1)) && (is_atomic (t[0]))) {
1600 // string s= t[0]->label;
1601 // if ((N(s) == 2) && ((s[0]=='m') && (s[1]>='a') && s[1]<='z'))
1602 // return upgrade_mod_symbol ("frak-", s(1,2));
1603 // if ((N(s) == 2) && ((s[0]=='M') && (s[1]>='A') && s[1]<='Z'))
1604 // return upgrade_mod_symbol ("frak-", s(1,2));
1605 // return t;
1606 //}
1607 else {
1608 int i, n= N(t);
1609 tree r (t, n);
1610 for (i=0; i<n; i++)
1611 r[i]= upgrade_mod_symbols (t[i]);
1612 return r;
1613 }
1614 }
1615
1616 /******************************************************************************
1617 * Upgrading menus in the help
1618 ******************************************************************************/
1619
1620 static tree
upgrade_menus_in_help(tree t)1621 upgrade_menus_in_help (tree t) {
1622 if (is_atomic (t)) return t;
1623 if (is_expand (t, "menu", 1) || is_expand (t, "submenu", 2) ||
1624 is_expand (t, "subsubmenu", 3) || is_expand (t, "subsubsubmenu", 4)) {
1625 int i, n= N(t);
1626 tree r (APPLY, n);
1627 r[0]= "menu";
1628 for (i=1; i<n; i++) r[i]= t[i];
1629 return r;
1630 }
1631 else {
1632 int i, n= N(t);
1633 tree r (t, n);
1634 for (i=0; i<n; i++)
1635 r[i]= upgrade_menus_in_help (t[i]);
1636 return r;
1637 }
1638 }
1639
1640 static tree
capitalize_sub(tree t)1641 capitalize_sub (tree t) {
1642 if (is_atomic (t)) return upcase_first (t->label);
1643 else return t;
1644 }
1645
1646 static tree
upgrade_capitalize_menus(tree t)1647 upgrade_capitalize_menus (tree t) {
1648 if (is_atomic (t)) return t;
1649 if (is_func (t, APPLY) && (t[0] == "menu")) {
1650 int i, n= N(t);
1651 tree r (APPLY, n);
1652 r[0]= "menu";
1653 for (i=1; i<n; i++) r[i]= capitalize_sub (t[i]);
1654 return r;
1655 }
1656 else {
1657 int i, n= N(t);
1658 tree r (t, n);
1659 for (i=0; i<n; i++)
1660 r[i]= upgrade_capitalize_menus (t[i]);
1661 return r;
1662 }
1663 }
1664
1665 /******************************************************************************
1666 * Upgrade branches
1667 ******************************************************************************/
1668
1669 static tree
upgrade_traverse_branch(tree t)1670 upgrade_traverse_branch (tree t) {
1671 if (is_atomic (t)) return t;
1672 else if (is_expand (t, "branch", 3) ||
1673 (is_func (t, APPLY, 4) && (t[0] == "branch")))
1674 return tree (APPLY, t[0], t[1], t[3]);
1675 else {
1676 int i, n= N(t);
1677 tree r (t, n);
1678 for (i=0; i<n; i++)
1679 r[i]= upgrade_traverse_branch (t[i]);
1680 return r;
1681 }
1682 }
1683
1684 /******************************************************************************
1685 * Upgrade sessions
1686 ******************************************************************************/
1687
1688 static tree
upgrade_session(tree t)1689 upgrade_session (tree t) {
1690 if (is_atomic (t)) return t;
1691 else if (is_expand (t, "session", 3)) {
1692 tree u= tree (EXPAND, "session", t[3]);
1693 tree w= tree (WITH);
1694 w << PROG_LANGUAGE << t[1] << PROG_SESSION << t[2] << u;
1695 return w;
1696 }
1697 else {
1698 int i, n= N(t);
1699 tree r (t, n);
1700 for (i=0; i<n; i++)
1701 r[i]= upgrade_session (t[i]);
1702 return r;
1703 }
1704 }
1705
1706 /******************************************************************************
1707 * Upgrade sessions
1708 ******************************************************************************/
1709
1710 static tree
upgrade_formatting(tree t)1711 upgrade_formatting (tree t) {
1712 if (is_atomic (t)) return t;
1713 else if (is_func (t, FORMAT, 1)) {
1714 string name= replace (t[0]->label, " ", "-");
1715 if (name == "line-separator") name= "line-sep";
1716 else if (name == "no-line-break") name= "no-break";
1717 else if (name == "no-first-indentation") name= "no-indent";
1718 else if (name == "enable-first-indentation") name= "yes-indent";
1719 else if (name == "no-indentation-after") name= "no-indent*";
1720 else if (name == "enable-indentation-after") name= "yes-indent*";
1721 else if (name == "page-break-before") name= "page-break*";
1722 else if (name == "no-page-break-before") name= "no-page-break*";
1723 else if (name == "no-page-break-after") name= "no-page-break";
1724 else if (name == "new-page-before") name= "new-page*";
1725 else if (name == "new-double-page-before") name= "new-dpage*";
1726 else if (name == "new-double-page") name= "new-dpage";
1727 return tree (as_tree_label (name));
1728 }
1729 else {
1730 int i, n= N(t);
1731 tree r (t, n);
1732 for (i=0; i<n; i++)
1733 r[i]= upgrade_formatting (t[i]);
1734 return r;
1735 }
1736 }
1737
1738 /******************************************************************************
1739 * Upgrade expand
1740 ******************************************************************************/
1741
1742 static tree
upgrade_expand(tree t,tree_label WHICH_EXPAND)1743 upgrade_expand (tree t, tree_label WHICH_EXPAND) {
1744 if (is_atomic (t)) return t;
1745 else if (is_func (t, WHICH_EXPAND) && is_atomic (t[0])) {
1746 int i, n= N(t)-1;
1747 string s= t[0]->label;
1748 if (s == "quote") s= s * "-env";
1749 tree_label l= make_tree_label (s);
1750 tree r (l, n);
1751 for (i=0; i<n; i++)
1752 r[i]= upgrade_expand (t[i+1], WHICH_EXPAND);
1753 return r;
1754 }
1755 else if (is_func (t, ASSIGN, 2) &&
1756 (t[0] == "quote") &&
1757 is_func (t[1], MACRO)) {
1758 tree arg= upgrade_expand (t[1], WHICH_EXPAND);
1759 return tree (ASSIGN, t[0]->label * "-env", arg);
1760 }
1761 else {
1762 int i, n= N(t);
1763 tree r (t, n);
1764 for (i=0; i<n; i++)
1765 r[i]= upgrade_expand (t[i], WHICH_EXPAND);
1766 return r;
1767 }
1768 }
1769
1770 static tree
upgrade_xexpand(tree t)1771 upgrade_xexpand (tree t) {
1772 if (is_atomic (t)) return t;
1773 else {
1774 int i, n= N(t);
1775 tree r (t, n);
1776 if (is_expand (t))
1777 r= tree (COMPOUND, n);
1778 for (i=0; i<n; i++)
1779 r[i]= upgrade_xexpand (t[i]);
1780 return r;
1781 }
1782 }
1783
1784 /******************************************************************************
1785 * Upgrade apply
1786 ******************************************************************************/
1787
1788 static tree
upgrade_apply(tree t)1789 upgrade_apply (tree t) {
1790 if (is_atomic (t)) return t;
1791 /*
1792 if (is_func (t, APPLY))
1793 cout << t[0] << "\n";
1794 */
1795 if (is_func (t, APPLY) && is_atomic (t[0])) {
1796 int i, n= N(t)-1;
1797 string s= t[0]->label;
1798 tree_label l= make_tree_label (s);
1799 tree r (l, n);
1800 for (i=0; i<n; i++)
1801 r[i]= upgrade_apply (t[i+1]);
1802 return r;
1803 }
1804
1805 int i, n= N(t);
1806 tree r (t, n);
1807 if (is_func (t, APPLY))
1808 r= tree (COMPOUND, n);
1809 for (i=0; i<n; i++)
1810 r[i]= upgrade_apply (t[i]);
1811 return r;
1812 }
1813
1814 static tree
upgrade_function_arg(tree t,tree var)1815 upgrade_function_arg (tree t, tree var) {
1816 if (is_atomic (t)) return t;
1817 else if ((t == tree (APPLY, var)) || (t == tree (VALUE, var)))
1818 return tree (ARG, var);
1819 else {
1820 int i, n= N(t);
1821 tree r (t, n);
1822 for (i=0; i<n; i++)
1823 r[i]= upgrade_function_arg (t[i], var);
1824 return r;
1825 }
1826 }
1827
1828 static tree
upgrade_function(tree t)1829 upgrade_function (tree t) {
1830 if (is_atomic (t)) return t;
1831 if (is_func (t, ASSIGN, 2) && is_func (t[1], FUNC)) {
1832 int i, n= N(t[1])-1;
1833 for (i=0; i<n; i++)
1834 if (ends (as_string (t[1][i]), "*"))
1835 cout << "TeXmacs] Deprecated argument list '" << t[1][i]
1836 << "' in function '" << t[0] << "'\n"
1837 << "TeXmacs] You should use the 'xmacro' primitive now\n";
1838 }
1839 /*
1840 if (is_func (t, ASSIGN, 2) && is_func (t[1], FUNC) && (N(t[1])>1)) {
1841 cout << "Function: " << t[0] << "\n";
1842 }
1843 */
1844 if (is_func (t, FUNC)) {
1845 int i, n= N(t)-1;
1846 tree u= t[n], r (MACRO, n+1);
1847 for (i=0; i<n; i++) {
1848 u= upgrade_function_arg (u, t[i]);
1849 r[i]= copy (t[i]);
1850 }
1851 r[n]= upgrade_function (u);
1852 /*
1853 if (n > 0) {
1854 cout << "t= " << t << "\n";
1855 cout << "r= " << r << "\n";
1856 cout << HRULE;
1857 }
1858 */
1859 return r;
1860 }
1861 else {
1862 int i, n= N(t);
1863 tree r (t, n);
1864 for (i=0; i<n; i++)
1865 r[i]= upgrade_function (t[i]);
1866 return r;
1867 }
1868 }
1869
1870 /******************************************************************************
1871 * Renaming environment variables
1872 ******************************************************************************/
1873
1874 static charp var_rename []= {
1875 "shrinking factor", "sfactor",
1876 "info flag", "info-flag",
1877
1878 "font family", "font-family",
1879 "font series", "font-series",
1880 "font shape", "font-shape",
1881 "font size", "font-size",
1882 "font base size", "font-base-size",
1883 "background color", "bg-color",
1884 "atom decorations", "atom-decorations",
1885 "line decorations", "line-decorations",
1886 "page decorations", "page-decorations",
1887 "xoff decorations", "xoff-decorations",
1888 "yoff decorations", "yoff-decorations",
1889
1890 "math language", "math-language",
1891 "math font", "math-font",
1892 "math font family", "math-font-family",
1893 "math font series", "math-font-series",
1894 "math font shape", "math-font-shape",
1895 "index level", "math-level",
1896 "formula style", "math-display",
1897 "math condensed", "math-condensed",
1898 "vertical position", "math-vpos",
1899
1900 "prog language", "prog-language",
1901 "prog font", "prog-font",
1902 "prog font family", "prog-font-family",
1903 "prog font series", "prog-font-series",
1904 "prog font shape", "prog-font-shape",
1905 "this session", "prog-session",
1906
1907 "paragraph mode", "par-mode",
1908 "paragraph hyphenation", "par-hyphen",
1909 "paragraph width", "par-width",
1910 "left margin", "par-left",
1911 "right margin", "par-right",
1912 "first indentation", "par-first",
1913 "no first indentation", "par-no-first",
1914 "interline space", "par-sep",
1915 "horizontal ink separation", "par-hor-sep",
1916 "line stretch", "par-line-sep",
1917 "interparagraph space", "par-par-sep",
1918 "interfootnote space", "par-fnote-sep",
1919 "nr columns", "par-columns",
1920 "column separation", "par-columns-sep",
1921
1922 "page medium", "page-medium",
1923 "page type", "page-type",
1924 "page orientation", "page-orientation",
1925 "page breaking", "page-breaking",
1926 "page flexibility", "page-flexibility",
1927 "page number", "page-nr",
1928 "thepage", "page-the-page",
1929 "page width", "page-width",
1930 "page height", "page-height",
1931 "odd page margin", "page-odd",
1932 "even page margin", "page-even",
1933 "page right margin", "page-right",
1934 "page top margin", "page-top",
1935 "page bottom margin", "page-bot",
1936 "page extend", "page-extend",
1937 "page shrink", "page-shrink",
1938 "page header separation", "page-head-sep",
1939 "page footer separation", "page-foot-sep",
1940 "odd page header", "page-odd-header",
1941 "odd page footer", "page-odd-footer",
1942 "even page header", "page-even-header",
1943 "even page footer", "page-even-footer",
1944 "this page header", "page-this-header",
1945 "this page footer", "page-this-footer",
1946 "reduction page left margin", "page-reduce-left",
1947 "reduction page right margin", "page-reduce-right",
1948 "reduction page top margin", "page-reduce-top",
1949 "reduction page bottom margin", "page-reduce-bot",
1950 "show header and footer", "page-show-hf",
1951 "footnote separation", "page-fnote-sep",
1952 "footnote bar length", "page-fnote-barlen",
1953 "float separation", "page-float-sep",
1954 "marginal note separation", "page-mnote-sep",
1955 "marginal note width", "page-mnote-width",
1956
1957 "table width", "table-width",
1958 "table height", "table-height",
1959 "table hmode", "table-hmode",
1960 "table vmode", "table-vmode",
1961 "table halign", "table-halign",
1962 "table valign", "table-valign",
1963 "table row origin", "table-row-origin",
1964 "table col origin", "table-col-origin",
1965 "table lsep", "table-lsep",
1966 "table rsep", "table-rsep",
1967 "table bsep", "table-bsep",
1968 "table tsep", "table-tsep",
1969 "table lborder", "table-lborder",
1970 "table rborder", "table-rborder",
1971 "table bborder", "table-bborder",
1972 "table tborder", "table-tborder",
1973 "table hyphen", "table-hyphen",
1974 "table min rows", "table-min-rows",
1975 "table min cols", "table-min-cols",
1976 "table max rows", "table-max-rows",
1977 "table max cols", "table-max-cols",
1978
1979 "cell format", "cell-format",
1980 "cell decoration", "cell-decoration",
1981 "cell background", "cell-background",
1982 "cell orientation", "cell-orientation",
1983 "cell width", "cell-width",
1984 "cell height", "cell-height",
1985 "cell hpart", "cell-hpart",
1986 "cell vpart", "cell-vpart",
1987 "cell hmode", "cell-hmode",
1988 "cell vmode", "cell-vmode",
1989 "cell halign", "cell-halign",
1990 "cell valign", "cell-valign",
1991 "cell lsep", "cell-lsep",
1992 "cell rsep", "cell-rsep",
1993 "cell bsep", "cell-bsep",
1994 "cell tsep", "cell-tsep",
1995 "cell lborder", "cell-lborder",
1996 "cell rborder", "cell-rborder",
1997 "cell bborder", "cell-bborder",
1998 "cell tborder", "cell-tborder",
1999 "cell vcorrect", "cell-vcorrect",
2000 "cell hyphen", "cell-hyphen",
2001 "cell row span", "cell-row-span",
2002 "cell col span", "cell-col-span",
2003 "cell row nr", "cell-row-nr",
2004 "cell col nr", "cell-col-nr",
2005
2006 "line width", "line-width",
2007 "line style", "line-style",
2008 "line arrows", "line-arrows",
2009 "line caps", "line-join",
2010 "fill mode", "fill-mode",
2011 "fill color", "fill-color",
2012 "fill style", "fill-style",
2013
2014 "graphical frame", "gr-frame",
2015 "graphical clip", "gr-clip",
2016 "graphical mode", "gr-mode",
2017 "graphical color", "gr-color",
2018 "graphical line width", "gr-line-width",
2019
2020 ""
2021 };
2022
2023 static hashmap<string,string> var_rename_table ("?");
2024
2025 static hashmap<string,string>
cached_renamer(charp * T,hashmap<string,string> & H)2026 cached_renamer (charp* T, hashmap<string,string>& H) {
2027 if (N (H) == 0) {
2028 int i;
2029 for (i=0; T[i][0] != '\0'; i+=2)
2030 H (T[i])= T[i+1];
2031 }
2032 return H;
2033 }
2034
2035
2036 static tree
rename_vars(tree t,hashmap<string,string> H,bool flag)2037 rename_vars (tree t, hashmap<string,string> H, bool flag) {
2038 if (is_atomic (t)) return t;
2039 else {
2040 int i, n= N(t);
2041 tree r (t, n);
2042 static tree_label MARKUP= make_tree_label ("markup");
2043 for (i=0; i<n; i++) {
2044 tree u= rename_vars (t[i], H, flag);
2045 if (is_atomic (u) && H->contains (u->label))
2046 if (((L(t) == WITH) && ((i%2) == 0) && (i < n-1)) ||
2047 ((L(t) == ASSIGN) && (i == 0)) ||
2048 ((L(t) == VALUE) && (i == 0)) ||
2049 ((L(t) == CWITH) && (i == 4)) ||
2050 ((L(t) == TWITH) && (i == 0)) ||
2051 ((L(t) == ASSOCIATE) && (i == 0)) ||
2052 ((L(t) == MARKUP) && (i == 0)))
2053 u= copy (H[u->label]);
2054 r[i]= u;
2055 }
2056 if (flag) {
2057 if (H->contains (as_string (L(t)))) {
2058 tree_label l= make_tree_label (H[as_string (L(t))]);
2059 r= tree (l, A(r));
2060 }
2061 }
2062 else {
2063 if ((n == 0) && H->contains (as_string (L(t)))) {
2064 string v= H[as_string (L(t))];
2065 r= tree (VALUE, copy (v));
2066 if (v == "page-the-page") r= tree (make_tree_label ("page-the-page"));
2067 }
2068 }
2069 return r;
2070 }
2071 }
2072
2073 tree
upgrade_env_vars(tree t)2074 upgrade_env_vars (tree t) {
2075 return rename_vars (t, cached_renamer (var_rename, var_rename_table), false);
2076 }
2077
2078 /******************************************************************************
2079 * Use package primitive for style files
2080 ******************************************************************************/
2081
2082 static tree
upgrade_use_package(tree t)2083 upgrade_use_package (tree t) {
2084 tree style= extract (t, "style");
2085 tree init = extract (t, "initial");
2086 bool preamble= false;
2087 int i, n= N(init);
2088 for (i=0; i<n; i++)
2089 if (init[i] == tree (ASSOCIATE, PREAMBLE, "true"))
2090 preamble= true;
2091
2092 bool no_style= true;
2093 if (preamble) {
2094 n= N(t);
2095 tree r (L(t));
2096 for (i=0; i<n; i++)
2097 if (is_compound (t[i], "style")) {
2098 r << compound ("style", "source");
2099 no_style= false;
2100 }
2101 else if (is_compound (t[i], "body", 1) && is_document (t[i][0])) {
2102 tree v (USE_PACKAGE);
2103 v << A (style);
2104 tree u (DOCUMENT);
2105 if (N(v) > 0) u << v;
2106 u << A (t[i][0]);
2107 if (no_style) r << compound ("style", "source");
2108 r << compound ("body", u);
2109 }
2110 else r << t[i];
2111 return r;
2112 }
2113 else return t;
2114 }
2115
2116 /******************************************************************************
2117 * Normalize names of tags in the style files
2118 ******************************************************************************/
2119
2120 static charp style_rename []= {
2121 "thelabel", "the-label",
2122
2123 "leftflush", "left-flush",
2124 "rightflush", "right-flush",
2125 "mathord", "math-ord",
2126 "mathopen", "math-open",
2127 "mathclose", "math-close",
2128 "mathpunct", "math-punct",
2129 "mathbin", "math-bin",
2130 "mathrel", "math-rel",
2131 "mathop", "math-op",
2132 "thetoc", "the-toc",
2133 "theidx", "the-idx",
2134 "thegly", "the-gly",
2135 "theitem", "the-item",
2136 "tocnr", "toc-nr",
2137 "idxnr", "idx-nr",
2138 "glynr", "gly-nr",
2139 "itemnr", "item-nr",
2140 "itemname", "item-name",
2141 "newitemize", "new-itemize",
2142 "newenumerate", "new-enumerate",
2143 "newdescription", "new-description",
2144
2145 "nextnumber", "next-number",
2146 "eqnumber", "eq-number",
2147 "leqnumber", "leq-number",
2148 "reqnumber", "req-number",
2149 "nonumber", "no-number",
2150 "thefootnote", "the-footnote",
2151 "theequation", "the-equation",
2152 "thetheorem", "the-theorem",
2153 "theproposition", "the-proposition",
2154 "thelemma", "the-lemma",
2155 "thecorollary", "the-corollary",
2156 "theaxiom", "the-axiom",
2157 "thedefinition", "the-definition",
2158 "thenotation", "the-notation",
2159 "theconjecture", "the-conjecture",
2160 "theremark", "the-remark",
2161 "theexample", "the-example",
2162 "thenote", "the-note",
2163 "thewarning", "the-warning",
2164 "theconvention", "the-convention",
2165 "theacknowledgments", "the-acknowledgments",
2166 "theexercise", "the-exercise",
2167 "theproblem", "the-problem",
2168 "thefigure", "the-figure",
2169 "thetable", "the-table",
2170 "footnotenr", "footnote-nr",
2171 "equationnr", "equation-nr",
2172 "theoremnr", "theorem-nr",
2173 "propositionnr", "proposition-nr",
2174 "lemmanr", "lemma-nr",
2175 "corollarynr", "corollary-nr",
2176 "axiomnr", "axiom-nr",
2177 "definitionnr", "definition-nr",
2178 "notationnr", "notation-nr",
2179 "conjecturenr", "conjecture-nr",
2180 "remarknr", "remark-nr",
2181 "examplenr", "example-nr",
2182 "notenr", "note-nr",
2183 "warningnr", "warning-nr",
2184 "conventionnr", "convention-nr",
2185 "acknowledgmentsnr", "acknowledgments-nr",
2186 "exercisenr", "exercise-nr",
2187 "problemnr", "problem-nr",
2188 "figurenr", "figure-nr",
2189 "tablenr", "table-nr",
2190 "theoremname", "theorem-name",
2191 "figurename", "figure-name",
2192 "exercisename", "exercise-name",
2193 "theoremsep", "theorem-sep",
2194 "figuresep", "figure-sep",
2195 "exercisesep", "exercise-sep",
2196 "footnotesep", "footnote-sep",
2197 "newtheorem", "new-theorem",
2198 "newremark", "new-remark",
2199 "newexercise", "new-exercise",
2200 "newfigure", "new-figure",
2201
2202 "theprefix", "the-prefix",
2203 "thechapter", "the-chapter",
2204 "theappendix", "the-appendix",
2205 "thesection", "the-section",
2206 "thesubsection", "the-subsection",
2207 "thesubsubsection", "the-subsubsection",
2208 "theparagraph", "the-paragraph",
2209 "thesubparagraph", "the-subparagraph",
2210 "chapternr", "chapter-nr",
2211 "appendixnr", "appendix-nr",
2212 "sectionnr", "section-nr",
2213 "subsectionnr", "subsection-nr",
2214 "subsubsectionnr", "subsubsection-nr",
2215 "paragraphnr", "paragraph-nr",
2216 "subparagraphnr", "subparagraph-nr",
2217 "sectionsep", "section-sep",
2218 "subsectionsep", "subsection-sep",
2219 "subsubsectionsep", "subsubsection-sep",
2220
2221 "theorem*", "render-theorem",
2222 "remark*", "render-remark",
2223 "exercise*", "render-exercise",
2224 "proof*", "render-proof",
2225 "small-figure*", "render-small-figure",
2226 "big-figure*", "render-big-figure",
2227
2228 "theanswer", "the-answer",
2229 "thealgorithm", "the-algorithm",
2230 "answernr", "answer-nr",
2231 "algorithmnr", "algorithm-nr",
2232
2233 ""
2234 };
2235
2236 static hashmap<string,string> style_rename_table ("?");
2237
2238 static tree
upgrade_style_rename_sub(tree t)2239 upgrade_style_rename_sub (tree t) {
2240 if (is_atomic (t)) return t;
2241 else if (is_func (t, MERGE, 2) && (t[0] == "the"))
2242 return tree (MERGE, "the-", t[1]);
2243 else if (is_func (t, MERGE, 2) && (t[1] == "nr"))
2244 return tree (MERGE, t[0], "-nr");
2245 else {
2246 int i, n= N(t);
2247 tree r (t, n);
2248 for (i=0; i<n; i++)
2249 r[i]= upgrade_style_rename_sub (t[i]);
2250 return r;
2251 }
2252 }
2253
2254 static tree
upgrade_style_rename(tree t)2255 upgrade_style_rename (tree t) {
2256 t= upgrade_style_rename_sub (t);
2257 return
2258 rename_vars (t, cached_renamer (style_rename, style_rename_table), true);
2259 }
2260
2261 /******************************************************************************
2262 * Remove trailing punctuation in item* tags
2263 ******************************************************************************/
2264
2265 static tree
upgrade_item_punct(tree t)2266 upgrade_item_punct (tree t) {
2267 if (is_atomic (t)) return t;
2268 else {
2269 int i, n= N(t);
2270 tree r (t, n);
2271 for (i=0; i<n; i++)
2272 r[i]= upgrade_item_punct (t[i]);
2273 if (is_compound (r, "item*", 1)) {
2274 tree& item= r[0];
2275 if (is_atomic (item)) {
2276 string s= item->label;
2277 if (ends (s, ".") || ends (s, ":") || ends (s, " "))
2278 item= s (0, N(s)-1);
2279 }
2280 else if (is_concat (item) && is_atomic (item[N(item)-1])) {
2281 string s= item [N(item)-1] -> label;
2282 if ((s == ".") || (s == ":") || (s == " ")) {
2283 if (N(item) == 2) item= item[0];
2284 else item= item (0, N(item) - 1);
2285 }
2286 }
2287 }
2288 return r;
2289 }
2290 }
2291
2292 /******************************************************************************
2293 * Forget default page parameters
2294 ******************************************************************************/
2295
2296 tree
upgrade_page_pars(tree t)2297 upgrade_page_pars (tree t) {
2298 if (is_atomic (t)) return t;
2299 else if (L(t) == COLLECTION) {
2300 int i, n= N(t);
2301 tree r (COLLECTION);
2302 for (i=0; i<n; i++) {
2303 tree u= t[i];
2304 if (!is_func (u, ASSOCIATE, 2));
2305 else if (u == tree (ASSOCIATE, PAGE_TYPE, "a4"));
2306 else if (u == tree (ASSOCIATE, PAGE_EVEN, "30mm"));
2307 else if (u == tree (ASSOCIATE, PAGE_ODD, "30mm"));
2308 else if (u == tree (ASSOCIATE, PAGE_RIGHT, "30mm"));
2309 else if (u == tree (ASSOCIATE, PAGE_TOP, "30mm"));
2310 else if (u == tree (ASSOCIATE, PAGE_BOT, "30mm"));
2311 else if (u == tree (ASSOCIATE, PAR_WIDTH, "150mm"));
2312 else if (u[0] == "page-reduce-left");
2313 else if (u[0] == "page-reduce-right");
2314 else if (u[0] == "page-reduce-top");
2315 else if (u[0] == "page-reduce-bot");
2316 else if (u[0] == "sfactor");
2317 else r << u;
2318 }
2319 return r;
2320 }
2321 else {
2322 int i, n= N(t);
2323 tree r (t, n);
2324 for (i=0; i<n; i++)
2325 r[i]= upgrade_page_pars (t[i]);
2326 return r;
2327 }
2328 }
2329
2330 /******************************************************************************
2331 * Substitutions
2332 ******************************************************************************/
2333
2334 tree
substitute(tree t,tree which,tree by)2335 substitute (tree t, tree which, tree by) {
2336 if (t == which) return by;
2337 else if (is_atomic (t)) return t;
2338 else {
2339 int i, n= N(t);
2340 tree r (t, n);
2341 for (i=0; i<n; i++)
2342 r[i]= substitute (t[i], which, by);
2343 return r;
2344 }
2345 }
2346
2347 /******************************************************************************
2348 * Upgrading title information
2349 ******************************************************************************/
2350
2351 static tree doc_keywords;
2352 static tree doc_ams_class;
2353
2354 static void
abstract_add(tree & data,tree what)2355 abstract_add (tree& data, tree what) {
2356 if (is_func (what, DOCUMENT, 1)) what= what[0];
2357 if (is_atomic (what)) {
2358 string s= what->label;
2359 int i, start, n= N(s);
2360 for (i=start=0; i<n; )
2361 if (s[i] == ',') {
2362 int next= i+1;
2363 while ((i>start) && (s[i-1]==' ')) i--;
2364 data << s (start, i);
2365 i= next; if (s[i] == ' ') i++;
2366 start= i;
2367 }
2368 else i++;
2369 while ((i>start) && (s[i-1]==' ')) i--;
2370 data << s (start, i);
2371 }
2372 else data << what;
2373 }
2374
2375 static tree
upgrade_abstract(tree t)2376 upgrade_abstract (tree t) {
2377 if (is_atomic (t)) return t;
2378 else if (is_compound (t, "abstract", 1) && is_document (t[0])) {
2379 int i, n= N(t[0]);
2380 tree r (DOCUMENT);
2381 for (i=0; i<n; i++)
2382 if (is_compound (t[0][i], "keywords", 1))
2383 abstract_add (doc_keywords, t[0][i][0]);
2384 else if (is_compound (t[0][i], "AMS-class"))
2385 abstract_add (doc_ams_class, t[0][i][0]);
2386 else r << t[0][i];
2387 if (N(r) == 0) r << "";
2388 return compound ("abstract", r);
2389 }
2390 else {
2391 int i, n= N(t);
2392 tree r (t, n);
2393 for (i=0; i<n; i++)
2394 r[i]= upgrade_abstract (t[i]);
2395 return r;
2396 }
2397 }
2398
2399 static tree
search_title_tag(tree t,string tag,bool flag=false)2400 search_title_tag (tree t, string tag, bool flag= false) {
2401 if (is_atomic (t)) return tuple ();
2402 else if (is_compound (t, tag, 1)) return tuple (t[0]);
2403 else if (flag && is_compound (t, tag)) return tuple (t);
2404 else {
2405 int i, n= N(t);
2406 tree r (TUPLE);
2407 for (i=0; i<n; i++)
2408 r << A (search_title_tag (t[i], tag, flag));
2409 return r;
2410 }
2411 }
2412
2413 static void
search_abstract_tag(tree t,tree & data,string tag)2414 search_abstract_tag (tree t, tree& data, string tag) {
2415 if (is_atomic (t)) return;
2416 else {
2417 int i, n= N(t);
2418 for (i=0; i<n; i++)
2419 if (is_compound (t[i], tag, 1))
2420 abstract_add (data, t[i][0]);
2421 }
2422 }
2423
2424 static void
title_add(tree & data,string tag,tree args,bool flag=false)2425 title_add (tree& data, string tag, tree args, bool flag= false) {
2426 int i, n= N(args);
2427 for (i=0; i<n; i++) {
2428 tree t= args[i];
2429 if (flag && (!is_document (t))) t= tree (DOCUMENT, t);
2430 if ((!flag) && is_func (t, DOCUMENT, 1)) t= t[0];
2431 data << compound (tag, t);
2432 }
2433 }
2434
2435 static void
add_info(tree & data,tree t,string ntag,string otag,bool flag1=false,bool flag2=false)2436 add_info (tree& data, tree t, string ntag, string otag,
2437 bool flag1= false, bool flag2= false) {
2438 tree u= search_title_tag (t, otag, flag1);
2439 if (N(t) != 0) title_add (data, ntag, u, flag2);
2440 }
2441
2442 static tree
upgrade_title2(tree t)2443 upgrade_title2 (tree t) {
2444 if (is_atomic (t)) return t;
2445 else if (is_compound (t, "make-title", 1)) {
2446 //cout << "t= " << t << "\n";
2447 tree u= t[0];
2448 if (!is_document (u) && !is_concat (u)) u= tree (DOCUMENT, u);
2449 tree title_data = compound ("doc-data");
2450 tree author_data= compound ("doc-author-data");
2451 tree meta_data = compound ("doc-data");
2452
2453 for (int i=0; i<N(u); i++) {
2454 tree v= u[i];
2455 add_info (title_data, v, "doc-title", "title");
2456 add_info (meta_data, v, "doc-date", "title-date");
2457 add_info (meta_data, v, "doc-running-title", "header-title");
2458 add_info (meta_data, v, "doc-running-author", "header-author");
2459 add_info (meta_data, v, "doc-note", "title-thanks", true, true);
2460 if (N (search_title_tag (v, "author")) != 0) {
2461 if (N (author_data) != 0 &&
2462 is_compound (author_data[0], "author-name"))
2463 title_data << author_data;
2464 author_data= compound ("doc-author-data");
2465 }
2466 add_info (author_data, v, "author-name", "author");
2467 add_info (author_data, v, "author-address", "address", false, true);
2468 add_info (author_data, v, "author-email", "title-email");
2469 add_info (author_data, v, "author-homepage", "title-web");
2470 }
2471 if (N (author_data) != 0) title_data << author_data;
2472 if (N (meta_data) != 0) title_data << A (meta_data);
2473
2474 tree notice= search_title_tag (t, "made-by-TeXmacs", true);
2475 if (N (notice) != 0)
2476 title_data << compound ("doc-note", compound ("with-TeXmacs-text"));
2477 search_abstract_tag (t[0], doc_keywords, "title-keywords");
2478 search_abstract_tag (t[0], doc_ams_class, "title-ams-class");
2479 if (N (doc_keywords) != 0) title_data << doc_keywords;
2480 if (N (doc_ams_class) != 0) title_data << doc_ams_class;
2481 //cout << "r= " << title_data << "\n";
2482 return title_data;
2483 }
2484 else {
2485 int i, n= N(t);
2486 tree r (t, n);
2487 for (i=0; i<n; i++)
2488 r[i]= upgrade_title2 (t[i]);
2489 return r;
2490 }
2491 }
2492
2493 static tree
upgrade_doc_info(tree t)2494 upgrade_doc_info (tree t) {
2495 doc_keywords = compound ("doc-keywords");
2496 doc_ams_class= compound ("doc-AMS-class");
2497 t= upgrade_abstract (t);
2498 t= upgrade_title2 (t);
2499 return t;
2500 }
2501
2502 /******************************************************************************
2503 * Upgrade bibliographies
2504 ******************************************************************************/
2505
2506 tree
upgrade_bibliography(tree t)2507 upgrade_bibliography (tree t) {
2508 if (is_atomic (t)) return t;
2509 else {
2510 int i, n= N(t);
2511 tree r (t, n);
2512 for (i=0; i<n; i++)
2513 r[i]= upgrade_bibliography (t[i]);
2514 if (is_compound (t, "bibliography") || is_compound (t, "bibliography*")) {
2515 int l= N(r)-1;
2516 if (is_func (r[l], DOCUMENT, 1) && is_compound (r[l][0], "bib-list"));
2517 else if (is_compound (r[l], "bib-list"));
2518 else r[l]= tree (DOCUMENT, compound ("bib-list", "[99]", r[l]));
2519 }
2520 return r;
2521 }
2522 }
2523
2524 /******************************************************************************
2525 * Upgrade switches
2526 ******************************************************************************/
2527
2528 tree
upgrade_switch(tree t)2529 upgrade_switch (tree t) {
2530 if (is_atomic (t)) return t;
2531 else {
2532 int i, n= N(t);
2533 tree r (t, n);
2534 for (i=0; i<n; i++)
2535 r[i]= upgrade_switch (t[i]);
2536 if (is_compound (r, "switch", 2)) {
2537 int i, n= N(r[1]);
2538 tree u (make_tree_label ("switch"), n);
2539 for (i=0; i<n; i++)
2540 if (is_compound (r[1][i], "tmarker", 0)) u[i]= r[0];
2541 else u[i]= compound ("hidden", r[1][i]);
2542 return u;
2543 }
2544 if (is_compound (r, "fold", 2))
2545 return compound ("folded", r[0], r[1]);
2546 if (is_compound (r, "unfold", 2))
2547 return compound ("unfolded", r[0], r[1]);
2548 if (is_compound (r, "fold-bpr", 2) ||
2549 is_compound (r, "fold-text", 2) ||
2550 is_compound (r, "fold-proof", 2) ||
2551 is_compound (r, "fold-exercise", 2))
2552 return compound ("summarized", r[0], r[1]);
2553 if (is_compound (r, "unfold-bpr", 2) ||
2554 is_compound (r, "unfold-text", 2) ||
2555 is_compound (r, "unfold-proof", 2) ||
2556 is_compound (r, "unfold-exercise", 2))
2557 return compound ("detailed", r[0], r[1]);
2558 if (is_compound (r, "fold-algorithm", 2))
2559 return compound ("summarized-algorithm", r[0], r[1]);
2560 if (is_compound (r, "unfold-algorithm", 2))
2561 return compound ("detailed-algorithm", r[0], r[1]);
2562 if (is_func (r, ASSIGN, 2) && r[0] == "fold-algorithm")
2563 return tree (ASSIGN, "summarized-algorithm", r[1]);
2564 if (is_func (r, ASSIGN, 2) && r[0] == "unfold-algorithm")
2565 return tree (ASSIGN, "detailed-algorithm", r[1]);
2566 return r;
2567 }
2568 }
2569
2570 /******************************************************************************
2571 * Upgrade graphics
2572 ******************************************************************************/
2573
2574 static int
find_attr_pos(tree t,string name)2575 find_attr_pos (tree t, string name) {
2576 int i, n= N(t);
2577 for (i=0; i<n; i+=2)
2578 if (t[i] == name && i%2 == 0 && i+1<n) return i;
2579 return -1;
2580 }
2581
2582 static bool
find_attr(tree t,string name)2583 find_attr (tree t, string name) {
2584 return find_attr_pos (t, name) != -1;
2585 }
2586
2587 static tree
get_attr(tree t,string name,tree ifnotfound)2588 get_attr (tree t, string name, tree ifnotfound) {
2589 int i= find_attr_pos (t, name);
2590 return i == -1 ? ifnotfound : t[i+1];
2591 }
2592
2593 static tree
add_attr(tree t,string name,tree value)2594 add_attr (tree t, string name, tree value) {
2595 int i, n= N(t);
2596 tree r (t, n+2);
2597 for (i=0; i<n-1; i++)
2598 r[i]= t[i];
2599 r[n-1]= name;
2600 r[n]= value;
2601 r[n+1]= t[n-1];
2602 return r;
2603 }
2604
2605 static tree
set_attr(tree t,string name,tree value)2606 set_attr (tree t, string name, tree value) {
2607 int i= find_attr_pos (t, name);
2608 if (i != -1)
2609 t[i+1]= value;
2610 else
2611 t= add_attr (t, name, value);
2612 return t;
2613 }
2614
2615 static tree
remove_attr(tree t,string name)2616 remove_attr (tree t, string name) {
2617 int i= find_attr_pos (t, name);
2618 if (i == -1)
2619 return t;
2620 else {
2621 int j, n= N(t);
2622 tree r (t, n-2);
2623 for (j=0; j<i; j++)
2624 r[j]= t[j];
2625 for (j=i+2; j<n; j++)
2626 r[j-2]= t[j];
2627 return r;
2628 }
2629 }
2630
2631 tree
upgrade_fill(tree t)2632 upgrade_fill (tree t) {
2633 int i;
2634 if (is_atomic (t)) return t;
2635 if (is_compound (t, "with")) {
2636 if ((i= find_attr_pos (t, "gr-mode")) != -1
2637 && is_tuple (t[i+1],"edit-prop"))
2638 t[i+1]= tuple ("group-edit","props");
2639
2640 tree fm= get_attr (t, "fill-mode", tree ("none"));
2641 t= remove_attr (t, "fill-mode");
2642 t= remove_attr (t, "gr-fill-mode");
2643 if (fm == "none")
2644 t= remove_attr (t, "fill-color");
2645 if (fm == "inside")
2646 t= set_attr (t, "color", tree ("none"));
2647 }
2648 int n= N(t);
2649 tree r (t, n);
2650 for (i=0; i<n; i++)
2651 r[i]= upgrade_fill (t[i]);
2652 return r;
2653 }
2654
2655 static void
length_split(string & num,string & unit,string l)2656 length_split (string &num, string &unit, string l) {
2657 int i, n= N(l), nu= 0;
2658 i= n-1;
2659 while (i>=0 && is_alpha (l[i])) i--, nu++;
2660 num= l (0, n-nu);
2661 unit= l (n-nu, n);
2662 }
2663
2664 static string
length_minus(string l)2665 length_minus (string l) {
2666 if (l[0] == '+') l[0]= '-';
2667 else
2668 if (l[0] == '-') l[0]= '+';
2669 else
2670 l= "-" * l;
2671 return l;
2672 }
2673
2674 static string
length_abs(string l)2675 length_abs (string l) {
2676 if (l[0] == '-') l[0]= '+';
2677 return l;
2678 }
2679
2680 static int length_add_error;
2681
2682 static string
length_add(string l1,string l2)2683 length_add (string l1, string l2) {
2684 length_add_error= 0;
2685 string n1, u1, n2, u2;
2686 length_split (n1, u1, l1);
2687 length_split (n2, u2, l2);
2688 double i1= as_double (n1);
2689 double i2= as_double (n2);
2690 if (i1 == 0.0) {
2691 i1= i2;
2692 i2= 0.0;
2693 string u= u1;
2694 u1= u2;
2695 u2= u;
2696 }
2697 if (u1 == "par" && (u2 == "par" || i2 == 0.0))
2698 return as_string (i1 + i2) * "par";
2699 else
2700 if ((u1 == "cm" || u1 == "mm")
2701 && (u2 == "cm" || u2 == "mm" || i2 == 0.0)) {
2702 if (u1 == "cm" && u2 == "mm") i2 /= 10;
2703 if (u1 == "mm" && u2 == "cm") i2 *= 10;
2704 return as_string (i1 + i2) * u1;
2705 }
2706 else {
2707 length_add_error= 1;
2708 return "0cm";
2709 }
2710 }
2711
2712 tree
upgrade_graphics(tree t)2713 upgrade_graphics (tree t) {
2714 int i;
2715 if (is_atomic (t)) return t;
2716 if (is_compound (t, "with") &&
2717 (find_attr (t, "gr-frame") || find_attr (t, "gr-clip"))) {
2718 tree fr= get_attr (t, "gr-frame",
2719 tuple ("scale", "1cm",
2720 tree (TUPLE, "0.5par", "0cm")));
2721 tree clip= get_attr (t, "gr-clip",
2722 tuple ("clip",
2723 tuple ("0par", "-0.3par"),
2724 tuple ("1par", "0.3par")));
2725 t= remove_attr (t, "gr-clip");
2726
2727 string ox= as_string (fr[2][0]), oy= as_string (fr[2][1]);
2728 string cg= as_string (clip[1][0]), cb= as_string (clip[1][1]);
2729 string cd= as_string (clip[2][0]), ch= as_string (clip[2][1]);
2730 string w= length_add (cd, length_minus (cg));
2731 string h= length_add (ch, length_minus (cb));
2732
2733 fr[2][0]= tree (length_add (length_abs (cg) , ox));
2734 if (length_add_error)
2735 fr[2][0]= tree (PLUS, length_abs (cg) , ox);
2736 fr[2][1]= tree (length_add (length_abs (cb) , oy));
2737 if (length_add_error)
2738 fr[2][1]= tree (PLUS, length_abs (cb) , oy);
2739 tree geom= tuple ("geometry", tree (w), tree (h));
2740 t= add_attr (t, "gr-geometry", geom);
2741 t= set_attr (t, "gr-frame", fr);
2742 }
2743 int n= N(t);
2744 tree r (t, n);
2745 for (i=0; i<n; i++)
2746 r[i]= upgrade_graphics (t[i]);
2747 return r;
2748 }
2749
2750 tree
upgrade_textat(tree t)2751 upgrade_textat (tree t) {
2752 int i;
2753 if (is_atomic (t)) return t;
2754 if (is_compound (t, "text-at") && N(t) == 4) {
2755 tree t0= t;
2756 t= tree (WITH, tree (TEXT_AT, t[0], t[1]));
2757 t= set_attr (t, "text-at-halign", t0[2]);
2758 t= set_attr (t, "text-at-valign", t0[3]);
2759 }
2760 int n= N(t);
2761 tree r (t, n);
2762 for (i=0; i<n; i++)
2763 r[i]= upgrade_textat (t[i]);
2764 return r;
2765 }
2766
2767 /******************************************************************************
2768 * Upgrade cell alignment
2769 ******************************************************************************/
2770
2771 tree
upgrade_cell_alignment(tree t)2772 upgrade_cell_alignment (tree t) {
2773 int i;
2774 if (is_atomic (t)) return t;
2775 if (is_func (t, CWITH) && (N(t) >= 2))
2776 if (t[N(t)-2] == CELL_HALIGN)
2777 if (t[N(t)-1] == "." || t[N(t)-1] == ",") {
2778 tree r= copy (t);
2779 r[N(t)-1]= "L" * t[N(t)-1]->label;
2780 return r;
2781 }
2782 int n= N(t);
2783 tree r (t, n);
2784 for (i=0; i<n; i++)
2785 r[i]= upgrade_cell_alignment (t[i]);
2786 return r;
2787 }
2788
2789 /******************************************************************************
2790 * Renaming primitives
2791 ******************************************************************************/
2792
2793 tree
rename_primitive(tree t,string which,string by)2794 rename_primitive (tree t, string which, string by) {
2795 int i;
2796 if (is_atomic (t)) return t;
2797 int n= N(t);
2798 tree r (t, n);
2799 if (is_compound (t, which))
2800 r= tree (make_tree_label (by), n);
2801 for (i=0; i<n; i++)
2802 r[i]= rename_primitive (t[i], which, by);
2803 return r;
2804 }
2805
2806 /******************************************************************************
2807 * Upgrade label assignment
2808 ******************************************************************************/
2809
2810 tree
upgrade_label_assignment(tree t)2811 upgrade_label_assignment (tree t) {
2812 int i;
2813 if (is_atomic (t)) return t;
2814 else if (is_func (t, ASSIGN, 2) && t[0] == "the-label")
2815 return tree (SET_BINDING, t[1]);
2816 else {
2817 int n= N(t);
2818 tree r (t, n);
2819 for (i=0; i<n; i++)
2820 r[i]= upgrade_label_assignment (t[i]);
2821 return r;
2822 }
2823 }
2824
2825 /******************************************************************************
2826 * Upgrade scheme documentation
2827 ******************************************************************************/
2828
2829 tree
upgrade_scheme_doc(tree t)2830 upgrade_scheme_doc (tree t) {
2831 int i;
2832 if (is_atomic (t)) return t;
2833 else if (is_compound (t, "scm-fun", 1) ||
2834 is_compound (t, "scm-macro", 1))
2835 return compound ("scm", t[0]);
2836 else if (is_compound (t, "explain-scm-fun") ||
2837 is_compound (t, "explain-scm-macro"))
2838 {
2839 tree r (CONCAT);
2840 r << "(" << t[0];
2841 for (int i=1; i<N(t); i++)
2842 r << " " << t[i];
2843 r << ")";
2844 return compound ("scm", simplify_concat (r));
2845 }
2846 else {
2847 int n= N(t);
2848 tree r (t, n);
2849 for (i=0; i<n; i++)
2850 r[i]= upgrade_scheme_doc (t[i]);
2851 return r;
2852 }
2853 }
2854
2855 /******************************************************************************
2856 * Upgrade Mathemagix tag
2857 ******************************************************************************/
2858
2859 tree
upgrade_mmx(tree t)2860 upgrade_mmx (tree t) {
2861 int i;
2862 if (is_atomic (t)) return t;
2863 else if (is_compound (t, "mmx", 0) || t == tree (VALUE, "mmx"))
2864 return compound ("mathemagix");
2865 else if (is_compound (t, "mml", 0) || t == tree (VALUE, "mml"))
2866 return compound ("mmxlib");
2867 else if (is_compound (t, "scheme", 0) || t == tree (VALUE, "scheme"))
2868 return compound ("scheme");
2869 else if (is_compound (t, "cpp", 0) || t == tree (VALUE, "cpp"))
2870 return compound ("c++");
2871 else if (is_compound (t, "scheme-code", 1))
2872 return compound ("scm", upgrade_mmx (t[0]));
2873 else if (is_compound (t, "scheme-fragment", 1))
2874 return compound ("scm-fragment", upgrade_mmx (t[0]));
2875 else if (is_compound (t, "cpp-code", 1))
2876 return compound ("cpp", upgrade_mmx (t[0]));
2877 else {
2878 int n= N(t);
2879 tree r (t, n);
2880 for (i=0; i<n; i++)
2881 r[i]= upgrade_mmx (t[i]);
2882 return r;
2883 }
2884 }
2885
2886 /******************************************************************************
2887 * Upgrade sessions
2888 ******************************************************************************/
2889
2890 static tree
upgrade_session(tree t,tree lan,tree ses)2891 upgrade_session (tree t, tree lan, tree ses) {
2892 if (is_atomic (t)) return t;
2893 else if (is_compound (t, "session", 1))
2894 return compound ("session", copy (lan), copy (ses),
2895 upgrade_session (t[0], lan, ses));
2896 else if (is_func (t, WITH, 5) &&
2897 t[0] == PROG_LANGUAGE &&
2898 t[2] == PROG_SESSION)
2899 return upgrade_session (t[4], t[1], t[3]);
2900 else {
2901 int i, n= N(t);
2902 tree r (L(t));
2903 for (i=0; i<n; i++) {
2904 if (is_document (t) && is_compound (t[i], "input", 2)) {
2905 bool m = is_compound (t[i][1], "math", 1);
2906 tree in= (m? t[i][1][0]: t[i][1]);
2907 if ((i+1)<n && is_compound (t[i+1], "output", 1)) {
2908 const char* op= (m? "unfolded-io-math": "unfolded-io");
2909 r << compound (op, t[i][0], in, t[i+1][0]);
2910 i++;
2911 }
2912 else {
2913 const char* op= (m? "input-math": "input");
2914 r << compound (op, t[i][0], in);
2915 }
2916 }
2917 else r << upgrade_session (t[i], lan, ses);
2918 }
2919 return r;
2920 }
2921 }
2922
2923 /******************************************************************************
2924 * Upgrade presentation style
2925 ******************************************************************************/
2926
2927 tree
upgrade_presentation(tree t)2928 upgrade_presentation (tree t) {
2929 int i;
2930 if (is_atomic (t)) return t;
2931 else if (is_compound (t, "style") || is_compound (t, "tuple")) {
2932 int n= N(t);
2933 tree r (t, n);
2934 for (i=0; i<n; i++)
2935 if (t[i] == "presentation") r[i]= "presentation-ridged-paper";
2936 else r[i]= upgrade_presentation (t[i]);
2937 return r;
2938 }
2939 else {
2940 int n= N(t);
2941 tree r (t, n);
2942 for (i=0; i<n; i++)
2943 r[i]= upgrade_presentation (t[i]);
2944 return r;
2945 }
2946 }
2947
2948 /******************************************************************************
2949 * Upgrade mathematical formulas
2950 ******************************************************************************/
2951
2952 bool
is_non_style_document(tree doc)2953 is_non_style_document (tree doc) {
2954 tree style= extract (doc, "style");
2955 if (!is_tuple (style) || N(style) == 0 || !is_atomic (style[0]))
2956 return false;
2957 for (int i=0; i<N(style); i++)
2958 if (style[i] == "source") return false;
2959 string ms= style[0]->label;
2960 return
2961 (starts (ms, "tm")) ||
2962 (starts (ms, "lycee")) ||
2963 (ms == "article") ||
2964 (ms == "beamer") ||
2965 (ms == "book") ||
2966 (ms == "exam") ||
2967 (ms == "generic") ||
2968 (ms == "letter") ||
2969 (ms == "seminar") ||
2970 (ms == "bibliography") ||
2971 (ms == "browser") ||
2972 (ms == "help") ||
2973 (ms == "manual") ||
2974 (ms == "mmxdoc") ||
2975 (ms == "elsart") ||
2976 (ms == "ifac") ||
2977 (ms == "jsc") ||
2978 (ms == "acmconf") ||
2979 (ms == "svjour") ||
2980 (ms == "svmono");
2981 }
2982
2983 tree
upgrade_math(tree t)2984 upgrade_math (tree t) {
2985 int i;
2986 if (is_atomic (t)) return t;
2987 else if (is_func (t, WITH, 3) && t[0] == MODE && t[1] == "math")
2988 return compound ("math", upgrade_math (t[2]));
2989 else if (is_func (t, WITH, 3) && t[0] == MODE && t[1] == "text")
2990 return compound ("text", upgrade_math (t[2]));
2991 else if (is_func (t, WITH) && N(t) >= 5 && t[0] == MODE && t[1] == "math")
2992 return compound ("math", upgrade_math (t (2, N(t))));
2993 else if (is_func (t, WITH) && N(t) >= 5 && t[0] == MODE && t[1] == "text")
2994 return compound ("text", upgrade_math (t (2, N(t))));
2995 else {
2996 int n= N(t);
2997 tree r (t, n);
2998 for (i=0; i<n; i++)
2999 r[i]= upgrade_math (t[i]);
3000 return r;
3001 }
3002 }
3003
3004 /******************************************************************************
3005 * Upgrade resize and clipped
3006 ******************************************************************************/
3007
3008 tree
upgrade_resize_arg(tree t)3009 upgrade_resize_arg (tree t) {
3010 if (is_func (t, MERGE, 2)) {
3011 if (is_atomic (t[0]) && is_atomic (t[1]))
3012 return upgrade_resize_arg (t[0]->label * t[1]->label);
3013 tree u= upgrade_resize_arg (t[0]);
3014 if (is_func (u, PLUS, 2) || is_func (u, MINUS, 2) ||
3015 is_func (u, MINIMUM, 2) || is_func (u, MAXIMUM, 2))
3016 if (u[1] == "") {
3017 u[1]= upgrade_resize_arg (t[1]);
3018 return u;
3019 }
3020 cout << "TeXmacs] warning, resize argument " << t << " not upgraded\n";
3021 return t;
3022 }
3023 if (is_func (t, ARG, 1) ||
3024 is_func (t, PLUS, 2) || is_func (t, MINUS, 2) ||
3025 is_func (t, MINIMUM, 2) || is_func (t, MAXIMUM, 2))
3026 return t;
3027 if (!is_atomic (t)) {
3028 cout << "TeXmacs] warning, resize argument " << t << " not upgraded\n";
3029 return t;
3030 }
3031 string s= t->label;
3032 if (starts (s, "c")) {
3033 cout << "TeXmacs] warning, resize argument " << t << " not upgraded\n";
3034 return t;
3035 }
3036 if (s == "l") return "1l";
3037 if (s == "r") return "1r";
3038 if (s == "t") return "1t";
3039 if (s == "b") return "1b";
3040 if (N(s) < 2) return t;
3041 if (s[0] != 'l' && s[0] != 'b' && s[0] != 'r' && s[0] != 't') return t;
3042 string s1= "1" * s (0, 1);
3043 string s2= s (2, N(s));
3044 if (s[1] == '+') return tree (PLUS, s1, s2);
3045 if (s[1] == '-') return tree (MINUS, s1, s2);
3046 if (s[1] == '[') return tree (MINIMUM, s1, s2);
3047 if (s[1] == ']') return tree (MAXIMUM, s1, s2);
3048 return t;
3049 }
3050
3051 tree
upgrade_resize_clipped(tree t)3052 upgrade_resize_clipped (tree t) {
3053 if (is_atomic (t)) return t;
3054 else if (N(t) >= 5 && (is_func (t, RESIZE) || is_func (t, CLIPPED))) {
3055 if (is_func (t, CLIPPED))
3056 t= tree (CLIPPED, t[4], t[0], t[1], t[2], t[3]);
3057 int i, n= 5;
3058 tree r (t, n);
3059 r[0]= upgrade_resize_clipped (t[0]);
3060 for (i=1; i<n; i++)
3061 r[i]= upgrade_resize_arg (t[i]);
3062 return r;
3063 }
3064 else {
3065 int i, n= N(t);
3066 tree r (t, n);
3067 for (i=0; i<n; i++)
3068 r[i]= upgrade_resize_clipped (t[i]);
3069 return r;
3070 }
3071 }
3072
3073 /******************************************************************************
3074 * Upgrade images
3075 ******************************************************************************/
3076
3077 tree
upgrade_image_length(tree t,string unit)3078 upgrade_image_length (tree t, string unit) {
3079 if (!is_atomic (t)) return t;
3080 string s= t->label;
3081 if (starts (s, "*") || starts (s, "/")) {
3082 double mag= get_magnification (s);
3083 return as_string (mag) * unit;
3084 }
3085 else return t;
3086 }
3087
3088 tree
upgrade_image(tree t)3089 upgrade_image (tree t) {
3090 if (is_atomic (t)) return t;
3091 else if (is_func (t, IMAGE, 7))
3092 return tree (IMAGE, t[0],
3093 upgrade_image_length (t[1], "w"),
3094 upgrade_image_length (t[2], "h"),
3095 "", "");
3096 else {
3097 int i, n= N(t);
3098 tree r (t, n);
3099 for (i=0; i<n; i++)
3100 r[i]= upgrade_image (t[i]);
3101 return r;
3102 }
3103 }
3104
3105 /******************************************************************************
3106 * Upgrade root switches
3107 ******************************************************************************/
3108
3109 tree
upgrade_root_switch(tree t,bool top=true)3110 upgrade_root_switch (tree t, bool top= true) {
3111 if (is_func (t, DOCUMENT) &&
3112 (top || N(t) == 1 ||
3113 (N(t) == 2 && is_compound (t[0], "hide-preamble")))) {
3114 int i, n= N(t);
3115 tree r (DOCUMENT, n);
3116 for (i=0; i<n; i++)
3117 r[i]= upgrade_root_switch (t[i], false);
3118 return r;
3119 }
3120 else if (is_compound (t, "body", 1))
3121 return compound ("body", upgrade_root_switch (t[0], false));
3122 else if (is_compound (t, "switch"))
3123 return compound ("screens", A(t));
3124 else return t;
3125 }
3126
3127 /******************************************************************************
3128 * Upgrade hyphenation
3129 ******************************************************************************/
3130
3131 tree
upgrade_hyphenation(tree t)3132 upgrade_hyphenation (tree t) {
3133 tree style= copy (extract (t, "style"));
3134 tree init = extract (t, "initial");
3135 if (is_atomic (style)) style= tuple (style);
3136 if (style == tree (TUPLE)) style= tuple ("generic");
3137 if (!is_tuple (style) || N(style) != 1 || !is_atomic (style[0])) return t;
3138 string ms= style[0]->label;
3139 if (ms == "article" || ms == "beamer" || ms == "book" || ms == "exam" ||
3140 ms == "generic" || ms == "letter" || ms == "seminar")
3141 {
3142 hashmap<string,tree> h (UNINIT, init);
3143 if (!h->contains (PAR_HYPHEN)) h (PAR_HYPHEN)= "normal";
3144 tree new_init= make_collection (h);
3145 return change_doc_attr (t, "initial", new_init);
3146 }
3147 else return t;
3148 }
3149
3150 /******************************************************************************
3151 * Renaming of symbols
3152 ******************************************************************************/
3153
3154 tree
rename_symbols(tree t,hashmap<string,string> h)3155 rename_symbols (tree t, hashmap<string,string> h) {
3156 if (is_atomic (t)) {
3157 bool same= true;
3158 int pos;
3159 string s= t->label;
3160 for (pos=0; pos<N(s); ) {
3161 int j=pos;
3162 tm_char_forwards (s, pos);
3163 if (j+2 < pos && h->contains (s (j, pos))) {
3164 same= false;
3165 break;
3166 }
3167 }
3168 if (same) return t;
3169 string r;
3170 for (pos=0; pos<N(s); ) {
3171 int j=pos;
3172 tm_char_forwards (s, pos);
3173 if (h->contains (s (j, pos))) r << h [s (j, pos)];
3174 else r << s (j, pos);
3175 }
3176 return r;
3177 }
3178 else if (is_func (t, RAW_DATA)) return t;
3179 else {
3180 int i, n= N(t);
3181 tree r (t, n);
3182 for (i=0; i<n; i++)
3183 r[i]= rename_symbols (t[i], h);
3184 return r;
3185 }
3186 }
3187
3188 /******************************************************************************
3189 * Rewrite bodies of algorithms
3190 ******************************************************************************/
3191
3192 tree
upgrade_algorithm(tree t,bool flag=true)3193 upgrade_algorithm (tree t, bool flag= true) {
3194 if (is_atomic (t)) return t;
3195 else if (is_compound (t, "algo", 1))
3196 return compound ("tt", upgrade_algorithm (t[0]));
3197 else if (is_compound (t, "algorithm", 2))
3198 return compound ("named-algorithm-old",
3199 upgrade_algorithm (t[0]), upgrade_algorithm (t[1]));
3200 else if (flag && is_compound (t, "body", 1))
3201 return compound ("algorithm-body", upgrade_algorithm (t[0]));
3202 else if (is_compound (t, "pile", 1))
3203 return compound ("tabbed", upgrade_algorithm (t[0]));
3204 else if (is_compound (t, "scm-fragment", 1))
3205 return compound ("scm-code", upgrade_algorithm (t[0]));
3206 else if (is_compound (t, "scheme-fragment", 1))
3207 return compound ("scm-code", upgrade_algorithm (t[0]));
3208 else if (is_compound (t, "mmx-fragment", 1))
3209 return compound ("mmx-code", upgrade_algorithm (t[0]));
3210 else if (is_compound (t, "cpp-fragment", 1))
3211 return compound ("cpp-code", upgrade_algorithm (t[0]));
3212 else if (is_compound (t, "shell-fragment", 1))
3213 return compound ("shell-code", upgrade_algorithm (t[0]));
3214 else {
3215 int i, n= N(t);
3216 tree r (t, n);
3217 flag= true;
3218 if (is_document (t))
3219 for (i=0; i<n; i++)
3220 if (is_compound (t[i], "TeXmacs", 1) ||
3221 is_compound (t[i], "style") ||
3222 is_compound (t[i], "initial") ||
3223 is_compound (t[i], "references"))
3224 flag= false;
3225 for (i=0; i<n; i++)
3226 r[i]= upgrade_algorithm (t[i], flag);
3227 return r;
3228 }
3229 }
3230
3231 /******************************************************************************
3232 * Upgrade mathematical operators
3233 ******************************************************************************/
3234
3235 tree
upgrade_math_ops(tree t)3236 upgrade_math_ops (tree t) {
3237 if (is_atomic (t)) return t;
3238 int i, n= N(t);
3239 tree r (t, n);
3240 for (i=0; i<n; i++)
3241 r[i]= upgrade_math_ops (t[i]);
3242 if (is_func (t, WITH, 3) &&
3243 is_atomic (t[2]) &&
3244 is_alpha (t[2]->label) &&
3245 t[0] == "math-font-family")
3246 {
3247 if (t[1] == "trm") return compound ("math-up", t[2]);
3248 if (t[1] == "tss") return compound ("math-ss", t[2]);
3249 if (t[1] == "ttt") return compound ("math-tt", t[2]);
3250 if (t[1] == "rm") return compound ("math-up", t[2]);
3251 if (t[1] == "up") return compound ("math-up", t[2]);
3252 if (t[1] == "bf") return compound ("math-bf", t[2]);
3253 if (t[1] == "sl") return compound ("math-sl", t[2]);
3254 if (t[1] == "it") return compound ("math-it", t[2]);
3255 if (t[1] == "ss") return compound ("math-ss", t[2]);
3256 if (t[1] == "tt") return compound ("math-tt", t[2]);
3257 }
3258 if (n == 1 && starts (as_string (L(t)), "math-")) {
3259 if (is_compound (t, "math-ord")) return compound ("math-ordinary", t[0]);
3260 if (is_compound (t, "math-punct")) return compound ("math-separator", t[0]);
3261 if (is_compound (t, "math-bin")) return compound ("math-plus", t[0]);
3262 if (is_compound (t, "math-rel")) return compound ("math-relation", t[0]);
3263 if (is_compound (t, "math-op")) return compound ("math-big", t[0]);
3264 }
3265 return r;
3266 }
3267
3268 /******************************************************************************
3269 * Cleaning spurious spaces in the document
3270 ******************************************************************************/
3271
3272 static bool
only_spaces(string s)3273 only_spaces (string s) {
3274 for (int i=0; i<N(s); i++)
3275 if (s[i] != ' ') return false;
3276 return true;
3277 }
3278
3279 static bool
eat_spaces(tree t,bool after)3280 eat_spaces (tree t, bool after) {
3281 (void) after;
3282 if (is_atomic (t)) return false;
3283 return
3284 is_compound (t, "hide-preamble") ||
3285 is_compound (t, "doc-data") ||
3286 is_compound (t, "abstract") ||
3287 is_compound (t, "bibliography") ||
3288 is_compound (t, "bibitem") ||
3289 is_compound (t, "bibitem*");
3290 }
3291
3292 static tree
clean_spaces(tree t)3293 clean_spaces (tree t) {
3294 if (is_atomic (t)) return t;
3295 int i, n= N(t);
3296 tree r (t, n);
3297 for (i=0; i<n; i++)
3298 r[i]= clean_spaces (t[i]);
3299 if (!is_func (r, CONCAT)) return r;
3300 t= r;
3301 r= tree (CONCAT);
3302 for (i=0; i<n; i++)
3303 if (!is_atomic (t[i])) r << t[i];
3304 else {
3305 string s= t[i]->label;
3306 if (i>0 && eat_spaces (t[i-1], true))
3307 while (starts (s, " ")) s= s (1, N(s));
3308 if (i<N(t)-1 && eat_spaces (t[i+1], false))
3309 while (ends (s, " ")) s= s (0, N(s)-1);
3310 if (s != "") r << tree (s);
3311 }
3312 if (N(r) == 0) return "";
3313 if (N(r) == 1) return r[0];
3314 return r;
3315 }
3316
3317 /******************************************************************************
3318 * Cleaning the document header
3319 ******************************************************************************/
3320
3321 static tree
search_header_tag(tree t,string which,tree & h)3322 search_header_tag (tree t, string which, tree& h) {
3323 if (is_compound (t, which)) {
3324 h << t;
3325 return "";
3326 }
3327 if (is_func (t, DOCUMENT)) {
3328 tree r (DOCUMENT);
3329 for (int i=0; i<N(t); i++) {
3330 if (is_compound (t[i], which)) h << t[i];
3331 else if (is_func (t[i], SURROUND, 3)) {
3332 tree x= search_header_tag (t[i], which, h);
3333 if (x != "") r << x;
3334 }
3335 else r << t[i];
3336 }
3337 return r;
3338 }
3339 if (is_func (t, SURROUND, 3)) {
3340 tree r (SURROUND, 3);
3341 r[0]= search_header_tag (t[0], which, h);
3342 r[2]= search_header_tag (t[2], which, h);
3343 r[1]= search_header_tag (t[1], which, h);
3344 if (r[0] == "" && r[1] == "") r= r[2];
3345 else if (r[0] == "" && r[2] == "") r= r[1];
3346 else if (r[1] == "" && r[2] == "") r= r[0];
3347 return r;
3348 }
3349 return t;
3350 }
3351
3352 tree
clean_header(tree t)3353 clean_header (tree t) {
3354 if (!is_func (t, DOCUMENT)) return t;
3355 tree r (DOCUMENT);
3356 tree preamble (DOCUMENT);
3357 tree title (DOCUMENT);
3358 tree abstract (DOCUMENT);
3359 t= search_header_tag (t, "hide-preamble", preamble);
3360 t= search_header_tag (t, "doc-data", title);
3361 t= search_header_tag (t, "abstract", abstract);
3362 while (N(t) > 0 && is_atomic (t[0]) && only_spaces (t[0]->label))
3363 t= t (1, N(t));
3364 r << A (preamble);
3365 r << A (title);
3366 r << A (abstract);
3367 r << A (t);
3368 return r;
3369 }
3370
3371 /******************************************************************************
3372 * Upgrade graphical attributes
3373 ******************************************************************************/
3374
3375 static void
replace_dash_style(tree & t,string var)3376 replace_dash_style (tree& t, string var) {
3377 if (find_attr (t, var)) {
3378 tree val= get_attr (t, var, "default");
3379 if (is_func (val, TUPLE)) {
3380 string nval;
3381 for (int i=0; i<N(val); i++)
3382 if (val[i] == "0") nval << "0";
3383 else nval << "1";
3384 t= set_attr (t, var, tree (nval));
3385 }
3386 }
3387 }
3388
3389 static tree
encode_arrow(tree t)3390 encode_arrow (tree t) {
3391 if (is_func (t, WITH, 3) && t[0] == "dash-style") {
3392 if (t[2] == tree (LINE,
3393 tuple ("10ln", "6ln"),
3394 tuple ("0ln", "0ln"),
3395 tuple ("10ln", "-6ln")))
3396 return "<less>";
3397 if (t[2] == tree (LINE,
3398 tuple ("-10ln", "6ln"),
3399 tuple ("0ln", "0ln"),
3400 tuple ("-10ln", "-6ln")))
3401 return "<gtr>";
3402 }
3403 return t;
3404 }
3405
3406 static void
replace_line_arrows(tree & t,string var,string begin,string end)3407 replace_line_arrows (tree& t, string var, string begin, string end) {
3408 if (find_attr (t, var)) {
3409 tree val= get_attr (t, var, "default");
3410 t= set_attr (t, "arrow-length", "10ln");
3411 t= set_attr (t, "arrow-height", "6ln");
3412 if (is_func (val, TUPLE, 1))
3413 t= set_attr (t, end, encode_arrow (val[0]));
3414 if (is_func (val, TUPLE, 2)) {
3415 t= set_attr (t, begin, encode_arrow (val[0]));
3416 t= set_attr (t, end, encode_arrow (val[1]));
3417 }
3418 t= remove_attr (t, var);
3419 }
3420 }
3421
3422 static void
replace_magnification(tree & t,string var,string repl)3423 replace_magnification (tree& t, string var, string repl) {
3424 tree body= t[N(t)-1];
3425 if (find_attr (t, var))
3426 if (is_func (body, GRAPHICS) ||
3427 is_func (body, GR_GROUP) ||
3428 is_func (body, TEXT_AT) ||
3429 is_func (body, _POINT) ||
3430 is_func (body, LINE) ||
3431 is_func (body, CLINE) ||
3432 is_func (body, SPLINE) ||
3433 is_func (body, CSPLINE) ||
3434 is_func (body, ARC) ||
3435 is_func (body, CARC) ||
3436 is_func (body, VAR_SPLINE))
3437 {
3438 tree val= get_attr (t, var, "1");
3439 if (is_func (val, TIMES, 2) &&
3440 is_func (val[1], VALUE, 1) &&
3441 val[1][0] == var)
3442 val= val[0];
3443 t= set_attr (t, repl, val);
3444 t= remove_attr (t, var);
3445 }
3446 }
3447
3448 static tree
upgrade_gr_attributes(tree t)3449 upgrade_gr_attributes (tree t) {
3450 int i;
3451 if (is_atomic (t)) return t;
3452 if (is_func (t, WITH)) {
3453 replace_dash_style (t, "dash-style");
3454 replace_dash_style (t, "gr-dash-style");
3455 replace_line_arrows (t, "line-arrows", "arrow-begin", "arrow-end");
3456 replace_line_arrows (t, "gr-line-arrows",
3457 "gr-arrow-begin", "gr-arrow-end");
3458 replace_magnification (t, "magnification", "magnify");
3459 }
3460 int n= N(t);
3461 tree r (t, n);
3462 for (i=0; i<n; i++)
3463 r[i]= upgrade_gr_attributes (t[i]);
3464 return r;
3465 }
3466
3467 /******************************************************************************
3468 * Upgrade cursor tag
3469 ******************************************************************************/
3470
3471 static tree
upgrade_cursor(tree t)3472 upgrade_cursor (tree t) {
3473 int i;
3474 if (is_atomic (t)) return t;
3475 if (is_func (t, VALUE)) {
3476 if (t == tree (VALUE, "cursor")) return compound ("cursor");
3477 if (t == tree (VALUE, "math-cursor")) return compound ("math-cursor");
3478 }
3479 int n= N(t);
3480 tree r (t, n);
3481 for (i=0; i<n; i++)
3482 r[i]= upgrade_cursor (t[i]);
3483 return r;
3484 }
3485
3486 /******************************************************************************
3487 * Upgrade encoding to unicode whenever cyrillic font is used
3488 ******************************************************************************/
3489
3490 bool
become_cyrillic(string s1,string s2)3491 become_cyrillic (string s1, string s2) {
3492 return (s1 == "font" && s2 == "cyrillic");}
3493
3494 bool
become_other(string s1,string s2)3495 become_other (string s1, string s2) {
3496 return (s1 == "font" && s2 != "cyrillic");
3497 }
3498
3499 tree
upgrade_cyrillic_encoding(tree t,bool cyrillic)3500 upgrade_cyrillic_encoding (tree t, bool cyrillic) {
3501 if (is_atomic (t)) {
3502 if (cyrillic) return cyrillic_subset_in_t2a_to_code_point (as_string(t));
3503 else return t;
3504 }
3505 else {
3506 int i = 0;
3507 if (is_func(t, WITH)) {
3508 for (i = 0 ; i < N(t) - 1 ; i+=2) {
3509 if (!cyrillic
3510 && become_cyrillic (as_string (t[i]), as_string (t[i+1])))
3511 cyrillic = true;
3512 else if (cyrillic
3513 && become_other (as_string (t[i]), as_string (t[i+1])))
3514 cyrillic = false;
3515 }
3516 t[N(t)-1] = upgrade_cyrillic_encoding (t[N(t)-1], cyrillic);
3517 }
3518 else {
3519 for (i = 0 ; i < N(t) ; i++)
3520 t[i] = upgrade_cyrillic_encoding (t[i], cyrillic);
3521 }
3522 return t;
3523 }
3524 }
3525
3526 array<tree>
get_childs_by_name(tree t,string s)3527 get_childs_by_name (tree t, string s) {
3528 array<tree> r = array<tree>();
3529 if (!is_atomic (t))
3530 for (int i = 0 ; i < N(t) ; i++) {
3531 if (as_string (L(t[i])) == s) r << t[i];
3532 }
3533 return r;
3534 }
3535
3536 static tree
upgrade_cyrillic(tree t)3537 upgrade_cyrillic (tree t) {
3538 bool cyrillic = false;
3539 array<tree> initial, collection, associate;
3540 initial = get_childs_by_name (t, "initial");
3541 for (int i = 0 ; i < N(initial) ; i++){
3542 collection = get_childs_by_name (initial[i], "collection");
3543 for (int j = 0 ; j < N(collection) ; j++){
3544 associate = get_childs_by_name (collection[j], "associate");
3545 for (int k = 0 ; k < N(associate) ; k++) {
3546 if (is_func(associate[k], ASSOCIATE, 2) && associate[k][0] == "font")
3547 cyrillic = (associate[k][1] == "cyrillic");
3548 }
3549 }
3550 }
3551 return upgrade_cyrillic_encoding(t, cyrillic);
3552 }
3553
3554 /******************************************************************************
3555 * Upgrade metadata storage format
3556 ******************************************************************************/
3557
3558 static tree
correct_metadata(tree t)3559 correct_metadata (tree t) {
3560 if (is_atomic (t)) return t;
3561 tree r;
3562
3563 if (is_compound (t, "author-misc"))
3564 r= compound ("author-note");
3565 else
3566 r= compound (as_string (L(t)));
3567
3568 for (int i=0; i<N(t); i++)
3569 r << correct_metadata (t[i]);
3570 return r;
3571 }
3572
3573 static tree
upgrade_metadata(tree t)3574 upgrade_metadata (tree t) {
3575 if (is_atomic (t)) return t;
3576 tree r;
3577 string l;
3578 if (is_compound (t, "doc-abstract")) l= "abstract";
3579 if (is_compound (t, "author-address")) l= "author-affiliation";
3580 if (is_compound (t, "doc-AMS-class")) l= "abstract-msc";
3581 if (is_compound (t, "doc-msc")) l= "abstract-msc";
3582 if (is_compound (t, "doc-keywords")) l= "abstract-keywords";
3583
3584 if (is_compound (t, "doc-author-data")) {
3585 tree r= compound ("author-data");
3586 for (int i=0; i<N(t); i++)
3587 r << upgrade_metadata (t[i]);
3588 return compound ("doc-author", r);
3589 }
3590
3591 if (l == "") r= compound (as_string (L(t)));
3592 else r= compound (l);
3593 for (int i=0; i<N(t); i++)
3594 r << upgrade_metadata (t[i]);
3595 return r;
3596 }
3597
3598 static tree
remove_abstract_data(tree t,array<tree> & abstract_data)3599 remove_abstract_data (tree t, array<tree> &abstract_data) {
3600 // Remove all abstract-msc and abstract-keywords found in a doc-data
3601 // structure, and store them in abstract_data.
3602 tree r(L(t));
3603 if (is_compound (t, "doc-data")) {
3604 for (int i=0; i<N(t); i++) {
3605 if (is_compound (t[i], "abstract-msc") ||
3606 is_compound (t[i], "abstract-keywords"))
3607 abstract_data << t[i];
3608 else r << t[i];
3609 }
3610 }
3611 else if (is_atomic (t))
3612 return t;
3613 else {
3614 r= tree (t, N(t));
3615 for (int i=0; i<N(t); i++)
3616 r[i]= remove_abstract_data (t[i], abstract_data);
3617 }
3618 return r;
3619 }
3620
3621 static array<tree>
sort_abstract_data(array<tree> abstract_data)3622 sort_abstract_data (array<tree> abstract_data) {
3623 // Sort and merge abstract-msc and abstract-keywords compounds
3624 bool has_doc_msc= false, has_doc_keywords= false;
3625 tree doc_msc (make_tree_label ("abstract-msc"));
3626 tree doc_keywords (make_tree_label ("abstract-keywords"));
3627 array<tree> r;
3628
3629 for (int i=0; i<N(abstract_data); i++) {
3630 if (is_compound (abstract_data[i], "abstract-msc")) {
3631 has_doc_msc= true;
3632 for (int j=0; j<N(abstract_data[i]); j++)
3633 doc_msc << abstract_data[i][j];
3634 }
3635 if (is_compound (abstract_data[i], "abstract-keywords")) {
3636 has_doc_keywords= true;
3637 for (int j=0; j<N(abstract_data[i]); j++)
3638 doc_keywords << abstract_data[i][j];
3639 }
3640 }
3641 if (has_doc_msc) r << doc_msc;
3642 if (has_doc_keywords) r << doc_keywords;
3643
3644 return r;
3645 }
3646
3647 static tree
merge_abstract_data(tree t,array<tree> abstract_data,bool & stop)3648 merge_abstract_data (tree t, array<tree> abstract_data, bool &stop) {
3649 // Merge abstract_data with the first abstract found.
3650 tree r;
3651 if (stop || is_atomic (t)) return t;
3652 else if (is_compound (t, "abstract", 1)) {
3653 stop= true;
3654 r= tree (make_tree_label ("abstract-data"));
3655 r << t;
3656 for (int i=0; i<N(abstract_data); i++)
3657 r << abstract_data[i];
3658 }
3659 else {
3660 r= tree (t, N(t));
3661 for (int i=0; i<N(t); i++)
3662 r[i]= merge_abstract_data (t[i], abstract_data, stop);
3663 }
3664 return r;
3665 }
3666
3667 static tree
add_abstract_data(tree t,array<tree> abstract_data,bool & stop)3668 add_abstract_data (tree t, array<tree> abstract_data, bool &stop) {
3669 // Add abstract_data after the first doc-data found.
3670 if (stop || is_atomic (t)) return t;
3671 tree r= tree (L(t));
3672 for (int i=0; i<N(t); i++) {
3673 if (is_compound (t[i], "doc-data")) {
3674 stop= true;
3675 r << t[i];
3676 r << tree (make_tree_label ("abstract-data"));
3677 for (int j=0; j<N(abstract_data); j++)
3678 r[N(r)-1] << abstract_data[j];
3679 }
3680 else
3681 r << add_abstract_data (t[i], abstract_data, stop);
3682 }
3683 return r;
3684 }
3685
3686 static tree
upgrade_abstract_data(tree t)3687 upgrade_abstract_data (tree t) {
3688 // Remove all abstract-msc and abstract-keywords found in a doc-data
3689 // structure, and merge them with the first abstract found.
3690 array<tree> abstract_data;
3691 tree r= remove_abstract_data (t, abstract_data);
3692 bool stop= false;
3693 if (N(abstract_data) > 0) {
3694 abstract_data= sort_abstract_data (abstract_data);
3695 r= merge_abstract_data (r, abstract_data, stop);
3696 if (stop) return r;
3697 else return add_abstract_data (r, abstract_data, stop);
3698 }
3699 return t;
3700 }
3701
3702 /******************************************************************************
3703 * Upgrade unroll
3704 ******************************************************************************/
3705
3706 tree
upgrade_unroll(tree t)3707 upgrade_unroll (tree t) {
3708 if (is_atomic (t)) return t;
3709 int i, n= N(t);
3710 tree r (t, n);
3711 for (i=0; i<n; i++) {
3712 r[i]= upgrade_unroll (t[i]);
3713 if (is_compound (t, "unroll") && is_func (r[i], HIDDEN, 1))
3714 r[i]= compound ("hidden*", r[i][0]);
3715 }
3716 return r;
3717 }
3718
3719 /******************************************************************************
3720 * Upgrade style files
3721 ******************************************************************************/
3722
3723 tree
upgrade_style(tree t,bool flag)3724 upgrade_style (tree t, bool flag) {
3725 int i;
3726 if (is_atomic (t)) return t;
3727 else if (is_compound (t, "style") || is_func (t, TUPLE)) {
3728 int n= N(t);
3729 tree r (t, 0);
3730 bool doc= false;
3731 for (i=0; i<n; i++)
3732 if (!flag) r << upgrade_style (t[i], is_compound (t, "style"));
3733 else if (t[i] == "beamer") r << "old-beamer";
3734 else if (t[i] == "generic") r << "old-generic";
3735 else if (t[i] == "help") r << "old-help";
3736 else if (t[i] == "letter") r << "old-letter";
3737 else if (t[i] == "seminar") r << "old-seminar";
3738 else if (t[i] == "tmdoc-keyboard") { if (!doc) r << "doc"; doc= true; }
3739 else if (t[i] == "tmdoc-markup") { if (!doc) r << "doc"; doc= true; }
3740 else if (t[i] == "tmdoc-traversal") { if (!doc) r << "doc"; doc= true; }
3741 else r << upgrade_style (t[i], flag);
3742 return r;
3743 }
3744 else {
3745 int n= N(t);
3746 tree r (t, n);
3747 for (i=0; i<n; i++)
3748 r[i]= upgrade_style (t[i], flag);
3749 return r;
3750 }
3751 }
3752
3753 /******************************************************************************
3754 * Upgrade document language
3755 ******************************************************************************/
3756
3757 tree
upgrade_doc_language(tree t)3758 upgrade_doc_language (tree t) {
3759 tree style= extract (t, "style");
3760 tree init = extract (t, "initial");
3761 if (init == "" || N(init) == 0) return t;
3762
3763 string lan= "";
3764 for (int i=0; i<N(init); i++)
3765 if (is_func (init[i], ASSOCIATE, 2) && init[i][0] == LANGUAGE)
3766 lan= as_string (init[i][1]);
3767
3768 tree new_style= copy (style);
3769 tree new_init = tree (COLLECTION);
3770 for (int i=0; i<N(init); i++)
3771 if (is_func (init[i], ASSOCIATE, 2) && init[i][0] == LANGUAGE)
3772 new_style << init[i][1];
3773 else if (is_func (init[i], ASSOCIATE, 2) && init[i][0] == FONT) {
3774 if (init[i][1] == "cyrillic" &&
3775 (lan == "bulgarian" || lan == "russian" || lan == "ukrainian"));
3776 else if ((init[i][1] == "sys-chinese" || init[i][1] == "fireflysung") &&
3777 (lan == "chinese" || lan == "taiwanese"));
3778 else if ((init[i][1] == "sys-japanese" || init[i][1] == "ipa") &&
3779 lan == "japanese");
3780 else if ((init[i][1] == "sys-korean" || init[i][1] == "unbatang") &&
3781 lan == "korean");
3782 else new_init << init[i];
3783 }
3784 else new_init << init[i];
3785
3786 if (new_style != style)
3787 t= change_doc_attr (t, "style", new_style);
3788 if (new_init != init)
3789 t= change_doc_attr (t, "initial", new_init);
3790 return t;
3791 }
3792
3793 /******************************************************************************
3794 * Rename varsession package
3795 ******************************************************************************/
3796
3797 tree
upgrade_varsession(tree t)3798 upgrade_varsession (tree t) {
3799 int i;
3800 if (is_atomic (t)) return t;
3801 else if (is_compound (t, "style") || is_func (t, TUPLE)) {
3802 int n= N(t);
3803 tree r (t, n);
3804 for (i=0; i<n; i++) {
3805 if (t[i] == "varsession") r[i]= "framed-session";
3806 else r[i]= upgrade_varsession (t[i]);
3807 }
3808 return r;
3809 }
3810 else if (is_func (t, DOCUMENT)) {
3811 int n= N(t);
3812 tree r (t, n);
3813 for (i=0; i<n; i++)
3814 r[i]= upgrade_varsession (t[i]);
3815 return r;
3816 }
3817 else return t;
3818 }
3819
3820 /******************************************************************************
3821 * Upgrade subsessions
3822 ******************************************************************************/
3823
3824 tree
upgrade_subsession(tree t,bool in_session=false)3825 upgrade_subsession (tree t, bool in_session= false) {
3826 int i;
3827 if (is_atomic (t)) return t;
3828 else if (in_session && is_compound (t, "folded", 2))
3829 return compound ("folded-subsession", upgrade_subsession (t[0]),
3830 upgrade_subsession (t[1], true));
3831 else if (in_session && is_compound (t, "unfolded", 2))
3832 return compound ("unfolded-subsession", upgrade_subsession (t[0]),
3833 upgrade_subsession (t[1], true));
3834 else {
3835 bool flag=
3836 (is_func (t, DOCUMENT) && in_session) ||
3837 is_compound (t, "session");
3838 int n= N(t);
3839 tree r (t, n);
3840 for (i=0; i<n; i++)
3841 r[i]= upgrade_subsession (t[i], flag);
3842 return r;
3843 }
3844 }
3845
3846 /******************************************************************************
3847 * Upgrade quotes
3848 ******************************************************************************/
3849
3850 static hashset<string> std_textual_envs;
3851
3852 static array<string>&
operator <<(array<string> & a,const char * s)3853 operator << (array<string>& a, const char* s) {
3854 return a << string (s);
3855 }
3856
3857 static bool
is_std_textual_env(string s)3858 is_std_textual_env (string s) {
3859 if (N(std_textual_envs) == 0) {
3860 array<string> a;
3861 a << "part" << "chapter" << "section" << "subsection"
3862 << "subsubsection" << "paragraph" << "subparagraph" << "appendix"
3863 << "part*" << "chapter*" << "section*" << "subsection*"
3864 << "subsubsection*" << "paragraph*" << "subparagraph*" << "appendix*"
3865 << "abstract" << "theorem" << "proposition" << "lemma"
3866 << "corollary" << "proof" << "axiom" << "definition"
3867 << "notation" << "conjecture" << "remark" << "note"
3868 << "example" << "exercise" << "warning" << "convention"
3869 << "theorem*" << "proposition*" << "lemma*"
3870 << "corollary*" << "proof*" << "axiom*" << "definition*"
3871 << "notation*" << "conjecture*" << "remark*" << "note*"
3872 << "example*" << "exercise*" << "warning*" << "convention*"
3873 << "acknowledgments" << "quote" << "quotation" << "verse"
3874 << "indent" << "compact" << "jump-in"
3875 << "algorithm" << "body" << "render-code"
3876 << "center" << "left-aligned" << "right-aligned"
3877 << "small-table" << "big-table" << "small-figure" << "big-figure"
3878 << "tabular" << "tabular*" << "block" << "block*" << "descriptive-table"
3879 << "description" << "itemize" << "enumerate"
3880 << "bibliography" << "bib-list" << "thebibliography"
3881 << "bib-field" << "bib-entry" << "db-field" << "db-entry"
3882 << "itemize-minus" << "enumerate-roman" << "enumerate-alpha"
3883 << "strong" << "em" << "dfn" << "sample"
3884 << "name" << "person" << "cite*" << "abbr" << "acronym"
3885 << "really-tiny" << "tiny" << "very-small" << "small" << "flat-size"
3886 << "normal-size" << "large" << "very-large" << "huge" << "really-huge"
3887 << "underline" << "overline" << "pastel" << "greyed" << "light"
3888 << "british" << "bulgarian" << "chinese" << "croatian"
3889 << "czech" << "danish" << "dutch" << "english" << "finnish"
3890 << "french" << "german" << "greek" << "hungarian" << "italian"
3891 << "japanese" << "korean" << "polish" << "portuguese" << "romanian"
3892 << "russian" << "slovene" << "spanish" << "swedish"
3893 << "taiwanese" << "ukrainian"
3894 << "switch" << "screens" << "tiny-switch"
3895 << "shown" << "hidden" << "shown*" << "hidden*"
3896 << "unroll" << "unroll-compressed" << "unroll-phantoms" << "unroll-greyed"
3897 << "folded" << "unfolded";
3898 for (int i=0; i<N(a); i++) std_textual_envs->insert (a[i]);
3899 }
3900 return std_textual_envs->contains (s);
3901 }
3902
3903 static string
upgrade_quotes(string s)3904 upgrade_quotes (string s) {
3905 string r;
3906 int i, n= N(s);
3907 for (i=0; i<n; )
3908 if (s[i] == '<') {
3909 int start= i;
3910 tm_char_forwards (s, i);
3911 r << s (start, i);
3912 }
3913 else if (s[i] == '-' && i+1 < n && s[i+1] == '-') { r << "\25"; i += 2; }
3914 else if (s[i] == '\'' && i+1 < n && s[i+1] == '\'') { r << "\21"; i += 2; }
3915 else if (s[i] == '`' && i+1 < n && s[i+1] == '`') { r << "\20"; i += 2; }
3916 else { r << s[i]; i++; }
3917 return r;
3918 }
3919
3920 tree
upgrade_quotes(tree t)3921 upgrade_quotes (tree t) {
3922 if (is_atomic (t))
3923 return upgrade_quotes (t->label);
3924 else if (is_concat (t)) {
3925 int i, n= N(t);
3926 tree r (t, n);
3927 bool adjust= false;
3928 for (i=0; i<n; i++) {
3929 adjust= adjust || is_compound (t[i], "emdash", 0);
3930 r[i]= upgrade_quotes (t[i]);
3931 }
3932 if (adjust) r= simplify_correct (r);
3933 return r;
3934 }
3935 else if (is_compound (t, "emdash", 0))
3936 return "\26";
3937 else if (is_compound (t, "body", 1))
3938 return compound ("body", upgrade_quotes (t[0]));
3939 else {
3940 int i, n= N(t);
3941 tree r (t, n);
3942 for (i=0; i<n; i++) {
3943 if (is_std_textual_env (as_string (L(t))))
3944 r[i]= upgrade_quotes (t[i]);
3945 else if (std_drd->get_type_child (t, i) != TYPE_REGULAR ||
3946 std_drd->get_env_child (t, i, MODE, "text") != "text")
3947 r[i]= t[i];
3948 else r[i]= upgrade_quotes (t[i]);
3949 }
3950 return r;
3951 }
3952 }
3953
3954 /******************************************************************************
3955 * Upgrade ancient
3956 ******************************************************************************/
3957
3958 static charp equation_tags[]= {
3959 "equation", "equation*", "eqnarray", "eqnarray*",
3960 "leqnarray", "leqnarray*", "align", "align*",
3961 "falign", "falign*", "aligned", "aligned*",
3962 "multline", "multline*", "gather", "gather*",
3963 "eqsplit", "eqsplit*",
3964 ""
3965 };
3966
3967 bool
is_equation_env(tree t)3968 is_equation_env (tree t) {
3969 if (is_atomic (t) || N(t) != 1) return false;
3970 static hashset<tree_label> H;
3971 if (N(H) == 0)
3972 for (int i=0; equation_tags[i][0] != '\0'; i++)
3973 H->insert (as_tree_label (equation_tags[i]));
3974 return H->contains (L(t));
3975 }
3976
3977 tree
upgrade_ancient(tree t)3978 upgrade_ancient (tree t) {
3979 // Miscellaneous upgradings for old documents
3980 if (is_atomic (t)) return t;
3981 else if (is_func (t, INACTIVE, 1) && is_func (t[0], RIGID))
3982 return upgrade_ancient (t[0]);
3983 else if (is_equation_env (t) && !is_func (t[0], DOCUMENT))
3984 return tree (L(t), tree (DOCUMENT, upgrade_ancient (t[0])));
3985 else {
3986 int i, n= N(t);
3987 tree r (t, n);
3988 for (i=0; i<n; i++)
3989 r[i]= upgrade_ancient (t[i]);
3990 if (is_func (r, WITH)) {
3991 bool font_series= false;
3992 for (i=0; i+1<n; i+=2)
3993 if (r[i] == FONT_SERIES) font_series= true;
3994 for (i=0; i+1<n; i+=2)
3995 if (r[i] == MATH_FONT_SERIES && !font_series) {
3996 tree ins= tree (WITH, FONT_SERIES, copy (r[i+1]));
3997 return r (0, i) * ins * r (i, N(r));
3998 }
3999 }
4000 return r;
4001 }
4002 }
4003
4004 /******************************************************************************
4005 * Upgrade from previous versions
4006 ******************************************************************************/
4007
4008 tree
upgrade_tex(tree t)4009 upgrade_tex (tree t) {
4010 upgrade_tex_flag= true;
4011 t= upgrade_apply_expand_value (t);
4012 t= upgrade_new_environments (t);
4013 t= upgrade_items (t);
4014 t= upgrade_table (t);
4015 t= upgrade_split (t, false);
4016 t= simplify_correct (upgrade_mod_symbols (t));
4017 t= upgrade_menus_in_help (t);
4018 t= upgrade_capitalize_menus (t);
4019 t= upgrade_formatting (t);
4020 t= upgrade_expand (t, EXPAND);
4021 t= upgrade_expand (t, HIDE_EXPAND);
4022 t= upgrade_expand (t, VAR_EXPAND);
4023 t= upgrade_xexpand (t);
4024 t= upgrade_function (t);
4025 t= upgrade_apply (t);
4026 t= upgrade_env_vars (t);
4027 t= upgrade_style_rename (t);
4028 t= upgrade_item_punct (t);
4029 t= substitute (t, tree (VALUE, "hrule"), compound ("hrule"));
4030 t= upgrade_math (t);
4031 t= upgrade_resize_clipped (t);
4032 t= with_correct (t);
4033 t= superfluous_with_correct (t);
4034 t= upgrade_brackets (t);
4035 t= move_brackets (t);
4036 t= upgrade_image (t);
4037 t= upgrade_math_ops (t);
4038 t= clean_spaces (t);
4039 t= clean_header (t);
4040 t= upgrade_doc_language (t);
4041 t= upgrade_quotes (t);
4042 upgrade_tex_flag= false;
4043 return t;
4044 }
4045
4046 tree
upgrade_mathml(tree t)4047 upgrade_mathml (tree t) {
4048 t= upgrade_brackets (t, "math");
4049 t= downgrade_big (t);
4050 return t;
4051 }
4052
4053 tree
upgrade(tree t,string version)4054 upgrade (tree t, string version) {
4055 if (version_inf (version, "0.3.1.9")) {
4056 path p;
4057 t= upgrade_textual (t, p);
4058 }
4059 if (version_inf (version, "0.3.3.1"))
4060 t= upgrade_apply_expand_value (t);
4061 if (version_inf (version, "0.3.3.20"))
4062 t= upgrade_new_environments (t);
4063 if (version_inf (version, "0.3.3.24"))
4064 t= upgrade_items (t);
4065 if (version_inf (version, "0.3.4.4"))
4066 t= upgrade_resize (t);
4067 if (version_inf_eq (version, "0.3.4.7"))
4068 t= upgrade_table (t);
4069 if (version_inf_eq (version, "0.3.4.8"))
4070 t= upgrade_split (t, false);
4071 if (version_inf_eq (version, "0.3.5.6"))
4072 t= upgrade_project (t);
4073 if (version_inf_eq (version, "0.3.5.10"))
4074 t= upgrade_title (t);
4075 if (version_inf_eq (version, "1.0.0.1"))
4076 t= upgrade_cas (t);
4077 if (version_inf_eq (version, "1.0.0.8"))
4078 t= simplify_correct (upgrade_mod_symbols (t));
4079 if (version_inf_eq (version, "1.0.0.11"))
4080 t= upgrade_menus_in_help (t);
4081 if (version_inf_eq (version, "1.0.0.13"))
4082 t= upgrade_capitalize_menus (t);
4083 if (version_inf_eq (version, "1.0.0.19"))
4084 t= upgrade_traverse_branch (t);
4085 if (version_inf_eq (version, "1.0.1.20"))
4086 t= upgrade_session (t);
4087 if (version_inf_eq (version, "1.0.2.0"))
4088 t= upgrade_formatting (t);
4089 if (version_inf_eq (version, "1.0.2.3"))
4090 t= upgrade_expand (t, EXPAND);
4091 if (version_inf_eq (version, "1.0.2.4"))
4092 t= upgrade_expand (t, HIDE_EXPAND);
4093 if (version_inf_eq (version, "1.0.2.5")) {
4094 t= upgrade_expand (t, VAR_EXPAND);
4095 t= upgrade_xexpand (t);
4096 }
4097 if (version_inf_eq (version, "1.0.2.6")) {
4098 t= upgrade_function (t);
4099 t= upgrade_apply (t);
4100 }
4101 if (version_inf_eq (version, "1.0.2.8"))
4102 t= upgrade_env_vars (t);
4103 if (version_inf_eq (version, "1.0.3.3"))
4104 t= upgrade_use_package (t);
4105 if (version_inf_eq (version, "1.0.3.4"))
4106 t= upgrade_style_rename (t);
4107 if (version_inf_eq (version, "1.0.3.4"))
4108 t= upgrade_item_punct (t);
4109 if (version_inf_eq (version, "1.0.3.7"))
4110 t= upgrade_page_pars (t);
4111 if (version_inf_eq (version, "1.0.4")) {
4112 t= substitute (t, tree (VALUE, "hrule"), compound ("hrule"));
4113 t= upgrade_doc_info (t);
4114 }
4115 if (version_inf_eq (version, "1.0.4.6"))
4116 t= upgrade_bibliography (t);
4117 if (version_inf_eq (version, "1.0.5.4"))
4118 t= upgrade_switch (t);
4119 if (version_inf_eq (version, "1.0.5.7"))
4120 t= upgrade_fill (t);
4121 if (version_inf_eq (version, "1.0.5.8"))
4122 t= upgrade_graphics (t);
4123 if (version_inf_eq (version, "1.0.5.11"))
4124 t= upgrade_textat (t);
4125 if (version_inf_eq (version, "1.0.6.1"))
4126 t= upgrade_cell_alignment (t);
4127 if (version_inf_eq (version, "1.0.6.2"))
4128 t= rename_primitive (t, "hyper-link", "hlink");
4129 if (version_inf_eq (version, "1.0.6.2"))
4130 t= upgrade_label_assignment (t);
4131 if (version_inf_eq (version, "1.0.6.10"))
4132 t= upgrade_scheme_doc (t);
4133 if (version_inf_eq (version, "1.0.6.14"))
4134 t= upgrade_mmx (t);
4135 if (version_inf_eq (version, "1.0.7.1"))
4136 t= upgrade_session (t, "scheme", "default");
4137 if (version_inf_eq (version, "1.0.7.6"))
4138 t= upgrade_presentation (t);
4139 if (version_inf_eq (version, "1.0.7.6") && is_non_style_document (t))
4140 t= upgrade_math (t);
4141 if (version_inf_eq (version, "1.0.7.7"))
4142 t= upgrade_resize_clipped (t);
4143 if (version_inf_eq (version, "1.0.7.7"))
4144 t= upgrade_image (t);
4145 if (version_inf_eq (version, "1.0.7.7"))
4146 t= upgrade_root_switch (t);
4147 if (version_inf_eq (version, "1.0.7.8"))
4148 t= upgrade_hyphenation (t);
4149 if (DEBUG_CORRECT)
4150 if (is_non_style_document (t))
4151 math_status_cumul (t);
4152 if (version_inf_eq (version, "1.0.7.8") && is_non_style_document (t)) {
4153 t= with_correct (t);
4154 t= superfluous_with_correct (t);
4155 t= upgrade_brackets (t);
4156 }
4157 if (version_inf_eq (version, "1.0.7.9")) {
4158 t= move_brackets (t);
4159 if (is_non_style_document (t))
4160 t= upgrade_algorithm (t, false);
4161 t= upgrade_math_ops (t);
4162 }
4163 if (version_inf_eq (version, "1.0.7.10"))
4164 t= downgrade_big (t);
4165 if (version_inf_eq (version, "1.0.7.13"))
4166 t= upgrade_gr_attributes (t);
4167 if (version_inf_eq (version, "1.0.7.14"))
4168 t= upgrade_cursor (t);
4169 if (version_inf_eq (version, "1.0.7.15"))
4170 t= upgrade_cyrillic (t);
4171 if (version_inf_eq (version, "1.0.7.17")) {
4172 t= upgrade_metadata (t);
4173 t= upgrade_abstract_data (t);
4174 t= correct_metadata (t);
4175 }
4176 if (version_inf_eq (version, "1.0.7.20")) {
4177 t= upgrade_unroll (t);
4178 t= upgrade_style (t, false);
4179 t= upgrade_doc_language (t);
4180 }
4181 if (version_inf_eq (version, "1.0.7.21")) {
4182 t= upgrade_varsession (t);
4183 t= upgrade_subsession (t);
4184 }
4185 if (version_inf_eq (version, "1.99.2")) {
4186 t= upgrade_quotes (t);
4187 t= upgrade_ancient (t);
4188 }
4189
4190 if (is_non_style_document (t))
4191 t= automatic_correct (t, version);
4192 return t;
4193 }
4194