]> git.lyx.org Git - features.git/commitdiff
*** empty log message ***
authorAndré Pönitz <poenitz@gmx.net>
Wed, 10 Oct 2001 13:20:51 +0000 (13:20 +0000)
committerAndré Pönitz <poenitz@gmx.net>
Wed, 10 Oct 2001 13:20:51 +0000 (13:20 +0000)
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@2852 a592a061-630c-0410-9148-cb99ea01b6c8

src/mathed/ChangeLog
src/mathed/array.C
src/mathed/array.h
src/mathed/math_atom.C
src/mathed/math_atom.h
src/mathed/math_cursor.C
src/mathed/math_cursor.h
src/mathed/xarray.C
src/mathed/xarray.h

index 02f040f10ccbceccbdba90862214bff4bc86c844..88612d353f5776ce839564d25a9046c2b5b2dd5d 100644 (file)
@@ -1,4 +1,12 @@
 
+2001-10-10  André Pönitz  <poenitz@gmx.net>
+
+       * math_cursor.C: introduce dummy "inner" position "between"
+       nucleus and scripts for smoother cursor movement
+
+       * math_cursor.C: use red dot to indicate empty nucleus
+
+
 2001-10-02  André Pönitz  <poenitz@gmx.net>
 
        * math_cursor.C: leave red backslash as visual clue
index cdf974e615889e990e7a862f4d770d72a1b02c92..482d1c8d8519ce038e1c047310b00c5f9b8957ec 100644 (file)
@@ -56,9 +56,15 @@ void MathArray::insert(size_type pos, MathArray const & array)
 }
 
 
+void MathArray::push_back(MathAtom const & t)
+{      
+       bf_.push_back(t);
+}
+
+
 void MathArray::push_back(MathInset * p)
 {      
-       insert(size(), p);
+       bf_.push_back(MathAtom(p));
 }
 
 
@@ -149,6 +155,8 @@ string charSequence(MathArray::const_iterator it, MathArray::const_iterator end)
                return s;
 
        for (MathTextCodes c = p->code(); it != end; ++it) {
+               if (!it->nucleus())
+                       break;
                p = it->nucleus()->asCharInset();
                if (!p || it->up() || it->down() || p->code() != c)
                        break;
@@ -161,8 +169,10 @@ string charSequence(MathArray::const_iterator it, MathArray::const_iterator end)
 void MathArray::write(ostream & os, bool fragile) const
 {
        for (const_iterator it = begin(); it != end(); ++it) {
-               MathCharInset const * p = it->nucleus()->asCharInset();
-               if (p && !it->up() && !it->down()) {
+               if (it->nucleus() && it->nucleus()->asCharInset()
+                               && !it->up() && !it->down())
+               {
+                       MathCharInset const * p = it->nucleus()->asCharInset();
                        // special handling for character sequences with the same code
                        string s = charSequence(it, end());
                        p->writeHeader(os);
index 11121766476bf6f8f71322f8a3d1c03cb63053f2..791427506552593468f1de324b06c90f7137d684 100644 (file)
@@ -80,6 +80,8 @@ public:
        ///
        void push_back(MathArray const &);
        ///
+       void push_back(MathAtom const &);
+       ///
        void pop_back();
        ///
        MathAtom & back();
index 0d90ab8d1d985f39108a154b5516b9cfeb67138e..c583e1d77ea2fbcbcdb6d4a277bab508488d0a83 100644 (file)
@@ -266,8 +266,8 @@ int MathAtom::dx1() const
 
 int MathAtom::dxx() const
 {
-       lyx::Assert(nucleus());
-       return hasLimits() ? (width() - nwid()) / 2 : 0;
+       //lyx::Assert(nucleus());
+       return hasLimits() ?  (width() - nwid()) / 2 : 0;
 }
 
 
@@ -305,7 +305,9 @@ int MathAtom::width() const
 
 int MathAtom::nwid() const
 {
-       return nucleus() ? nucleus()->width() : 0;
+       return nucleus() ?
+               nucleus()->width() :
+               mathed_char_width(LM_TC_TEX, LM_ST_TEXT, '.');
 }
 
 
@@ -329,6 +331,8 @@ void MathAtom::draw(Painter & pain, int x, int y) const
        yo(y);
        if (nucleus())
                nucleus()->draw(pain, x + dxx(), y);
+       else
+               drawStr(pain, LM_TC_TEX, LM_ST_TEXT, x + dxx(), y, ".");
        if (up())
                up()->draw(pain, x + dx1(), y - dy1());
        if (down())
@@ -370,6 +374,12 @@ bool MathAtom::hasLimits() const
 }
 
 
+bool MathAtom::hasInner() const
+{
+       return nucleus_ && (script_[0] || script_[1]);
+}
+
+
 void MathAtom::substitute(MathMacro const & m)
 {
        if (nucleus())
@@ -389,3 +399,24 @@ void MathAtom::removeEmptyScripts()
                        script_[i] = 0;
                }
 }
+
+
+void MathAtom::removeNucleus()
+{
+       delete nucleus_;
+       nucleus_ = 0;
+}
+
+
+void MathAtom::removeUp()
+{
+       delete script_[1];
+       script_[1] = 0;
+}
+
+
+void MathAtom::removeDown()
+{
+       delete script_[0];
+       script_[0] = 0;
+}
index c5ef2c5b860e8ff53c3c3a51f91ade945d4a9eee..a97ad307bb15fbe93d807769424d06ee5d0a50ec 100644 (file)
@@ -86,6 +86,12 @@ public:
        MathScriptInset * ensure(bool up);
        /// delete subscript array if empty
        void removeEmptyScripts();
+       /// delete nucleus
+       void removeNucleus();
+       /// delete superscript
+       void removeUp();
+       /// delete subscript
+       void removeDown();
        /// can we add a super- or subscript?
        virtual bool allows(bool up) const { return script_[up] == 0; }
        /// can we add a super- or subscript?
@@ -96,6 +102,8 @@ public:
        int limits() const { return limits_; }
        ///
        bool hasLimits() const;
+       /// true if we have an "inner" position
+       bool hasInner() const;
        /// returns superscript
        MathScriptInset * up() const;
        /// returns subscript
@@ -107,11 +115,15 @@ public:
        ///
        MathInset * nucleus() const { return nucleus_; }
        ///
+       MathInset * & nucleus() { return nucleus_; }
+       ///
        void substitute(const MathMacro &);
        ///
        void write(std::ostream &, bool) const;
        ///
        void writeNormal(std::ostream &) const;
+       /// returns width of nucleus if any
+       int nwid() const;
 
 protected:
        /// possible subscript (index 0) and superscript (index 1)
@@ -137,14 +149,12 @@ private:
        int dy0() const;
        /// returns y offset for subscript
        int dy1() const;
+       /// returns x offset for main part
+       int dxx() const;
        /// returns x offset for superscript
        int dx0() const;
        /// returns x offset for subscript
        int dx1() const;
-       /// returns x offset for main part
-       int dxx() const;
-       /// returns width of nucleus if any
-       int nwid() const;
        /// returns ascent of nucleus if any
        int nasc() const;
        /// returns descent of nucleus if any
index 89184125627a7ef14696f9382bd6e79d502b85ba..72b978816bcf03081425bd7ee30ea9ce3f16d2f4 100644 (file)
@@ -58,8 +58,21 @@ struct Selection
                MathCursorPos i1;
                MathCursorPos i2;
                cursor.getSelection(i1, i2); 
-               if (i1.idx_ == i2.idx_)
-                       data_.push_back(MathArray(i1.cell(), i1.pos_, i2.pos_));
+               if (i1.idx_ == i2.idx_) {
+                       MathArray ar;
+                       if (i1.inner_) {
+                               ar.push_back(*i1.at());
+                               ar.back().removeNucleus();
+                               ++i1.pos_;
+                       }
+                       ar.push_back(MathArray(i1.cell(), i1.pos_, i2.pos_));
+                       if (i2.inner_) {
+                               ar.push_back(*i2.at());
+                               ar.back().removeUp();
+                               ar.back().removeDown();
+                       }
+                       data_.push_back(ar);
+               }
                else {
                        std::vector<MathInset::idx_type> indices =
                                i1.par_->idxBetween(i1.idx_, i2.idx_);
@@ -73,10 +86,21 @@ struct Selection
                MathCursorPos i1;
                MathCursorPos i2;
                cursor.getSelection(i1, i2); 
-               if (i1.idx_ == i2.idx_)
+               if (i1.idx_ == i2.idx_) {
+                       if (i1.inner_) {
+                               i1.inner_ = false;
+                               i1.at()->removeUp();
+                               i1.at()->removeDown();
+                               ++i1.pos_;
+                       }
+                       if (i2.inner_) {
+                               i2.inner_ = false;
+                               i2.at()->removeNucleus();
+                       }
                        i1.cell().erase(i1.pos_, i2.pos_);
-               else {
-                       std::vector<MathInset::idx_type> indices = i1.par_->idxBetween(i1.idx_, i2.idx_);
+               } else {
+                       std::vector<MathInset::idx_type> indices =
+                               i1.par_->idxBetween(i1.idx_, i2.idx_);
                        for (unsigned i = 0; i < indices.size(); ++i)
                                i1.cell(indices[i]).erase();
                }
@@ -113,7 +137,7 @@ Selection theSelection;
 std::ostream & operator<<(std::ostream & os, MathCursorPos const & p)
 {
        os << "(par: " << p.par_ << " idx: " << p.idx_
-          << " pos: " << p.pos_ << ")";
+          << " pos: " << p.pos_ << " inner: " << p.inner_ << ")";
        return os;
 }
 #endif
@@ -131,7 +155,8 @@ MathCursor::MathCursor(InsetFormulaBase * formula)
 void MathCursor::pushLeft(MathInset * par)
 {
        MathCursorPos p;
-       p.par_ = par;
+       p.par_   = par;
+       p.inner_ = false;
        par->idxFirst(p.idx_, p.pos_);
        Cursor_.push_back(p);
 }
@@ -141,7 +166,8 @@ void MathCursor::pushRight(MathInset * par)
 {
        posLeft();
        MathCursorPos p;
-       p.par_ = par;
+       p.par_   = par;
+       p.inner_ = false;
        par->idxLast(p.idx_, p.pos_);
        Cursor_.push_back(p);
 }
@@ -274,18 +300,39 @@ MathInset * MathCursor::positionable(MathAtom * t, int x, int y) const
 
 bool MathCursor::posLeft()
 {
+       if (inner()) {
+               inner() = false;
+               return true;
+       }
+
        if (pos() == 0)
                return false;
+
        --pos();
+
+       if (nextAtom()->hasInner())
+               inner() = true;
+
        return true;
 }
 
 
 bool MathCursor::posRight()
 {
+       if (inner()) {
+               ++pos();
+               inner() = false;
+               return true;
+       }
+
        if (pos() == size())
                return false;
-       ++pos();
+
+       if (nextAtom()->hasInner())
+               inner() = true;
+       else 
+               ++pos();
+
        return true;
 }
 
@@ -367,7 +414,7 @@ void MathCursor::setPos(int x, int y)
                        int x1 = x - ar.xo();
                        int y1 = y - ar.yo();
                        MathXArray::size_type c  = ar.x2pos(x1);
-                       int xx = abs(x1 - ar.pos2x(c));
+                       int xx = abs(x1 - ar.pos2x(c, false));
                        int yy = abs(y1);
                        //lyxerr << "idx: " << i << " xx: " << xx << " yy: " << yy
                        //      << " c: " << c  << " xo: " << ar.xo() << "\n";
@@ -420,11 +467,32 @@ void MathCursor::plainErase()
 }
 
 
+void MathCursor::plainInsert(MathInset * p)
+{
+       if (inner()) {
+               array().insert(pos(), p);
+               ++pos();
+               swap(prevAtom()->nucleus(), nextAtom()->nucleus());
+               return;
+       }
+
+       MathAtom * n = nextAtom();
+
+       if (n && !n->nucleus()) {
+               n->nucleus() = p;
+               inner() = true;
+               return;
+       }
+
+       array().insert(pos(), p); // this invalidates the pointer!
+       ++pos();
+}
+
+
 void MathCursor::insert(char c, MathTextCodes t)
 {
        //lyxerr << "inserting '" << c << "'\n";
-       array().insert(pos(), new MathCharInset(c, t));
-       posRight();
+       plainInsert(new MathCharInset(c, t));
 }
 
 
@@ -432,16 +500,14 @@ void MathCursor::insert(MathInset * p)
 {
        macroModeClose();
 
-       if (selection_) {
+       if (p && selection_) {
                if (p->nargs())
                        selCut();
                else
                        selDel();
        }
 
-       array().insert(pos(), p); // this invalidates the pointer!
-       p = array().at(pos())->nucleus();
-       posRight();
+       plainInsert(p);
 }
 
 
@@ -476,25 +542,63 @@ void MathCursor::insert(MathArray const & ar)
 }
 
 
+void MathCursor::glueAdjacentAtoms()
+{
+       MathAtom * p = prevAtom();
+       if (!p)
+               return;
+
+       MathAtom * n = nextAtom();
+       if (!n)
+               return;
+
+       if (p->up() && n->up())
+               return;
+
+       if (p->down() && n->down())
+               return;
+
+       // move everything to the previous atom
+       if (n->up())
+               swap(p->up(), n->up());
+
+       if (n->down())
+               swap(p->down(), n->down());
+       
+       plainErase();
+       --pos();
+       inner() = nextAtom()->hasInner();
+}
+
+
 void MathCursor::backspace()
 {
-       if (posLeft()) {
-               erase();
+       if (inner()) {
+               nextAtom()->removeNucleus();
+               inner() = false;
+               glueAdjacentAtoms();
                return;
        }
 
-       if (size()) {
-               pullArg(false);
+       if (pos() == 0) {
+               if (size())
+                       pullArg(false);
+               return;
+       }       
+
+       if (prevAtom()->hasInner()) {
+               --pos();
+               inner() = true;
                return;
        }
 
-       erase();
+       --pos();
+       plainErase();
 }
 
 
 void MathCursor::erase()
 {
-       dump("erase 1");
        if (inMacroMode())
                return;
 
@@ -504,7 +608,7 @@ void MathCursor::erase()
        }
 
        // delete empty cells if necessary
-       if (pos() == 0 && array().empty()) {
+       if (array().empty()) {
                bool popit;
                bool removeit;
                par()->idxDelete(idx(), popit, removeit);
@@ -513,42 +617,30 @@ void MathCursor::erase()
                return;
        }
 
-       if (pos() == size())
+       MathAtom * n = nextAtom();
+
+       if (!n)
                return;
 
-       // delete nucleus, keep scripts if possible
-       MathAtom * p = prevAtom();
-       MathAtom * n = nextAtom();
-       if (pos() > 0) {
-               bool need_parans = (p->up() && n->up()) || (p->down() && n->down());
-               if (need_parans) {
-                       // need empty block
-                       insert('{', LM_TC_TEX);
-                       insert('}', LM_TC_TEX);
-                       p = prevAtom();
-                       n = nextAtom();
-               }
-               // move indices to the left
+       if (inner()) {
                if (n->up())
-                       swap(p->up(), n->up());
-               if (n->down())
-                       swap(p->down(), n->down());
-               plainErase();
+                       n->removeUp();
+               else if (n->down())
+                       n->removeDown();
+               if (!n->up() && !n->down()) {
+                       ++pos();
+                       inner() = false;
+               }
                return;
        }
 
-       // pos == 0 now
-       if (n->up() || n->down()) {
-               insert('{', LM_TC_TEX);
-               insert('}', LM_TC_TEX);
-               p = prevAtom();
-               n = nextAtom();
-               swap(p->up(), n->up());
-               swap(p->down(), n->down());
+       if (n->hasInner()) {
+               n->removeNucleus();
+               inner() = true;
+               return;
        }
 
        plainErase();
-       dump("erase 2");
 }
 
 
@@ -741,9 +833,9 @@ void MathCursor::drawSelection(Painter & pain) const
 
        if (i1.idx_ == i2.idx_) {
                MathXArray & c = i1.xcell();
-               int x1 = c.xo() + c.pos2x(i1.pos_);
+               int x1 = c.xo() + c.pos2x(i1.pos_, i1.inner_);
                int y1 = c.yo() - c.ascent();
-               int x2 = c.xo() + c.pos2x(i2.pos_);
+               int x2 = c.xo() + c.pos2x(i2.pos_, i2.inner_);
                int y2 = c.yo() + c.descent();
                pain.fillRectangle(x1, y1, x2 - x1, y2 - y1, LColor::selection);
        } else {
@@ -811,7 +903,7 @@ void MathCursor::getPos(int & x, int & y)
 #ifdef WITH_WARNINGS
 #warning This should probably take cellXOffset and cellYOffset into account
 #endif
-       x = xarray().xo() + xarray().pos2x(pos());
+       x = xarray().xo() + xarray().pos2x(pos(), inner());
        y = xarray().yo();
 }
 
@@ -852,6 +944,18 @@ MathCursor::pos_type & MathCursor::pos()
 }
 
 
+bool MathCursor::inner() const
+{
+       return cursor().inner_;
+}
+
+
+bool & MathCursor::inner()
+{
+       return cursor().inner_;
+}
+
+
 bool MathCursor::inMacroMode() const
 {
        return lastcode_ == LM_TC_TEX;
@@ -1132,7 +1236,7 @@ int MathCursor::cellYOffset() const
 
 int MathCursor::xpos() const
 {
-       return cellXOffset() + xarray().pos2x(pos());
+       return cellXOffset() + xarray().pos2x(pos(), inner());
 }
 
 
@@ -1281,12 +1385,12 @@ void MathCursor::interpret(string const & s)
        // we got just a single char now
 
        if (c == '^' || c == '_') {
-               bool const up = (s[0] == '^');
-               selCut();       
-               if (!prevInset()) {
-                       insert('{', LM_TC_TEX);
-                       insert('}', LM_TC_TEX);
-               }
+               const bool up = (s[0] == '^');
+               selCut();
+               if (inner())
+                       ++pos();
+               if (!prevAtom())
+                       insert(0);
                MathInset * par = prevAtom()->ensure(up);
                pushRight(par);
                selPaste();
@@ -1324,7 +1428,12 @@ void MathCursor::interpret(string const & s)
                return;
        }
 
-       if (lastcode_ != LM_TC_TEX && strchr("#$%{}", c)) {
+       if (lastcode_ != LM_TC_TEX && strchr("{}", c)) {
+               insert(c, LM_TC_TEX);
+               return;
+       }
+
+       if (lastcode_ != LM_TC_TEX && strchr("#$%", c)) {
                insert(new MathSpecialCharInset(c));    
                lastcode_ = LM_TC_VAR;
                return;
@@ -1343,8 +1452,9 @@ void MathCursor::interpret(string const & s)
                                macroModeClose();
                                lastcode_ = LM_TC_VAR;
                        }
-                       else if (isalpha(c))
+                       else if (isalpha(c)) {
                                insert(c, LM_TC_TEX);
+                       }
                        else {
                                macroModeClose();
                                lastcode_ = LM_TC_VAR;
@@ -1390,7 +1500,7 @@ void MathCursor::interpret(string const & s)
        }
 
        // no special circumstances, so insert the character without any fuss
-       insert(c);
+       insert(c, LM_TC_MIN);
 }
 
 
@@ -1440,6 +1550,12 @@ MathXArray & MathCursorPos::xcell() const
 }
 
 
+MathAtom * MathCursorPos::at() const
+{
+       return cell().at(pos_);
+}
+
+
 MathCursorPos MathCursor::normalAnchor() const
 {
        // use Anchor on the same level as Cursor
index d37b66a55430a67dd8e0a51208aefd860d211062..b59c376894384eeb0ae019c34f60706c6e4ea2ff 100644 (file)
@@ -45,6 +45,9 @@ struct MathCursorPos {
        MathInset::idx_type idx_;
        /// cell position
        MathInset::pos_type pos_;
+       /// faked position "inside an atom"
+       bool inner_;
+
        /// returns cell corresponding to this position
        MathArray & cell() const;
        /// returns cell corresponding to this position
@@ -53,6 +56,9 @@ struct MathCursorPos {
        MathXArray & xcell() const;
        /// returns xcell corresponding to this position
        MathXArray & xcell(MathInset::idx_type idx) const;
+
+       /// returns atom corresponding to this position
+       MathAtom * at() const;
 };
 
 /// 
@@ -101,18 +107,6 @@ public:
        void first();
        /// Put the cursor in the last position
        void last();
-       /// moves cursor position one cell to the left
-       bool posLeft();
-       /// moves cursor position one cell to the right
-       bool posRight();
-       /// moves cursor index one cell to the left
-       bool idxLeft();
-       /// moves cursor index one cell to the right
-       bool idxRight();
-       /// moves position somehow up
-       bool goUp();
-       /// moves position somehow down
-       bool goDown();
        ///
        void idxNext();
        ///
@@ -123,6 +117,7 @@ public:
        void plainInsert(MathInset * p);
        ///
        void niceInsert(MathInset * p);
+
        ///
        void delLine();
        /// This is in pixels from (maybe?) the top of inset
@@ -136,6 +131,8 @@ public:
        ///
        InsetFormulaBase const * formula();
        ///
+       bool inner() const;
+       ///
        pos_type pos() const;
        ///
        idx_type idx() const;
@@ -261,15 +258,33 @@ public:
        MathScriptInset * prevScriptInset() const;
        ///
        MathSpaceInset * prevSpaceInset() const;
+
 private:
+       /// moves cursor position one cell to the left
+       bool posLeft();
+       /// moves cursor position one cell to the right
+       bool posRight();
+       /// moves cursor index one cell to the left
+       bool idxLeft();
+       /// moves cursor index one cell to the right
+       bool idxRight();
+       /// moves position somehow up
+       bool goUp();
+       /// moves position somehow down
+       bool goDown();
+       /// glue adjacent atoms if possible
+       void glueAdjacentAtoms();
+
        ///
        string macroName() const;
        ///
-       void insert(char, MathTextCodes t = LM_TC_MIN);
+       void insert(char, MathTextCodes t);
        /// can we enter the inset? 
        bool openable(MathInset *, bool selection) const;
        /// can the setPos routine enter that inset?
        MathInset * positionable(MathAtom *, int x, int y) const;
+       /// write access to "inner" flag
+       bool & inner();
        /// write access to cursor cell position
        pos_type & pos();
        /// write access to cursor cell index
index f90008e817a4e025744caac7e0e7c9fe3f5900cc..2faafbed91926e30e881f093c22a8ef7f6e761f4 100644 (file)
@@ -59,12 +59,14 @@ void MathXArray::draw(Painter & pain, int x, int y) const
 }
 
 
-int MathXArray::pos2x(size_type targetpos) const
+int MathXArray::pos2x(size_type targetpos, bool inner) const
 {
        int x = 0;
        targetpos = std::min(targetpos, data_.size());
        for (size_type pos = 0; pos < targetpos; ++pos) 
-               x += width(pos);
+               x += width(pos);        
+       if (inner)
+               x += innerwidth(targetpos);
        return x;
 }
 
@@ -91,6 +93,13 @@ int MathXArray::width(size_type pos) const
 }
 
 
+int MathXArray::innerwidth(size_type pos) const
+{
+       MathAtom const * t = data_.at(pos);
+       return t ? t->nwid() : 0;
+}
+
+
 std::ostream & operator<<(std::ostream & os, MathXArray const & ar)
 {
        os << ar.data_;
index 5df0ea5b809cfc5eba4febbc3251659e40b1d4b6..ba5d073d7ca717a5a987965f4fb8b77b9bfeb7e3 100644 (file)
@@ -31,11 +31,13 @@ public:
        ///
        int yo() const { return yo_; }
        ///
-       int pos2x(size_type pos) const;
+       int pos2x(size_type pos, bool inner) const;
        ///
        size_type x2pos(int pos) const;
        ///
        int width(size_type pos) const;
+       ///
+       int innerwidth(size_type pos) const;
 
        ///
        int ascent() const { return ascent_; }