Back to index

texmacs  1.0.7.15
edit_delete.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : edit_delete.cpp
00004 * DESCRIPTION: treat deletions
00005 * COPYRIGHT  : (C) 1999  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 "edit_text.hpp"
00013 #include "tree_traverse.hpp"
00014 #include "analyze.hpp"
00015 
00016 bool is_empty_cell (tree t);
00017 
00018 /******************************************************************************
00019 * Getting the point where to delete
00020 ******************************************************************************/
00021 
00022 void
00023 edit_text_rep::get_deletion_point (
00024   path& p, int& last, int& rix, tree& t, tree& u, bool forward)
00025 {
00026   // make right-glued positions left-glued
00027   p= tp;
00028   if (forward) {
00029     //cout << HRULE;
00030     if ((rp < p) && (N (p / rp) >= 2) &&
00031        is_concat (subtree (et, path_up (p, 2))) &&
00032        (last_item (p) == right_index (subtree (et, path_up (p)))) &&
00033        (last_item (path_up (p)) < (N (subtree (et, path_up (p, 2))) - 1)))
00034       {
00035        p= path_up (p);
00036        p= path_inc (p) * start (subtree (et, path_inc (p)), path ());
00037       }
00038     //cout << "p= " << p << "\n";
00039   }
00040 
00041   // get the position where to delete
00042   last= last_item (p);
00043   p   = path_up (p);
00044   t   = subtree (et, p);
00045   rix = right_index (t);
00046   //cout << "  t   = " << t << "\n";
00047   //cout << "  last= " << last << "\n";
00048   //cout << "  rix = " << rix << "\n";
00049   while (((forward && (last >= rix)) || ((!forward) && (last == 0))) &&
00050         (rp < p) && is_format (subtree (et, path_up (p))))
00051     {
00052       last= last_item (p);
00053       p   = path_up (p);
00054       t   = subtree (et, p);
00055       rix = N(t) - 1;
00056       //cout << "  t   = " << t << "\n";
00057       //cout << "  last= " << last << "\n";
00058       //cout << "  rix = " << rix << "\n";
00059     }
00060   if (rp < p) u= subtree (et, path_up (p));
00061 }
00062 
00063 /******************************************************************************
00064 * Normal deletions
00065 ******************************************************************************/
00066 
00067 static bool
00068 is_multi_paragraph_or_sectional (tree t) {
00069   if (is_atomic (t)) return false;
00070   if (is_multi_paragraph (t)) return true;
00071   eval ("(use-modules (utils library tree) (text std-text-drd))");
00072   return as_bool (call ("tree-in?", t, call ("section-tag-list")));
00073 }
00074 
00075 void
00076 edit_text_rep::remove_text (bool forward) {
00077   path p;
00078   int  last, rix;
00079   tree t, u;
00080   get_deletion_point (p, last, rix, t, u, forward);
00081 
00082   // multiparagraph delete
00083   if (is_document (t)) {
00084     if ((forward && (last >= rix)) || ((!forward) && (last == 0))) {
00085       if (rp < p) {
00086        tree u= subtree (et, path_up (p));
00087        if (is_func (u, _FLOAT) || is_func (u, WITH) ||
00088            is_func (u, STYLE_WITH) || is_func (u, VAR_STYLE_WITH) ||
00089            is_func (u, LOCUS) ||
00090            is_extension (u))
00091          {
00092            if (is_extension (u) && (N(u) > 1)) {
00093              int i, n= N(u);
00094              bool empty= true;
00095              for (i=0; i<n; i++)
00096               empty= empty && ((u[i]=="") || (u[i]==tree (DOCUMENT, "")));
00097              if (!empty) {
00098               if (forward) go_to (next_valid (et, tp));
00099               else go_to (previous_valid (et, tp));
00100               return;
00101              }
00102            }
00103            if (t == tree (DOCUMENT, "")) {
00104              if (is_func (u, _FLOAT) || is_compound (u, "footnote", 1)) {
00105               assign (path_up (p), "");
00106               correct (path_up (p, 2));
00107              }
00108              else if (is_document (subtree (et, path_up (p, 2))))
00109               assign (path_up (p), "");
00110              else assign (path_up (p), tree (DOCUMENT, ""));
00111            }
00112            else go_to_border (path_up (p), !forward);
00113          }
00114        else if (is_func (u, TABLE) || is_func (u, SUBTABLE) ||
00115                is_func (u, CELL) || is_func (u, ROW) ||
00116                is_func (u, TFORMAT)) {
00117          if (t == tree (DOCUMENT, ""))
00118            back_in_table (u, p, forward);
00119        } 
00120       }
00121       return;
00122     }
00123     else {
00124       int l1= forward? last: last-1;
00125       int l2= forward? last+1: last;
00126       if (is_multi_paragraph_or_sectional (subtree (et, p * l1)) ||
00127          is_multi_paragraph_or_sectional (subtree (et, p * l2)))
00128        {
00129          if (subtree (et, p * l1) == "") remove (p * l1, 1);
00130          else {
00131            if (subtree (et, p * l2) == "") remove (p * l2, 1);
00132            if (!forward) go_to_end (p * l1);
00133            else if (last < N (subtree (et, p)) - 1) go_to_start (p * l2);
00134          }
00135        }
00136       else remove_return (p * l1);
00137     }
00138     return;
00139   }
00140 
00141   // deleting text
00142   if (forward && is_atomic (t) && (last != rix)) {
00143     language lan= get_env_language ();
00144     int end= last;
00145     tm_char_forwards (t->label, end);
00146     remove (p * last, end-last);
00147     correct (path_up (p));
00148     return;
00149   }
00150 
00151   if ((!forward) && is_atomic (t) && (last != 0)) {
00152     language lan= get_env_language ();
00153     int start= last;
00154     tm_char_backwards (t->label, start);
00155     remove (p * start, last-start);
00156     correct (path_up (p));
00157     return;
00158   }
00159 
00160   // deletion governed by parent t
00161   if (last == (forward? 0: 1))
00162     switch (L(t)) {
00163     case RAW_DATA:
00164     case HSPACE:
00165     case VAR_VSPACE:
00166     case VSPACE:
00167     case SPACE:
00168     case HTAB:
00169       back_monolithic (p);
00170       return;
00171     case AROUND:
00172     case VAR_AROUND:
00173     case BIG_AROUND:
00174       back_around (t, p, forward);
00175       return;
00176     case LEFT:
00177     case MID:
00178     case RIGHT:
00179     case BIG:
00180       back_monolithic (p);
00181       return;
00182     case LPRIME:
00183     case RPRIME:
00184       back_prime (t, p, forward);
00185       return;
00186     case WIDE:
00187     case VAR_WIDE:
00188       go_to_border (p * 0, forward);
00189       return;
00190     case TFORMAT:
00191     case TABLE:
00192     case ROW:
00193     case CELL:
00194     case SUBTABLE:
00195       back_table (p, forward);
00196       return;
00197     case WITH:
00198     case STYLE_WITH:
00199     case VAR_STYLE_WITH:
00200     case LOCUS:
00201       go_to_border (p * (N(t) - 1), forward);
00202       return;
00203     case VALUE:
00204     case QUOTE_VALUE:
00205     case ARG:
00206     case QUOTE_ARG:
00207       if (N(t) == 1) back_monolithic (p);
00208       else back_general (p, forward);
00209       return;
00210     default:
00211       if (is_compound (t, "separating-space", 1)) back_monolithic (p);
00212       else back_general (p, forward);
00213       break;
00214     }
00215 
00216   // deletion depends on children u
00217   if (last == (forward? rix: 0)) {
00218     switch (L (u)) {
00219     case AROUND:
00220     case VAR_AROUND:
00221     case BIG_AROUND:
00222       back_in_around (u, p, forward);
00223       return;
00224     case LONG_ARROW:
00225       back_in_long_arrow (u, p, forward);
00226       return;
00227     case WIDE:
00228     case VAR_WIDE:
00229       back_in_wide (u, p, forward);
00230       return;
00231     case TREE:
00232       back_in_tree (u, p, forward);
00233       return;
00234     case TFORMAT:
00235     case TABLE:
00236     case ROW:
00237     case CELL:
00238     case SUBTABLE:
00239       back_in_table (u, p, forward);
00240       return;
00241     case WITH:
00242     case STYLE_WITH:
00243     case VAR_STYLE_WITH:
00244     case LOCUS:
00245       back_in_with (u, p, forward);
00246       return;
00247     default:
00248       if (is_graphical_text (u))
00249         back_in_text_at (u, p, forward);
00250       else if (is_compound (u, "cell-inert") ||
00251                is_compound (u, "cell-input") ||
00252                is_compound (u, "cell-output")) {
00253         tree st= subtree (et, path_up (p, 2));
00254         back_in_table (u, p, forward);
00255       }
00256       else
00257         back_in_general (u, p, forward);
00258       break;
00259     }
00260   }
00261 }
00262 
00263 /******************************************************************************
00264 * Structured deletions
00265 ******************************************************************************/
00266 
00267 void
00268 edit_text_rep::remove_structure (bool forward) {
00269   path p;
00270   int  last, rix;
00271   tree t, u;
00272   get_deletion_point (p, last, rix, t, u, forward);
00273 
00274   // multiparagraph delete
00275   if (!(rp < p)) {
00276     if (forward) {
00277       if (last >= rix) return;
00278       remove_return (path (last));
00279     }
00280     else {
00281       if (last == 0) return;
00282       remove_return (path (last-1));
00283     }
00284     return;
00285   }
00286 
00287   // deleting text
00288   if (is_atomic (t) && (last != (forward? rix: 0))) {
00289     language lan= get_env_language ();
00290     int start= last, end= last, pos;
00291     string s= t->label;
00292     while (true) {
00293       if (forward) {
00294        pos= start;
00295        (void) lan->advance (t, pos);
00296        if (pos <= last) break;
00297       }
00298       else {
00299        int pos= max (start-1, 0);
00300        (void) lan->advance (t, pos);
00301        if (pos < last) break;
00302       }
00303       end= pos;
00304       if (start == 0) break;
00305       start--;
00306     }
00307     if (forward) {
00308       start= min (start+1, last);
00309       while ((end < N(s)) && (s[end] == ' ')) end++;
00310     }
00311     else while ((start>0) && (s[start-1] == ' ')) start--;
00312     if (end>start) {
00313       remove (p * start, end-start);
00314       correct (path_up (p));
00315     }
00316     return;
00317   }
00318 
00319   // deleting structure
00320   if (forward) {
00321     if (is_concat (t) && (last < rix)) {
00322       remove (p * (last+1), 1);
00323       correct (path_up (p));
00324     }
00325     else if (is_compound (t) && (last == 0)) {
00326       assign (p, "");
00327       correct (path_up (p));
00328     }
00329     else remove_structure_upwards ();
00330   }
00331   else {
00332     if (last==1) {
00333       if (!is_concat (u)) assign (p, "");
00334       else remove (p, 1);
00335       correct (path_up (p));
00336     }
00337     else remove_structure_upwards ();
00338   }
00339 }
00340 
00341 /******************************************************************************
00342 * Deletion of an object
00343 ******************************************************************************/
00344 
00345 void
00346 edit_text_rep::remove_structure_upwards () {
00347   path p= path_up (tp);
00348   while ((rp < p) && is_format (subtree (et, path_up (p)))) p= path_up (p);
00349   if (!(rp < p)) return;
00350   int last= last_item (p);
00351   p= path_up (p);
00352   tree st= subtree (et, p);
00353   if (is_func (st, AROUND, 3) ||
00354       is_func (st, VAR_AROUND, 3) ||
00355       is_func (st, BIG_AROUND, 2))
00356     pre_remove_around (p);
00357   bool recurse=
00358     is_func (st, TFORMAT) || is_func (st, TABLE) ||
00359     is_func (st, ROW) || is_func (st, CELL) ||
00360     is_compound (st, "shown") ||
00361     drd->var_without_border (L(st));
00362   remove (p * (last+1), N(st)-(last+1));
00363   remove (p * 0, last);
00364 
00365   do {
00366     remove_node (p * 0);
00367     last= last_item (p);
00368     p= path_up (p);
00369     st= subtree (et, p);
00370   } while (is_mod_active_once (st));
00371 
00372   if (is_document (st) && is_document (st[last])) {
00373     int very_last= 0;
00374     if ((N(tp) >= N(p)+2) && (tp[N(p)] == last)) very_last= tp[N(p)+1];
00375     tree left = st[last] (0, very_last);
00376     tree right= st[last] (very_last+1, N(st[last]));
00377     remove (p * path (last, very_last+1), N(st[last])- (very_last+1));
00378     remove (p * path (last, 0), very_last);
00379     remove_node (p * path (last, 0));
00380     insert (p * (last+1), right);
00381     insert (p * last, left);
00382   }
00383   else correct (p);
00384 
00385   if (recurse) remove_structure_upwards ();
00386 }