Back to index

texmacs  1.0.7.15
new_buffer.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : new_buffer.cpp
00004 * DESCRIPTION: Buffer management
00005 * COPYRIGHT  : (C) 1999-2012  Joris van der Hoeven
00006 *******************************************************************************
00007 * This software falls under the GNU general public license version 3 or later.
00008 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
00009 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
00010 ******************************************************************************/
00011 
00012 #include "tm_data.hpp"
00013 #include "convert.hpp"
00014 #include "file.hpp"
00015 #include "web_files.hpp"
00016 #include "tm_link.hpp"
00017 #include "message.hpp"
00018 #include "dictionary.hpp"
00019 #include "new_document.hpp"
00020 
00021 array<tm_buffer> bufs;
00022 
00023 /******************************************************************************
00024 * Check for changes in the buffer
00025 ******************************************************************************/
00026 
00027 bool
00028 tm_buffer_rep::needs_to_be_saved () {
00029   if (!buf->in_menu) return false;
00030   for (int i=0; i<N(vws); i++)
00031     if (vws[i]->ed->need_save ())
00032       return true;
00033   return false;
00034 }
00035 
00036 bool
00037 tm_buffer_rep::needs_to_be_autosaved () {
00038   if (!buf->in_menu) return false;
00039   for (int i=0; i<N(vws); i++)
00040     if (vws[i]->ed->need_save (false))
00041       return true;
00042   return false;
00043 }
00044 
00045 /******************************************************************************
00046 * Finding buffers
00047 ******************************************************************************/
00048 
00049 url
00050 get_all_buffers () {
00051   url u= url_none ();
00052   for (int i=N(bufs)-1; i>=0; i--)
00053     u= bufs[i]->buf->name | u;
00054   return u;
00055 }
00056 
00057 int
00058 nr_bufs () {
00059   return N(bufs);
00060 }
00061 
00062 bool
00063 no_bufs () {
00064   return N(bufs) == 0;
00065 }
00066 
00067 int
00068 find_buffer (tm_buffer buf) {
00069   int i;
00070   for (i=0; i<N(bufs); i++)
00071     if (bufs[i] == buf)
00072       return i;
00073   return -1;
00074 }
00075 
00076 int
00077 find_buffer (path p) {
00078   int i;
00079   for (i=0; i<N(bufs); i++)
00080     if (bufs[i]->rp <= p)
00081       return i;
00082   return -1;
00083 }
00084 
00085 int
00086 find_buffer (url name) {
00087   int i;
00088   for (i=0; i<N(bufs); i++)
00089     if (bufs[i]->buf->name == name)
00090       return i;
00091   return -1;
00092 }
00093 
00094 /******************************************************************************
00095 * Information attached to buffers
00096 ******************************************************************************/
00097 
00098 string
00099 new_menu_name (url u) {
00100   string name= as_string (tail (u));
00101   if (starts (name, "no_name_") && ends (name, ".tm")) {
00102     string no_name= translate ("No name");
00103     for (int i=0; i<N(no_name); i++)
00104       if (((unsigned char) (no_name[i])) >= (unsigned char) 128)
00105        { no_name= "No name"; break; }
00106     name= no_name * " [" * name (8, N(name) - 3) * "]";
00107   }
00108   if ((name == "") || (name == "."))
00109     name= as_string (tail (u * url_parent ()));
00110   if ((name == "") || (name == "."))
00111     name= as_string (u);
00112   if (is_rooted_tmfs (u))
00113     name= as_string (call ("tmfs-name", as_string (u)));
00114 
00115   int i, j;
00116   for (j=1; true; j++) {
00117     bool flag= true;
00118     string ret (name);
00119     if (j>1) ret= name * " (" * as_string (j) * ")";
00120     for (i=0; i<N(bufs); i++)
00121       if (bufs[i]->buf->abbr == ret) flag= false;
00122     if (flag) return ret;
00123   }
00124 }
00125 
00126 url
00127 get_this_buffer () {
00128   tm_buffer buf= get_buffer ();
00129   return buf->buf->name;
00130 }
00131 
00132 url
00133 get_name_buffer () {
00134   tm_buffer buf= get_buffer ();
00135   if (!is_none (buf->buf->extra)) return buf->buf->extra;
00136   return buf->buf->name;
00137 }
00138 
00139 url
00140 get_name_buffer (path p) {
00141   int nr= find_buffer (p);
00142   if (nr == -1) return url_none ();
00143   return bufs[nr]->buf->name;
00144 }
00145 
00146 void
00147 set_name_buffer (url name) {
00148   tm_buffer buf= get_buffer ();
00149   if (buf->buf->name == name) return;
00150   buf->buf->name= name;
00151   set_abbr_buffer (name, new_menu_name (name));
00152 }
00153 
00154 string
00155 get_abbr_buffer (url name) {
00156   int nr= find_buffer (name);
00157   if (nr == -1) return "";
00158   else return bufs[nr]->buf->abbr;
00159 }
00160 
00161 void
00162 set_abbr_buffer (url name, string abbr) {
00163   int nr= find_buffer (name);
00164   if (nr == -1) return;
00165   tm_buffer buf= bufs[nr];
00166   if (buf->buf->abbr == abbr) return;
00167   buf->buf->abbr= abbr;
00168   for (int i=0; i<N(buf->vws); i++) {
00169     tm_view vw2= buf->vws[i];
00170     if (vw2->win != NULL) {
00171       vw2->win->set_window_name (buf->buf->abbr);
00172       vw2->win->set_window_url (is_none (buf->buf->extra)?
00173                                 buf->buf->name: buf->buf->extra);
00174     }
00175   }
00176 }
00177 
00178 bool
00179 buffer_in_menu (url name) {
00180   int nr= find_buffer (name);
00181   if (nr == -1) return false;
00182   else return bufs[nr]->buf->in_menu;
00183 }
00184 
00185 bool
00186 is_aux_buffer (url name) {
00187   int nr= find_buffer (name);
00188   if (nr == -1) return false;
00189   else return !is_none (bufs[nr]->buf->extra);
00190 }
00191 
00192 double
00193 last_visited (url name) {
00194   int nr= find_buffer (name);
00195   if (nr == -1) return (double) texmacs_time ();
00196   else return (double) bufs[nr]->buf->last_visit;
00197 }
00198 
00199 bool
00200 buffer_modified (url name) {
00201   int nr= find_buffer (name);
00202   if (nr == -1) return false;
00203   return bufs[nr]->needs_to_be_saved ();
00204 }
00205 
00206 void
00207 set_buffer_tree (url name, tree doc) {
00208   int nr= find_buffer (name);
00209   if (nr == -1) create_buffer (name, tree (DOCUMENT, ""));
00210   nr= find_buffer (name);
00211   tm_buffer buf= bufs[nr];
00212   assign (buf->rp, doc);
00213 }
00214 
00215 tree
00216 get_buffer_tree (url name) {
00217   int nr= find_buffer (name);
00218   if (nr == -1) return "";
00219   tm_buffer buf= bufs[nr];
00220   return subtree (the_et, buf->rp);
00221 }
00222 
00223 /******************************************************************************
00224 * Creating and destroying buffers
00225 ******************************************************************************/
00226 
00227 tm_buffer
00228 create_buffer (url name) {
00229   int nr= find_buffer (name);
00230   if (nr != -1) return bufs[nr];
00231   tm_buffer buf= tm_new<tm_buffer_rep> (name);
00232   buf->buf->abbr= new_menu_name (name);
00233   bufs << buf;
00234   return buf;
00235 }
00236 
00237 tm_buffer
00238 create_buffer (url name, tree doc) {
00239   int nr= find_buffer (name);
00240   if (nr != -1) return bufs[nr];
00241   tm_buffer buf= create_buffer (name);
00242   tree body= detach_data (doc, buf->data);
00243   set_document (buf->rp, body);
00244   if (buf->data->project != "") {
00245     url prj_name= head (name) * as_string (buf->data->project);
00246     buf->prj= load_passive_buffer (prj_name);
00247   }
00248   return buf;
00249 }
00250 
00251 url
00252 create_buffer () {
00253   int i=1;
00254   while (true) {
00255     url name= url_scratch ("no_name_", ".tm", i);
00256     int nr= find_buffer (name);
00257     if (nr == -1) {
00258       new_buffer_in_this_window (name, tree (DOCUMENT));
00259       return name;
00260     }
00261     else i++;
00262   }
00263 }
00264 
00265 void
00266 revert_buffer (url name, tree doc) {
00267   int i, nr= find_buffer (name);
00268   if (nr == -1) return;
00269   tm_buffer buf= bufs[nr];
00270   tree body= detach_data (doc, buf->data);
00271   if (N(buf->vws)==0) set_document (buf->rp, body);
00272   else for (i=0; i<N(buf->vws); i++) {
00273     tm_view vw= buf->vws[i];
00274     if (i==0) assign (vw->ed->rp, body);
00275     vw->ed->set_data (buf->data);
00276     vw->ed->notify_save ();
00277   }
00278 }
00279 
00280 void
00281 revert_buffer () {
00282   tm_buffer buf= get_buffer ();
00283   web_cache_invalidate (buf->buf->name);
00284   tree doc= load_tree (buf->buf->name, buf->buf->fm);
00285   if (doc == "error") set_message ("Error: file not found", "revert buffer");
00286   else revert_buffer (buf->buf->name, doc);
00287 }
00288 
00289 void
00290 delete_buffer (tm_buffer buf) {
00291   int nr= find_buffer (buf), n= N(bufs);
00292   if (nr >= 0) {
00293     for (int i=nr; i<(n-1); i++) bufs[i]= bufs[i+1];
00294     bufs->resize (n-1);
00295   }
00296   for (int i=0; i<N(buf->vws); i++)
00297     delete_view (buf->vws[i]);
00298   tm_delete (buf);
00299 }
00300 
00301 void
00302 kill_buffer () {
00303   int i, nr;
00304   if (N(bufs) <= 1) get_server () -> quit();
00305   tm_buffer buf= get_buffer();
00306   for (nr=0; nr<N(bufs); nr++) if (buf == bufs[nr]) break;
00307   ASSERT (nr != N(bufs), "buffer not found");
00308   for (nr=0; nr<N(bufs); nr++) if (buf != bufs[nr]) break;
00309   ASSERT (nr != N(bufs), "no suitable new buffer");
00310   tm_buffer new_buf = bufs[nr];
00311 
00312   for (i=0; i<N(buf->vws); i++) {
00313     tm_view old_vw= buf->vws[i];
00314     if (old_vw->win != NULL) {
00315       tm_window win = old_vw->win;
00316       tm_view new_vw= get_passive_view (new_buf);
00317       detach_view (old_vw);
00318       attach_view (win, new_vw);
00319       if (get_view () == old_vw) set_view (new_vw);
00320     }
00321   }
00322   delete_buffer (buf);
00323 }
00324 
00325 /******************************************************************************
00326 * Switching to another buffer
00327 ******************************************************************************/
00328 
00329 void
00330 switch_to_buffer (int nr) {
00331   // cout << "Switching to buffer " << nr << "\n";
00332   tm_window win    = get_window ();
00333   tm_buffer buf    = bufs[nr];
00334   tm_view   old_vw = get_view ();
00335   tm_view   new_vw = get_passive_view (buf);
00336   detach_view (old_vw);
00337   attach_view (win, new_vw);
00338   set_view (new_vw);
00339   buf->buf->last_visit= texmacs_time ();
00340   tm_window nwin= new_vw->win;
00341   nwin->set_shrinking_factor (nwin->get_shrinking_factor ());
00342   // cout << "Switched to buffer " << nr << "\n";
00343 }
00344 
00345 bool
00346 switch_to_buffer (path p) {
00347   int nr= find_buffer (p);
00348   if (nr != -1) switch_to_buffer (nr);
00349   return nr != -1;
00350 }
00351 
00352 void
00353 switch_to_buffer (url name) {
00354   int nr= find_buffer (name);
00355   if (nr == -1) {
00356     load_passive_buffer (name);
00357     nr= find_buffer (name);
00358   }
00359   if (nr != -1) switch_to_buffer (nr);
00360 }
00361 
00362 void
00363 switch_to_active_buffer (url name) {
00364   // This function is a temporary hack for coq
00365   // Switching to buffers in other windows should be completely rewritten
00366 
00367   int nr= find_buffer (name);
00368   if (nr == -1) {
00369     load_passive_buffer (name);
00370     nr= find_buffer (name);
00371   }
00372   if (nr != -1) {
00373     int i;
00374     tm_buffer buf= bufs[nr];
00375     for (i=0; i<N(buf->vws); i++) // search active view
00376       if (buf->vws[i]->win != NULL) {
00377         tm_view vw= buf->vws[i];
00378         set_view (vw);
00379         buf->buf->last_visit= texmacs_time ();
00380         return;
00381       }
00382   }
00383   switch_to_buffer (name);
00384 }
00385 
00386 /******************************************************************************
00387 * Auxiliary buffers and help buffers
00388 ******************************************************************************/
00389 
00390 void
00391 set_aux (string aux, url name) {
00392   int i, nr= find_buffer (aux);
00393   if (nr != -1) {
00394     tm_buffer buf= bufs[nr];
00395     buf->buf->extra= name;
00396     if (starts (aux, "Help - ")) {
00397       buf->buf->fm= "help";
00398       buf->buf->read_only= true;
00399     }
00400     for (i=0; i<N(buf->vws); i++) {
00401       tm_view vw= buf->vws[i];
00402       vw->ed->set_base_name (name);
00403     }
00404   }
00405 }
00406 
00407 void
00408 set_aux_buffer (string aux, url name, tree doc) {
00409   int nr= find_buffer (aux);
00410   if (nr == -1) create_buffer (aux, doc);
00411   else revert_buffer (aux, doc);
00412   nr= find_buffer (aux);
00413   if (nr != -1) {
00414     set_aux (aux, name);
00415     switch_to_buffer (nr);
00416   }
00417 }
00418 
00419 static string
00420 get_doc_title (tree t) {
00421   if (is_atomic (t)) return "";
00422   if (is_compound (t, "doc-title") ||
00423       is_compound (t, "tmdoc-title") ||
00424       is_compound (t, "tmdoc-title*") ||
00425       is_compound (t, "tmweb-title"))
00426     return tree_to_verbatim (t[0]);
00427   else {
00428     for (int i=0; i<N(t); i++) {
00429       string r= get_doc_title (t[i]);
00430       if (r != "") return r;
00431     }
00432     return "";
00433   }
00434 }
00435 
00436 string
00437 get_help_title (url name, tree t) {
00438   string s= get_doc_title (t);
00439   if (s == "") return "Help - " * as_string (tail (name));
00440   else return "Help - " * s;
00441 }
00442 
00443 void
00444 set_help_buffer (url name, tree doc) {
00445   set_aux_buffer (get_help_title (name, doc), name, doc);
00446 }