PageRenderTime 77ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/TeXmacs-1.0.7.11-src/src/Typeset/Line/lazy_typeset.cpp

#
C++ | 545 lines | 425 code | 53 blank | 67 comment | 95 complexity | 3fa671be22c5768d9f37df3ccdf66db4 MD5 | raw file
Possible License(s): GPL-3.0, GPL-2.0, MPL-2.0-no-copyleft-exception
  1. /******************************************************************************
  2. * MODULE : lazy_typeset.cpp
  3. * DESCRIPTION: Lazy typesetting of various primitives
  4. * COPYRIGHT : (C) 1999 Joris van der Hoeven
  5. *******************************************************************************
  6. * This software falls under the GNU general public license version 3 or later.
  7. * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
  8. * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
  9. ******************************************************************************/
  10. #include "Line/lazy_typeset.hpp"
  11. #include "Line/lazy_vstream.hpp"
  12. #include "Format/format.hpp"
  13. #include "Stack/stacker.hpp"
  14. #include "Boxes/construct.hpp"
  15. #include "analyze.hpp"
  16. #include "packrat.hpp"
  17. array<line_item> typeset_marker (edit_env env, path ip);
  18. array<line_item> typeset_concat (edit_env, tree t, path ip);
  19. array<line_item> join (array<line_item> a, array<line_item> b);
  20. lazy make_lazy_paragraph (edit_env env, tree t, path ip);
  21. lazy make_lazy_table (edit_env env, tree t, path ip);
  22. lazy make_lazy_canvas (edit_env env, tree t, path ip);
  23. lazy make_lazy_ornament (edit_env env, tree t, path ip);
  24. /******************************************************************************
  25. * Documents
  26. ******************************************************************************/
  27. lazy_document_rep::lazy_document_rep (edit_env env, tree t, path ip):
  28. lazy_rep (LAZY_DOCUMENT, ip), par (N(t))
  29. {
  30. int i, n= N(t);
  31. for (i=0; i<n; i++)
  32. par[i]= make_lazy (env, t[i], descend (ip, i));
  33. }
  34. format
  35. lazy_document_rep::query (lazy_type request, format fm) {
  36. if ((request == LAZY_BOX) && (fm->type == QUERY_VSTREAM_WIDTH)) {
  37. query_vstream_width qvw= (query_vstream_width) fm;
  38. array<line_item> before= qvw->before;
  39. array<line_item> after = qvw->after;
  40. SI w= 1;
  41. int i, n= N(par);
  42. for (i=0; i<n; i++) {
  43. format tmp_fm= make_query_vstream_width (
  44. i==0 ? before: array<line_item> (),
  45. i==n-1? after : array<line_item> ());
  46. format ret_fm= par[i]->query (request, tmp_fm);
  47. format_width fmw= (format_width) ret_fm;
  48. w= max (w, fmw->width);
  49. }
  50. return make_format_width (w);
  51. }
  52. return lazy_rep::query (request, fm);
  53. }
  54. lazy
  55. lazy_document_rep::produce (lazy_type request, format fm) {
  56. if (request == type) return this;
  57. if (request == LAZY_VSTREAM) {
  58. int i, n= N(par);
  59. SI width= 1;
  60. array<line_item> before;
  61. array<line_item> after;
  62. if (fm->type == FORMAT_VSTREAM) {
  63. format_vstream fs= (format_vstream) fm;
  64. width = fs->width ;
  65. before= fs->before;
  66. after = fs->after ;
  67. }
  68. array<page_item> l;
  69. stack_border sb;
  70. for (i=0; i<n; i++) {
  71. format tmp_fm= make_format_vstream (width,
  72. i==0 ? before: array<line_item> (),
  73. i==n-1? after : array<line_item> ());
  74. lazy tmp= par[i]->produce (request, tmp_fm);
  75. lazy_vstream tmp_vs= (lazy_vstream) tmp;
  76. if (i == 0) {
  77. l = tmp_vs->l ;
  78. sb= tmp_vs->sb;
  79. }
  80. else merge_stack (l, sb, tmp_vs->l, tmp_vs->sb);
  81. }
  82. return lazy_vstream (ip, "", l, sb);
  83. }
  84. return lazy_rep::produce (request, fm);
  85. }
  86. /******************************************************************************
  87. * Surround
  88. ******************************************************************************/
  89. lazy_surround_rep::lazy_surround_rep (edit_env env, tree t, path ip):
  90. lazy_rep (LAZY_SURROUND, ip)
  91. {
  92. a = typeset_concat (env, t[0], descend (ip, 0));
  93. b = typeset_concat (env, t[1], descend (ip, 1));
  94. par= make_lazy (env, t[2], descend (ip, 2));
  95. }
  96. lazy_surround_rep::lazy_surround_rep (
  97. array<line_item> a2, array<line_item> b2, lazy par2, path ip):
  98. lazy_rep (LAZY_SURROUND, ip), a (a2), b (b2), par (par2) {}
  99. format
  100. lazy_surround_rep::query (lazy_type request, format fm) {
  101. if ((request == LAZY_BOX) && (fm->type == QUERY_VSTREAM_WIDTH)) {
  102. query_vstream_width qvw= (query_vstream_width) fm;
  103. array<line_item> before= qvw->before;
  104. array<line_item> after = qvw->after;
  105. if (N(a) != 0) before= join (before, a);
  106. if (N(b) != 0) after = join (b, after);
  107. format tmp_fm= make_query_vstream_width (before, after);
  108. return par->query (request, tmp_fm);
  109. }
  110. return lazy_rep::query (request, fm);
  111. }
  112. lazy
  113. lazy_surround_rep::produce (lazy_type request, format fm) {
  114. if (request == type) return this;
  115. if (request == LAZY_VSTREAM) {
  116. SI width = 1;
  117. array<line_item> before= a;
  118. array<line_item> after = b;
  119. if (fm->type == FORMAT_VSTREAM) {
  120. format_vstream fs= (format_vstream) fm;
  121. width = fs->width ;
  122. before= join (fs->before, before);
  123. after = join (after, fs->after);
  124. }
  125. format ret_fm= make_format_vstream (width, before, after);
  126. return par->produce (request, ret_fm);
  127. }
  128. return lazy_rep::produce (request, fm);
  129. }
  130. /******************************************************************************
  131. * Hidden
  132. ******************************************************************************/
  133. lazy
  134. make_lazy_hidden (edit_env env, tree t, path ip) {
  135. (void) make_lazy (env, t[0], descend (ip, 0));
  136. return lazy_document (env, tree (DOCUMENT), ip);
  137. }
  138. /******************************************************************************
  139. * Formatting
  140. ******************************************************************************/
  141. lazy
  142. make_lazy_formatting (edit_env env, tree t, path ip, string v) {
  143. int last= N(t)-1;
  144. tree new_format= env->read (v) * t (0, last);
  145. tree old_format= env->local_begin (v, new_format);
  146. array<line_item> a;
  147. array<line_item> b;
  148. if (v != CELL_FORMAT) {
  149. a= typeset_marker (env, descend (ip, 0));
  150. b= typeset_marker (env, descend (ip, 1));
  151. }
  152. lazy par= make_lazy (env, t[last], descend (ip, last));
  153. env->local_end (v, old_format);
  154. return lazy_surround (a, b, par, ip);
  155. }
  156. /******************************************************************************
  157. * With
  158. ******************************************************************************/
  159. lazy
  160. make_lazy_with (edit_env env, tree t, path ip) {
  161. int last= N(t)-1;
  162. int i, k= last>>1; // is k=0 allowed ?
  163. // if ((last&1) != 0) return;
  164. STACK_NEW_ARRAY(vars,string,k);
  165. STACK_NEW_ARRAY(oldv,tree,k);
  166. STACK_NEW_ARRAY(newv,tree,k);
  167. for (i=0; i<k; i++) {
  168. tree var_t= env->exec (t[i<<1]);
  169. if (is_atomic (var_t)) {
  170. string var= var_t->label;
  171. vars[i]= var;
  172. oldv[i]= env->read (var);
  173. newv[i]= env->exec (t[(i<<1)+1]);
  174. }
  175. /*
  176. else {
  177. STACK_DELETE_ARRAY(vars);
  178. STACK_DELETE_ARRAY(oldv);
  179. STACK_DELETE_ARRAY(newv);
  180. return;
  181. }
  182. */
  183. }
  184. // for (i=0; i<k; i++) env->monitored_write_update (vars[i], newv[i]);
  185. for (i=0; i<k; i++) env->write_update (vars[i], newv[i]);
  186. array<line_item> a= typeset_marker (env, descend (ip, 0));
  187. array<line_item> b= typeset_marker (env, descend (ip, 1));
  188. lazy par= make_lazy (env, t[last], descend (ip, last));
  189. for (i=k-1; i>=0; i--) env->write_update (vars[i], oldv[i]);
  190. STACK_DELETE_ARRAY(vars);
  191. STACK_DELETE_ARRAY(oldv);
  192. STACK_DELETE_ARRAY(newv);
  193. return lazy_surround (a, b, par, ip);
  194. }
  195. /******************************************************************************
  196. * Compound
  197. ******************************************************************************/
  198. lazy
  199. make_lazy_compound (edit_env env, tree t, path ip) {
  200. int d; tree f;
  201. if (L(t) == COMPOUND) {
  202. d= 1;
  203. f= t[0];
  204. if (is_compound (f)) f= env->exec (f);
  205. if (is_atomic (f)) {
  206. string var= f->label;
  207. if (env->provides (var)) f= env->read (var);
  208. else f= tree (ERROR, "compound " * var);
  209. }
  210. }
  211. else {
  212. string var= as_string (L(t));
  213. if (env->provides (var)) f= env->read (var);
  214. else f= tree (ERROR, "compound " * var);
  215. d= 0;
  216. }
  217. array<line_item> a;
  218. array<line_item> b;
  219. if (/*NON_CHILD_ENFORCING(t)&&*/ (!is_decoration (ip))) {
  220. a= typeset_marker (env, descend (ip, 0));
  221. b= typeset_marker (env, descend (ip, 1));
  222. }
  223. lazy par;
  224. if (is_applicable (f)) {
  225. int i, n=N(f)-1, m=N(t)-d;
  226. env->macro_arg= list<hashmap<string,tree> > (
  227. hashmap<string,tree> (UNINIT), env->macro_arg);
  228. env->macro_src= list<hashmap<string,path> > (
  229. hashmap<string,path> (path (DECORATION)), env->macro_src);
  230. if (L(f) == XMACRO) {
  231. if (is_atomic (f[0])) {
  232. string var= f[0]->label;
  233. env->macro_arg->item (var)= t;
  234. env->macro_src->item (var)= ip;
  235. }
  236. }
  237. else for (i=0; i<n; i++)
  238. if (is_atomic (f[i])) {
  239. string var= f[i]->label;
  240. env->macro_arg->item (var)=
  241. i<m? t[i+d]: attach_dip (tree (UNINIT), decorate_right(ip));
  242. env->macro_src->item (var)= i<m? descend (ip,i+d): decorate_right(ip);
  243. }
  244. if (is_decoration (ip)) par= make_lazy (env, attach_here (f[n], ip));
  245. else par= make_lazy (env, attach_right (f[n], ip));
  246. env->macro_arg= env->macro_arg->next;
  247. env->macro_src= env->macro_src->next;
  248. }
  249. else {
  250. if (is_decoration (ip)) par= make_lazy (env, attach_here (f, ip));
  251. else par= make_lazy (env, attach_right (f, ip));
  252. }
  253. return lazy_surround (a, b, par, ip);
  254. }
  255. /******************************************************************************
  256. * Rewrite
  257. ******************************************************************************/
  258. lazy
  259. make_lazy_rewrite (edit_env env, tree t, path ip) {
  260. tree r= env->rewrite (t);
  261. array<line_item> a= typeset_marker (env, descend (ip, 0));
  262. array<line_item> b= typeset_marker (env, descend (ip, 1));
  263. lazy par= make_lazy (env, attach_right (r, ip));
  264. return lazy_surround (a, b, par, ip);
  265. }
  266. /******************************************************************************
  267. * Eval
  268. ******************************************************************************/
  269. lazy
  270. make_lazy_eval (edit_env env, tree t, path ip) {
  271. tree r= env->exec (is_func (t, EVAL, 1)? t[0]: tree (QUASIQUOTE, t[0]));
  272. array<line_item> a= typeset_marker (env, descend (ip, 0));
  273. array<line_item> b= typeset_marker (env, descend (ip, 1));
  274. lazy par= make_lazy (env, attach_right (r, ip));
  275. return lazy_surround (a, b, par, ip);
  276. }
  277. /******************************************************************************
  278. * Auto
  279. ******************************************************************************/
  280. lazy
  281. make_lazy_auto (edit_env env, tree t, path ip, tree f) {
  282. array<line_item> a;
  283. array<line_item> b;
  284. if (!is_decoration (ip)) {
  285. a= typeset_marker (env, descend (ip, 0));
  286. b= typeset_marker (env, descend (ip, 1));
  287. }
  288. lazy par;
  289. env->macro_arg= list<hashmap<string,tree> > (
  290. hashmap<string,tree> (UNINIT), env->macro_arg);
  291. env->macro_src= list<hashmap<string,path> > (
  292. hashmap<string,path> (path (DECORATION)), env->macro_src);
  293. string var= f[0]->label;
  294. env->macro_arg->item (var)= t;
  295. env->macro_src->item (var)= ip;
  296. if (is_decoration (ip)) par= make_lazy (env, attach_here (f[1], ip));
  297. else par= make_lazy (env, attach_right (f[1], ip));
  298. env->macro_arg= env->macro_arg->next;
  299. env->macro_src= env->macro_src->next;
  300. return lazy_surround (a, b, par, ip);
  301. }
  302. /******************************************************************************
  303. * Argument
  304. ******************************************************************************/
  305. lazy
  306. make_lazy_argument (edit_env env, tree t, path ip) {
  307. string name;
  308. tree value;
  309. path valip= decorate_right (ip);
  310. tree r= t[0];
  311. if (is_compound (r)) value= tree (ERROR, "value");
  312. else {
  313. name = r->label;
  314. if ((!is_nil (env->macro_arg)) && env->macro_arg->item->contains (r->label)) {
  315. value= env->macro_arg->item [name];
  316. if (!is_func (value, BACKUP)) {
  317. path new_valip= env->macro_src->item [name];
  318. if (is_accessible (new_valip)) valip= new_valip;
  319. }
  320. }
  321. else value= tree (ERROR, "value " * name);
  322. }
  323. array<line_item> a= typeset_marker (env, descend (ip, 0));
  324. array<line_item> b= typeset_marker (env, descend (ip, 1));
  325. list<hashmap<string,tree> > old_var= env->macro_arg;
  326. list<hashmap<string,path> > old_src= env->macro_src;
  327. if (!is_nil (env->macro_arg)) env->macro_arg= env->macro_arg->next;
  328. if (!is_nil (env->macro_src)) env->macro_src= env->macro_src->next;
  329. if (N(t) > 1) {
  330. int i, n= N(t);
  331. for (i=1; i<n; i++) {
  332. tree r= env->exec (t[i]);
  333. if (!is_int (r)) break;
  334. int nr= as_int (r);
  335. if ((!is_compound (value)) || (nr<0) || (nr>=N(value))) break;
  336. value= value[nr];
  337. valip= descend (valip, nr);
  338. }
  339. }
  340. lazy par= make_lazy (env, attach_here (value, valip));
  341. env->macro_arg= old_var;
  342. env->macro_src= old_src;
  343. return lazy_surround (a, b, par, ip);
  344. }
  345. /******************************************************************************
  346. * Mark and expand_as
  347. ******************************************************************************/
  348. lazy
  349. make_lazy_mark (edit_env env, tree t, path ip) {
  350. // cout << "Lazy mark: " << t << ", " << ip << "\n";
  351. array<line_item> a= typeset_marker (env, descend (ip, 0));
  352. array<line_item> b= typeset_marker (env, descend (ip, 1));
  353. if (is_func (t[0], ARG) &&
  354. is_atomic (t[0][0]) &&
  355. (!is_nil (env->macro_arg)) &&
  356. env->macro_arg->item->contains (t[0][0]->label))
  357. {
  358. string name = t[0][0]->label;
  359. tree value= env->macro_arg->item [name];
  360. path valip= decorate_right (ip);
  361. if (!is_func (value, BACKUP)) {
  362. path new_valip= env->macro_src->item [name];
  363. if (is_accessible (new_valip)) valip= new_valip;
  364. }
  365. if (N(t[0]) > 1) {
  366. int i, n= N(t[0]);
  367. for (i=1; i<n; i++) {
  368. tree r= env->exec (t[0][i]);
  369. if (!is_int (r)) break;
  370. int nr= as_int (r);
  371. if ((!is_compound (value)) || (nr<0) || (nr>=N(value))) break;
  372. value= value[nr];
  373. valip= descend (valip, nr);
  374. }
  375. }
  376. if (is_compound (value)) {
  377. a= typeset_marker (env, descend (valip, 0));
  378. b= typeset_marker (env, descend (valip, 1));
  379. }
  380. }
  381. lazy par= make_lazy (env, t[1], descend (ip, 1));
  382. return lazy_surround (a, b, par, ip);
  383. }
  384. lazy
  385. make_lazy_expand_as (edit_env env, tree t, path ip) {
  386. array<line_item> a= typeset_marker (env, descend (ip, 0));
  387. array<line_item> b= typeset_marker (env, descend (ip, 1));
  388. lazy par= make_lazy (env, t[1], descend (ip, 1));
  389. return lazy_surround (a, b, par, ip);
  390. }
  391. /******************************************************************************
  392. * Locus
  393. ******************************************************************************/
  394. lazy
  395. make_lazy_locus (edit_env env, tree t, path ip) {
  396. extern bool build_locus (edit_env env, tree t, list<string>& ids, string& c);
  397. list<string> ids;
  398. string col;
  399. if (!build_locus (env, t, ids, col))
  400. system_warning ("Ignored unaccessible loci");
  401. int last= N(t)-1;
  402. tree old_col= env->read (COLOR);
  403. env->write_update (COLOR, col);
  404. array<line_item> a= typeset_marker (env, descend (ip, 0));
  405. array<line_item> b= typeset_marker (env, descend (ip, 1));
  406. lazy par= make_lazy (env, t[last], descend (ip, last));
  407. env->write_update (COLOR, old_col);
  408. return lazy_surround (a, b, par, ip);
  409. }
  410. /******************************************************************************
  411. * Main routine
  412. ******************************************************************************/
  413. static tree inactive_m
  414. (MACRO, "x",
  415. tree (REWRITE_INACTIVE, tree (ARG, "x", "0"), "once*"));
  416. static tree var_inactive_m
  417. (MACRO, "x",
  418. tree (REWRITE_INACTIVE, tree (ARG, "x", "0"), "recurse*"));
  419. lazy
  420. make_lazy (edit_env env, tree t, path ip) {
  421. /*
  422. if (is_accessible (ip)) {
  423. if (obtain_ip (t) != ip)
  424. cout << "TeXmacs] Wrong ip: " << t << "\n";
  425. }
  426. */
  427. if (!is_accessible (ip)) {
  428. path ip2= obtain_ip (t);
  429. if (ip2 != path (DETACHED))
  430. ip= ip2;
  431. }
  432. if (env->hl_lan != 0)
  433. env->lan->highlight (t);
  434. switch (L(t)) {
  435. case DOCUMENT:
  436. return lazy_document (env, t, ip);
  437. case SURROUND:
  438. return lazy_surround (env, t, ip);
  439. //case HIDDEN:
  440. //return make_lazy_hidden (env, t, ip);
  441. case DATOMS:
  442. return make_lazy_formatting (env, t, ip, ATOM_DECORATIONS);
  443. case DLINES:
  444. return make_lazy_formatting (env, t, ip, LINE_DECORATIONS);
  445. case DPAGES:
  446. return make_lazy_formatting (env, t, ip, PAGE_DECORATIONS);
  447. case TFORMAT:
  448. return make_lazy_formatting (env, t, ip, CELL_FORMAT);
  449. case TABLE:
  450. return make_lazy_table (env, t, ip);
  451. case WITH:
  452. return make_lazy_with (env, t, ip);
  453. case ARG:
  454. return make_lazy_argument (env, t, ip);
  455. case MARK:
  456. return make_lazy_mark (env, t, ip);
  457. case EXPAND_AS:
  458. return make_lazy_expand_as (env, t, ip);
  459. case EVAL:
  460. case QUASI:
  461. return make_lazy_eval (env, t, ip);
  462. case COMPOUND:
  463. return make_lazy_compound (env, t, ip);
  464. case EXTERN:
  465. return make_lazy_rewrite (env, t, ip);
  466. case INCLUDE:
  467. return make_lazy_rewrite (env, t, ip);
  468. case STYLE_ONLY:
  469. case VAR_STYLE_ONLY:
  470. case ACTIVE:
  471. case VAR_ACTIVE:
  472. return make_lazy_compound (env, t, ip);
  473. case INACTIVE:
  474. return make_lazy_auto (env, t, ip, inactive_m);
  475. case VAR_INACTIVE:
  476. return make_lazy_auto (env, t, ip, var_inactive_m);
  477. case REWRITE_INACTIVE:
  478. return make_lazy_rewrite (env, t, ip);
  479. case LOCUS:
  480. return make_lazy_locus (env, t, ip);
  481. case HLINK:
  482. case ACTION:
  483. return make_lazy_compound (env, t, ip);
  484. case CANVAS:
  485. return make_lazy_canvas (env, t, ip);
  486. case ORNAMENT:
  487. return make_lazy_ornament (env, t, ip);
  488. default:
  489. if (L(t) < START_EXTENSIONS) return make_lazy_paragraph (env, t, ip);
  490. else return make_lazy_compound (env, t, ip);
  491. }
  492. }