Back to index

texmacs  1.0.7.15
edit_math.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : edit_math.cpp
00004 * DESCRIPTION: modify mathematical structures
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_math.hpp"
00013 #include "analyze.hpp"
00014 
00015 /******************************************************************************
00016 * Constructors and destructors
00017 ******************************************************************************/
00018 
00019 edit_math_rep::edit_math_rep () {}
00020 edit_math_rep::~edit_math_rep () {}
00021 
00022 /******************************************************************************
00023 * Making mathematical objects
00024 ******************************************************************************/
00025 
00026 void
00027 edit_math_rep::make_rigid () {
00028   if (selection_active_small ())
00029     insert_tree (tree (RIGID, selection_get_cut ()));
00030   else {
00031     insert_tree (tree (RIGID, ""), path (0, 0));
00032     set_message ("move to the right when finished", "group");
00033   }
00034 }
00035 
00036 void
00037 edit_math_rep::make_lprime (string s) {
00038   tree& st= subtree (et, path_up (tp));
00039   if (is_func (st, LPRIME, 1) && (last_item (tp) == 1)) {
00040     if (is_atomic (st[0]))
00041       insert (path_up (tp) * path (0, N (st[0]->label)), s);
00042   }
00043   else insert_tree (tree (LPRIME, s));
00044 }
00045 
00046 void
00047 edit_math_rep::make_rprime (string s) {
00048   tree& st= subtree (et, path_up (tp));
00049   if (is_func (st, RPRIME, 1) && (last_item (tp) == 1)) {
00050     if (is_atomic (st[0]))
00051       insert (path_up (tp) * path (0, N (st[0]->label)), s);
00052   }
00053   else insert_tree (tree (RPRIME, s));
00054 }
00055 
00056 void
00057 edit_math_rep::make_below () {
00058   if (selection_active_small ()) {
00059     insert_tree (tree (BELOW, selection_get_cut (), ""), path (1, 0));
00060     set_message ("type script, move right", "under");
00061   }
00062   else {
00063     insert_tree (tree (BELOW, "", ""), path (0, 0));
00064     set_message ("type body, move down, type script", "under");
00065   }
00066 }
00067 
00068 void
00069 edit_math_rep::make_above () {
00070   if (selection_active_small ()) {
00071     insert_tree (tree (ABOVE, selection_get_cut (), ""), path (1, 0));
00072     set_message ("type script, move right", "above");
00073   }
00074   else {
00075     insert_tree (tree (ABOVE, "", ""), path (0, 0));
00076     set_message ("type body, move up, type script", "above");
00077   }
00078 }
00079 
00080 void
00081 edit_math_rep::make_script (bool sup, bool right) {
00082   tree_label s (sup? SUP (right): SUB (right));
00083   if (selection_active_small ())
00084     insert_tree (tree (s, selection_get_cut ()));
00085   else {
00086     path   p= path_up (tp);
00087     tree   t= subtree (et, p);
00088     bool   flag;
00089 
00090     if (is_format (p))
00091       FAILED ("bad cursor position");
00092     if (is_script (t, flag) && (flag==right) && (L(t)==s)) {
00093       go_to_end (p * 0);
00094       return;
00095     }
00096     insert_tree (tree (s, ""), path (0, 0));
00097     set_message ("move to the right when finished",
00098                (char*) (sup? (right? "superscript": "left superscript"):
00099                             (right? "subscript": "left subscript")));
00100   }
00101 }
00102 
00103 void
00104 edit_math_rep::make_fraction () {
00105   if (selection_active_small ()) {
00106     insert_tree (tree (FRAC, selection_get_cut (), ""), path (1, 0));
00107     set_message ("type denominator, move right", "fraction");
00108   }
00109   else {
00110     insert_tree (tree (FRAC, "", ""), path (0, 0));
00111     set_message ("type numerator, move down, type denominator", "fraction");
00112   }
00113 }
00114 
00115 void
00116 edit_math_rep::make_sqrt () {
00117   if (selection_active_small ())
00118     insert_tree (tree (SQRT, selection_get_cut ()));
00119   else {
00120     insert_tree (tree (SQRT, ""), path (0, 0));
00121     set_message ("move to the right when finished", "square root");
00122   }
00123 }
00124 
00125 void
00126 edit_math_rep::make_var_sqrt () {
00127   if (selection_active_small ()) {
00128     tree t= selection_get_cut ();
00129     if (is_func (t, SQRT, 1))
00130       insert_tree (tree (SQRT, t[0], ""), path (1, 0));
00131     else insert_tree (tree (SQRT, t, ""), path (1, 0));
00132   }
00133   else {
00134     insert_tree (tree (SQRT, "", ""), path (0, 0));
00135     set_message (concat (kbd ("left"), ": set n",
00136                       kbd ("right"), ": when finished"),
00137                "n-th root");
00138   }
00139 }
00140 
00141 void
00142 edit_math_rep::make_wide (string wide) {
00143   if (selection_active_small ())
00144     insert_tree (tree (WIDE, selection_get_cut (), wide));
00145   else {
00146     insert_tree (tree (WIDE, "", wide), path (0, 0));
00147     set_message ("move to the right when finished", "wide accent");
00148   }
00149 }
00150 
00151 void
00152 edit_math_rep::make_wide_under (string wide) {
00153   if (selection_active_small ())
00154     insert_tree (tree (VAR_WIDE, selection_get_cut (), wide));
00155   else {
00156     insert_tree (tree (VAR_WIDE, "", wide), path (0, 0));
00157     set_message ("move to the right when finished", "wide under accent");
00158   }
00159 }
00160 
00161 void
00162 edit_math_rep::make_neg () {
00163   if (selection_active_small ())
00164     insert_tree (tree (NEG, selection_get_cut ()));
00165   else {
00166     insert_tree (tree (NEG, ""), path (0, 0));
00167     set_message ("move to the right when finished", "negation");
00168   }
00169 }
00170 
00171 /******************************************************************************
00172 * Deleting mathematical objects
00173 ******************************************************************************/
00174 
00175 static bool
00176 is_deleted (tree t) {
00177   return t == "<nobracket>" || t == tree (LEFT, ".") || t == tree (RIGHT, ".");
00178 }
00179 
00180 void
00181 edit_math_rep::back_around (tree t, path p, bool forward) {
00182   bool match= (get_preference ("automatic brackets") != "off");
00183   if (is_func (t, BIG_AROUND)) {
00184     if (match || forward)
00185       go_to_border (p * 1, forward);
00186     else {
00187       remove_node (t, 1);
00188       correct (path_up (p));
00189     }
00190   }
00191   else {
00192     int i= (forward? 0: 2);
00193     if (is_deleted (t[i]));
00194     else if (is_atomic (t[i]))
00195       assign (t[i], "<nobracket>");
00196     else if (is_func (t[i], LEFT))
00197       assign (t[i], tree (LEFT, "."));
00198     else if (is_func (t[i], RIGHT))
00199       assign (t[i], tree (RIGHT, "."));
00200     go_to_border (p * 1, forward);
00201     if (is_deleted (t[0]) && is_deleted (t[2])) {
00202       remove_node (t, 1);
00203       correct (path_up (p));
00204     }
00205   }
00206   if (!match) call ("brackets-refresh");
00207 }
00208 
00209 void
00210 edit_math_rep::back_in_around (tree t, path p, bool forward) {
00211   bool match= (get_preference ("automatic brackets") != "off");
00212   if (is_empty (t[1]) && match) {
00213     assign (t, "");
00214     correct (path_up (p, 2));
00215   }
00216   else if (is_func (t, BIG_AROUND)) {
00217     if (match || forward)
00218       go_to_border (path_up (p), !forward);
00219     else {
00220       remove_node (t, 1);
00221       correct (path_up (p, 2));
00222     }
00223   }
00224   else {
00225     int i= (forward? 2: 0);
00226     if (is_deleted (t[i]));
00227     else if (is_atomic (t[i]))
00228       assign (t[i], "<nobracket>");
00229     else if (is_func (t[i], LEFT))
00230       assign (t[i], tree (LEFT, "."));
00231     else if (is_func (t[i], RIGHT))
00232       assign (t[i], tree (RIGHT, "."));
00233     go_to_border (path_up (p), !forward);
00234     if (is_deleted (t[0]) && is_deleted (t[2])) {
00235       remove_node (t, 1);
00236       correct (path_up (p, 2));
00237     }
00238   }
00239   if (!match) call ("brackets-refresh");  
00240 }
00241 
00242 void
00243 edit_math_rep::back_in_long_arrow (tree t, path p, bool forward) {
00244   int i= last_item (p);
00245   if (i == 2) {
00246     if (is_empty (t[2])) remove (path_up (p) * 2, 1);
00247     if (forward) go_to_border (path_up (p), !forward);
00248     else go_to_border (path_up (p) * 1, forward);
00249   }
00250   else if (i == 1) {
00251     if (N(t) == 2 && is_empty (t[1])) {
00252       assign (path_up (p), "");
00253       correct (path_up (p, 2));
00254     }
00255     else if (forward && N(t) >= 3)
00256       go_to_border (path_up (p) * 2, forward);
00257     else go_to_border (path_up (p), !forward);
00258   }
00259   else go_to_border (path_up (p), !forward);
00260 }
00261 
00262 void
00263 edit_math_rep::back_prime (tree t, path p, bool forward) {
00264   if ((N(t) == 1) && is_atomic (t[0])) {
00265     string s= t[0]->label;
00266     if (forward) {
00267       int i= 0, n= N(s);
00268       tm_char_forwards (s, i);
00269       if (i >= n) {
00270        assign (p, "");
00271        correct (path_up (p));
00272       }
00273       else remove (p * path (0, 0), i);
00274     }
00275     else {
00276       int n= N(s), i= n;
00277       tm_char_backwards (s, i);
00278       if (i <= 0) {
00279        assign (p, "");
00280        correct (path_up (p));
00281       }
00282       else remove (p * path (0, i), n-i);
00283     }
00284   }
00285 }
00286 
00287 void
00288 edit_math_rep::back_in_wide (tree t, path p, bool forward) {
00289   int i= last_item (p);
00290   if ((i == 0) && is_empty (t[0])) {
00291     assign (path_up (p), "");
00292     correct (path_up (p, 2));
00293   }
00294   else go_to_border (path_up (p), !forward);
00295 }
00296 
00297 void
00298 edit_math_rep::pre_remove_around (path p) {
00299   tree st= subtree (et, p);
00300   if (is_script (st[1]) || is_prime (st[1])) assign (st[1], "");
00301   else if (is_concat (st[1]) && N(st[1]) > 0) {
00302     int li= 0, ri= N(st[1])-1;
00303     while (li<N(st[1])) {
00304       tree sst= st[1][li];
00305       if (!is_func (sst, RSUB) &&
00306          !is_func (sst, RSUP) &&
00307          !is_func (sst, RPRIME))
00308        break;
00309       li++;
00310     }
00311     while (ri >= 0) {
00312       tree sst= st[1][ri];
00313       if (!is_func (sst, LSUB) &&
00314          !is_func (sst, LSUP) &&
00315          !is_func (sst, LPRIME))
00316        break;
00317       ri--;
00318     }
00319     if (ri != N(st[1])-1) remove (p * path (1, ri+1), N(st[1])-1-ri);
00320     if (li != 0) remove (p * path (1, 0), li);
00321     correct (p * 1);
00322   }
00323 }
00324 
00325 /******************************************************************************
00326 * Trees
00327 ******************************************************************************/
00328 
00329 void
00330 edit_math_rep::make_tree () {
00331   if (selection_active_small ())
00332     insert_tree (tree (TREE, selection_get_cut (), ""), path (1, 0));
00333   else {
00334     insert_tree (tree (TREE, "", ""), path (0, 0));
00335     set_message (concat (kbd_shortcut ("(structured-insert-right)"),
00336                       ": insert a new branch"),
00337                "tree");
00338   }
00339 }
00340 
00341 void
00342 edit_math_rep::back_in_tree (tree t, path p, bool forward) {
00343   int i= last_item (p);
00344   if (i>0) {
00345     if ((i>0) && (t[i] == "")) {
00346       path q= path_up (p);
00347       if (N (t) == 2) {
00348        assign (q, t[0]);
00349        correct (path_up (q));
00350       }
00351       else {
00352        remove (q * i, 1);
00353        if (forward) {
00354          if (i == N (subtree (et, q))) go_to_end (q);
00355          else go_to_start (q * i);
00356        }
00357       }
00358     }
00359     else if (!forward) go_to_end (path_up (p) * (i-1));
00360     else if (i == N(t)-1) go_to_end (path_up (p));
00361     else go_to_start (path_up (p) * (i+1));
00362   }
00363   else {
00364     if (t == tree (TREE, "", "")) {
00365       p= path_up (p);
00366       assign (p, "");
00367       correct (path_up (p));
00368     }
00369     else if (forward) go_to_start (path_inc (p));
00370     else go_to_start (path_up (p));
00371   }
00372 }