Back to index

texmacs  1.0.7.15
highlight_observer.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : highlight_observer.cpp
00004 * DESCRIPTION: Attach highlighting information to trees
00005 * COPYRIGHT  : (C) 2010  Joris van der Hoeven
00006 *******************************************************************************
00007 * An inverse path observer maintains the inverse path of the position
00008 * of the corresponding tree with respect to the global meta-tree.
00009 *******************************************************************************
00010 * This software falls under the GNU general public license version 3 or later.
00011 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
00012 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
00013 ******************************************************************************/
00014 
00015 #include "modification.hpp"
00016 
00017 /******************************************************************************
00018 * Definition of the highlight_observer_rep class
00019 ******************************************************************************/
00020 
00021 class highlight_observer_rep: public observer_rep {
00022   int lan;
00023   array<int> cols;
00024 public:
00025   highlight_observer_rep (int lan2, array<int> cols2):
00026     lan (lan2), cols (cols2) {}
00027   int get_type () { return OBSERVER_HIGHLIGHT; }
00028   tm_ostream& print (tm_ostream& out) {
00029     return out << " highlight<" << lan << ">"; }
00030 
00031   void announce (tree& ref, modification mod);
00032   bool set_highlight (int lan, int col, int start, int end);
00033   bool get_highlight (int lan, array<int>& cols);
00034 };
00035 
00036 /******************************************************************************
00037 * Call back routines and highlighting methods
00038 ******************************************************************************/
00039 
00040 void
00041 highlight_observer_rep::announce (tree& ref, modification mod) {
00042   (void) mod;
00043   remove_observer (ref->obs, observer (this));
00044 }
00045 
00046 bool
00047 highlight_observer_rep::set_highlight (int l, int col, int start, int end) {
00048   if (l != lan) return false;
00049   ASSERT (0 <= start && start <= end && end <= N(cols), "out of range");
00050   for (int i=start; i<end; i++) cols[i]= col;
00051   return true;
00052 }
00053 
00054 
00055 bool
00056 highlight_observer_rep::get_highlight (int l, array<int>& c) {
00057   if (l != lan) return false;
00058   c= cols;
00059   return true;
00060 }
00061 
00062 /******************************************************************************
00063 * Attaching and detaching highlighters
00064 ******************************************************************************/
00065 
00066 observer
00067 highlight_observer (int lan, array<int> cols) {
00068   return tm_new<highlight_observer_rep> (lan, cols);
00069 }
00070 
00071 void
00072 remove_highlight (observer& obs, int lan) {
00073   if (is_nil (obs)) return;
00074   else if (obs->get_type () == OBSERVER_HIGHLIGHT) {
00075     array<int> r;
00076     if (obs->get_highlight (lan, r))
00077       obs= nil_observer;
00078   }
00079   else {
00080     remove_highlight (obs->get_child (0), lan);
00081     remove_highlight (obs->get_child (1), lan);
00082   }
00083 }
00084 
00085 void
00086 attach_highlight (tree& ref, int lan) {
00087   //cout << "Attach highlight " << ref << "\n";
00088   if (!has_highlight (ref, lan))
00089     attach_highlight (ref, lan, 0, 0, 0);
00090   if (is_compound (ref))
00091     for (int i=0; i<N(ref); i++)
00092       attach_highlight (ref[i], lan);
00093 }
00094 
00095 void
00096 attach_highlight (tree& ref, int lan, int col, int start, int end) {
00097   int n= (is_atomic (ref)? N(ref->label): 1);
00098   ASSERT (0 <= start && start <= end && end <= n, "out of range");
00099   if (is_nil (ref->obs) || !ref->obs->set_highlight (lan, col, start, end)) {
00100     array<int> cols (n);
00101     for (int i=0; n>i; i++) cols[i]= 0;
00102     for (int i=start; i<end; i++) cols[i]= col;
00103     attach_observer (ref, highlight_observer (lan, cols));
00104   }
00105 }
00106 
00107 bool
00108 has_highlight (tree& ref, int lan) {
00109   if (lan == 0 || is_nil (ref->obs)) return false;
00110   array<int> cols;
00111   return ref->obs->get_highlight (lan, cols);
00112 }
00113 
00114 array<int>
00115 obtain_highlight (tree& ref, int lan) {
00116   if (lan == 0 || is_nil (ref->obs)) return array<int> ();
00117   array<int> cols;
00118   if (ref->obs->get_highlight (lan, cols)) return cols;
00119   return array<int> ();
00120 }
00121 
00122 bool
00123 detach_highlight_sub (tree& ref, int lan) {
00124   //cout << "Detach highlight " << ref << "\n";
00125   array<int> cols;
00126   bool r= !is_nil (ref->obs) && ref->obs->get_highlight (lan, cols);
00127   remove_highlight (ref->obs, lan);
00128   if (is_compound (ref))
00129     for (int i=0; i<N(ref); i++)
00130       r= detach_highlight_sub (ref[i], lan) | r;
00131   return r;
00132 }
00133 
00134 void
00135 detach_highlight (tree& ref, int lan) {
00136   if (detach_highlight_sub (ref, lan))
00137     touch (ref);
00138 }