diff --git a/ChangeLog b/ChangeLog index fcd9f67291..c39564bc9b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,64 @@ +2000-04-19 Juergen Vigna + + * src/insets/insettext.C (init): using a LyXCursor now for cursor + position. Set the inset_owner of the used paragraph so that it knows + that it is inside an inset. Fixed cursor handling with mouse and + cursor keys. Fixed wrong timed inset redraws and lots of other changes + and cleanups to make TextInsets work better. + + * src/insets/insettext.h: Using a LyXCursor now. Added a clear() call. + Changed parameters of various functions and added LockInsetInInset(). + + * src/insets/insettext.C: + + * src/insets/insetcollapsable.h: + * src/insets/insetcollapsable.C: + * src/insets/insetfoot.h: + * src/insets/insetfoot.C: + * src/insets/insetert.h: + * src/insets/insetert.C: cleaned up the code so that it works now + correctly with insettext. + + * src/insets/inset.C: + * src/insets/lyxinset.h: inserted inset_owner and some more changes so + that insets in insets are supported right. + + * src/table.h: + * src/table.C: lots of changes for use with inset tabular (and cleanup) + + * src/paragraph.C: some small fixes + + * src/debug.h: inserted INSETS debug info + + * src/lyxfunc.C (Dispatch): added code for InsetTabular and some inset + fixes (f.ex. calling LFUN_DOWN if exiting inset with LFUN_DOWN). + + * src/commandtags.h: + * src/LyXAction.C: insert code for InsetTabular. + + * src/BufferView_pimpl.C (workAreaMotionNotify): do return always if + not Button1MotionMask. + (workAreaButtonRelease): send always a InsetButtonRelease event to + the_locking_inset. + (checkInsetHit): some setCursor fixes (always with insets). + + * src/BufferView2.C (lockInset): returns a bool now and extended for + locking insets inside insets. + (showLockedInsetCursor): it is important to have the cursor always + before the locked inset. + (fitLockedInsetCursor): forgot adding of InsetInInsetY()-offset. + + * src/BufferView.h: made lockInset return a bool. + + * src/lyxtext.h: inserted function SetCursor(LyXCursor, ...). + + * src/text2.C (SetCursor): This now has a version with a LyXCursor + that is used also internally but can be called as public to have back + a cursor pos which is not set internally. + (SetCursorIntern): Changed to use above function. + + * src/CutAndPaste.C (DeleteBuffer): forgot to inizialize textclass + 2000-04-19 Lars Gullik Bjønnes * ANNOUNCE: diff --git a/po/POTFILES.in b/po/POTFILES.in index 60b54c6d45..cd76751ff2 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -12,10 +12,12 @@ src/buffer.C src/bufferlist.C src/BufferView2.C +src/bufferview_funcs.C src/BufferView_pimpl.C src/bullet_forms.C src/bullet_forms_cb.C src/Chktex.C +src/ColorHandler.C src/combox.C src/credits.C src/credits_form.C @@ -41,6 +43,7 @@ src/insets/insetlof.C src/insets/insetlot.C src/insets/insetparent.C src/insets/insetref.C +src/insets/insettabular.C src/insets/insettext.C src/insets/insettoc.C src/insets/inseturl.C @@ -75,7 +78,6 @@ src/mathed/math_forms.C src/mathed/math_panel.C src/menus.C src/minibuffer.C -src/Painter.C src/PaperLayout.C src/paragraph.C src/ParagraphExtra.C @@ -86,6 +88,7 @@ src/support/filetools.C src/support/getUserName.C src/support/path.C src/support/path.h +src/table.C src/TableLayout.C src/text2.C src/text.C diff --git a/src/BufferView.h b/src/BufferView.h index cc44535382..adf43ec5a8 100644 --- a/src/BufferView.h +++ b/src/BufferView.h @@ -160,7 +160,7 @@ public: /// Inserts a lyx file at cursor position. Returns false if it fails. bool insertLyXFile(string const & file); /// - int lockInset(UpdatableInset * inset); + bool lockInset(UpdatableInset * inset); /// void showLockedInsetCursor(long x, long y, int asc, int desc); /// diff --git a/src/BufferView2.C b/src/BufferView2.C index bd3c8e4201..6bb8540835 100644 --- a/src/BufferView2.C +++ b/src/BufferView2.C @@ -723,24 +723,29 @@ void BufferView::replaceWord(string const & replacestring) // End of spellchecker stuff - -/* these functions return 1 if an error occured, - otherwise 0 */ -int BufferView::lockInset(UpdatableInset * inset) +bool BufferView::lockInset(UpdatableInset * inset) { - if (!the_locking_inset && inset){ + if (!the_locking_inset && inset) { the_locking_inset = inset; - return 0; + return true; + } else if (inset) { + return the_locking_inset->LockInsetInInset(this, inset); } - return 1; + return false; } void BufferView::showLockedInsetCursor(long x, long y, int asc, int desc) { if (the_locking_inset && available()) { - y += text->cursor.y + - the_locking_inset->InsetInInsetY(); + LyXCursor cursor = text->cursor; + if ((cursor.pos - 1 >= 0) && + (cursor.par->GetChar(cursor.pos-1) == + LyXParagraph::META_INSET) && + (cursor.par->GetInset(cursor.pos - 1) == + the_locking_inset->GetLockingInset())) + text->SetCursor(cursor, cursor.par, cursor.pos-1); + y += cursor.y + the_locking_inset->InsetInInsetY(); pimpl_->screen->ShowManualCursor(x, y, asc, desc, LyXScreen::BAR_SHAPE); } @@ -758,7 +763,7 @@ void BufferView::hideLockedInsetCursor() void BufferView::fitLockedInsetCursor(long x, long y, int asc, int desc) { if (the_locking_inset && available()){ - y += text->cursor.y; + y += text->cursor.y + the_locking_inset->InsetInInsetY(); if (pimpl_->screen->FitManualCursor(x, y, asc, desc)) updateScrollbar(); } diff --git a/src/BufferView_pimpl.C b/src/BufferView_pimpl.C index 7c5689c8cf..f5bae8bf44 100644 --- a/src/BufferView_pimpl.C +++ b/src/BufferView_pimpl.C @@ -551,6 +551,10 @@ void BufferView::Pimpl::workAreaMotionNotify(int x, int y, unsigned int state) { if (buffer_ == 0 || !screen) return; + // Only use motion with button 1 + if (!state & Button1MotionMask) + return; + // Check for inset locking if (bv_->the_locking_inset) { LyXCursor cursor = bv_->text->cursor; @@ -561,10 +565,6 @@ void BufferView::Pimpl::workAreaMotionNotify(int x, int y, unsigned int state) state); return; } - - // Only use motion with button 1 - if (!state & Button1MotionMask) - return; /* The selection possible is needed, that only motion events are * used, where the bottom press event was on the drawing area too */ @@ -849,6 +849,7 @@ void BufferView::Pimpl::workAreaButtonRelease(int x, int y, unsigned int button) UpdatableInset *inset = (UpdatableInset *)inset_hit; inset->InsetButtonRelease(bv_, x, y, button); } else { + inset_hit->InsetButtonRelease(bv_, x, y, button); inset_hit->Edit(bv_, x, y, button); } return; @@ -938,7 +939,7 @@ void BufferView::Pimpl::workAreaButtonRelease(int x, int y, unsigned int button) * If hit, the coordinates are changed relative to the inset. * Otherwise coordinates are not changed, and false is returned. */ -Inset * BufferView::Pimpl::checkInsetHit(int & x, int & y, unsigned int button) +Inset * BufferView::Pimpl::checkInsetHit(int & x, int & y, unsigned int /* button */) { if (!screen) return 0; @@ -947,12 +948,8 @@ Inset * BufferView::Pimpl::checkInsetHit(int & x, int & y, unsigned int button) LyXCursor cursor; bv_->text->SetCursorFromCoordinates(cursor, x, y_tmp); -#if 1 - bool move_cursor = true; -#else bool move_cursor = ((cursor.par != bv_->text->cursor.par) || - (cursor.pos != bv_->text->cursor.pos)) && (button < 2); -#endif + (cursor.pos != bv_->text->cursor.pos)); if (cursor.pos < cursor.par->Last() && cursor.par->GetChar(cursor.pos) == LyXParagraph::META_INSET @@ -976,8 +973,8 @@ Inset * BufferView::Pimpl::checkInsetHit(int & x, int & y, unsigned int button) if (x > start_x && x < end_x && y_tmp > cursor.y - tmpinset->ascent(bv_->painter(), font) && y_tmp < cursor.y + tmpinset->descent(bv_->painter(), font)) { - if (move_cursor) - bv_->text->SetCursorFromCoordinates(x, y_tmp); + if (move_cursor && (tmpinset != bv_->the_locking_inset)) + bv_->text->SetCursor(cursor.par,cursor.pos,true); x = x - start_x; // The origin of an inset is on the baseline y = y_tmp - (bv_->text->cursor.y); @@ -1004,8 +1001,8 @@ Inset * BufferView::Pimpl::checkInsetHit(int & x, int & y, unsigned int button) if (x > start_x && x < end_x && y_tmp > cursor.y - tmpinset->ascent(bv_->painter(), font) && y_tmp < cursor.y + tmpinset->descent(bv_->painter(), font)) { - if (move_cursor) - bv_->text->SetCursorFromCoordinates(x, y_tmp); + if (move_cursor && (tmpinset != bv_->the_locking_inset)) + bv_->text->SetCursor(cursor.par,cursor.pos,true); x = x - start_x; // The origin of an inset is on the baseline y = y_tmp - (bv_->text->cursor.y); diff --git a/src/CutAndPaste.C b/src/CutAndPaste.C index fd308dfb43..52ff00ad6a 100644 --- a/src/CutAndPaste.C +++ b/src/CutAndPaste.C @@ -32,7 +32,7 @@ using std::pair; // easy to implement. (Lgb) static LyXParagraph * buf = 0; -static LyXTextClassList::size_type textclass; +static LyXTextClassList::size_type textclass = 0; // for now here this should be in another Cut&Paste Class! // Jürgen, I moved this out of CutAndPaste since it does not operate on any diff --git a/src/LyXAction.C b/src/LyXAction.C index 5202a947f8..46d250c00d 100644 --- a/src/LyXAction.C +++ b/src/LyXAction.C @@ -340,6 +340,8 @@ void LyXAction::init() { LFUN_TAB, "tab-forward", "", Noop }, { LFUN_TABINSERT, "tab-insert", "", Noop }, { LFUN_TABLE, "table-insert", N_("Insert Table"), Noop }, + { LFUN_INSET_TABULAR, "tabular-inset-insert", + N_("Insert a new Tabular Inset"), Noop }, { LFUN_TEX, "tex-mode", N_("Toggle TeX style"), Noop }, { LFUN_INSET_TEXT, "text-inset-insert", N_("Insert a new Text Inset"), Noop }, diff --git a/src/commandtags.h b/src/commandtags.h index 92e8d9939e..231710e401 100644 --- a/src/commandtags.h +++ b/src/commandtags.h @@ -244,8 +244,9 @@ enum kb_action { LFUN_INSET_ERT, // Jug 20000218 LFUN_INSERT_GRAPHICS, // Lgb 20000226 LFUN_INSET_FOOTNOTE, // Jug 20000307 - LFUN_INSET_NUMBER, // Dekel 20000402 + LFUN_INSET_NUMBER, // Dekel 20000402 LFUN_PARAGRAPH_SPACING, // Lgb 20000411 + LFUN_INSET_TABULAR, // Jug 20000412 LFUN_LASTACTION /* this marks the end of the table */ }; diff --git a/src/debug.C b/src/debug.C index 6928f52a86..0306f0fe6f 100644 --- a/src/debug.C +++ b/src/debug.C @@ -44,6 +44,7 @@ static error_item errorTags[] = { { Debug::ROFF, "roff", "Keep *roff temporary files"}, { Debug::ACTION, "action", "User commands"}, { Debug::LYXLEX, "lyxlex", "The LyX Lexxer"}, + { Debug::INSETS, "insets", "LyX Insets"}, { Debug::NONE, "none", "No debugging message"}, { Debug::ANY, "any", "All debugging messages"} }; diff --git a/src/debug.h b/src/debug.h index b854283af0..8f787f728c 100644 --- a/src/debug.h +++ b/src/debug.h @@ -50,14 +50,16 @@ struct Debug { /// LYXLEX = (1 << 15), /// - DEPEND = (1 << 16) + DEPEND = (1 << 16), + /// + INSETS = (1 << 17) }; /// static const type ANY = type(INFO | INIT | KEY | TOOLBAR | PARSER | LYXRC | KBMAP | LATEX | MATHED | FONT | TCLASS | LYXVC | LYXSERVER | ROFF | ACTION | LYXLEX | - DEPEND); + DEPEND | INSETS); /// friend inline void operator|=(Debug::type & d1, Debug::type d2); diff --git a/src/insets/Makefile.am b/src/insets/Makefile.am index 1480e4d383..276a510daf 100644 --- a/src/insets/Makefile.am +++ b/src/insets/Makefile.am @@ -52,6 +52,8 @@ libinsets_la_SOURCES = \ insetref.h \ insetspecialchar.C \ insetspecialchar.h \ + insettabular.C \ + insettabular.h \ insettext.C \ insettext.h \ insettoc.C \ diff --git a/src/insets/inset.C b/src/insets/inset.C index 430dca4c75..2bf3430274 100644 --- a/src/insets/inset.C +++ b/src/insets/inset.C @@ -122,6 +122,14 @@ void UpdatableInset::ToggleInsetCursor(BufferView *) { } +void UpdatableInset::ShowInsetCursor(BufferView *) +{ +} + +void UpdatableInset::HideInsetCursor(BufferView *) +{ +} + void UpdatableInset::Edit(BufferView * bv, int, int, unsigned int) { @@ -170,10 +178,9 @@ UpdatableInset::LocalDispatch(BufferView *, int, string const &) return UNDISPATCHED; } -int UpdatableInset::getMaxWidth(Painter & pain) const +int UpdatableInset::getMaxWidth(Painter & pain, UpdatableInset const *inset) const { - if (owner_) - return owner_->getMaxWidth(pain); + if (owner()) + return static_cast(owner())->getMaxWidth(pain, inset); return pain.paperWidth(); } - diff --git a/src/insets/insetcollapsable.C b/src/insets/insetcollapsable.C index 3cde4b52d5..289f1614e1 100644 --- a/src/insets/insetcollapsable.C +++ b/src/insets/insetcollapsable.C @@ -25,11 +25,12 @@ InsetCollapsable::InsetCollapsable(Buffer * bf) { collapsed = true; label = "Label"; - autocolapse = true; + autocollapse = true; autoBreakRows = true; framecolor = LColor::footnoteframe; widthOffset = 10; - button_x = button_top_y = button_bottom_y = top_x = -1; + button_length = button_top_y = button_bottom_y = 0; + setInsetName("Collapsable"); } @@ -42,6 +43,31 @@ Inset * InsetCollapsable::Clone() const return result; } +void InsetCollapsable::Write(ostream & os) const +{ + os << getInsetName() << "\n\ncollapsed "; + if (display()) + os << "false\n"; + else + os << "true\n"; + WriteParagraphData(os); +} + + +void InsetCollapsable::Read(LyXLex & lex) +{ + if (lex.IsOK()) { + lex.next(); + string token = lex.GetString(); + if (token == "collapsed") { + lex.next(); + collapsed = lex.GetBool(); + } + } + InsetText::Read(lex); +} + + int InsetCollapsable::ascent_collapsed(Painter & pain, LyXFont const &) const { int width = 0, ascent = 0, descent = 0; @@ -92,7 +118,7 @@ int InsetCollapsable::width(Painter & pain, LyXFont const & font) const if (collapsed) return width_collapsed(pain, font); - return getMaxWidth(pain) - widthOffset + 2; + return getMaxWidth(pain, this) - widthOffset + 2; } @@ -109,41 +135,39 @@ void InsetCollapsable::draw_collapsed(Painter & pain, LyXFont const &, void InsetCollapsable::draw(Painter & pain, LyXFont const & f, int baseline, float & x) const { + button_length = width_collapsed(pain, labelfont) + 2; + button_top_y = -ascent_collapsed(pain, f); + button_bottom_y = descent_collapsed(pain, f); if (collapsed) { draw_collapsed(pain, f, baseline, x); return; } - top_x = int(x); - top_baseline = baseline; - draw_collapsed(pain, f, baseline, x); - button_x = int(x); - button_top_y = -ascent_collapsed(pain, f); - button_bottom_y = descent_collapsed(pain, f); - - maxWidth = getMaxWidth(pain) - button_x; - x += 2; + int - w = maxWidth - widthOffset, - h = ascent(pain,f) + descent(pain,f); + top_x = int(x); + + draw_collapsed(pain, f, baseline, x); + x += 2; + + int w = getMaxTextWidth(pain,this); + int h = ascent(pain,f) + descent(pain,f); pain.rectangle(int(x), baseline - ascent(pain, f), w, h, framecolor); x += 4; - top_x = int(x - top_x); + drawTextXOffset = int(x) - top_x; InsetText::draw(pain, f, baseline, x); } void InsetCollapsable::Edit(BufferView *bv, int x, int y, unsigned int button) { - if (collapsed) { + if (collapsed && autocollapse) { collapsed = false; UpdateLocal(bv, true); InsetText::Edit(bv, 0, 0, button); - } else if (button && (x < button_x)) { - return; - } else { - InsetText::Edit(bv, x-top_x, y, button); + } else if (!collapsed) { + InsetText::Edit(bv, x, y, button); } } @@ -157,45 +181,69 @@ Inset::EDITABLE InsetCollapsable::Editable() const void InsetCollapsable::InsetUnlock(BufferView *bv) { - if (autocolapse) { + if (autocollapse) { collapsed = true; } InsetText::InsetUnlock(bv); - UpdateLocal(bv, true); + UpdateLocal(bv, false); } void InsetCollapsable::UpdateLocal(BufferView * bv, bool flag) { - maxWidth = getMaxWidth(bv->painter()) - - width_collapsed(bv->painter(), labelfont); InsetText::UpdateLocal(bv, flag); } void InsetCollapsable::InsetButtonPress(BufferView *bv,int x,int y,int button) { - if ((x >= button_x) && (y >= button_top_y)) { - InsetText::InsetButtonPress(bv, x-top_x, y, button); + if (!collapsed && (x >= button_length)) { + InsetText::InsetButtonPress(bv, x, y, button); } } void InsetCollapsable::InsetButtonRelease(BufferView *bv, int x, int y, int button) { - if ((x < button_x) && (y >= button_top_y) && (y <= button_bottom_y)) { - collapsed = true; - UpdateLocal(bv, false); - bv->unlockInset(this); - } else if ((x >= button_x) && (y >= button_top_y)) { - InsetText::InsetButtonRelease(bv, x-top_x, y, button); + if ((x >= 0) && (x < button_length) && + (y >= button_top_y) && (y < button_bottom_y)) { + if (collapsed) { + collapsed = false; + InsetText::InsetButtonRelease(bv, 0, 0, button); + UpdateLocal(bv, true); + } else { + collapsed = true; + UpdateLocal(bv, false); + bv->unlockInset(this); + } + } else if (!collapsed && (x >= button_length) && (y >= button_top_y)) { + InsetText::InsetButtonRelease(bv, x, y, button); } } - -void InsetCollapsable::InsetMotionNotify(BufferView *bv, int x, int y, int button) +void InsetCollapsable::InsetMotionNotify(BufferView *bv, int x, int y, int state) { - if ((x >= button_x) && (y >= button_top_y)) { - InsetText::InsetMotionNotify(bv, x-top_x, y, button); + if (x >= button_length) { + InsetText::InsetMotionNotify(bv, x, y, state); } } + +int InsetCollapsable::getMaxWidth(Painter & pain, UpdatableInset const * inset) const +{ + if ((this == inset) && !owner()) + return pain.paperWidth(); + if (this == inset) + return (static_cast(owner())->getMaxWidth(pain,inset)); + if (owner()) + return (static_cast(owner())->getMaxWidth(pain,inset)- + width_collapsed(pain, labelfont) - 2 - widthOffset); + + return pain.paperWidth()-width_collapsed(pain, labelfont)-2-widthOffset; +} + +int InsetCollapsable::getMaxTextWidth(Painter & pain, + UpdatableInset const * inset, int) const +{ + return getMaxWidth(pain, inset) - + width_collapsed(pain, labelfont) - widthOffset - 2; +} diff --git a/src/insets/insetcollapsable.h b/src/insets/insetcollapsable.h index 9c5a34b389..0fe13d317a 100644 --- a/src/insets/insetcollapsable.h +++ b/src/insets/insetcollapsable.h @@ -41,6 +41,10 @@ public: /// Inset * Clone() const; /// + void Read(LyXLex &); + /// + void Write(std::ostream &) const; + /// int ascent(Painter &, LyXFont const &) const; /// int descent(Painter &, LyXFont const &) const; @@ -67,7 +71,9 @@ public: /// void setLabelFont(LyXFont & f) { labelfont = f; } /// - void setAutoCollapse(bool f) { autocolapse = f; } + void setAutoCollapse(bool f) { autocollapse = f; } + /// + int getMaxWidth(Painter & pain, UpdatableInset const *) const; protected: /// @@ -80,6 +86,8 @@ protected: void draw_collapsed(Painter & pain, const LyXFont &, int , float &) const; /// void UpdateLocal(BufferView *, bool); + /// + int getMaxTextWidth(Painter & pain, UpdatableInset const *, int x=0) const; /// bool collapsed; @@ -92,11 +100,12 @@ private: /// LyXFont labelfont; /// - bool autocolapse; + bool autocollapse; /// mutable int - top_baseline, top_x, - button_x, button_top_y, button_bottom_y; + button_length, button_top_y, button_bottom_y; + /// + int widthOffset; }; #endif diff --git a/src/insets/insetert.C b/src/insets/insetert.C index bbbd43edc2..795ca2c042 100644 --- a/src/insets/insetert.C +++ b/src/insets/insetert.C @@ -36,6 +36,7 @@ InsetERT::InsetERT(Buffer * bf) labelfont.setColor(LColor::ert); setLabelFont(labelfont); setAutoCollapse(false); + setInsetName("ERT"); } @@ -43,17 +44,12 @@ Inset * InsetERT::Clone() const { InsetERT * result = new InsetERT(buffer); result->init(buffer, this); + + result->collapsed = collapsed; return result; } -void InsetERT::Write(ostream & os) const -{ - os << "ERT\n"; - WriteParagraphData(os); -} - - char const * InsetERT::EditMessage() const { return _("Opened ERT Inset"); diff --git a/src/insets/insetert.h b/src/insets/insetert.h index 91917b24be..d49fae2742 100644 --- a/src/insets/insetert.h +++ b/src/insets/insetert.h @@ -36,8 +36,6 @@ public: /// Inset * Clone() const; /// - void Write(std::ostream &) const; - /// char const * EditMessage() const; /// bool InsertInset(BufferView *, Inset *); diff --git a/src/insets/insetfoot.C b/src/insets/insetfoot.C index ed2fb66624..ee5316f97c 100644 --- a/src/insets/insetfoot.C +++ b/src/insets/insetfoot.C @@ -33,6 +33,7 @@ InsetFoot::InsetFoot(Buffer * bf) font.setColor(LColor::footnote); setLabelFont(font); setAutoCollapse(false); + setInsetName("Foot"); } @@ -54,41 +55,15 @@ char const * InsetFoot::EditMessage() const int InsetFoot::Latex(ostream & os, bool fragile, bool fp) const { - if (fragile) - os << "\\footnote{"; // was footnotemark but that won't work - else - os << "\\footnote{"; - - int i = InsetText::Latex(os, fragile, fp); - os << "}"; - - return i; -} - - -void InsetFoot::Write(ostream & os) const -{ - os << "Foot\n" - << "\ncollapsed "; - if (display()) - os << "false\n"; - else - os << "true\n"; - WriteParagraphData(os); -} - - -void InsetFoot::Read(LyXLex & lex) -{ - if (lex.IsOK()) { - lex.next(); - string token = lex.GetString(); - if (token == "collapsed") { - lex.next(); - collapsed = lex.GetBool(); - } - } - InsetText::Read(lex); + if (fragile) + os << "\\footnote{"; // was footnotemark but that won't work + else + os << "\\footnote{"; + + int i = InsetText::Latex(os, fragile, fp); + os << "}"; + + return i; } diff --git a/src/insets/insetfoot.h b/src/insets/insetfoot.h index a08fa5a01f..c3cadca668 100644 --- a/src/insets/insetfoot.h +++ b/src/insets/insetfoot.h @@ -39,10 +39,6 @@ public: /// int Latex(std::ostream &, bool fragile, bool fp) const; /// - void Write(std::ostream &) const; - /// - void Read(LyXLex &); - /// const char * EditMessage() const; /// bool InsertInset(BufferView *, Inset * inset); diff --git a/src/insets/insettabular.C b/src/insets/insettabular.C new file mode 100644 index 0000000000..f14093d070 --- /dev/null +++ b/src/insets/insettabular.C @@ -0,0 +1,964 @@ +/* This file is part of + * ====================================================== + * + * LyX, The Document Processor + * + * Copyright (C) 2000 The LyX Team. + * + *====================================================== + */ + +#include + +#include +#include + +#include + +#ifdef __GNUG__ +#pragma implementation +#endif + +#include "insettabular.h" + +#include "buffer.h" +#include "commandtags.h" +#include "LaTeXFeatures.h" +#include "Painter.h" +#include "font.h" +#include "insets/insettext.h" + +const int ADD_TO_HEIGHT = 2; +const int ADD_TO_TABLE_WIDTH = 2; + +using std::ostream; +using std::ifstream; + +InsetTabular::InsetTabular(Buffer * buf, int rows=1, int columns=1) +{ + if (rows <= 0) + rows = 1; + if (columns <= 0) + columns = 1; + tabular = new LyXTable(rows,columns,buf); + the_locking_inset = 0; + buffer = buf; + cursor_visible = false; + old_x = -1; + sel_pos_start = sel_pos_end = 0; + no_selection = false; + init = true; +} + +InsetTabular::InsetTabular(InsetTabular const & tab, Buffer * buf) +{ + tabular = new LyXTable(*(tab.tabular), buf); + the_locking_inset = 0; + buffer = buf; + cursor_visible = false; + old_x = -1; + sel_pos_start = sel_pos_end = 0; + no_selection = false; + init = true; +} + +InsetTabular::~InsetTabular() +{ + if (tabular) + delete tabular; +} + + +InsetTabular * InsetTabular::Clone() const +{ + InsetTabular * t = new InsetTabular(*this, buffer); + return t; +} + + +void InsetTabular::Write(ostream & os) const +{ + os << "\\begin_inset Tabular\n"; + tabular->Write(os,false); + os << "\\end_inset\n"; +} + + +void InsetTabular::Read(LyXLex & lex) +{ + if (tabular) + delete tabular; + +// bool old_format = (lex.GetString() == "\\LyXTable"); + tabular = new LyXTable(lex, buffer); + init = true; +} + + +int InsetTabular::ascent(Painter & pain, LyXFont const & font) const +{ + if (init) { + calculate_width_of_cells(pain, font); + init = false; + } + return tabular->AscentOfRow(0); +} + + +int InsetTabular::descent(Painter & pain, LyXFont const & font) const +{ + if (init) { + calculate_width_of_cells(pain, font); + init = false; + } + return tabular->HeightOfTable() - tabular->AscentOfRow(0); +} + + +int InsetTabular::width(Painter & pain, LyXFont const & font) const +{ + if (init) { + calculate_width_of_cells(pain, font); + init = false; + } + return tabular->WidthOfTable() + (2 * ADD_TO_TABLE_WIDTH); +} + + +void InsetTabular::draw(Painter & pain, const LyXFont & font, int, + float &) const +{ + calculate_width_of_cells(pain, font); +} + + +const char * InsetTabular::EditMessage() const +{ + return _("Opened Tabular Inset"); +} + + +void InsetTabular::Edit(BufferView * bv, int x, int y, unsigned int button) +{ + UpdatableInset::Edit(bv, x, y, button); + + bv->lockInset(this); + the_locking_inset = 0; + inset_pos = inset_x = inset_y = 0; + no_selection = true; + setPos(x,y); + sel_pos_start = sel_pos_end = actpos; + sel_cell_start = sel_cell_end = actcell; +// bv->getOwner()->getPopups().updateFormTable(); +} + + +void InsetTabular::InsetUnlock(BufferView * bv) +{ + if (the_locking_inset) + the_locking_inset->InsetUnlock(bv); + HideInsetCursor(bv); + the_locking_inset = 0; + if (hasCharSelection()) { + sel_pos_start = sel_pos_end = actpos; + UpdateLocal(bv, false); + } else + sel_pos_start = sel_pos_end = actpos; + no_selection = false; +} + +bool InsetTabular::LockInsetInInset(UpdatableInset *) +{ + return true; +} + + +bool InsetTabular::UnlockInsetInInset(BufferView * bv, UpdatableInset * inset, + bool lr) +{ + if (!the_locking_inset) + return false; + if (the_locking_inset == inset) { + the_locking_inset->InsetUnlock(bv); + the_locking_inset = 0; + if (lr) + moveRight(false); + return true; + } + return the_locking_inset->UnlockInsetInInset(bv, inset, lr); +} + + +void InsetTabular::UpdateLocal(BufferView * bv, bool flag) +{ + resetPos(); + bv->updateInset(this, flag); +} + +bool InsetTabular::UpdateInsetInInset(BufferView * bv, Inset * inset) +{ + if (!the_locking_inset) + return false; + if (the_locking_inset != inset) + return the_locking_inset->UpdateInsetInInset(bv, inset); + UpdateLocal(bv); + return true; +} + +void InsetTabular::InsetButtonRelease(BufferView *bv, int x, int y, int button) +{ + if (the_locking_inset) { + the_locking_inset->InsetButtonRelease(bv, x-inset_x,y-inset_y,button); + return; + } + no_selection = false; +} + +void InsetTabular::InsetButtonPress(BufferView *bv, int x, int y, int) +{ + if (hasCharSelection()) { + sel_pos_start = sel_pos_end = 0; + UpdateLocal(bv, false); + } + no_selection = false; + setPos(x,y,false); + if (the_locking_inset) { +#if 0 + UpdatableInset + * inset=0; + if (par->GetChar(actpos)==LYX_META_INSET) + inset=(UpdatableInset*)par->GetInset(actpos); + if (the_locking_inset == inset) { + the_locking_inset->InsetButtonPress(bv,x-inset_x,y-inset_y,button); + return; + } else if (inset) { + // otherwise unlock the_locking_inset and lock the new inset + inset_x = cx-top_x; + inset_y = cy; + inset_pos = actpos; + the_locking_inset->InsetUnlock(bv); + the_locking_inset = inset; + the_locking_inset->Edit(bv, x - inset_x, y - inset_y, button); + return; + } +#endif + // otherwise only unlock the_locking_inset + the_locking_inset->InsetUnlock(bv); + } +#if 0 + int + oldcell = actcell; +#endif + setPos(x,y); + the_locking_inset = 0; + sel_pos_start = sel_pos_end = actpos; + sel_cell_start = sel_cell_end = actcell; +#if 0 + if (button == 3) + bview->getOwner()->getPopups().showFormTable(); + else if (oldcell != actcell) + bview->getOwner()->getPopups().updateFormTable(); +#endif +} + + +void InsetTabular::InsetMotionNotify(BufferView * bv, int x, int y, int button) +{ + if (the_locking_inset) { + the_locking_inset->InsetMotionNotify(bv, x-inset_x,y-inset_y,button); + return; + } + if (!no_selection) { + int +// oldcell = actcell, + old = sel_pos_end; + + setPos(x,y); + sel_pos_end = actpos; + sel_cell_end = actcell; + if (old != sel_pos_end) + UpdateLocal(bv, false); +#if 0 + if (oldcell != actcell) + bview->getOwner()->getPopups().updateFormTable(); +#endif + } + no_selection = false; +} + + +void InsetTabular::InsetKeyPress(XKeyEvent * xke) +{ + if (the_locking_inset) { + the_locking_inset->InsetKeyPress(xke); + return; + } +} + + +UpdatableInset::RESULT InsetTabular::LocalDispatch(BufferView *bv, int action, + string const & arg) +{ + no_selection = false; + if (UpdatableInset::LocalDispatch(bv, action, arg)) { + resetPos(); + return DISPATCHED; + } + + UpdatableInset::RESULT + result=DISPATCHED; + if ((action < 0) && arg.empty()) + return FINISHED; + + if ((action != LFUN_DOWN) && (action != LFUN_UP) && + (action != LFUN_DOWNSEL) && (action != LFUN_UPSEL)) + old_x = -1; + if (the_locking_inset) { + result=the_locking_inset->LocalDispatch(bv, action, arg); + if (result == DISPATCHED) { + setWidthOfCell(actpos,actcell,actrow); + the_locking_inset->ToggleInsetCursor(bv); + UpdateLocal(bv, false); + the_locking_inset->ToggleInsetCursor(bv); + return result; + } else if (result == FINISHED) { + if ((action == LFUN_RIGHT) || (action == -1)) { + actpos = inset_pos + 1; + resetPos(); + } + the_locking_inset=0; + result = DISPATCHED; + return result; + } + } + + HideInsetCursor(bv); + switch (action) { + // Normal chars not handled here + case -1: + break; + // --- Cursor Movements --------------------------------------------- + case LFUN_RIGHTSEL: + moveRight(false); + sel_pos_end = actpos; + UpdateLocal(bv, false); + break; + case LFUN_RIGHT: + result= DISPATCH_RESULT(moveRight()); + if (hasCharSelection()) { + sel_pos_start = sel_pos_end = actpos; + UpdateLocal(bv, false); + } else + sel_pos_start = sel_pos_end = actpos; + break; + case LFUN_LEFTSEL: + moveLeft(false); + sel_pos_end = actpos; + UpdateLocal(bv, false); + break; + case LFUN_LEFT: + result= DISPATCH_RESULT(moveLeft()); + if (hasCharSelection()) { + sel_pos_start = sel_pos_end = actpos; + UpdateLocal(bv, false); + } else + sel_pos_start = sel_pos_end = actpos; + break; + case LFUN_DOWNSEL: + moveDown(false); + sel_pos_end = actpos; + UpdateLocal(bv, false); + break; + case LFUN_DOWN: + result= DISPATCH_RESULT(moveDown()); + if (hasCharSelection()) { + sel_pos_start = sel_pos_end = actpos; + UpdateLocal(bv, false); + } else + sel_pos_start = sel_pos_end = actpos; + break; + case LFUN_UPSEL: + moveUp(false); + sel_pos_end = actpos; + UpdateLocal(bv, false); + break; + case LFUN_UP: + result= DISPATCH_RESULT(moveUp()); + if (hasCharSelection()) { + sel_pos_start = sel_pos_end = actpos; + UpdateLocal(bv, false); + } else + sel_pos_start = sel_pos_end = actpos; + break; + case LFUN_BACKSPACE: + break; + case LFUN_DELETE: + break; + case LFUN_HOME: + break; + case LFUN_END: + break; + case LFUN_TAB: + if (hasCharSelection()) { + sel_pos_start = sel_pos_end = actpos; + UpdateLocal(bv, false); + } + sel_pos_start = sel_pos_end = actpos; + moveNextCell(); + break; + default: + result = UNDISPATCHED; + break; + } + if (result!=FINISHED) { + if (!the_locking_inset) { +#if 0 + if (oldcell != actcell) + bview->getOwner()->getPopups().updateFormTable(); +#endif + ShowInsetCursor(bv); + } + } else + bv->unlockInset(this); + return result; +} + + +int InsetTabular::Latex(ostream & os, bool, bool) const +{ + return tabular->Latex(os); +} + +int InsetTabular::Linuxdoc(ostream &) const +{ + return 0; +} + +int InsetTabular::DocBook(ostream &) const +{ + return 0; +} + +void InsetTabular::Validate(LaTeXFeatures & features) const +{ + if (tabular->IsLongTable()) + features.longtable = true; +} + + +void InsetTabular::calculate_width_of_cells(Painter & pain, LyXFont const & font) const +{ + int + cell=-1, + i,j, + maxAsc, maxDesc; + InsetText + *inset; + + for(i=0; i < tabular->rows; ++i) { + maxAsc = maxDesc = 0; + for(j=0; j < tabular->columns; ++j) { + if (tabular->IsPartOfMultiColumn(i,j)) + continue; + ++cell; + inset = tabular->GetCellInset(cell); + maxAsc = max(maxAsc, inset->ascent(pain, font)); + maxDesc = max(maxDesc, inset->descent(pain, font)); + tabular->SetWidthOfCell(cell, inset->width(pain, font)); + } + tabular->SetAscentOfRow(i,maxAsc+ADD_TO_HEIGHT); + tabular->SetDescentOfRow(i,maxDesc+ADD_TO_HEIGHT); + } +} + + +void InsetTabular::DrawCellLines(Painter & pain, int x, int baseline, + int row, int cell) +{ + // Juergen, have you thought about drawing the on-off lines in a + // different color (gray of some kind), especially since those + // lines will not be there on the hardcopy anyway. (Lgb) + int + x_old = x; + bool + on_off; + + x_old -= tabular->WidthOfColumn(cell); + on_off = !tabular->TopLine(cell); + if ((!on_off || !tabular->TopAlreadyDrawed(cell)) && + !tabular->IsContRow(cell)) + pain.line(x_old, baseline - tabular->AscentOfRow(row), + x, baseline - tabular->AscentOfRow(row), + LColor::tableline, + on_off ? Painter::line_onoffdash:Painter::line_solid); + on_off = !tabular->BottomLine(cell); + if ((!on_off && !tabular->RowHasContRow(cell)) || + tabular->VeryLastRow(cell)) + pain.line(x_old ,baseline + tabular->DescentOfRow(row), + x, baseline + tabular->DescentOfRow(row), + LColor::tableline, + on_off ? Painter::line_onoffdash:Painter::line_solid); + on_off = !tabular->LeftLine(cell); + pain.line(x_old, baseline - tabular->AscentOfRow(row), + x_old, baseline + tabular->DescentOfRow(row), + LColor::tableline, + on_off ? Painter::line_onoffdash:Painter::line_solid); + on_off = !tabular->RightLine(cell); + pain.line(x - tabular->AdditionalWidth(cell), + baseline - tabular->AscentOfRow(row), + x - tabular->AdditionalWidth(cell), + baseline + tabular->DescentOfRow(row), + LColor::tableline, + on_off ? Painter::line_onoffdash:Painter::line_solid); +} + + +void InsetTabular::GetCursorPos(int & x, int & y) +{ + x = cx-top_x; + y = cy; +} + + +void InsetTabular::ToggleInsetCursor(BufferView * bv) +{ + if (the_locking_inset) { + the_locking_inset->ToggleInsetCursor(bv); + return; + } + int + x=0,y=0, + asc,desc; + + LyXFont + font; // = the_locking_inset->GetFont(par, actpos); + + asc = lyxfont::maxAscent(font); + desc = lyxfont::maxDescent(font); + + if (cursor_visible) + bv->hideLockedInsetCursor(); + else + bv->showLockedInsetCursor(cx+x, cy+y, asc, desc); + cursor_visible = !cursor_visible; +} + + +void InsetTabular::ShowInsetCursor(BufferView * bv) +{ + if (!cursor_visible) { + int + asc,desc; + LyXFont + font; // = GetFont(par, actpos); + + asc = lyxfont::maxAscent(font); + desc = lyxfont::maxDescent(font); + bv->fitLockedInsetCursor(cx, cy, asc, desc); + bv->showLockedInsetCursor(cx, cy, asc, desc); + cursor_visible = true; + } +} + + +void InsetTabular::HideInsetCursor(BufferView * bv) +{ + if (cursor_visible) + ToggleInsetCursor(bv); +} + + +void InsetTabular::setPos(int, int, bool) +{ +} + +void InsetTabular::setWidthOfCell(int, int, int) +{ +} + +bool InsetTabular::moveRight(bool) +{ + return false; +} + +bool InsetTabular::moveLeft(bool) +{ + return false; +} + +bool InsetTabular::moveUp(bool) +{ + return false; +} + +bool InsetTabular::moveDown(bool) +{ + return false; +} + +bool InsetTabular::moveNextCell() +{ + return false; +} + +bool InsetTabular::movePrevCell() +{ + return false; +} + +void InsetTabular::resetPos() +{ +} + +bool InsetTabular::Delete() +{ + return true; +} + +void InsetTabular::SetFont(LyXFont const &) +{ +} + +void InsetTabular::TableFeatures(int, string) +{ +#if 0 + int + i, + selection_start, + selection_end, + setLines = 0, + setAlign = LYX_ALIGN_LEFT, + lineSet; + bool + what; + + switch (feature) { + case LyXTable::ALIGN_LEFT: + setAlign=LYX_ALIGN_LEFT; + break; + case LyXTable::ALIGN_RIGHT: + setAlign=LYX_ALIGN_RIGHT; + break; + case LyXTable::ALIGN_CENTER: + setAlign=LYX_ALIGN_CENTER; + break; + default: + break; + } + if (hasCellSelection()) { + if (sel_cell_start > sel_cell_end) { + selection_start = sel_cell_end; + selection_end = sel_cell_start; + } else { + selection_start = sel_cell_start; + selection_end = sel_cell_end; + } + } else + selection_start = selection_end = actcell; + switch (feature) { + case LyXTable::SET_PWIDTH: + tabular->SetPWidth(actcell,val); + break; + case LyXTable::SET_SPECIAL_COLUMN: + case LyXTable::SET_SPECIAL_MULTI: + tabular->SetAlignSpecial(actcell,val,feature); + break; + case LyXTable::APPEND_ROW: + { + int + pos = actpos, + cell_org = actcell, + cell = actcell; + + // if there is a ContRow following this row I have to add + // the row after the ContRow's + if ((pos < par->last()) && tabular->RowHasContRow(cell_org)) { + while((pos < par->last()) && !tabular->IsContRow(cell)) { + while (pos < par->last() && !par->IsNewline(pos)) + ++pos; + if (pos < par->last()) + ++pos; + ++cell; + } + while((pos < par->last()) && tabular->IsContRow(cell)) { + while (pos < par->last() && !par->IsNewline(pos)) + ++pos; + if (pos < par->last()) + ++pos; + ++cell; + } + cell_org = --cell; + if (pos < par->last()) + --pos; + } + while ((pos < par->last()) && + ((cell == cell_org) || !tabular->IsFirstCell(cell))) { + while ((pos < par->last()) && !par->IsNewline(pos)) + ++pos; + if (pos < par->last()) + ++pos; + ++cell; + } + // insert the new cells + int number = tabular->NumberOfCellsInRow(cell_org); + for (i=0; iInsertChar(pos, LYX_META_NEWLINE); + + // append the row into the table + tabular->AppendRow(cell_org); + calculate_width_of_cells(); + UpdateLocal(); + return; + } + case LyXTable::APPEND_CONT_ROW: + { + int + pos = actpos, + cell_org = actcell, + cell = actcell; + + // if there is already a controw but not for this cell + // the AppendContRow sets only the right values but does + // not actually add a row + if (tabular->RowHasContRow(cell_org) && + (tabular->CellHasContRow(cell_org) < 0)) { + tabular->AppendContRow(cell_org); + calculate_width_of_cells(); + UpdateLocal(); + return; + } + while ((pos < par->last()) && + ((cell == cell_org) || !tabular->IsFirstCell(cell))) { + while (pos < par->last() && !par->IsNewline(pos)) + ++pos; + if (pos < par->last()) + ++pos; + ++cell; + } + // insert the new cells + int number = tabular->NumberOfCellsInRow(cell_org); + for (i=0; iInsertChar(pos, LYX_META_NEWLINE); + // append the row into the table + tabular->AppendContRow(cell_org); + calculate_width_of_cells(); + UpdateLocal(); + return; + } + case LyXTable::APPEND_COLUMN: + { + int + pos = 0, + cell_org = actcell, + cell = 0; + do { + if (pos && (par->IsNewline(pos-1))) { + if (tabular->AppendCellAfterCell(cell_org, cell)) { + par->InsertChar(pos, LYX_META_NEWLINE); + if (pos <= actpos) + ++actpos; + ++pos; + } + ++cell; + } + ++pos; + } while (pos <= par->last()); + // remember that the very last cell doesn't end with a newline. + // This saves one byte memory per table ;-) + if (tabular->AppendCellAfterCell(cell_org, cell)) + par->InsertChar(par->last(), LYX_META_NEWLINE); + // append the column into the table + tabular->AppendColumn(cell_org); + calculate_width_of_cells(); + UpdateLocal(); + return; + } + case LyXTable::DELETE_ROW: + RemoveTableRow(); + calculate_width_of_cells(); + UpdateLocal(); + return; + case LyXTable::DELETE_COLUMN: + { + int pos = 0; + int cell = 0; + do { + if (!pos || (par->IsNewline(pos-1))){ + if (tabular->DeleteCellIfColumnIsDeleted(cell, actcell)) { + // delete one cell + while (pos < par->last() && !par->IsNewline(pos)) + par->Erase(pos); + if (pos < par->last()) + par->Erase(pos); + else + par->Erase(pos - 1); // the missing newline + // at the end of a table + --pos; // because of ++pos below + } + ++cell; + } + ++pos; + } while (pos <= par->last()); + /* delete the column from the table */ + tabular->DeleteColumn(actcell); + calculate_width_of_cells(); + UpdateLocal(); + return; + } + case LyXTable::TOGGLE_LINE_TOP: + lineSet = !tabular->TopLine(actcell); + for(i=selection_start; i<=selection_end; ++i) + tabular->SetTopLine(i,lineSet); + calculate_width_of_cells(); + UpdateLocal(); + return; + + case LyXTable::TOGGLE_LINE_BOTTOM: + lineSet = !tabular->BottomLine(actcell); + for(i=selection_start; i<=selection_end; ++i) + tabular->SetBottomLine(i,lineSet); + calculate_width_of_cells(); + UpdateLocal(); + return; + + case LyXTable::TOGGLE_LINE_LEFT: + lineSet = !tabular->LeftLine(actcell); + for(i=selection_start; i<=selection_end; ++i) + tabular->SetLeftLine(i,lineSet); + calculate_width_of_cells(); + UpdateLocal(); + return; + + case LyXTable::TOGGLE_LINE_RIGHT: + lineSet = !tabular->RightLine(actcell); + for(i=selection_start; i<=selection_end; ++i) + tabular->SetRightLine(i,lineSet); + calculate_width_of_cells(); + UpdateLocal(); + return; + case LyXTable::ALIGN_LEFT: + case LyXTable::ALIGN_RIGHT: + case LyXTable::ALIGN_CENTER: + for(i=selection_start; i<=selection_end; ++i) + tabular->SetAlignment(i,setAlign); + UpdateLocal(); + return; + case LyXTable::MULTICOLUMN: + { + if (tabular->row_of_cell(selection_start) != + tabular->row_of_cell(selection_end)) { + WriteAlert(_("Impossible Operation!"), + _("Multicolumns can only be horizontally."), + _("Sorry.")); + return; + } + // just multicol for one Single Cell + if (!hasCellSelection()) { + // check wether we are completly in a multicol + if (tabular->IsMultiColumn(actcell)) { + int + newlines, + pos = actpos; + if ((newlines=tabular->UnsetMultiColumn(actcell))) { + while ((pos < par->last()) && !par->IsNewline(pos)) + ++pos; + for (;newlines;--newlines) + par->InsertChar(pos, LYX_META_NEWLINE); + } + calculate_width_of_cells(); + } else { + tabular->SetMultiColumn(actcell, 1); + } + UpdateLocal(); + return; + } + // we have a selection so this means we just add all this + // cells to form a multicolumn cell + int + number = 1, + s_start, s_end; + + if (sel_pos_start > sel_pos_end) { + s_start = sel_pos_end; + s_end = sel_pos_start; + } else { + s_start = sel_pos_start; + s_end = sel_pos_end; + } + for(i=s_start; i < s_end; ++i) { + if (par->IsNewline(i)) { + par->Erase(i); + // check for double-blanks + if ((i && !par->IsLineSeparator(i-1)) && + (i < par->last()) && !par->IsLineSeparator(i)) + par->InsertChar(i, ' '); + else + --i; + ++number; + } + } + tabular->SetMultiColumn(selection_start,number); + actpos = s_start; + sel_cell_end = sel_cell_start; + calculate_width_of_cells(); + UpdateLocal(); + return; + } + case LyXTable::SET_ALL_LINES: + setLines = 1; + case LyXTable::UNSET_ALL_LINES: + for(i=selection_start; i<=selection_end; ++i) + tabular->SetAllLines(i, setLines); + calculate_width_of_cells(); + UpdateLocal(); + return; + case LyXTable::SET_LONGTABLE: + tabular->SetLongTable(true); + UpdateLocal(); // because this toggles displayed + return; + case LyXTable::UNSET_LONGTABLE: + tabular->SetLongTable(false); + UpdateLocal(); // because this toggles displayed + return; + case LyXTable::SET_ROTATE_TABLE: + tabular->SetRotateTable(true); + return; + case LyXTable::UNSET_ROTATE_TABLE: + tabular->SetRotateTable(false); + return; + case LyXTable::SET_ROTATE_CELL: + for(i=selection_start; i<=selection_end; ++i) + tabular->SetRotateCell(i,true); + return; + case LyXTable::UNSET_ROTATE_CELL: + for(i=selection_start; i<=selection_end; ++i) + tabular->SetRotateCell(i,false); + return; + case LyXTable::SET_LINEBREAKS: + what = !tabular->Linebreaks(tabular->FirstVirtualCell(actcell)); + for(i=selection_start; i<=selection_end; ++i) + tabular->SetLinebreaks(i,what); + return; + case LyXTable::SET_LTFIRSTHEAD: + tabular->SetLTHead(actcell,true); + return; + case LyXTable::SET_LTHEAD: + tabular->SetLTHead(actcell,false); + return; + case LyXTable::SET_LTFOOT: + tabular->SetLTFoot(actcell,false); + return; + case LyXTable::SET_LTLASTFOOT: + tabular->SetLTFoot(actcell,true); + return; + case LyXTable::SET_LTNEWPAGE: + what = !tabular->LTNewPage(actcell); + tabular->SetLTNewPage(actcell,what); + return; + } +#endif +} + +void InsetTabular::RemoveTableRow() +{ +} diff --git a/src/insets/insettabular.h b/src/insets/insettabular.h new file mode 100644 index 0000000000..d5f322aebe --- /dev/null +++ b/src/insets/insettabular.h @@ -0,0 +1,188 @@ +// -*- C++ -*- +/* This file is part of + * ====================================================== + * + * LyX, The Document Processor + * + * Copyright (C) 1995-2000 The LyX Team. + * + *====================================================== + */ +// This is the rewrite of the tabular (table) support. + +// It will probably be a lot of work. + +// One first goal could be to make the inset read the old table format +// and just output it again... no viewing at all. + +// When making the internal structure of tabular support I really think +// that STL containers should be used. This will separate the container from +// the rest of the code, which is a good thing. + +// Ideally the tabular support should do as the mathed and use +// LaTeX in the .lyx file too. + +// Things to think of when desingning the new tabular support: +// - color support (colortbl, color) +// - decimal alignment (dcloumn) +// - custom lines (hhline) +// - rotation +// - multicolumn +// - multirow +// - column styles + +// This is what I have written about tabular support in the LyX3-Tasks file: +// +// o rewrite of table code. Should probably be written as some +// kind of an inset. At least get the code out of the kernel. +// - colortbl -multirow +// - hhline -multicolumn +// - dcolumn +// o enhance longtable support + +// Lgb + +#ifndef INSETTABULAR_H +#define INSETTABULAR_H + +#ifdef __GNUG__ +#pragma interface +#endif + +#include "lyxinset.h" +#include "table.h" +#include "LString.h" + +class LyXLex; +class Painter; +class BufferView; +class Buffer; +class TexRow; + +class InsetTabular : public UpdatableInset { +public: + /// + InsetTabular(Buffer *, int rows=1, int columns=1); + /// + InsetTabular(InsetTabular const &, Buffer *); + /// + ~InsetTabular(); + /// + InsetTabular * InsetTabular::Clone() const; + /// + void Read(LyXLex &); + /// + void Write(std::ostream &) const; + /// + int ascent(Painter &, LyXFont const &) const; + /// + int descent(Painter &, LyXFont const &) const; + /// + int width(Painter &, LyXFont const & f) const; + /// + void draw(Painter & pain, const LyXFont &, int , float &) const; + /// + const char * EditMessage() const; + /// + void Edit(BufferView *, int x, int y, unsigned int); + /// + void InsetUnlock(BufferView *); + /// + bool LockInsetInInset(UpdatableInset *); + /// + bool UnlockInsetInInset(BufferView *, UpdatableInset *, bool lr=false); + /// + void UpdateLocal(BufferView *, bool flag = true); + /// + bool UpdateInsetInInset(BufferView *, Inset *); + /// + bool display() const { return tabular->IsLongTable(); } + /// + void InsetButtonRelease(BufferView *, int, int, int); + /// + void InsetButtonPress(BufferView *, int, int, int); + /// + void InsetMotionNotify(BufferView *, int, int, int); + /// + void InsetKeyPress(XKeyEvent *); + /// + UpdatableInset::RESULT LocalDispatch(BufferView *, int, string const &); + /// + int Latex(std::ostream &, bool, bool) const; + /// + int Linuxdoc(std::ostream &) const; + /// + int DocBook(std::ostream &) const; + /// + void Validate(LaTeXFeatures & features) const; + /// + Inset::Code LyxCode() const { return Inset::TABULAR_CODE; } + /// + void GetCursorPos(int & x, int & y); + /// + void ToggleInsetCursor(BufferView *); + /// + void TableFeatures(int feature, string val=""); + /// + int GetActCell() { return actcell; } + /// + void SetFont(LyXFont const &); + /// + /// Public structures and variables + /// + LyXTable * tabular; + +private: + void calculate_width_of_cells(Painter &, LyXFont const &) const; + /// + void DrawCellLines(Painter &, int x, int baseline, int row, int cell); + /// + void ShowInsetCursor(BufferView *); + /// + void HideInsetCursor(BufferView *); + /// + void setPos(int x, int y, bool activate_inset=true); + /// + void setWidthOfCell(int pos, int cell, int row); + /// + bool moveRight(bool activate_inset=true); + bool moveLeft(bool activate_inset=true); + bool moveUp(bool activate_inset=true); + bool moveDown(bool activate_inset=true); + bool moveNextCell(); + bool movePrevCell(); + bool Delete(); + /// + void resetPos(); + /// + void RemoveTableRow(); + /// + bool hasCharSelection() const {return (sel_pos_start != sel_pos_end);} + bool hasCellSelection() const {return hasCharSelection() && + (sel_cell_start != sel_cell_end);} + /// + /// Private structures and variables + /// + UpdatableInset + * the_locking_inset; + Buffer + * buffer; + int + inset_pos, + inset_x, inset_y, + sel_pos_start, + sel_pos_end, + sel_cell_start, + sel_cell_end, + old_x, + cx, cy, + actpos, + actcell, + actcol, + actrow; + bool + no_selection; + mutable bool + init; +}; +#endif diff --git a/src/insets/insettext.C b/src/insets/insettext.C index 606c17a99a..d06b57abcb 100644 --- a/src/insets/insettext.C +++ b/src/insets/insettext.C @@ -4,7 +4,7 @@ * * LyX, The Document Processor * - * Copyright 1998 The LyX Team. + * Copyright 1998-2000 The LyX Team. * * ====================================================== */ @@ -64,7 +64,6 @@ extern unsigned char getCurrentTextClass(Buffer *); InsetText::InsetText(Buffer * buf) { par = new LyXParagraph(); - widthOffset = 0; init(buf); } @@ -72,7 +71,6 @@ InsetText::InsetText(Buffer * buf) InsetText::InsetText(InsetText const & ins, Buffer * buf) { par = 0; - widthOffset = 0; init(buf, &ins); autoBreakRows = ins.autoBreakRows; } @@ -82,12 +80,13 @@ void InsetText::init(Buffer * buf, InsetText const * ins) the_locking_inset = 0; buffer = buf; cursor_visible = false; - maxWidth = old_x = -1; - actpos = selection_start = selection_end = 0; + cursor.x_fix = -1; + selection_start = selection_end = 0; interline_space = 1; no_selection = false; init_inset = true; maxAscent = maxDescent = insetWidth = 0; + drawTextXOffset = drawTextYOffset = 0; autoBreakRows = false; xpos = 0.0; if (ins) { @@ -97,6 +96,8 @@ void InsetText::init(Buffer * buf, InsetText const * ins) autoBreakRows = ins->autoBreakRows; } par->SetInsetOwner(this); + cursor.par = par; + cursor.pos = 0; } @@ -138,6 +139,7 @@ void InsetText::Read(LyXLex & lex) delete par; par = new LyXParagraph; + par->SetInsetOwner(this); while (lex.IsOK()) { lex.nextToken(); @@ -167,6 +169,7 @@ int InsetText::ascent(Painter & pain, LyXFont const & font) const { if (init_inset) { computeTextRows(pain, xpos); + resetPos(pain); init_inset = false; } if (maxAscent) @@ -179,6 +182,7 @@ int InsetText::descent(Painter & pain, LyXFont const & font) const { if (init_inset) { computeTextRows(pain, xpos); + resetPos(pain); init_inset = false; } if (maxDescent) @@ -191,6 +195,7 @@ int InsetText::width(Painter & pain, LyXFont const &) const { if (init_inset) { computeTextRows(pain, xpos); + resetPos(pain); init_inset = false; } return insetWidth; @@ -207,6 +212,11 @@ void InsetText::draw(Painter & pain, LyXFont const & f, top_baseline = baseline; computeTextRows(pain, x); computeBaselines(baseline); + if (the_locking_inset && (cursor.pos == inset_pos)) { + resetPos(pain); + inset_x = cursor.x - top_x + drawTextXOffset; + inset_y = cursor.y + drawTextYOffset; + } for(RowList::size_type r = 0; r < rows.size() - 1; ++r) { drawRowSelection(pain, rows[r].pos, rows[r + 1].pos, r, rows[r].baseline, x); @@ -328,32 +338,69 @@ void InsetText::Edit(BufferView * bv, int x, int y, unsigned int button) par->SetInsetOwner(this); UpdatableInset::Edit(bv, x, y, button); - bv->lockInset(this); + if (!bv->lockInset(this)) { + lyxerr[Debug::INSETS] << "Cannot lock inset" << endl; + return; + } the_locking_inset = 0; - inset_pos = inset_x = inset_y = 0; - no_selection = true; - setPos(bv, x,y); - selection_start = selection_end = actpos; - current_font = real_current_font = GetFont(par, actpos); + selection_start = selection_end = inset_pos = inset_x = inset_y = 0; +// no_selection = true; + setPos(bv->painter(), x, y); + checkAndActivateInset(bv, x, y, button); + selection_start = selection_end = cursor.pos; + current_font = real_current_font = GetFont(par, cursor.pos); bv->text->FinishUndo(); + UpdateLocal(bv, true); } void InsetText::InsetUnlock(BufferView * bv) { - if (the_locking_inset) + if (the_locking_inset) { the_locking_inset->InsetUnlock(bv); - HideInsetCursor(bv); + the_locking_inset = 0; + } + lyxerr[Debug::INSETS] << "InsetText::InsetUnlock(" << this << + ")" << endl; if (hasSelection()) { - selection_start = selection_end = actpos; + selection_start = selection_end = cursor.pos; UpdateLocal(bv, false); } - the_locking_inset = 0; no_selection = false; } +bool InsetText::LockInsetInInset(BufferView * bv, UpdatableInset * inset) +{ + lyxerr[Debug::INSETS] << "InsetText::LockInsetInInset(" << inset << "): "; + if (!inset) + return false; + if (inset == par->GetInset(cursor.pos)) { + lyxerr[Debug::INSETS] << "OK" << endl; + the_locking_inset = inset; + resetPos(bv->painter()); + inset_x = cursor.x - top_x + drawTextXOffset; + inset_y = cursor.y + drawTextYOffset; + inset_pos = cursor.pos; + return true; + } else if (the_locking_inset && (the_locking_inset == inset)) { + if (cursor.pos == inset_pos) { + lyxerr[Debug::INSETS] << "OK" << endl; + resetPos(bv->painter()); + inset_x = cursor.x - top_x + drawTextXOffset; + inset_y = cursor.y + drawTextYOffset; + } else { + lyxerr[Debug::INSETS] << "cursor.pos != inset_pos" << endl; + } + } else if (the_locking_inset) { + lyxerr[Debug::INSETS] << "MAYBE" << endl; + return the_locking_inset->LockInsetInInset(bv, inset); + } + lyxerr[Debug::INSETS] << "NOT OK" << endl; + return false; +} -bool InsetText::UnlockInsetInInset(BufferView * bv, Inset * inset, bool lr) +bool InsetText::UnlockInsetInInset(BufferView * bv, UpdatableInset * inset, + bool lr) { if (!the_locking_inset) return false; @@ -364,7 +411,7 @@ bool InsetText::UnlockInsetInInset(BufferView * bv, Inset * inset, bool lr) moveRight(bv, false); return true; } - return the_locking_inset->UnlockInsetInInset(bv, inset,lr); + return the_locking_inset->UnlockInsetInInset(bv, inset, lr); } @@ -374,74 +421,103 @@ bool InsetText::UpdateInsetInInset(BufferView * bv, Inset * inset) return false; if (the_locking_inset != inset) return the_locking_inset->UpdateInsetInInset(bv, inset); - float x = inset_x; - inset->draw(bv->painter(), real_current_font, inset_y, x); + lyxerr[Debug::INSETS] << "InsetText::UpdateInsetInInset(" << inset << + ")" << endl; UpdateLocal(bv, true); - return true; -} - - -void InsetText::InsetButtonRelease(BufferView * bv, int x, int y, int button) -{ - if (the_locking_inset) { - the_locking_inset->InsetButtonRelease(bv, x-inset_x, y-inset_y,button); - return; + if (cursor.pos == inset_pos) { + inset_x = cursor.x - top_x + drawTextXOffset; + inset_y = cursor.y + drawTextYOffset; } - no_selection = false; + return true; } void InsetText::InsetButtonPress(BufferView * bv, int x, int y, int button) { if (hasSelection()) { - selection_start = selection_end = actpos; + selection_start = selection_end = cursor.pos; UpdateLocal(bv, false); } no_selection = false; + setPos(bv->painter(), x, y); + cursor.x_fix = -1; if (the_locking_inset) { - setPos(bv, x, y, false); UpdatableInset *inset = 0; - if (par->GetChar(actpos) == LyXParagraph::META_INSET) - inset = static_cast(par->GetInset(actpos)); + if (par->GetChar(cursor.pos) == LyXParagraph::META_INSET) + inset = static_cast(par->GetInset(cursor.pos)); if (the_locking_inset == inset) { the_locking_inset->InsetButtonPress(bv,x-inset_x,y-inset_y,button); return; } else if (inset) { // otherwise unlock the_locking_inset and lock the new inset - inset_x = cx-top_x; - inset_y = cy; - inset_pos = actpos; the_locking_inset->InsetUnlock(bv); - the_locking_inset = inset; - the_locking_inset->Edit(bv, x - inset_x, y - inset_y, button); + inset_x = cursor.x - top_x + drawTextXOffset; + inset_y = cursor.y + drawTextYOffset; + inset->InsetButtonPress(bv, x-inset_x, y-inset_y, button); + inset->Edit(bv, x - inset_x, y - inset_y, button); + UpdateLocal(bv, true); return; } // otherwise only unlock the_locking_inset the_locking_inset->InsetUnlock(bv); + the_locking_inset = 0; } - HideInsetCursor(bv); - the_locking_inset = 0; - setPos(bv, x, y); - selection_start = selection_end = actpos; - if (!the_locking_inset) - ShowInsetCursor(bv); + if (bv->the_locking_inset) { + if ((par->GetChar(cursor.pos) == LyXParagraph::META_INSET) && + par->GetInset(cursor.pos) && + (par->GetInset(cursor.pos)->Editable() == Inset::HIGHLY_EDITABLE)) { + UpdatableInset *inset = + static_cast(par->GetInset(cursor.pos)); + inset_x = cursor.x - top_x + drawTextXOffset; + inset_y = cursor.y + drawTextYOffset; + inset->InsetButtonPress(bv, x-inset_x, y-inset_y, button); + inset->Edit(bv, x-inset_x, y-inset_y, 0); + UpdateLocal(bv, true); + } + } + selection_start = selection_end = cursor.pos; } -void InsetText::InsetMotionNotify(BufferView * bv, int x, int y, int button) +void InsetText::InsetButtonRelease(BufferView * bv, int x, int y, int button) +{ + UpdatableInset * inset = 0; + + if (the_locking_inset) { + the_locking_inset->InsetButtonRelease(bv, x-inset_x, y-inset_y,button); + } else { + if (par->GetChar(cursor.pos) == LyXParagraph::META_INSET) { + inset = static_cast(par->GetInset(cursor.pos)); + if (inset->Editable()==Inset::HIGHLY_EDITABLE) { + inset->InsetButtonRelease(bv, x-inset_x, y-inset_y,button); + } else { + inset_x = cursor.x - top_x + drawTextXOffset; + inset_y = cursor.y + drawTextYOffset; + inset->InsetButtonRelease(bv, x-inset_x, y-inset_y,button); + inset->Edit(bv, x-inset_x, y-inset_y, button); + } + } + } + no_selection = false; +} + + +void InsetText::InsetMotionNotify(BufferView * bv, int x, int y, int state) { if (the_locking_inset) { the_locking_inset->InsetMotionNotify(bv, x - inset_x, - y - inset_y,button); + y - inset_y,state); return; } if (!no_selection) { int old = selection_end; - setPos(bv, x, y, false); - selection_end = actpos; + HideInsetCursor(bv); + setPos(bv->painter(), x, y); + selection_end = cursor.pos; if (old != selection_end) UpdateLocal(bv, false); + ShowInsetCursor(bv); } no_selection = false; } @@ -461,31 +537,39 @@ InsetText::LocalDispatch(BufferView * bv, int action, string const & arg) { no_selection = false; - if (UpdatableInset::LocalDispatch(bv, action, arg)) { - resetPos(bv); + UpdatableInset::RESULT + result= UpdatableInset::LocalDispatch(bv, action, arg); + if (result != UNDISPATCHED) { + resetPos(bv->painter()); return DISPATCHED; } - UpdatableInset::RESULT - result=DISPATCHED; - + result=DISPATCHED; if ((action < 0) && arg.empty()) return FINISHED; if ((action != LFUN_DOWN) && (action != LFUN_UP) && (action != LFUN_DOWNSEL) && (action != LFUN_UPSEL)) - old_x = -1; + cursor.x_fix = -1; if (the_locking_inset) { result = the_locking_inset->LocalDispatch(bv, action, arg); - if (result == DISPATCHED) { + if (result == DISPATCHED_NOUPDATE) + return result; + else if (result == DISPATCHED) { the_locking_inset->ToggleInsetCursor(bv); UpdateLocal(bv, false); the_locking_inset->ToggleInsetCursor(bv); return result; } else if (result == FINISHED) { - if ((action == LFUN_RIGHT) || (action == -1)) { - actpos = inset_pos + 1; - resetPos(bv); + switch(action) { + case -1: + case LFUN_RIGHT: + cursor.pos = inset_pos + 1; + resetPos(bv->painter()); + break; + case LFUN_DOWN: + moveDown(bv); + break; } the_locking_inset = 0; return DISPATCHED; @@ -499,90 +583,82 @@ InsetText::LocalDispatch(BufferView * bv, bv->text->cursor.par->ParFromPos(bv->text->cursor.pos)->previous, bv->text->cursor.par->ParFromPos(bv->text->cursor.pos)->next); cutSelection(); - actpos = selection_start; - par->InsertChar(actpos,arg[0]); - SetCharFont(actpos,current_font); - ++actpos; - selection_start = selection_end = actpos; + cursor.pos = selection_start; + par->InsertChar(cursor.pos,arg[0]); + SetCharFont(cursor.pos,current_font); + ++cursor.pos; + selection_start = selection_end = cursor.pos; UpdateLocal(bv, true); break; // --- Cursor Movements --------------------------------------------- case LFUN_RIGHTSEL: bv->text->FinishUndo(); moveRight(bv, false); - selection_end = actpos; + selection_end = cursor.pos; UpdateLocal(bv, false); - resetPos(bv, true); break; case LFUN_RIGHT: bv->text->FinishUndo(); - result= DISPATCH_RESULT(moveRight(bv)); + result = moveRight(bv); if (hasSelection()) { - selection_start = selection_end = actpos; + selection_start = selection_end = cursor.pos; UpdateLocal(bv, false); } else { - selection_start = selection_end = actpos; + selection_start = selection_end = cursor.pos; } - resetPos(bv, true); break; case LFUN_LEFTSEL: bv->text->FinishUndo(); moveLeft(bv, false); - selection_end = actpos; + selection_end = cursor.pos; UpdateLocal(bv, false); - resetPos(bv, true); break; case LFUN_LEFT: bv->text->FinishUndo(); - result= DISPATCH_RESULT(moveLeft(bv)); + result= moveLeft(bv); if (hasSelection()) { - selection_start = selection_end = actpos; + selection_start = selection_end = cursor.pos; UpdateLocal(bv, false); } else { - selection_start = selection_end = actpos; + selection_start = selection_end = cursor.pos; } - resetPos(bv, true); break; case LFUN_DOWNSEL: bv->text->FinishUndo(); - moveDown(bv, false); - selection_end = actpos; + moveDown(bv); + selection_end = cursor.pos; UpdateLocal(bv, false); - resetPos(bv, true); break; case LFUN_DOWN: bv->text->FinishUndo(); - result= DISPATCH_RESULT(moveDown(bv)); + result = moveDown(bv); if (hasSelection()) { - selection_start = selection_end = actpos; + selection_start = selection_end = cursor.pos; UpdateLocal(bv, false); } else { - selection_start = selection_end = actpos; + selection_start = selection_end = cursor.pos; } - resetPos(bv, true); break; case LFUN_UPSEL: bv->text->FinishUndo(); - moveUp(bv, false); - selection_end = actpos; + moveUp(bv); + selection_end = cursor.pos; UpdateLocal(bv, false); - resetPos(bv, true); break; case LFUN_UP: bv->text->FinishUndo(); - result= DISPATCH_RESULT(moveUp(bv)); + result = moveUp(bv); if (hasSelection()) { - selection_start = selection_end = actpos; + selection_start = selection_end = cursor.pos; UpdateLocal(bv, false); } else { - selection_start = selection_end = actpos; + selection_start = selection_end = cursor.pos; } - resetPos(bv, true); break; case LFUN_BACKSPACE: - if (!actpos) { // || par->IsNewline(actpos-1)) { + if (!cursor.pos) { // || par->IsNewline(cursor.pos-1)) { if (hasSelection()) { - selection_start = selection_end = actpos; + selection_start = selection_end = cursor.pos; UpdateLocal(bv, false); } break; @@ -602,14 +678,14 @@ InsetText::LocalDispatch(BufferView * bv, } else ret = Delete(); if (ret) { // we need update - selection_start = selection_end = actpos; + selection_start = selection_end = cursor.pos; UpdateLocal(bv, true); } else if (hasSelection()) { - selection_start = selection_end = actpos; + selection_start = selection_end = cursor.pos; UpdateLocal(bv, false); } } - resetPos(bv, true); + resetPos(bv->painter()); break; case LFUN_CUT: bv->text->SetUndo(Undo::DELETE, @@ -618,22 +694,22 @@ InsetText::LocalDispatch(BufferView * bv, if (cutSelection()) { // we need update - actpos = selection_end = selection_start; + cursor.pos = selection_end = selection_start; UpdateLocal(bv, true); } else if (hasSelection()) { - selection_start = selection_end = actpos; + selection_start = selection_end = cursor.pos; UpdateLocal(bv, false); } - resetPos(bv, true); + resetPos(bv->painter()); break; case LFUN_COPY: bv->text->FinishUndo(); if (copySelection()) { // we need update - selection_start = selection_end = actpos; + selection_start = selection_end = cursor.pos; UpdateLocal(bv, true); } else if (hasSelection()) { - selection_start = selection_end = actpos; + selection_start = selection_end = cursor.pos; UpdateLocal(bv, false); } break; @@ -643,24 +719,24 @@ InsetText::LocalDispatch(BufferView * bv, bv->text->cursor.par->ParFromPos(bv->text->cursor.pos)->previous, bv->text->cursor.par->ParFromPos(bv->text->cursor.pos)->next); if (pasteSelection()) { - selection_start = selection_end = actpos; + selection_start = selection_end = cursor.pos; UpdateLocal(bv, true); } } - resetPos(bv, true); + resetPos(bv->painter()); break; case LFUN_HOME: bv->text->FinishUndo(); - for(; actpos > rows[actrow].pos; --actpos) - cx -= SingleWidth(bv->painter(), par, actpos); - cx -= SingleWidth(bv->painter(), par, actpos); + for(; cursor.pos > rows[actrow].pos; --cursor.pos) + cursor.x -= SingleWidth(bv->painter(), par, cursor.pos); + cursor.x -= SingleWidth(bv->painter(), par, cursor.pos); if (hasSelection()) { - selection_start = selection_end = actpos; + selection_start = selection_end = cursor.pos; UpdateLocal(bv, false); } else { - selection_start = selection_end = actpos; + selection_start = selection_end = cursor.pos; } - resetPos(bv, true); + resetPos(bv->painter()); break; case LFUN_END: { @@ -668,28 +744,22 @@ InsetText::LocalDispatch(BufferView * bv, int checkpos = (int)rows[actrow + 1].pos; if ((actrow + 2) < (int)rows.size()) --checkpos; - for(; actpos < checkpos; ++actpos) - cx += SingleWidth(bv->painter(), par, actpos); + for(; cursor.pos < checkpos; ++cursor.pos) + cursor.x += SingleWidth(bv->painter(), par, cursor.pos); if (hasSelection()) { - selection_start = selection_end = actpos; + selection_start = selection_end = cursor.pos; UpdateLocal(bv, false); } else { - selection_start = selection_end = actpos; + selection_start = selection_end = cursor.pos; } } - resetPos(bv, true); + resetPos(bv->painter()); break; - case LFUN_MATH_MODE: // Open or create a math inset - bv->text->SetUndo(Undo::INSERT, - bv->text->cursor.par->ParFromPos(bv->text->cursor.pos)->previous, - bv->text->cursor.par->ParFromPos(bv->text->cursor.pos)->next); + case LFUN_MATH_MODE: InsertInset(bv, new InsetFormula); - if (hasSelection()) { - selection_start = selection_end = actpos; - UpdateLocal(bv, false); - } else { - selection_start = selection_end = actpos; - } + return DISPATCHED; + case LFUN_INSET_ERT: + InsertInset(bv, new InsetERT(buffer)); return DISPATCHED; case LFUN_BREAKPARAGRAPH: case LFUN_BREAKLINE: @@ -698,20 +768,19 @@ InsetText::LocalDispatch(BufferView * bv, bv->text->SetUndo(Undo::INSERT, bv->text->cursor.par->ParFromPos(bv->text->cursor.pos)->previous, bv->text->cursor.par->ParFromPos(bv->text->cursor.pos)->next); - par->InsertChar(actpos,LyXParagraph::META_NEWLINE); - SetCharFont(actpos,current_font); + par->InsertChar(cursor.pos,LyXParagraph::META_NEWLINE); + SetCharFont(cursor.pos,current_font); UpdateLocal(bv, true); - ++actpos; - selection_start = selection_end = actpos; - resetPos(bv); + ++cursor.pos; + selection_start = selection_end = cursor.pos; + resetPos(bv->painter()); break; default: result = UNDISPATCHED; break; } if (result != FINISHED) { - if (!the_locking_inset) - ShowInsetCursor(bv); + ShowInsetCursor(bv); } else bv->unlockInset(this); return result; @@ -866,8 +935,8 @@ int InsetText::BeginningOfMainBody(LyXParagraph * par) const void InsetText::GetCursorPos(int & x, int & y) const { - x = cx; - y = cy; + x = cursor.x; + y = cursor.y; } @@ -876,8 +945,7 @@ int InsetText::InsetInInsetY() if (!the_locking_inset) return 0; - int y = inset_y; - return (y + the_locking_inset->InsetInInsetY()); + return (inset_y + the_locking_inset->InsetInInsetY()); } @@ -888,7 +956,7 @@ void InsetText::ToggleInsetCursor(BufferView * bv) return; } - LyXFont font = GetDrawFont(par, actpos); + LyXFont font = GetDrawFont(par, cursor.pos); int asc = lyxfont::maxAscent(font); int desc = lyxfont::maxDescent(font); @@ -896,20 +964,24 @@ void InsetText::ToggleInsetCursor(BufferView * bv) if (cursor_visible) bv->hideLockedInsetCursor(); else - bv->showLockedInsetCursor(cx, cy, asc, desc); + bv->showLockedInsetCursor(cursor.x, cursor.y, asc, desc); cursor_visible = !cursor_visible; } void InsetText::ShowInsetCursor(BufferView * bv) { + if (the_locking_inset) { + the_locking_inset->ShowInsetCursor(bv); + return; + } if (!cursor_visible) { - LyXFont font = GetDrawFont(par, actpos); + LyXFont font = GetDrawFont(par, cursor.pos); int asc = lyxfont::maxAscent(font); int desc = lyxfont::maxDescent(font); - bv->fitLockedInsetCursor(cx, cy, asc, desc); - bv->showLockedInsetCursor(cx, cy, asc, desc); + bv->fitLockedInsetCursor(cursor.x, cursor.y, asc, desc); + bv->showLockedInsetCursor(cursor.x, cursor.y, asc, desc); cursor_visible = true; } } @@ -917,175 +989,158 @@ void InsetText::ShowInsetCursor(BufferView * bv) void InsetText::HideInsetCursor(BufferView * bv) { - if (cursor_visible) - ToggleInsetCursor(bv); + if (cursor_visible) { + bv->hideLockedInsetCursor(); + cursor_visible = false; + } + if (the_locking_inset) + the_locking_inset->HideInsetCursor(bv); } -void InsetText::setPos(BufferView * bv, int x, int y, bool activate_inset) +void InsetText::setPos(Painter & pain, int x, int y) const { - int ox = x; - int oy = y; - + x -= drawTextXOffset; + y -= drawTextYOffset; // search right X-pos x==0 -> top_x - actpos = actrow = 0; - cy = top_baseline; - y += cy; + cursor.pos = actrow = 0; + cursor.y = top_baseline; + y += cursor.y; for(unsigned int i = 1; - ((cy + rows[i - 1].desc) < y) && (i < rows.size() - 1); ++i) { - cy = rows[i].baseline; - actpos = rows[i].pos; + ((cursor.y + rows[i - 1].desc) < y) && (i < rows.size() - 1); ++i) { + cursor.y = rows[i].baseline; + cursor.pos = rows[i].pos; actrow = i; } - cy -= top_baseline; - cx = top_x; + cursor.y -= top_baseline; + cursor.x = top_x; x += top_x; int swh; - int sw = swh = SingleWidth(bv->painter(), par,actpos); - if (par->GetChar(actpos)!=LyXParagraph::META_INSET) + int sw = swh = SingleWidth(pain, par,cursor.pos); + if (par->GetChar(cursor.pos)!=LyXParagraph::META_INSET) swh /= 2; int checkpos = rows[actrow + 1].pos; if ((actrow+2) < (int)rows.size()) --checkpos; - while ((actpos < checkpos) && ((cx + swh) < x)) { - cx += sw; - ++actpos; - sw = swh = SingleWidth(bv->painter(), par,actpos); - if (par->GetChar(actpos)!=LyXParagraph::META_INSET) + while ((cursor.pos < checkpos) && ((cursor.x + swh) < x)) { + cursor.x += sw; + ++cursor.pos; + sw = swh = SingleWidth(pain, par,cursor.pos); + if (par->GetChar(cursor.pos)!=LyXParagraph::META_INSET) swh /= 2; } - if (activate_inset && par->GetChar(actpos)==LyXParagraph::META_INSET) { - the_locking_inset = - static_cast(par->GetInset(actpos)); - inset_x = cx - top_x; - inset_y = cy; - inset_pos = actpos; - the_locking_inset->Edit(bv, ox - inset_x, oy - inset_y, 0); - } } -bool InsetText::moveRight(BufferView * bv, bool activate_inset) +void InsetText::resetPos(Painter & pain) const { - if (actpos >= par->Last()) - return false; - if (activate_inset && par->GetChar(actpos)==LyXParagraph::META_INSET) { - the_locking_inset = - static_cast(par->GetInset(actpos)); - inset_x = cx - top_x; - inset_y = cy; - inset_pos = actpos; - the_locking_inset->Edit(bv, 0, 0, 0); - } else { - ++actpos; - resetPos(bv); - } - return true; -} - - -bool InsetText::moveLeft(BufferView * bv, bool activate_inset) -{ - if (actpos <= 0) - return false; - --actpos; - if (activate_inset && par->GetChar(actpos)==LyXParagraph::META_INSET) { - the_locking_inset = - static_cast(par->GetInset(actpos)); - resetPos(bv); - inset_x = cx - top_x; - inset_y = cy; - inset_pos = actpos; - the_locking_inset->Edit(bv, the_locking_inset-> - width(bv->painter(), GetDrawFont(par,actpos)), - 0, 0); - } else { - resetPos(bv); - } - return true; -} - - -bool InsetText::moveUp(BufferView * bv, bool activate_inset) -{ - if (!actrow) - return false; - cy = rows[actrow - 1].baseline - top_baseline; - setPos(bv, cx - top_x, cy, activate_inset); - return true; -} - - -bool InsetText::moveDown(BufferView * bv, bool activate_inset) -{ - if (actrow >= int(rows.size() - 2)) - return false; - cy = rows[actrow + 1].baseline - top_baseline; - setPos(bv, cx - top_x, cy, activate_inset); - return true; -} - - -void InsetText::resetPos(BufferView * bv, bool setfont) -{ - if (setfont) { - real_current_font = current_font = GetDrawFont(par, actpos); - } if (!rows.size()) return; - int old_pos = actpos; + int old_pos = cursor.pos; - cy = top_baseline; + cursor.y = top_baseline; actrow = 0; - for(unsigned int i = 0; (i < (rows.size()-1)) && (rows[i].pos <= actpos); + for(unsigned int i = 0; (i < (rows.size()-1)) && (rows[i].pos <= cursor.pos); ++i) { - cy = rows[i].baseline; + cursor.y = rows[i].baseline; actrow = i; } - cy -= top_baseline; - setPos(bv, 0, cy, false); - cx = top_x; - while(actpos < old_pos) { - cx += SingleWidth(bv->painter(), par,actpos); - ++actpos; + cursor.y -= top_baseline; + setPos(pain, 0, cursor.y); + cursor.x = top_x; + while(cursor.pos < old_pos) { + cursor.x += SingleWidth(pain, par,cursor.pos); + ++cursor.pos; } } +UpdatableInset::RESULT +InsetText::moveRight(BufferView * bv, bool activate_inset) +{ + if (cursor.pos >= par->Last()) + return FINISHED; + if (activate_inset && checkAndActivateInset(bv)) { + return DISPATCHED; + } + ++cursor.pos; + resetPos(bv->painter()); + real_current_font = current_font = GetFont(par, cursor.pos); + return DISPATCHED_NOUPDATE; +} + + +UpdatableInset::RESULT +InsetText::moveLeft(BufferView * bv, bool activate_inset) +{ + if (cursor.pos <= 0) + return FINISHED; + --cursor.pos; + resetPos(bv->painter()); + if (activate_inset) + if (checkAndActivateInset(bv, -1, -1)) + return DISPATCHED; + return DISPATCHED_NOUPDATE; +} + + +UpdatableInset::RESULT +InsetText::moveUp(BufferView * bv) +{ + if (!actrow) + return FINISHED; + cursor.y = rows[actrow - 1].baseline - top_baseline; + if (cursor.x_fix < 0) + cursor.x_fix = cursor.x; + setPos(bv->painter(), cursor.x_fix-top_x+drawTextXOffset, cursor.y); + return DISPATCHED_NOUPDATE; +} + + +UpdatableInset::RESULT +InsetText::moveDown(BufferView * bv) +{ + if (actrow >= int(rows.size() - 2)) + return FINISHED; + cursor.y = rows[actrow + 1].baseline - top_baseline; + if (cursor.x_fix < 0) + cursor.x_fix = cursor.x; + setPos(bv->painter(), cursor.x_fix-top_x+drawTextXOffset, cursor.y); + return DISPATCHED_NOUPDATE; +} + + bool InsetText::Delete() { - /* some insets are undeletable here */ - if (par->GetChar(actpos)==LyXParagraph::META_INSET) { - /* force complete redo when erasing display insets */ - /* this is a cruel method but save..... Matthias */ - if (par->GetInset(actpos)->Deletable() && - par->GetInset(actpos)->display()) { - par->Erase(actpos); - return true; - } - return false; + if ((par->GetChar(cursor.pos)==LyXParagraph::META_INSET) && + !par->GetInset(cursor.pos)->Deletable()) { + return false; } - par->Erase(actpos); + par->Erase(cursor.pos); return true; } bool InsetText::InsertInset(BufferView * bv, Inset * inset) { + bv->text->SetUndo(Undo::INSERT, + bv->text->cursor.par->ParFromPos(bv->text->cursor.pos)->previous, + bv->text->cursor.par->ParFromPos(bv->text->cursor.pos)->next); if (inset->Editable() == Inset::IS_EDITABLE) { UpdatableInset *i = (UpdatableInset *)inset; i->setOwner((UpdatableInset *)this); } - par->InsertChar(actpos, LyXParagraph::META_INSET); - par->InsertInset(actpos, inset); + par->InsertChar(cursor.pos, LyXParagraph::META_INSET); + par->InsertInset(cursor.pos, inset); + if (hasSelection()) { + selection_start = selection_end = cursor.pos; + } else { + selection_start = selection_end = cursor.pos; + } UpdateLocal(bv, true); - the_locking_inset = static_cast(inset); - inset_x = cx - top_x; - inset_y = cy; - inset_pos = actpos; - inset->Edit(bv, 0, 0, 0); + static_cast(inset)->Edit(bv, 0, 0, 0); return true; } @@ -1102,7 +1157,7 @@ void InsetText::SetFont(BufferView * bv, LyXFont const & font, bool toggleall) if (!hasSelection()) { // Determine basis font LyXFont layoutfont; - if (actpos < BeginningOfMainBody(par)) + if (cursor.pos < BeginningOfMainBody(par)) layoutfont = GetFont(par, -2); else layoutfont = GetFont(par, -1); @@ -1207,10 +1262,9 @@ void InsetText::computeTextRows(Painter & pain, float x) const } bool is_first_word_in_row = true; - int cw, lastWordWidth = 0; + int maxWidth = getMaxTextWidth(pain, this, x); - maxWidth = getMaxWidth(pain) - widthOffset; for(p = 0; p < par->Last(); ++p) { cw = SingleWidth(pain, par, p); width += cw; @@ -1219,14 +1273,28 @@ void InsetText::computeTextRows(Painter & pain, float x) const wordAscent = max(wordAscent, asc); wordDescent = max(wordDescent, desc); if (par->IsNewline(p)) { + if (!is_first_word_in_row && (width >= maxWidth)) { + // we have to split also the row above + rows.back().asc = oasc; + rows.back().desc = odesc; + row.pos = nwp; + rows.push_back(row); + oasc = wordAscent; + odesc = wordDescent; + insetWidth = max(insetWidth, owidth); + width = lastWordWidth; + lastWordWidth = 0; + } rows.back().asc = wordAscent; rows.back().desc = wordDescent; - row.pos = p+1; + row.pos = ++p; // +1; rows.push_back(row); SingleHeight(pain, par, p, oasc, odesc); - width = lastWordWidth = 0; + insetWidth = max(insetWidth, owidth); + width = 0; is_first_word_in_row = true; - wordAscent = wordDescent = 0; + wordAscent = wordDescent = lastWordWidth = 0; + nwp = p; continue; } Inset const * inset = 0; @@ -1234,7 +1302,7 @@ void InsetText::computeTextRows(Painter & pain, float x) const (par->GetChar(p + 1)==LyXParagraph::META_INSET)) inset = par->GetInset(p + 1); if (inset && inset->display()) { - if (!is_first_word_in_row && (width >= (maxWidth - x))) { + if (!is_first_word_in_row && (width >= maxWidth)) { // we have to split also the row above rows.back().asc = oasc; rows.back().desc = odesc; @@ -1263,7 +1331,7 @@ void InsetText::computeTextRows(Painter & pain, float x) const wordAscent = wordDescent = 0; continue; } else if (par->IsSeparator(p)) { - if (width >= maxWidth - x) { + if (width >= maxWidth) { if (is_first_word_in_row) { rows.back().asc = wordAscent; rows.back().desc = wordDescent; @@ -1294,7 +1362,7 @@ void InsetText::computeTextRows(Painter & pain, float x) const } // if we have some data in the paragraph we have ascent/descent if (p) { - if (width >= (maxWidth - x)) { + if (width >= maxWidth) { // assign upper row rows.back().asc = oasc; rows.back().desc = odesc; @@ -1320,15 +1388,6 @@ void InsetText::computeTextRows(Painter & pain, float x) const for (RowList::size_type i = 1; i < rows.size() - 1; ++i) { maxDescent += rows[i].asc + rows[i].desc + interline_space; } -#if 0 - if (the_locking_inset) { - computeBaselines(top_baseline); - actpos = inset_pos; - resetPos(bv); - inset_x = cx - top_x; - inset_y = cy; - } -#endif } @@ -1343,15 +1402,18 @@ void InsetText::computeBaselines(int baseline) const void InsetText::UpdateLocal(BufferView *bv, bool flag) { - HideInsetCursor(bv); +#if 1 if (flag) { computeTextRows(bv->painter(), xpos); computeBaselines(top_baseline); } bv->updateInset(this, flag); if (flag) - resetPos(bv); - ShowInsetCursor(bv); + resetPos(bv->painter()); +#else + init_inset = flag; + bv->updateInset(this, flag); +#endif } bool InsetText::cutSelection() @@ -1391,6 +1453,34 @@ bool InsetText::pasteSelection() LyXParagraph *endpar; LyXParagraph *actpar = par; - return cap.pasteSelection(&actpar, &endpar, actpos, + return cap.pasteSelection(&actpar, &endpar, cursor.pos, buffer->params.textclass); } + +bool InsetText::checkAndActivateInset(BufferView * bv, int x, int y, + int button) +{ + if (par->GetChar(cursor.pos) == LyXParagraph::META_INSET) { + UpdatableInset * inset = + static_cast(par->GetInset(cursor.pos)); + LyXFont font = GetFont(par, cursor.pos); + if (x < 0) + x = inset->width(bv->painter(), font); + if (y < 0) + y = inset->descent(bv->painter(), font); + inset_x = cursor.x - top_x + drawTextXOffset; + inset_y = cursor.y + drawTextYOffset; + inset->Edit(bv, x-inset_x, y-inset_y, button); + if (!the_locking_inset) + return false; + UpdateLocal(bv, true); + return true; + } + return false; +} + +int InsetText::getMaxTextWidth(Painter & pain, UpdatableInset const * inset, + int x) const +{ + return getMaxWidth(pain, inset) - x; +} diff --git a/src/insets/insettext.h b/src/insets/insettext.h index f3e88c38da..e05c4b0d10 100644 --- a/src/insets/insettext.h +++ b/src/insets/insettext.h @@ -19,9 +19,9 @@ #endif #include "lyxinset.h" -#include "lyxparagraph.h" #include "LString.h" -//#include "buffer.h" +#include "lyxparagraph.h" +#include "lyxcursor.h" class Painter; class BufferView; @@ -46,6 +46,8 @@ public: /// Inset * Clone() const; /// + void clear() const { par->clearContents(); } + /// void Read(LyXLex &); /// void Write(std::ostream &) const; @@ -64,7 +66,9 @@ public: /// void InsetUnlock(BufferView *); /// - bool UnlockInsetInInset(BufferView *, Inset *, bool lr = false); + bool LockInsetInInset(BufferView *, UpdatableInset *); + /// + bool UnlockInsetInInset(BufferView *, UpdatableInset *, bool lr = false); /// bool UpdateInsetInInset(BufferView *, Inset *); /// @@ -110,7 +114,7 @@ protected: /// void WriteParagraphData(std::ostream &) const; /// - void resetPos(BufferView *, bool setfont=false); + void resetPos(Painter &) const; /// void drawSelection(Painter &, int pos, int baseline, float x); /// @@ -122,6 +126,9 @@ protected: LyXFont GetFont(LyXParagraph * par, int pos) const; /// virtual LyXFont GetDrawFont(LyXParagraph * par, int pos) const; + /// + virtual int getMaxTextWidth(Painter &, UpdatableInset const *, + int x=0) const; Buffer * buffer; /// @@ -129,15 +136,14 @@ protected: /// LyXFont real_current_font; /// - mutable int maxWidth; - /// mutable int maxAscent; /// mutable int maxDescent; /// mutable int insetWidth; /// - int widthOffset; + mutable int drawTextXOffset; + mutable int drawTextYOffset; /// bool autoBreakRows; @@ -159,12 +165,12 @@ private: /// void HideInsetCursor(BufferView *); /// - void setPos(BufferView *, int x, int y, bool activate_inset = true); + void setPos(Painter &, int x, int y) const; /// - bool moveRight(BufferView *, bool activate_inset = true); - bool moveLeft(BufferView *, bool activate_inset = true); - bool moveUp(BufferView *, bool activate_inset = true); - bool moveDown(BufferView *, bool activate_inset = true); + UpdatableInset::RESULT moveRight(BufferView *, bool activate_inset = true); + UpdatableInset::RESULT moveLeft(BufferView *, bool activate_inset = true); + UpdatableInset::RESULT moveUp(BufferView *); + UpdatableInset::RESULT moveDown(BufferView *); bool Delete(); bool cutSelection(); bool copySelection(); @@ -175,14 +181,17 @@ private: void SetCharFont(int pos, LyXFont const & font); /// string getText(int); + /// + bool checkAndActivateInset(BufferView * bv, int x = 0, int y = 0, + int button = 0); /* Private structures and variables */ /// int inset_pos; /// - int inset_x; + mutable int inset_x; /// - int inset_y; + mutable int inset_y; /// int interline_space; /// @@ -190,15 +199,11 @@ private: /// int selection_end; /// - int old_x; + mutable LyXCursor cursor; /// - int cx; + mutable LyXCursor old_cursor; /// - int cy; - /// - int actpos; - /// - int actrow; + mutable int actrow; /// bool no_selection; /// @@ -227,7 +232,6 @@ private: buffer = it.buffer; // suspect current_font = it.current_font; real_current_font = it.real_current_font; - maxWidth = it.maxWidth; maxAscent = it.maxAscent; maxDescent = it.maxDescent; insetWidth = it.insetWidth; @@ -237,10 +241,7 @@ private: interline_space = it.interline_space; selection_start = it.selection_start; selection_end = it.selection_end; - old_x = it.old_x; - cx = it.cx; - cy = it.cy; - actpos = it.actpos; + cursor = it.cursor; actrow = it.actrow; no_selection = it.no_selection; the_locking_inset = it.the_locking_inset; // suspect diff --git a/src/insets/lyxinset.h b/src/insets/lyxinset.h index 738ad9be04..7466d33232 100644 --- a/src/insets/lyxinset.h +++ b/src/insets/lyxinset.h @@ -4,7 +4,6 @@ * * LyX, The Document Processor * - * Copyright 1995 Matthias Ettrich * Copyright 1995-2000 the LyX Team. * * ====================================================== */ @@ -92,7 +91,9 @@ public: /// SPECIALCHAR_CODE, /// - NUMBER_CODE + NUMBER_CODE, + /// + TABULAR_CODE }; enum EDITABLE { @@ -101,6 +102,8 @@ public: HIGHLY_EDITABLE }; + /// + Inset() { owner_ = 0; } /// virtual ~Inset() {} /// @@ -121,6 +124,12 @@ public: /// virtual EDITABLE Editable() const; /// + virtual void InsetButtonPress(BufferView *, int, int, int) {} + /// + virtual void InsetButtonRelease(BufferView *, int, int, int) {} + /// + virtual void InsetMotionNotify(BufferView *, int , int , int) {} + /// bool IsTextInset() const; /// virtual bool AutoDelete() const; @@ -172,6 +181,20 @@ public: virtual void init(BufferView *) {} /// virtual bool InsertInsetAllowed(Inset *) const { return false; } + /// + virtual void setInsetName(const char * s) { name = s; } + /// + virtual string getInsetName() const { return name; } + /// + virtual void setOwner(Inset * inset) { owner_ = inset; } + /// + virtual Inset * owner() const { return owner_; } + /// +private: + /// + Inset * owner_; + /// + string name; }; @@ -209,6 +232,8 @@ public: are not enough. DISPATCHED = the inset catched the action + DISPATCHED_NOUPDATE = the inset catched the action and no update + is needed here to redraw the inset FINISHED = the inset must be unlocked as a result of the action UNDISPATCHED = the action was not catched, it should be @@ -217,6 +242,7 @@ public: enum RESULT { UNDISPATCHED = 0, DISPATCHED, + DISPATCHED_NOUPDATE, FINISHED }; @@ -226,10 +252,7 @@ public: } /// - UpdatableInset() { - scx = mx_scx = 0; - owner_ = 0; - } + UpdatableInset() { scx = mx_scx = 0; } /// //virtual ~UpdatableInset() {} /// @@ -238,6 +261,10 @@ public: /// may call ToggleLockedInsetCursor virtual void ToggleInsetCursor(BufferView *); /// + virtual void ShowInsetCursor(BufferView *); + /// + virtual void HideInsetCursor(BufferView *); + /// virtual void GetCursorPos(int &, int &) const {} /// virtual void InsetButtonPress(BufferView *, int x, int y, int button); @@ -270,7 +297,10 @@ public: virtual bool UpdateInsetInInset(BufferView *, Inset *) { return false; } /// - virtual bool UnlockInsetInInset(BufferView *, Inset *, + virtual bool LockInsetInInset(BufferView *, UpdatableInset *) + { return false; } + /// + virtual bool UnlockInsetInInset(BufferView *, UpdatableInset *, bool /*lr*/ = false) { return false; } /// An updatable inset could handle lyx editing commands @@ -278,11 +308,7 @@ public: /// virtual bool isCursorVisible() const { return cursor_visible; } /// - virtual int getMaxWidth(Painter & pain) const; - /// - virtual void setOwner(UpdatableInset * inset) { owner_ = inset; } - /// - virtual UpdatableInset * owner() { return owner_; } + virtual int getMaxWidth(Painter & pain, UpdatableInset const *) const; protected: /// @@ -296,8 +322,5 @@ private: /// int mx_scx; mutable int scx; - /// - UpdatableInset * owner_; - }; #endif diff --git a/src/lyxfunc.C b/src/lyxfunc.C index 9a2c0783e4..0eb04a67ca 100644 --- a/src/lyxfunc.C +++ b/src/lyxfunc.C @@ -54,6 +54,7 @@ using std::istringstream; #include "insets/insetert.h" #include "insets/insetgraphics.h" #include "insets/insetfoot.h" +#include "insets/insettabular.h" #include "mathed/formulamacro.h" #include "toolbar.h" #include "spellchecker.h" // RVDK_PATCH_5 @@ -533,6 +534,7 @@ string LyXFunc::Dispatch(int ac, // the math inset [asierra060396] if (owner->view()->available() && owner->view()->the_locking_inset) { + UpdatableInset::RESULT result; if (action > 1 || (action == LFUN_UNKNOWN_ACTION && keyseq.length >= -1)) { @@ -574,10 +576,11 @@ string LyXFunc::Dispatch(int ac, if (inset) inset->Edit(owner->view(),slx,sly,0); return string(); - } else if (owner->view()->the_locking_inset-> + } else if (((result=owner->view()->the_locking_inset-> LocalDispatch(owner->view(), action, - argument) == - UpdatableInset::DISPATCHED) + argument)) == + UpdatableInset::DISPATCHED) || + (result == UpdatableInset::DISPATCHED_NOUPDATE)) return string(); else { setMessage(N_("Text mode")); @@ -605,6 +608,12 @@ string LyXFunc::Dispatch(int ac, Set(CurrentState(owner->view())); } return string(); + case LFUN_DOWN: + owner->view()->text->CursorDown(); + moveCursorUpdate(false); + owner->getMiniBuffer()-> + Set(CurrentState(owner->view())); + return string(); default: break; } @@ -2048,6 +2057,14 @@ string LyXFunc::Dispatch(int ac, } break; + case LFUN_INSET_TABULAR: + { + InsetTabular * new_inset = new InsetTabular(owner->buffer(),2,2); + owner->view()->insertInset(new_inset); + new_inset->Edit(owner->view(), 0, 0, 0); + } + break; + // --- lyxserver commands ---------------------------- case LFUN_CHARATCURSOR: diff --git a/src/lyxtext.h b/src/lyxtext.h index 5d6d95db98..b9df6e38da 100644 --- a/src/lyxtext.h +++ b/src/lyxtext.h @@ -239,6 +239,8 @@ public: void SetCursor(LyXParagraph * par, LyXParagraph::size_type pos, bool setfont = true) const; + void SetCursor(LyXCursor &, LyXParagraph * par, + LyXParagraph::size_type pos) const; /// void SetCursorIntern(LyXParagraph * par, LyXParagraph::size_type pos, diff --git a/src/mathed/formula.C b/src/mathed/formula.C index a17b6db0e9..7b499e5863 100644 --- a/src/mathed/formula.C +++ b/src/mathed/formula.C @@ -1,5 +1,5 @@ /* - * File: formula.h + * File: formula.C * Purpose: Implementation of formula inset * Author: Alejandro Aguilar Sierra * Created: January 1996 @@ -461,7 +461,8 @@ char const * InsetFormula::EditMessage() const void InsetFormula::Edit(BufferView * bv, int x, int y, unsigned int) { mathcursor = new MathedCursor(par); - bv->lockInset(this); + if (!bv->lockInset(this)) + lyxerr[Debug::MATHED] << "Cannot lock inset!!!" << endl; par->Metrics(); bv->updateInset(this, false); x += par->xo; diff --git a/src/paragraph.C b/src/paragraph.C index 83f400f8ce..747e7e0dcc 100644 --- a/src/paragraph.C +++ b/src/paragraph.C @@ -644,6 +644,8 @@ void LyXParagraph::InsertInset(LyXParagraph::size_type pos, "there is an inset in position: " << pos << endl; else insetlist.insert(it, InsetTable(pos,inset)); + if (inset_owner) + inset->setOwner(inset_owner); } } @@ -3483,7 +3485,9 @@ LyXParagraph * LyXParagraph::TeXDeeper(ostream & os, TexRow & texrow, lyxerr[Debug::LATEX] << "TeXDeeper... " << this << endl; LyXParagraph * par = this; - while (par && par->depth == depth) { + while (par && + (par->depth == depth) && + (par->footnoteflag == footnoteflag)) { if (par->IsDummy()) lyxerr << "ERROR (LyXParagraph::TeXDeeper)" << endl; if (textclasslist.Style(current_view->buffer()->params.textclass, @@ -3736,7 +3740,8 @@ LyXParagraph * LyXParagraph::TeXEnvironment(ostream & os, TexRow & texrow, } while (par && par->layout == layout && par->depth == depth - && par->pextra_type == pextra_type); + && par->pextra_type == pextra_type + && par->footnoteflag == footnoteflag); if (style.isEnvironment()) { os << "\\end{" << style.latexname() << '}'; diff --git a/src/table.C b/src/table.C index 2bf349786e..14482eab50 100644 --- a/src/table.C +++ b/src/table.C @@ -24,6 +24,8 @@ #include "layout.h" #include "support/lstrings.h" #include "support/lyxmanip.h" +#include "lyx_gui_misc.h" +#include "insets/insettext.h" using std::ostream; using std::istream; @@ -32,33 +34,162 @@ using std::endl; static int const WIDTH_OF_LINE = 5; +/// Define a few methods for the inner structs + +LyXTable::cellstruct::cellstruct(Buffer * buf) +{ + cellno = 0; //should be initilaized correctly later. + width_of_cell = 0; + multicolumn = LyXTable::CELL_NORMAL; + alignment = LYX_ALIGN_CENTER; + top_line = true; + bottom_line = false; + has_cont_row = false; + rotate = false; + linebreaks = false; + buf ? inset = new InsetText(buf): inset = 0; + +} + +LyXTable::cellstruct::~cellstruct() +{ + if (inset) + delete inset; +} + +LyXTable::cellstruct & + LyXTable::cellstruct::operator=(cellstruct const & cs) +{ + cellno = cs.cellno; + width_of_cell = cs.width_of_cell; + multicolumn = cs.multicolumn; + alignment = cs.alignment; + top_line = cs.top_line; + bottom_line = cs.bottom_line; + has_cont_row = cs.has_cont_row; + rotate = cs.rotate; + linebreaks = cs.linebreaks; + return *this; +} + +LyXTable::rowstruct::rowstruct() +{ + top_line = true; + bottom_line = false; + is_cont_row = false; + ascent_of_row = 0; + descent_of_row = 0; + newpage = false; +} + +// Nothing to do, but gcc 2.7.2.3 wants one... (JMarc) +LyXTable::rowstruct::~rowstruct() +{ +} + +LyXTable::rowstruct & + LyXTable::rowstruct::operator=(rowstruct const & rs) +{ + top_line = rs.top_line; + bottom_line = rs.bottom_line; + is_cont_row = rs.is_cont_row; + ascent_of_row = rs.ascent_of_row; + descent_of_row = rs.descent_of_row; + newpage = rs.newpage; + return *this; +} + +LyXTable::columnstruct::columnstruct() +{ + left_line = true; + right_line = false; + alignment = LYX_ALIGN_CENTER; + width_of_column = 0; +} + +LyXTable::columnstruct::~columnstruct() +{ +} + +LyXTable::columnstruct & + LyXTable::columnstruct::operator=(columnstruct const & cs) +{ + left_line = cs.left_line; + right_line = cs.right_line; + alignment = cs.alignment; + width_of_column = cs.width_of_column; + p_width = cs.p_width; + align_special = cs.align_special; + return *this; +} /* konstruktor */ -LyXTable::LyXTable(int rows_arg, int columns_arg) +LyXTable::LyXTable(int rows_arg, int columns_arg, Buffer *buf) { - Init(rows_arg, columns_arg); + buffer = buf; + Init(rows_arg, columns_arg); } -LyXTable::LyXTable(LyXLex & lex) +LyXTable::LyXTable(LyXTable const & lt, Buffer * buf) { - istream & is = lex.getStream(); - Read(is); + buffer = buf; + Init(lt.rows, lt.columns); + + operator=(lt); +} + +LyXTable::LyXTable(LyXLex & lex, Buffer *buf) +{ + istream & is = lex.getStream(); + buffer = buf; + Read(is); } -LyXTable::~LyXTable() { - delete[] rowofcell; - delete[] columnofcell; - delete[] column_info; - delete[] row_info; - for (int i = 0; i < rows; ++i) { - delete[] cell_info[i]; // verify that this shoudn't be freed with delete - } - delete[] cell_info; +LyXTable::~LyXTable() +{ + delete[] rowofcell; + delete[] columnofcell; + delete[] column_info; + delete[] row_info; + for (int i = 0; i < rows; ++i) { + delete[] cell_info[i]; + } + delete[] cell_info; } +LyXTable & LyXTable::operator=(LyXTable const & lt) +{ + // If this and lt is not of the same size we have a serious bug + // So then it is ok to throw an exception, or for now + // call abort() + Assert(rows == lt.rows && columns == lt.columns); + + int row = 0, column = 0; + + for (row = 0; row < rows; ++row) { + for (column = 0; column < columns; ++column) { + cell_info[row][column] = lt.cell_info[row][column]; + } + } + + for (row = 0; row < rows; ++row) { + row_info[row] = lt.row_info[row]; + } + + for (column = 0; column < columns; ++column) { + column_info[column] = lt.column_info[column]; + } + + SetLongTable(lt.is_long_table); + rotate = lt.rotate; + Reinit(); + + return *this; +} + LyXTable * LyXTable::Clone() { LyXTable * result = new LyXTable(rows, columns); @@ -101,33 +232,15 @@ void LyXTable::Init(int rows_arg, int columns_arg) int cellno = 0; for (i = 0; i < rows; ++i) { - cell_info[i] = new cellstruct[columns]; - row_info[i].top_line = true; - row_info[i].bottom_line = false; - row_info[i].is_cont_row = false; - row_info[i].newpage = false; + cell_info[i] = new cellstruct[columns](buffer); for (j = 0; j < columns; ++j) { cell_info[i][j].cellno = cellno++; - cell_info[i][j].width_of_cell = 0; - cell_info[i][j].multicolumn = LyXTable::CELL_NORMAL; - cell_info[i][j].alignment = LYX_ALIGN_CENTER; - cell_info[i][j].top_line = row_info[i].top_line; - cell_info[i][j].bottom_line = row_info[i].bottom_line; - cell_info[i][j].has_cont_row = false; - cell_info[i][j].rotate = false; - cell_info[i][j].linebreaks = false; } } row_info[i-1].bottom_line = true; row_info[0].bottom_line = true; for (i = 0; i < columns; ++i) { - column_info[i].left_line = true; - column_info[i].right_line = false; - column_info[i].alignment = LYX_ALIGN_CENTER; - // set width_of_column to zero before it is used in - // calculate_width_of_column() (thornley) - column_info[i].width_of_column = 0; calculate_width_of_column(i); } column_info[i-1].right_line = true; @@ -780,7 +893,7 @@ void LyXTable::calculate_width_of_table() } -int LyXTable::row_of_cell(int cell) +int LyXTable::row_of_cell(int cell) const { if (cell >= numberofcells) return rows-1; @@ -790,7 +903,7 @@ int LyXTable::row_of_cell(int cell) } -int LyXTable::column_of_cell(int cell) +int LyXTable::column_of_cell(int cell) const { if (cell >= numberofcells) return columns-1; @@ -811,29 +924,30 @@ int LyXTable::right_column_of_cell(int cell) } -void LyXTable::Write(ostream & os) +void LyXTable::Write(ostream & os, bool old_format) { - int i, j; - os << "multicol5\n" - << rows << " " << columns << " " << is_long_table << " " - << rotate << " " << endhead << " " << endfirsthead << " " - << endfoot << " " << endlastfoot << "\n"; - for (i = 0; i < rows; ++i) { + if (old_format) { + int i, j; + os << "multicol5\n" + << rows << " " << columns << " " << is_long_table << " " + << rotate << " " << endhead << " " << endfirsthead << " " + << endfoot << " " << endlastfoot << "\n"; + for (i = 0; i < rows; ++i) { os << row_info[i].top_line << " " << row_info[i].bottom_line << " " << row_info[i].is_cont_row << " " << row_info[i].newpage << "\n"; - } - for (i = 0; i < columns; ++i) { + } + for (i = 0; i < columns; ++i) { os << column_info[i].alignment << " " << column_info[i].left_line << " " << column_info[i].right_line << " \"" << VSpace(column_info[i].p_width).asLyXCommand() << "\" \"" << column_info[i].align_special << "\"\n"; - } + } - for (i = 0; i < rows; ++i) { - for (j = 0; j < columns; ++j) { + for (i = 0; i < rows; ++i) { + for (j = 0; j < columns; ++j) { os << cell_info[i][j].multicolumn << " " << cell_info[i][j].alignment << " " << cell_info[i][j].top_line << " " @@ -843,7 +957,10 @@ void LyXTable::Write(ostream & os) << cell_info[i][j].linebreaks << " \"" << cell_info[i][j].align_special << "\" \"" << cell_info[i][j].p_width << "\"\n"; - } + } + } + } else { + lyxerr << "New format type not yet implemented!!!\n" << endl; } } @@ -871,13 +988,13 @@ void LyXTable::Read(istream & is) version = atoi(s.c_str() + 8); else version = 1; -#ifdef WITH_WARNINGS -#warning Insert a error message window here that this format is not supported anymore -#endif if (version < 5) { lyxerr << "Tabular format < 5 is not supported anymore\n" "Get an older version of LyX (< 1.1.x) for conversion!" << endl; + WriteAlert(_("Warning:"), + _("Tabular format < 5 is not supported anymore\n"), + _("Get an older version of LyX (< 1.1.x) for conversion!")); if (version > 2) { is >> rows_arg >> columns_arg >> is_long_table_arg >> rotate_arg >> a >> b >> c >> d; @@ -1915,3 +2032,60 @@ bool LyXTable::LTNewPage(int cell) { return row_info[row_of_cell(cell)].newpage; } + +void LyXTable::SetAscentOfRow(int row, int height) +{ + if (row >= rows) + return; + row_info[row].ascent_of_row = height; +} + +void LyXTable::SetDescentOfRow(int row, int height) +{ + if (row >= rows) + return; + row_info[row].descent_of_row = height; +} + +int LyXTable::AscentOfRow(int row) +{ + if (row >= rows) + return 0; + return row_info[row].ascent_of_row; +} + +int LyXTable::DescentOfRow(int row) +{ + if (row >= rows) + return 0; + return row_info[row].descent_of_row; +} + +int LyXTable::HeightOfTable() +{ + int + height, + row; + + for(row=0,height=0;(row= rows) || (column >= columns)) + return false; + return (cell_info[row][column].multicolumn==CELL_PART_OF_MULTICOLUMN); +} + +int LyXTable::Latex(ostream &) +{ + return 0; +} + +InsetText * LyXTable::GetCellInset(int cell) const +{ + return cell_info[row_of_cell(cell)][column_of_cell(cell)].inset; +} diff --git a/src/table.h b/src/table.h index f2bb08a80d..e83e3e2e6f 100644 --- a/src/table.h +++ b/src/table.h @@ -20,327 +20,377 @@ #include "lyxlex.h" #include "LString.h" +class InsetText; +class Buffer; + /* The features the text class offers for tables */ /// class LyXTable { public: - // Are the values of these enums important? (Lgb) - enum { - APPEND_ROW = 0, - APPEND_COLUMN = 1, - DELETE_ROW = 2, - DELETE_COLUMN = 3, - TOGGLE_LINE_TOP = 4, - TOGGLE_LINE_BOTTOM = 5, - TOGGLE_LINE_LEFT = 6, - TOGGLE_LINE_RIGHT = 7, - ALIGN_LEFT = 8, // what are these alignment enums used for? - ALIGN_RIGHT = 9, - ALIGN_CENTER = 10, - DELETE_TABLE = 11, - MULTICOLUMN = 12, - SET_ALL_LINES = 13, - UNSET_ALL_LINES = 14, - SET_LONGTABLE = 15, - UNSET_LONGTABLE = 16, - SET_PWIDTH = 17, - APPEND_CONT_ROW = 18, - SET_ROTATE_TABLE = 19, - UNSET_ROTATE_TABLE = 20, - SET_ROTATE_CELL = 21, - UNSET_ROTATE_CELL = 22, - SET_LINEBREAKS = 23, - SET_LTHEAD = 24, - SET_LTFIRSTHEAD = 25, - SET_LTFOOT = 26, - SET_LTLASTFOOT = 27, - SET_LTNEWPAGE = 28, - SET_SPECIAL_COLUMN = 29, - SET_SPECIAL_MULTI = 30 - }; + // Are the values of these enums important? (Lgb) + enum { + APPEND_ROW = 0, + APPEND_COLUMN = 1, + DELETE_ROW = 2, + DELETE_COLUMN = 3, + TOGGLE_LINE_TOP = 4, + TOGGLE_LINE_BOTTOM = 5, + TOGGLE_LINE_LEFT = 6, + TOGGLE_LINE_RIGHT = 7, + ALIGN_LEFT = 8, // what are these alignment enums used for? + ALIGN_RIGHT = 9, + ALIGN_CENTER = 10, + DELETE_TABLE = 11, + MULTICOLUMN = 12, + SET_ALL_LINES = 13, + UNSET_ALL_LINES = 14, + SET_LONGTABLE = 15, + UNSET_LONGTABLE = 16, + SET_PWIDTH = 17, + APPEND_CONT_ROW = 18, + SET_ROTATE_TABLE = 19, + UNSET_ROTATE_TABLE = 20, + SET_ROTATE_CELL = 21, + UNSET_ROTATE_CELL = 22, + SET_LINEBREAKS = 23, + SET_LTHEAD = 24, + SET_LTFIRSTHEAD = 25, + SET_LTFOOT = 26, + SET_LTLASTFOOT = 27, + SET_LTNEWPAGE = 28, + SET_SPECIAL_COLUMN = 29, + SET_SPECIAL_MULTI = 30 + }; - enum { - CELL_NORMAL = 0, - CELL_BEGIN_OF_MULTICOLUMN = 1, - CELL_PART_OF_MULTICOLUMN = 2 - }; - /* konstruktor */ - /// - LyXTable(int columns_arg, int rows_arg); - /// - explicit - LyXTable(LyXLex & lex); - /// - ~LyXTable(); - /// - LyXTable * Clone(); - - /// Returns true if there is a topline, returns false if not - bool TopLine(int cell); - /// Returns true if there is a topline, returns false if not - bool BottomLine(int cell); - /// Returns true if there is a topline, returns false if not - bool LeftLine(int cell); - /// Returns true if there is a topline, returns false if not - bool RightLine(int cell); + enum { + CELL_NORMAL = 0, + CELL_BEGIN_OF_MULTICOLUMN = 1, + CELL_PART_OF_MULTICOLUMN = 2 + }; + /* konstruktor */ + /// + LyXTable(int columns_arg, int rows_arg, Buffer *buf = 0); + /// + /// + LyXTable(LyXTable const &, Buffer *buf = 0); + /// + explicit + LyXTable(LyXLex & lex, Buffer *buf = 0); + /// + ~LyXTable(); + /// + LyXTable & operator=(LyXTable const &); + /// + LyXTable * Clone(); + + /// Returns true if there is a topline, returns false if not + bool TopLine(int cell); + /// Returns true if there is a topline, returns false if not + bool BottomLine(int cell); + /// Returns true if there is a topline, returns false if not + bool LeftLine(int cell); + /// Returns true if there is a topline, returns false if not + bool RightLine(int cell); + + /// + bool TopAlreadyDrawed(int cell); + /// + bool VeryLastRow(int cell); + + /// + int AdditionalHeight(int cell); + /// + int AdditionalWidth(int cell); + + /* returns the maximum over all rows */ + /// + int WidthOfColumn(int cell); + /// + int WidthOfTable(); + /// + int AscentOfRow(int row); + /// + int DescentOfRow(int row); + /// + int HeightOfTable(); + /// + void SetAscentOfRow(int row, int height); + /// + void SetDescentOfRow(int row, int height); + /// Returns true if a complete update is necessary, otherwise false + bool SetWidthOfCell(int cell, int new_width); + /// Returns true if a complete update is necessary, otherwise false + bool SetAllLines(int cell, bool line); + /// Returns true if a complete update is necessary, otherwise false + bool SetTopLine(int cell, bool line); + /// Returns true if a complete update is necessary, otherwise false + bool SetBottomLine(int cell, bool line); + /// Returns true if a complete update is necessary, otherwise false + bool SetLeftLine(int cell, bool line); + /// Returns true if a complete update is necessary, otherwise false + bool SetRightLine(int cell, bool line); + /// Returns true if a complete update is necessary, otherwise false + bool SetAlignment(int cell, char align); + /// + bool SetPWidth(int cell, string width); + /// + bool SetAlignSpecial(int cell, string special, int what); + /// + char GetAlignment(int cell); // add approp. signedness + /// + string GetPWidth(int cell); + /// + string GetAlignSpecial(int cell, int what); + + /// + int GetWidthOfCell(int cell); + /// + int GetBeginningOfTextInCell(int cell); + + /// + void AppendRow(int cell); + /// + void DeleteRow(int cell); + + /// + void AppendColumn(int cell); + /// + void DeleteColumn(int cell); + + /// + bool IsFirstCell(int cell); + /// + bool IsLastCell(int cell); + + /// + int GetNumberOfCells(); + /// + int AppendCellAfterCell(int append_cell, int question_cell); + /// + int DeleteCellIfColumnIsDeleted(int cell, int delete_column_cell); + /// + int NumberOfCellsInRow(int cell); + /// + void Reinit(); /// - bool TopAlreadyDrawed(int cell); - /// - bool VeryLastRow(int cell); + void Init(int columns_arg, int rows_arg); - /// - int AdditionalHeight(int cell); - /// - int AdditionalWidth(int cell); - - /* returns the maximum over all rows */ - /// - int WidthOfColumn(int cell); - /// - int WidthOfTable(); - - /// Returns true if a complete update is necessary, otherwise false - bool SetWidthOfCell(int cell, int new_width); - /// Returns true if a complete update is necessary, otherwise false - bool SetAllLines(int cell, bool line); - /// Returns true if a complete update is necessary, otherwise false - bool SetTopLine(int cell, bool line); - /// Returns true if a complete update is necessary, otherwise false - bool SetBottomLine(int cell, bool line); - /// Returns true if a complete update is necessary, otherwise false - bool SetLeftLine(int cell, bool line); - /// Returns true if a complete update is necessary, otherwise false - bool SetRightLine(int cell, bool line); - /// Returns true if a complete update is necessary, otherwise false - bool SetAlignment(int cell, char align); - /// - bool SetPWidth(int cell, string width); - /// - bool SetAlignSpecial(int cell, string special, int what); - /// - char GetAlignment(int cell); // add approp. signedness - /// - string GetPWidth(int cell); - /// - string GetAlignSpecial(int cell, int what); + /// + void Write(std::ostream &, bool old_format=true); + /// + void Read(std::istream &); + /// + int Latex(std::ostream &); - /// - int GetWidthOfCell(int cell); - /// - int GetBeginningOfTextInCell(int cell); - - /// - void AppendRow(int cell); - /// - void DeleteRow(int cell); - - /// - void AppendColumn(int cell); - /// - void DeleteColumn(int cell); - - /// - bool IsFirstCell(int cell); - /// - bool IsLastCell(int cell); - - /// - int GetNumberOfCells(); - /// - int AppendCellAfterCell(int append_cell, int question_cell); - /// - int DeleteCellIfColumnIsDeleted(int cell, int delete_column_cell); - /// - int NumberOfCellsInRow(int cell); - /// - void Reinit(); - - /// - void Init(int columns_arg, int rows_arg); - - /// - void Write(std::ostream &); - /// - void Read(std::istream &); - - // cell <0 will tex the preamble - // returns the number of printed newlines - /// - int TexEndOfCell(std::ostream &, int cell); - /// - int DocBookEndOfCell(std::ostream &, int cell, int & depth); + // cell <0 will tex the preamble + // returns the number of printed newlines + /// + int TexEndOfCell(std::ostream &, int cell); + /// + int DocBookEndOfCell(std::ostream &, int cell, int & depth); #if 0 - /// - int RoffEndOfCell(std::ostream &, int cell); + /// + int RoffEndOfCell(std::ostream &, int cell); #endif - /// - char const * getDocBookAlign(int cell, bool isColumn = false); + /// + char const * getDocBookAlign(int cell, bool isColumn = false); - /// - bool IsMultiColumn(int cell); - /// - void SetMultiColumn(int cell, int number); - /// - int UnsetMultiColumn(int cell); // returns number of new cells - /// - int row_of_cell(int cell); - /// - int column_of_cell(int cell); - /// - int rows; - /// - int columns; - /// - void SetLongTable(int what); - /// - bool IsLongTable(); - /// - void SetRotateTable(int what); - /// - bool RotateTable(); - /// - void SetRotateCell(int cell, int what); - /// - bool RotateCell(int cell); - /// - bool NeedRotating(); - /// - void AppendContRow(int cell); - /// - bool IsContRow(int cell); - /// returns the number of the cell which continues - /// or -1 if no ContRow - int CellHasContRow(int cell); - /// - bool RowHasContRow(int cell); - /// - int FirstVirtualCell(int cell); - /// - int NextVirtualCell(int cell); - /// - bool ShouldBeVeryLastCell(int cell); - /// - bool ShouldBeVeryLastRow(int cell); - /// - int GetCellAbove(int cell); - /// - int GetCellNumber(int column, int row); - /// - void SetLinebreaks(int cell, bool what); - /// - bool Linebreaks(int cell); - /// - /// Long Table Options - /// - void SetLTHead(int cell, bool first); - /// - bool RowOfLTHead(int cell); - /// - bool RowOfLTFirstHead(int cell); - /// - void SetLTFoot(int cell, bool last); - /// - bool RowOfLTFoot(int cell); - /// - bool RowOfLTLastFoot(int cell); - /// - void SetLTNewPage(int cell, bool what); - /// - bool LTNewPage(int cell); -private: - /// - struct cellstruct { - /// - int cellno; - /// - int width_of_cell; - /// - int multicolumn; // add approp. signedness - /// - int alignment; // add approp. signedness - /// - bool top_line; - /// - bool bottom_line; - /// - bool has_cont_row; - /// - bool linebreaks; - /// - int rotate; - /// - string align_special; - /// - string p_width; // this is only set for multicolumn!!! - }; - /// - struct rowstruct { - bool top_line; - bool bottom_line; - bool is_cont_row; - /// This are for longtables only - bool newpage; - }; - /// - struct columnstruct { - int alignment; // add approp. signedness - bool left_line; - bool right_line; - int width_of_column; - string p_width; - string align_special; - }; - /// - int numberofcells; - /// - int * rowofcell; - /// - int * columnofcell; - /// - void set_row_column_number_info(); + /// + bool IsMultiColumn(int cell); + /// + void SetMultiColumn(int cell, int number); + /// + int UnsetMultiColumn(int cell); // returns number of new cells + /// + bool IsPartOfMultiColumn(int row, int column); + /// + int row_of_cell(int cell) const; + /// + int column_of_cell(int cell) const; + /// + int rows; + /// + int columns; + /// + void SetLongTable(int what); + /// + bool IsLongTable(); + /// + void SetRotateTable(int what); + /// + bool RotateTable(); + /// + void SetRotateCell(int cell, int what); + /// + bool RotateCell(int cell); + /// + bool NeedRotating(); + /// + void AppendContRow(int cell); + /// + bool IsContRow(int cell); + /// returns the number of the cell which continues + /// or -1 if no ContRow + int CellHasContRow(int cell); + /// + bool RowHasContRow(int cell); + /// + int FirstVirtualCell(int cell); + /// + int NextVirtualCell(int cell); + /// + bool ShouldBeVeryLastCell(int cell); + /// + bool ShouldBeVeryLastRow(int cell); + /// + int GetCellAbove(int cell); + /// + int GetCellNumber(int column, int row); + /// + void SetLinebreaks(int cell, bool what); + /// + bool Linebreaks(int cell); + /// + /// Long Table Options + /// + void SetLTHead(int cell, bool first); + /// + bool RowOfLTHead(int cell); + /// + bool RowOfLTFirstHead(int cell); + /// + void SetLTFoot(int cell, bool last); + /// + bool RowOfLTFoot(int cell); + /// + bool RowOfLTLastFoot(int cell); + /// + void SetLTNewPage(int cell, bool what); + /// + bool LTNewPage(int cell); + /// + InsetText * GetCellInset(int cell) const; + /// +private: ////////////////////////////////////////////////////////////////// + /// + struct cellstruct { /// - rowstruct * row_info; - /// - columnstruct * column_info; - /// - cellstruct ** cell_info; + cellstruct(Buffer * buf = 0); /// - int width_of_table; - /// - /// for long tables - /// - int endhead; // row of endhead - int endfirsthead; // row of endfirsthead - int endfoot; // row of endfoot - int endlastfoot; // row of endlastfoot - - /// Returns true if a complete update is necessary, otherwise false - bool SetWidthOfMulticolCell(int cell, int new_width); - void recalculateMulticolCells(int cell, int new_width); - /// Returns true if change - bool calculate_width_of_column(int column); - bool calculate_width_of_column_NMC(int column); // no multi cells + ~cellstruct(); /// - void calculate_width_of_table(); - - /// - int right_column_of_cell(int cell); - + cellstruct & operator=(cellstruct const &); /// - cellstruct * cellinfo_of_cell(int cell); - + int cellno; /// - void delete_column(int column); - + int width_of_cell; /// - int cells_in_multicolumn(int cell); + int multicolumn; // add approp. signedness /// - int is_long_table; + int alignment; // add approp. signedness + /// + bool top_line; + /// + bool bottom_line; + /// + bool has_cont_row; + /// + bool linebreaks; /// int rotate; + /// + string align_special; + /// + string p_width; // this is only set for multicolumn!!! + /// + InsetText *inset; + }; + /// + struct rowstruct { + /// + rowstruct(); + /// + ~rowstruct(); + /// + rowstruct & operator=(rowstruct const &); + /// + bool top_line; + bool bottom_line; + bool is_cont_row; + int ascent_of_row; + int descent_of_row; + /// This are for longtables only + bool newpage; + }; + /// + struct columnstruct { + /// + columnstruct(); + /// + ~columnstruct(); + /// + columnstruct & operator=(columnstruct const &); + /// + int alignment; // add approp. signedness + bool left_line; + bool right_line; + int width_of_column; + string p_width; + string align_special; + }; + /// + int numberofcells; + /// + int * rowofcell; + /// + int * columnofcell; + /// + rowstruct * row_info; + /// + columnstruct * column_info; + /// + cellstruct ** cell_info; + /// + int width_of_table; + /// + /// for long tables + /// + int endhead; // row of endhead + int endfirsthead; // row of endfirsthead + int endfoot; // row of endfoot + int endlastfoot; // row of endlastfoot + /// + Buffer *buffer; + + /// + void set_row_column_number_info(); + /// Returns true if a complete update is necessary, otherwise false + bool SetWidthOfMulticolCell(int cell, int new_width); + void recalculateMulticolCells(int cell, int new_width); + /// Returns true if change + bool calculate_width_of_column(int column); + bool calculate_width_of_column_NMC(int column); // no multi cells + /// + void calculate_width_of_table(); + + /// + int right_column_of_cell(int cell); + + /// + cellstruct * cellinfo_of_cell(int cell); + + /// + void delete_column(int column); + + /// + int cells_in_multicolumn(int cell); + /// + int is_long_table; + /// + int rotate; }; #endif diff --git a/src/text2.C b/src/text2.C index c32fd0ba45..e15b93454a 100644 --- a/src/text2.C +++ b/src/text2.C @@ -3156,10 +3156,136 @@ void LyXText::SetCursor(LyXParagraph * par, DeleteEmptyParagraphMechanism(old_cursor); } +void LyXText::SetCursor(LyXCursor & cur, LyXParagraph * par, + LyXParagraph::size_type pos) const +{ + // correct the cursor position if impossible + if (pos > par->Last()){ + LyXParagraph * tmppar = par->ParFromPos(pos); + pos = par->PositionInParFromPos(pos); + par = tmppar; + } + if (par->IsDummy() && par->previous && + par->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) { + while (par->previous && + ((par->previous->IsDummy() && + (par->previous->previous->footnoteflag == + LyXParagraph::CLOSED_FOOTNOTE)) || + (par->previous->footnoteflag == + LyXParagraph::CLOSED_FOOTNOTE))) { + par = par->previous ; + if (par->IsDummy() && + (par->previous->footnoteflag == + LyXParagraph::CLOSED_FOOTNOTE)) + pos += par->size() + 1; + } + if (par->previous) { + par = par->previous; + } + pos += par->size() + 1; + } + + cur.par = par; + cur.pos = pos; + + /* get the cursor y position in text */ + long y = 0; + Row * row = GetRow(par, pos, y); + /* y is now the beginning of the cursor row */ + y += row->baseline; + /* y is now the cursor baseline */ + cur.y = y; + + /* now get the cursors x position */ + float x; + float fill_separator, fill_hfill, fill_label_hfill; + PrepareToPrint(row, x, fill_separator, fill_hfill, fill_label_hfill); + LyXParagraph::size_type cursor_vpos; + LyXParagraph::size_type last = RowLastPrintable(row); + + if (pos > last + 1) // This shouldn't happen. + pos = last+1; + + if (last < row->pos) + cursor_vpos = 0; + else if ((pos > last) || + ((pos - 1 >= row->pos) && + (row->par->IsSeparator(pos) || + (row->par->table && row->par->IsNewline(pos))))) + /// Place cursor after char at (logical) position pos-1 + cursor_vpos = !(bidi_level(pos-1) % 2) + ? log2vis(pos-1) + 1 : log2vis(pos-1); + else + /// Place cursor before char at (logical) position pos + cursor_vpos = !(bidi_level(pos) % 2) + ? log2vis(pos) : log2vis(pos) + 1; + + /* table stuff -- begin*/ + if (row->par->table) { + int cell = NumberOfCell(row->par, row->pos); + float x_old = x; + x += row->par->table->GetBeginningOfTextInCell(cell); + for (LyXParagraph::size_type vpos = row->pos; + vpos < cursor_vpos; ++vpos) { + pos = vis2log(vpos); + if (row->par->IsNewline(pos)) { + x = x_old + row->par->table->WidthOfColumn(cell); + x_old = x; + ++cell; + x += row->par->table->GetBeginningOfTextInCell(cell); + } else { + x += SingleWidth(row->par, pos); + } + } + } else { + /* table stuff -- end*/ + LyXParagraph::size_type main_body = + BeginningOfMainBody(row->par); + if ((main_body > 0) && + ((main_body-1 > last) || + !row->par->IsLineSeparator(main_body-1))) + main_body = 0; + + for (LyXParagraph::size_type vpos = row->pos; + vpos < cursor_vpos; ++vpos) { + pos = vis2log(vpos); + if (main_body > 0 && pos == main_body-1) { + x += fill_label_hfill + + lyxfont::width(textclasslist.Style( + buffer->params.textclass, + row->par->GetLayout()) + .labelsep, + GetFont(row->par, -2)); + if (row->par->IsLineSeparator(main_body-1)) + x -= SingleWidth(row->par,main_body-1); + } + if (HfillExpansion(row, pos)) { + x += SingleWidth(row->par, pos); + if (pos >= main_body) + x += fill_hfill; + else + x += fill_label_hfill; + } else if (row->par->IsSeparator(pos)) { + x += SingleWidth(row->par, pos); + if (pos >= main_body) + x += fill_separator; + } else + x += SingleWidth(row->par, pos); + } + } + + cur.x = int(x); + cur.x_fix = cur.x; + cur.row = row; +} + void LyXText::SetCursorIntern(LyXParagraph * par, LyXParagraph::size_type pos, bool setfont) const { + SetCursor(cursor, par, pos); +#warning Remove this when verified working (Jug 20000413) +#if 0 // correct the cursor position if impossible if (pos > par->Last()){ LyXParagraph * tmppar = par->ParFromPos(pos); @@ -3185,18 +3311,6 @@ void LyXText::SetCursorIntern(LyXParagraph * par, cursor.par = par; cursor.pos = pos; - if (setfont) - if (cursor.pos && - (cursor.pos == cursor.par->Last() || cursor.par->IsSeparator(cursor.pos) - || (cursor.par->table && cursor.par->IsNewline(cursor.pos)) - )) { - current_font = cursor.par->GetFontSettings(cursor.pos - 1); - real_current_font = GetFont(cursor.par, cursor.pos - 1); - } else { - current_font = cursor.par->GetFontSettings(cursor.pos); - real_current_font = GetFont(cursor.par, cursor.pos); - } - /* get the cursor y position in text */ long y = 0; Row * row = GetRow(par, pos, y); @@ -3287,6 +3401,19 @@ void LyXText::SetCursorIntern(LyXParagraph * par, cursor.x_fix = cursor.x; cursor.row = row; +#endif + if (setfont) { + if (cursor.pos && + (cursor.pos == cursor.par->Last() || cursor.par->IsSeparator(cursor.pos) + || (cursor.par->table && cursor.par->IsNewline(cursor.pos)) + )) { + current_font = cursor.par->GetFontSettings(cursor.pos - 1); + real_current_font = GetFont(cursor.par, cursor.pos - 1); + } else { + current_font = cursor.par->GetFontSettings(cursor.pos); + real_current_font = GetFont(cursor.par, cursor.pos); + } + } }