PageRenderTime 193ms CodeModel.GetById 4ms RepoModel.GetById 12ms app.codeStats 0ms

/source/src/Texmacs/Data/tm_data.cpp

http://itexmacs.googlecode.com/
C++ | 901 lines | 745 code | 99 blank | 57 comment | 242 complexity | 3d3e16387fa49664b52dc0950cf57b41 MD5 | raw file
Possible License(s): GPL-3.0, GPL-2.0, MPL-2.0-no-copyleft-exception, LGPL-2.0
  1. /******************************************************************************
  2. * MODULE : tm_data.cpp
  3. * DESCRIPTION: Buffer management for TeXmacs server
  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 "tm_data.hpp"
  11. #include "convert.hpp"
  12. #include "file.hpp"
  13. #include "web_files.hpp"
  14. #include "tm_link.hpp"
  15. #include "message.hpp"
  16. #include "dictionary.hpp"
  17. #ifdef QTTEXMACS
  18. #include "Qt/qt_utilities.hpp"
  19. #endif
  20. url tm_init_buffer_file= url_none ();
  21. url my_init_buffer_file= url_none ();
  22. /******************************************************************************
  23. * Constructor and destructor
  24. ******************************************************************************/
  25. tm_data_rep::tm_data_rep () {}
  26. tm_data_rep::~tm_data_rep () {}
  27. /******************************************************************************
  28. * Low level functions for maintaining the buffer menu
  29. ******************************************************************************/
  30. int
  31. tm_data_rep::find_buffer (path p) {
  32. int i;
  33. for (i=0; i<N(bufs); i++)
  34. if (bufs[i]->rp <= p)
  35. return i;
  36. return -1;
  37. }
  38. int
  39. tm_data_rep::find_buffer (url name) {
  40. int i;
  41. for (i=0; i<N(bufs); i++)
  42. if (bufs[i]->name == name)
  43. return i;
  44. return -1;
  45. }
  46. string
  47. tm_data_rep::new_menu_name (url u) {
  48. string name= as_string (tail (u));
  49. #ifdef QTTEXMACS
  50. name = from_qstring( QString::fromLocal8Bit (as_charp (name)));
  51. #endif
  52. if (starts (name, "no_name_") && ends (name, ".tm")) {
  53. string no_name= translate ("No name");
  54. for (int i=0; i<N(no_name); i++)
  55. if (((unsigned char) (no_name[i])) >= (unsigned char) 128)
  56. { no_name= "No name"; break; }
  57. name= no_name * " [" * name (8, N(name) - 3) * "]";
  58. }
  59. if ((name == "") || (name == "."))
  60. name= as_string (tail (u * url_parent ()));
  61. if ((name == "") || (name == "."))
  62. name= as_string (u);
  63. if (is_rooted_tmfs (u))
  64. name= as_string (call ("tmfs-name", as_string (u)));
  65. int i, j;
  66. for (j=1; true; j++) {
  67. bool flag= true;
  68. string ret (name);
  69. if (j>1) ret= name * " (" * as_string (j) * ")";
  70. for (i=0; i<N(bufs); i++)
  71. if (bufs[i]->abbr == ret) flag= false;
  72. if (flag) return ret;
  73. }
  74. }
  75. static void
  76. menu_append_buffer (string& s, tm_buffer buf) {
  77. if (buf->in_menu) {
  78. string name= copy (buf->abbr);
  79. if (buf->needs_to_be_saved ()) name << " *";
  80. string mname= scm_quote (name);
  81. if (!starts (name, "Help")) mname= "(verbatim " * mname * ")";
  82. s << " (" << mname;
  83. s << " (switch-to-buffer " * scm_quote (as_string (buf->name)) * "))";
  84. }
  85. }
  86. object
  87. tm_data_rep::get_buffer_menu () {
  88. int i, count;
  89. bool two_types= false;;
  90. string s ("(menu-dynamic");
  91. for (i=0, count=0; i<N(bufs); i++) {
  92. if (is_none (bufs[i]->extra) == is_none (bufs[0]->extra)) {
  93. menu_append_buffer (s, bufs[i]);
  94. count++;
  95. }
  96. else two_types= true;
  97. if (count == 10) break;
  98. }
  99. if (two_types) {
  100. s << " ---";
  101. for (i=0, count=0; i<N(bufs); i++) {
  102. if (is_none (bufs[i]->extra) != is_none (bufs[0]->extra)) {
  103. menu_append_buffer (s, bufs[i]);
  104. count++;
  105. }
  106. if (count == 10) break;
  107. }
  108. }
  109. s << ")";
  110. return eval (s);
  111. }
  112. bool
  113. tm_data_rep::buffer_in_menu (url u, bool flag) {
  114. int nr= find_buffer (u);
  115. if (nr == -1) return false;
  116. tm_buffer buf= bufs[nr];
  117. bool old= buf->in_menu;
  118. buf->in_menu= flag;
  119. return old;
  120. }
  121. void
  122. tm_data_rep::menu_insert_buffer (tm_buffer buf) {
  123. // bufs << ((pointer) buf); // causes compilation error
  124. bufs << buf; // WARNING: that one compile, what was the use of the cast?
  125. }
  126. void
  127. tm_data_rep::menu_delete_buffer (tm_buffer buf) {
  128. int i, nr, n=N(bufs);
  129. for (nr=0; nr<n; nr++)
  130. if (bufs[nr] == ((pointer) buf)) break;
  131. if (nr==N(bufs)) return;
  132. for (i=nr; i<(n-1); i++) bufs[i]= bufs[i+1];
  133. bufs->resize (n-1);
  134. }
  135. void
  136. tm_data_rep::menu_focus_buffer (tm_buffer buf) {
  137. int i, nr;
  138. for (nr=0; nr<N(bufs); nr++)
  139. if (bufs[nr] == ((pointer) buf)) break;
  140. if (nr==N(bufs)) return;
  141. for (i=nr; i>=1; i--) bufs[i]= bufs[i-1];
  142. bufs[0]= buf;
  143. }
  144. /******************************************************************************
  145. * Low level buffer routines
  146. ******************************************************************************/
  147. tm_buffer
  148. tm_data_rep::new_buffer (url name) {
  149. int nr= find_buffer (name);
  150. if (nr != -1) return bufs[nr];
  151. tm_buffer buf= tm_new<tm_buffer_rep> (name);
  152. buf->abbr= new_menu_name (name);
  153. menu_insert_buffer (buf);
  154. return buf;
  155. }
  156. tm_buffer
  157. tm_data_rep::new_buffer (url name, tree doc) {
  158. int nr= find_buffer (name);
  159. if (nr != -1) return bufs[nr];
  160. tm_buffer buf= new_buffer (name);
  161. set_document (buf->rp, extract (doc, "body"));
  162. buf->project= extract (doc, "project");
  163. buf->style = extract (doc, "style");
  164. buf->init = hashmap<string,tree> (UNINIT, extract (doc, "initial"));
  165. buf->fin = hashmap<string,tree> (UNINIT, extract (doc, "final"));
  166. buf->ref = hashmap<string,tree> (UNINIT, extract (doc, "references"));
  167. buf->aux = hashmap<string,tree> (UNINIT, extract (doc, "auxiliary"));
  168. if (buf->project != "") {
  169. url prj_name= head (name) * as_string (buf->project);
  170. buf->prj= load_passive_buffer (prj_name);
  171. }
  172. return buf;
  173. }
  174. void
  175. tm_data_rep::revert_buffer (url name, tree doc) {
  176. int i, nr= find_buffer (name);
  177. if (nr == -1) return;
  178. tm_buffer buf= bufs[nr];
  179. buf->project= extract (doc, "project");
  180. buf->style = extract (doc, "style");
  181. buf->init = hashmap<string,tree> (UNINIT, extract (doc, "initial"));
  182. buf->fin = hashmap<string,tree> (UNINIT, extract (doc, "final"));
  183. buf->ref = hashmap<string,tree> (UNINIT, extract (doc, "references"));
  184. buf->aux = hashmap<string,tree> (UNINIT, extract (doc, "auxiliary"));
  185. if (N(buf->vws)==0) set_document (buf->rp, extract (doc, "body"));
  186. else for (i=0; i<N(buf->vws); i++) {
  187. tm_view vw= buf->vws[i];
  188. if (i==0) assign (vw->ed->rp, extract (doc, "body"));
  189. vw->ed->set_style (buf->style);
  190. vw->ed->set_init (buf->init);
  191. vw->ed->set_fin (buf->fin);
  192. vw->ed->notify_page_change ();
  193. vw->ed->add_init (buf->init);
  194. vw->ed->notify_change (THE_DECORATIONS);
  195. vw->ed->typeset_invalidate_env ();
  196. vw->ed->notify_save ();
  197. }
  198. }
  199. void
  200. tm_data_rep::delete_buffer (tm_buffer buf) {
  201. int i;
  202. menu_delete_buffer (buf);
  203. for (i=0; i<N(buf->vws); i++)
  204. delete_view (buf->vws[i]);
  205. tm_delete (buf);
  206. }
  207. void
  208. tm_data_rep::set_name_buffer (url name) {
  209. tm_buffer buf= get_buffer ();
  210. if (buf->name == name) return;
  211. buf->name= name;
  212. set_abbr_buffer (new_menu_name (name));
  213. }
  214. string
  215. tm_data_rep::get_abbr_buffer () {
  216. tm_buffer buf= get_buffer ();
  217. return buf->abbr;
  218. }
  219. void
  220. tm_data_rep::set_abbr_buffer (string abbr) {
  221. int i;
  222. tm_buffer buf= get_buffer ();
  223. if (buf->abbr == abbr) return;
  224. buf->abbr= abbr;
  225. for (i=0; i<N(buf->vws); i++) {
  226. tm_view vw2= buf->vws[i];
  227. if (vw2->win != NULL) {
  228. vw2->win->set_window_name (buf->abbr);
  229. vw2->win->set_window_url (is_none (buf->extra)? buf->name: buf->extra);
  230. }
  231. }
  232. }
  233. url
  234. tm_data_rep::get_name_buffer () {
  235. tm_buffer buf= get_buffer ();
  236. if (!is_none (buf->extra)) return buf->extra;
  237. return buf->name;
  238. }
  239. url
  240. tm_data_rep::get_name_buffer (path p) {
  241. int nr= find_buffer (p);
  242. if (nr == -1) return url_none ();
  243. return bufs[nr]->name;
  244. }
  245. url
  246. tm_data_rep::get_all_buffers () {
  247. url u= url_none ();
  248. for (int i=N(bufs)-1; i>=0; i--)
  249. u= bufs[i]->name | u;
  250. return u;
  251. }
  252. /******************************************************************************
  253. * Low level view routines
  254. ******************************************************************************/
  255. tm_view
  256. tm_data_rep::new_view (url name) {
  257. // cout << "Creating new view\n";
  258. tm_buffer buf= new_buffer (name);
  259. editor ed = new_editor (get_server (), buf);
  260. tm_view vw = tm_new<tm_view_rep> (buf, ed);
  261. buf->vws << vw;
  262. ed->set_style (buf->style);
  263. ed->set_init (buf->init);
  264. ed->set_fin (buf->fin);
  265. ed->notify_page_change ();
  266. ed->add_init (buf->init);
  267. ed->notify_change (THE_DECORATIONS);
  268. ed->typeset_invalidate_env ();
  269. tm_view temp_vw= get_view (false);
  270. set_view (vw);
  271. if (is_none (tm_init_buffer_file))
  272. tm_init_buffer_file= "$TEXMACS_PATH/progs/init-buffer.scm";
  273. if (is_none (my_init_buffer_file))
  274. my_init_buffer_file= "$TEXMACS_HOME_PATH/progs/my-init-buffer.scm";
  275. if (exists (tm_init_buffer_file)) exec_file (tm_init_buffer_file);
  276. if (exists (my_init_buffer_file)) exec_file (my_init_buffer_file);
  277. set_view (temp_vw);
  278. // cout << "View created\n";
  279. return vw;
  280. }
  281. tm_view
  282. tm_data_rep::get_passive_view (tm_buffer buf) {
  283. int i;
  284. for (i=0; i<N(buf->vws); i++)
  285. if (buf->vws[i]->win == NULL)
  286. return buf->vws[i];
  287. return new_view (buf->name);
  288. }
  289. void
  290. tm_data_rep::delete_view (tm_view vw) {
  291. tm_buffer buf= vw->buf;
  292. int i, j, n= N(buf->vws);
  293. for (i=0; i<n; i++)
  294. if (buf->vws[i] == vw) {
  295. array<tm_view> a (n-1);
  296. for (j=0; j<n-1; j++)
  297. if (j<i) a[j]= buf->vws[j];
  298. else a[j]= buf->vws[j+1];
  299. buf->vws= a;
  300. }
  301. // tm_delete (vw);
  302. // FIXME: causes very annoying segfault;
  303. // recently introduced during reorganization
  304. }
  305. void
  306. tm_data_rep::attach_view (tm_window win, tm_view vw) {
  307. // cout << "Attach view " << vw->buf->name << "\n";
  308. vw->win= win;
  309. widget wid= win->wid;
  310. set_canvas (wid, vw->ed);
  311. ASSERT (is_attached (wid), "widget should be attached");
  312. vw->ed->resume ();
  313. win->set_window_name (vw->buf->abbr);
  314. win->set_window_url (is_none (vw->buf->extra)? vw->buf->name: vw->buf->extra);
  315. // cout << "View attached\n";
  316. }
  317. void
  318. tm_data_rep::detach_view (tm_view vw) {
  319. // cout << "Detach view " << vw->buf->name << "\n";
  320. tm_window win= vw->win;
  321. if (win == NULL) return;
  322. vw->win= NULL;
  323. widget wid= win->wid;
  324. ASSERT (is_attached (wid), "widget should be attached");
  325. vw->ed->suspend ();
  326. set_canvas (wid, glue_widget ());
  327. win->set_window_name ("TeXmacs");
  328. win->set_window_url (url_none ());
  329. // cout << "View detached\n";
  330. }
  331. /******************************************************************************
  332. * Low level window routines
  333. ******************************************************************************/
  334. class kill_window_command_rep: public command_rep {
  335. public:
  336. inline kill_window_command_rep () {}
  337. inline void apply () { exec_delayed (scheme_cmd ("(safely-kill-window)")); }
  338. tm_ostream& print (tm_ostream& out) { return out << "kill window"; }
  339. };
  340. tm_window
  341. tm_data_rep::new_window (bool map_flag, tree geom) {
  342. int mask= 0;
  343. if (get_preference ("header") == "on") mask += 1;
  344. if (get_preference ("main icon bar") == "on") mask += 2;
  345. if (get_preference ("mode dependent icons") == "on") mask += 4;
  346. if (get_preference ("focus dependent icons") == "on") mask += 8;
  347. if (get_preference ("user provided icons") == "on") mask += 16;
  348. if (get_preference ("status bar") == "on") mask += 32;
  349. command quit= tm_new<kill_window_command_rep> ();
  350. tm_window win= tm_new<tm_window_rep> (texmacs_widget (mask, quit), geom);
  351. if (map_flag) win->map ();
  352. return win;
  353. }
  354. bool
  355. tm_data_rep::delete_view_from_window (tm_window win) {
  356. int i, j;
  357. for (i=0; i<N(bufs); i++) {
  358. tm_buffer buf= bufs[i];
  359. for (j=0; j<N(buf->vws); j++) {
  360. tm_view vw= buf->vws[j];
  361. if (vw->win == win) {
  362. detach_view (vw);
  363. delete_view (vw);
  364. return true;
  365. }
  366. }
  367. }
  368. return false;
  369. }
  370. void
  371. tm_data_rep::delete_window (tm_window win) {
  372. while (delete_view_from_window (win)) {}
  373. win->unmap ();
  374. destroy_window_widget (win->win);
  375. tm_delete (win);
  376. }
  377. /******************************************************************************
  378. * Other subroutines
  379. ******************************************************************************/
  380. void
  381. tm_data_rep::new_buffer_in_this_window (url name, tree doc) {
  382. int nr= find_buffer (name);
  383. if (nr != -1) switch_to_buffer (nr);
  384. else {
  385. (void) new_buffer (name, doc);
  386. switch_to_buffer (name);
  387. }
  388. }
  389. void
  390. tm_data_rep::new_buffer_in_new_window (url name, tree doc, tree geom) {
  391. tm_window win= new_window (true, geom);
  392. tm_buffer buf= new_buffer (name, doc);
  393. tm_view vw = get_passive_view (buf);
  394. attach_view (win, vw);
  395. set_view (vw);
  396. menu_focus_buffer (buf);
  397. }
  398. /******************************************************************************
  399. * Exported routines
  400. ******************************************************************************/
  401. int
  402. tm_data_rep::nr_bufs () {
  403. return N(bufs);
  404. }
  405. tm_buffer
  406. tm_data_rep::get_buf (int i) {
  407. return (tm_buffer) bufs[i];
  408. }
  409. tm_buffer
  410. tm_data_rep::get_buf (path p) {
  411. int nr= find_buffer (p);
  412. if (nr >= 0) return bufs[nr];
  413. else return NULL;
  414. }
  415. url
  416. tm_data_rep::new_buffer () {
  417. int i=1;
  418. while (true) {
  419. url name= url_scratch ("no_name_", ".tm", i);
  420. int nr= find_buffer (name);
  421. if (nr == -1) {
  422. new_buffer_in_this_window (name, tree (DOCUMENT));
  423. return name;
  424. }
  425. else i++;
  426. }
  427. }
  428. void
  429. tm_data_rep::switch_to_buffer (int nr) {
  430. // cout << "Switching to buffer " << nr << "\n";
  431. tm_window win = get_window ();
  432. tm_buffer buf = bufs[nr];
  433. tm_view old_vw = get_view ();
  434. tm_view new_vw = get_passive_view (buf);
  435. detach_view (old_vw);
  436. attach_view (win, new_vw);
  437. set_view (new_vw);
  438. menu_focus_buffer (buf);
  439. tm_window nwin= new_vw->win;
  440. nwin->set_shrinking_factor (nwin->get_shrinking_factor ());
  441. // cout << "Switched to buffer " << nr << "\n";
  442. }
  443. bool
  444. tm_data_rep::switch_to_buffer (path p) {
  445. int nr= find_buffer (p);
  446. if (nr != -1) switch_to_buffer (nr);
  447. return nr != -1;
  448. }
  449. void
  450. tm_data_rep::switch_to_buffer (url name) {
  451. int nr= find_buffer (name);
  452. if (nr == -1) {
  453. load_passive_buffer (name);
  454. nr= find_buffer (name);
  455. }
  456. if (nr != -1) switch_to_buffer (nr);
  457. }
  458. void
  459. tm_data_rep::switch_to_active_buffer (url name) {
  460. // This function is a temporary hack for coq
  461. // Switching to buffers in other windows should be completely rewritten
  462. int nr= find_buffer (name);
  463. if (nr == -1) {
  464. load_passive_buffer (name);
  465. nr= find_buffer (name);
  466. }
  467. if (nr != -1) {
  468. int i;
  469. tm_buffer buf= bufs[nr];
  470. for (i=0; i<N(buf->vws); i++) // search active view
  471. if (buf->vws[i]->win != NULL) {
  472. tm_view vw= buf->vws[i];
  473. set_view (vw);
  474. menu_focus_buffer (buf);
  475. return;
  476. }
  477. }
  478. switch_to_buffer (name);
  479. }
  480. void
  481. tm_data_rep::revert_buffer () {
  482. tm_buffer buf= get_buffer ();
  483. web_cache_invalidate (buf->name);
  484. tree doc= load_tree (buf->name, buf->fm);
  485. if (doc == "error") set_message ("Error: file not found", "revert buffer");
  486. else revert_buffer (buf->name, doc);
  487. }
  488. void
  489. tm_data_rep::kill_buffer () {
  490. int i, nr;
  491. if (N(bufs) <= 1) quit();
  492. tm_buffer buf= get_buffer();
  493. for (nr=0; nr<N(bufs); nr++) if (buf == bufs[nr]) break;
  494. ASSERT (nr != N(bufs), "buffer not found");
  495. for (nr=0; nr<N(bufs); nr++) if (buf != bufs[nr]) break;
  496. ASSERT (nr != N(bufs), "no suitable new buffer");
  497. tm_buffer new_buf = bufs[nr];
  498. for (i=0; i<N(buf->vws); i++) {
  499. tm_view old_vw= buf->vws[i];
  500. if (old_vw->win != NULL) {
  501. tm_window win = old_vw->win;
  502. tm_view new_vw= get_passive_view (new_buf);
  503. detach_view (old_vw);
  504. attach_view (win, new_vw);
  505. if (get_view () == old_vw) set_view (new_vw);
  506. }
  507. }
  508. delete_buffer (buf);
  509. }
  510. url
  511. tm_data_rep::open_window (tree geom) {
  512. int i=1;
  513. while (true) {
  514. url name= url_scratch ("no_name_", ".tm", i);
  515. int nr= find_buffer (name);
  516. if (nr == -1) {
  517. new_buffer_in_new_window (name, tree (DOCUMENT), geom);
  518. return name;
  519. }
  520. else i++;
  521. }
  522. }
  523. void
  524. tm_data_rep::clone_window () {
  525. tm_window win= new_window ();
  526. tm_buffer buf= get_buffer ();
  527. tm_view vw = get_passive_view (buf);
  528. attach_view (win, vw);
  529. set_view (vw);
  530. menu_focus_buffer (buf);
  531. }
  532. void
  533. tm_data_rep::kill_window () {
  534. int i, j;
  535. tm_window win= get_window ();
  536. for (i=0; i<N(bufs); i++) {
  537. tm_buffer buf= bufs[i];
  538. for (j=0; j<N(buf->vws); j++) {
  539. tm_view vw= buf->vws[j];
  540. if ((vw->win != NULL) && (vw->win != win)) {
  541. set_view (vw);
  542. menu_focus_buffer (vw->buf);
  543. delete_window (win);
  544. return;
  545. }
  546. }
  547. }
  548. if (number_of_servers () == 0) quit ();
  549. else delete_window (win);
  550. }
  551. void
  552. tm_data_rep::kill_window_and_buffer () {
  553. if (N(bufs) <= 1) quit();
  554. int i;
  555. bool kill= true;
  556. tm_buffer buf= get_buffer();
  557. tm_window win= get_window ();
  558. for (i=0; i<N(buf->vws); i++) {
  559. tm_view old_vw= buf->vws[i];
  560. if (old_vw->win != win) kill= false;
  561. }
  562. kill_window ();
  563. if (kill) delete_buffer (buf);
  564. }
  565. bool
  566. tm_data_rep::no_bufs () {
  567. return N(bufs) == 0;
  568. }
  569. void
  570. tm_data_rep::set_aux (string aux, url name) {
  571. int i, nr= find_buffer (aux);
  572. if (nr != -1) {
  573. tm_buffer buf= bufs[nr];
  574. buf->extra= name;
  575. if (starts (aux, "Help - ")) {
  576. buf->fm= "help";
  577. buf->read_only= true;
  578. }
  579. for (i=0; i<N(buf->vws); i++) {
  580. tm_view vw= buf->vws[i];
  581. vw->ed->set_base_name (name);
  582. }
  583. }
  584. }
  585. void
  586. tm_data_rep::set_aux_buffer (string aux, url name, tree doc) {
  587. int nr= find_buffer (aux);
  588. if (nr == -1) new_buffer (aux, doc);
  589. else revert_buffer (aux, doc);
  590. nr= find_buffer (aux);
  591. if (nr != -1) {
  592. set_aux (aux, name);
  593. switch_to_buffer (nr);
  594. }
  595. }
  596. static string
  597. get_doc_title (tree t) {
  598. if (is_atomic (t)) return "";
  599. if (is_compound (t, "doc-title") ||
  600. is_compound (t, "tmdoc-title") ||
  601. is_compound (t, "tmdoc-title*") ||
  602. is_compound (t, "tmweb-title"))
  603. return tree_to_verbatim (t[0]);
  604. else {
  605. for (int i=0; i<N(t); i++) {
  606. string r= get_doc_title (t[i]);
  607. if (r != "") return r;
  608. }
  609. return "";
  610. }
  611. }
  612. string
  613. get_help_title (url name, tree t) {
  614. string s= get_doc_title (t);
  615. if (s == "") return "Help - " * as_string (tail (name));
  616. else return "Help - " * s;
  617. }
  618. void
  619. tm_data_rep::set_help_buffer (url name, tree doc) {
  620. set_aux_buffer (get_help_title (name, doc), name, doc);
  621. }
  622. void
  623. tm_data_rep::set_buffer_tree (url name, tree doc) {
  624. int nr= find_buffer (name);
  625. if (nr == -1) new_buffer (name, tree (DOCUMENT));
  626. nr= find_buffer (name);
  627. tm_buffer buf= bufs[nr];
  628. assign (buf->rp, doc);
  629. }
  630. tree
  631. tm_data_rep::get_buffer_tree (url name) {
  632. int nr= find_buffer (name);
  633. if (nr == -1) return "";
  634. tm_buffer buf= bufs[nr];
  635. return subtree (the_et, buf->rp);
  636. }
  637. /******************************************************************************
  638. * Projects
  639. ******************************************************************************/
  640. void
  641. tm_data_rep::project_attach (string prj_name) {
  642. int i;
  643. tm_buffer buf= get_buffer ();
  644. buf->project= prj_name;
  645. for (i=0; i<N(buf->vws); i++) {
  646. tm_view vw= buf->vws[i];
  647. vw->ed->notify_change (THE_DECORATIONS);
  648. vw->ed->require_save ();
  649. }
  650. if (prj_name == "") buf->prj= NULL;
  651. else {
  652. url full_name= head (buf->name) * prj_name;
  653. buf->prj= load_passive_buffer (full_name);
  654. }
  655. }
  656. bool
  657. tm_data_rep::project_attached () {
  658. tm_buffer buf= get_buffer ();
  659. return buf->project != "";
  660. }
  661. object
  662. tm_data_rep::get_project_buffer_menu () {
  663. tm_buffer buf= get_buffer ();
  664. if (buf->prj == NULL) return eval ("(menu-dynamic)");
  665. string s ("(menu-dynamic ");
  666. s << "(" << scm_quote (buf->prj->abbr) << " ";
  667. s << "(switch-to-buffer " * scm_quote (as_string (buf->prj->name)) * "))";
  668. tree t= subtree (the_et, buf->prj->rp);
  669. int i, j, n= N(t);
  670. for (i=0; i<n; i++)
  671. if (is_func (t[i], INCLUDE, 1) && is_atomic (t[i][0])) {
  672. string name= as_string (head (buf->prj->name) * as_string (t[i][0]));
  673. for (j=N(name)-1; j>=0; j--)
  674. if (name[j]=='/') break;
  675. s << " ((verbatim " << scm_quote (name (j+1, N(name))) << ") ";
  676. s << "(switch-to-buffer " * scm_quote (name) * "))";
  677. }
  678. s << ")";
  679. return eval (s);
  680. }
  681. /******************************************************************************
  682. * Management of all edit trees
  683. ******************************************************************************/
  684. tree the_et;
  685. path
  686. new_document () {
  687. int i, n= N(the_et);
  688. for (i=0; i<n; i++)
  689. if (the_et[i] == UNINIT) {
  690. assign (the_et[i], tree (DOCUMENT, ""));
  691. return path (i); // obtain_ip (the_et[i]);
  692. }
  693. insert (the_et, n, tuple (tree (DOCUMENT, "")));
  694. return path (n); // obtain_ip (the_et[n]);
  695. }
  696. void
  697. delete_document (path rp) {
  698. assign (subtree (the_et, rp), UNINIT);
  699. clean_observers (subtree (the_et, rp));
  700. }
  701. void
  702. set_document (path rp, tree t) {
  703. //assign (subtree (the_et, rp), t);
  704. assign (subtree (the_et, rp), copy (t));
  705. }
  706. /******************************************************************************
  707. * Window management
  708. ******************************************************************************/
  709. static int last_window= 1;
  710. static path the_windows;
  711. int
  712. create_window_id () {
  713. the_windows= path (last_window, the_windows);
  714. return last_window++;
  715. }
  716. static path
  717. reset (path p, int i) {
  718. if (is_nil (p)) return p;
  719. else if (p->item == i) return p->next;
  720. else return path (p->item, reset (p->next, i));
  721. }
  722. void
  723. destroy_window_id (int i) {
  724. the_windows= reset (the_windows, i);
  725. }
  726. int
  727. tm_data_rep::window_current () {
  728. tm_window win= get_window ();
  729. return win->id;
  730. }
  731. path
  732. tm_data_rep::windows_list () {
  733. return the_windows;
  734. }
  735. path
  736. tm_data_rep::buffer_to_windows (url name) {
  737. path p;
  738. int nr= find_buffer (name);
  739. if (nr == -1) return path ();
  740. tm_buffer buf= bufs[nr];
  741. for (int i=0; i<N(buf->vws); i++)
  742. if (buf->vws[i]->win != NULL)
  743. p= path (buf->vws[i]->win->id, p);
  744. return p;
  745. }
  746. url
  747. tm_data_rep::window_to_buffer (int id) {
  748. for (int i=0; i<N(bufs); i++)
  749. for (int j=0; j<N(bufs[i]->vws); j++)
  750. if (bufs[i]->vws[j]->win != NULL)
  751. if (bufs[i]->vws[j]->win->id == id)
  752. return bufs[i]->name;
  753. return url_none ();
  754. }
  755. tm_view
  756. tm_data_rep::window_find_view (int id) {
  757. for (int i=0; i<N(bufs); i++)
  758. for (int j=0; j<N(bufs[i]->vws); j++)
  759. if (bufs[i]->vws[j]->win != NULL)
  760. if (bufs[i]->vws[j]->win->id == id)
  761. return bufs[i]->vws[j];
  762. return NULL;
  763. }
  764. void
  765. tm_data_rep::window_set_buffer (int id, url name) {
  766. tm_view old_vw= window_find_view (id);
  767. if (old_vw == NULL || old_vw->buf->name == name) return;
  768. tm_window win= old_vw->win;
  769. int nr= find_buffer (name);
  770. if (nr == -1) return;
  771. tm_buffer buf = bufs[nr];
  772. tm_view new_vw= get_passive_view (buf);
  773. detach_view (old_vw);
  774. attach_view (win, new_vw);
  775. }
  776. void
  777. tm_data_rep::window_focus (int id) {
  778. if (id == window_current ()) return;
  779. tm_view vw= window_find_view (id);
  780. if (vw == NULL) return;
  781. set_view (vw);
  782. menu_focus_buffer (vw->buf);
  783. }
  784. /******************************************************************************
  785. * Check for changes in the buffer
  786. ******************************************************************************/
  787. bool
  788. tm_buffer_rep::needs_to_be_saved () {
  789. if (!in_menu) return false;
  790. for (int i=0; i<N(vws); i++)
  791. if (vws[i]->ed->need_save ())
  792. return true;
  793. return false;
  794. }
  795. bool
  796. tm_buffer_rep::needs_to_be_autosaved () {
  797. if (!in_menu) return false;
  798. for (int i=0; i<N(vws); i++)
  799. if (vws[i]->ed->need_save (false))
  800. return true;
  801. return false;
  802. }