Back to index

texmacs  1.0.7.15
tree_select.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : tree_select.cpp
00004 * DESCRIPTION: abstract cursor handling
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 "tree_select.hpp"
00013 #include "drd_std.hpp"
00014 #include "analyze.hpp"
00015 
00016 /******************************************************************************
00017 * Structural correction of the selection
00018 ******************************************************************************/
00019 
00020 static void
00021 selection_adjust_border (tree t, path i1, path i2, path& o1, path& o2)
00022 {
00023   o1= i1; o2= i2;
00024   if (is_compound (t) && !is_atom (i1) && !is_atom (i2) &&
00025       i1->item == i2->item) {
00026     path O1, O2;
00027     selection_adjust_border (t[i1->item], i1->next, i2->next, O1, O2);
00028     if (the_drd->var_without_border (L(t[i1->item])) &&
00029         (O1->item != O2->item)) {
00030       o1= path (0);
00031       o2= path (1);
00032     }
00033     else {
00034       o1= path (i1->item, O1);
00035       o2= path (i1->item, O2);
00036     }
00037   }
00038 }
00039 
00040 static void
00041 adjust_right_script (tree t, path& o1) {
00042   while (is_concat (t) && o1->item > 0 && o1->next == path (0)) {
00043     tree st= t[o1->item];
00044     if (is_func (st, RSUB) || is_func (st, RSUP) || is_func (st, RPRIME)) {
00045       tree pt= t[o1->item-1];
00046       if (!is_atomic (pt))
00047         o1= path (o1->item-1, start (pt));
00048       else {
00049         string s= pt->label;
00050         int pos= N(s);
00051         while (pos > 0) {
00052           int prev= pos;
00053           tm_char_backwards (s, prev);
00054           if (pos == N(s));
00055           else if (is_numeric (s (prev, N(s))));
00056           else if (is_iso_alpha (s (prev, N(s))));
00057           else break;
00058           pos= prev;
00059         }
00060         o1= path (o1->item-1, pos);
00061       }
00062     }
00063     else break;
00064   }
00065 }
00066 
00067 static void
00068 adjust_left_script (tree t, path& o2) {
00069   while (is_concat (t) && o2->item + 1 < N(t) && o2->next == path (1)) {
00070     tree st= t[o2->item];
00071     if (is_func (st, LSUB) || is_func (st, LSUP) || is_func (st, LPRIME)) {
00072       tree nt= t[o2->item+1];
00073       if (!is_atomic (nt)) o2= path (o2->item+1, end (nt));
00074       else {
00075         string s= nt->label;
00076         int pos= 0;
00077         while (pos < N(s)) {
00078           int next= pos;
00079           tm_char_forwards (s, next);
00080           if (pos == 0);
00081           else if (is_numeric (s (0, next)));
00082           else if (is_iso_alpha (s (0, next)));
00083           else break;
00084           pos= next;
00085         }
00086         o2= path (o2->item+1, pos);
00087       }
00088     }
00089     else break;
00090   }
00091 }
00092 
00093 static void
00094 selection_adjust (tree t, path i1, path i2, path& o1, path& o2) {
00095   //cout << "Adjust " << i1 << " -- " << i2 << " in " << t << "\n";
00096   if (i1 == i2) {
00097     o1= i1;
00098     o2= i2;
00099   }
00100   else if (is_atom (i1) || is_atom (i2)) {
00101     if (is_atomic (t)) {
00102       o1= i1;
00103       o2= i2;
00104     }
00105     else {
00106       o1= start (t);
00107       o2= end (t);
00108     }
00109   }
00110   else if (i1->item == i2->item) {
00111     selection_adjust (t[i1->item], i1->next, i2->next, o1, o2);
00112     o1= path (i1->item, o1);
00113     o2= path (i2->item, o2);
00114     adjust_right_script (t, o1);
00115     adjust_left_script (t, o2);
00116   }
00117   else {
00118     tree_label l= L(t);
00119     if ((l==DOCUMENT) || (l==PARA) || (l==CONCAT)) {
00120       if (is_compound (t[i1->item])) {
00121         path mid;
00122         selection_adjust (t[i1->item], i1->next, end (t[i1->item]), o1, mid);
00123         o1= path (i1->item, o1);
00124       }
00125       else o1= i1;
00126       if (is_compound (t[i2->item])) {
00127         path mid;
00128         selection_adjust (t[i2->item], start(t[i2->item]), i2->next, mid, o2);
00129         o2= path (i2->item, o2);
00130       }
00131       else o2= i2;
00132       if (l == CONCAT) {
00133         adjust_right_script (t, o1);
00134         adjust_left_script (t, o2);
00135       }
00136     }
00137     else {
00138       o1= start (t);
00139       o2= end (t);
00140     }
00141   }
00142   //cout << "Adjusted " << o1 << " -- " << o2 << " in " << t << "\n";
00143 }
00144 
00145 static void
00146 selection_make_accessible (tree t, path i1, path i2, path& o1, path& o2) {
00147   o1= i1; o2= i2;
00148   if (!is_accessible_cursor (t, o1))
00149     o1= previous_accessible (t, o1);
00150   if (!is_accessible_cursor (t, o1))
00151     o1= next_accessible (t, o1);
00152   if (!is_accessible_cursor (t, o2))
00153     o2= next_accessible (t, o2);
00154   if (!is_accessible_cursor (t, o2))
00155     o2= previous_accessible (t, o2);
00156   if (path_inf (o1, o2))
00157     o1= shift (t, o1, 1);
00158 }
00159 
00160 void
00161 selection_correct (tree t, path i1, path i2, path& o1, path& o2) {
00162   o1= i1; o2= i2;
00163   while (true) {
00164     i1= o1; i2= o2;
00165     selection_adjust_border (t, i1, i2, o1, o2);
00166     i1= o1; i2= o2;
00167     selection_adjust (t, i1, i2, o1, o2);
00168     i1= o1; i2= o2;
00169     selection_make_accessible (t, i1, i2, o1, o2);
00170     if (o1 == i1 && o2 == i2) break;
00171   }
00172 }
00173 
00174 /******************************************************************************
00175 * Computation of the selected tree
00176 ******************************************************************************/
00177 
00178 tree
00179 selection_compute (tree t, path start, path end) {
00180   int  i1= start->item;
00181   int  i2= end->item;
00182   path p1= start->next;
00183   path p2= end->next;
00184 
00185   if (is_nil (p1) || is_nil (p2)) {
00186     if (start == path (right_index (t))) return "";
00187     if (end == path (0)) return "";
00188     if (start == end) return "";
00189     if (is_nil (p1) && is_nil (p2)) {
00190       if (is_compound (t)) return copy (t);
00191       if (i1>=i2) return "";
00192       return t->label (i1, i2);
00193     }
00194     if (is_compound (t) && (!is_format (t))) return copy (t);
00195     if (is_nil (p1)) {
00196       i1= 0;
00197       p1= (start->item==0? 0: right_index (t[i1]));
00198     }
00199     if (is_nil (p2)) {
00200       i2= N(t)-1;
00201       p2= (end->item==0? 0: right_index (t[i2]));
00202     }
00203   }
00204 
00205   if (i1==i2) return selection_compute (t[i1], p1, p2);
00206   if (is_compound (t) && (!is_format (t))) return copy (t);
00207 
00208   int i;
00209   tree r (t, i2-i1+1);
00210   r[0]     = selection_compute (t[i1], p1, path (right_index (t[i1])));
00211   r[N(r)-1]= selection_compute (t[i2], path (0), p2);
00212   for (i=1; i<N(r)-1; i++) r[i]= copy (t[i+i1]);
00213   return r;
00214 }