From: Jürgen Vigna Date: Mon, 10 Apr 2000 14:29:05 +0000 (+0000) Subject: Added clean CutAndPaste handling with it's own class. Various updates for X-Git-Tag: 1.6.10~22308 X-Git-Url: https://git.lyx.org/gitweb/?a=commitdiff_plain;h=e97f3d1b3146f8ee10f8542d65c09620826dac84;p=features.git Added clean CutAndPaste handling with it's own class. Various updates for text-insets (look at the ChangeLog Entries) git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@643 a592a061-630c-0410-9148-cb99ea01b6c8 --- diff --git a/ChangeLog b/ChangeLog index b22425a6de..1b2a1993d3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,59 @@ +2000-04-10 Juergen Vigna + + * src/insets/insetfoot.C (GetDrawFont): implemented this as the + footnote font should be decreased in size twice when displaying. + + * src/insets/insettext.C (GetDrawFont): inserted this function as + the drawing-font may differ from the real paragraph font. + + * src/lyxfunc.C (processKeyEvent): fixed Esc-handling when unlocking + insets (inset in inset!). + + * src/insets/insetfoot.C (InsertInsetAllowed): implemented the below + function here because we don't want footnotes inside footnotes. + + * src/insets/insettext.C (InsetText): forgot to set autoBreakRows for + Cloned insets. + (init): now set the inset_owner in paragraph.C + (LocalDispatch): added some resetPos() in the right position + (cutSelection): + (copySelection): + (pasteSelection): changed to use the new CutAndPaste-Class. + + * src/insets/lyxinset.h: inserted new function InsertInsetAllowed + which tells if it is allowed to insert another inset inside this one. + + * src/lyx_cb.C (DocumentApplyCB): Using CutAndPaste-Class for + SwitchLayoutsBetweenClasses. + + * src/text2.C (InsertInset): checking of the new paragraph-function + InsertInsetAllowed. + (DeleteSimpleCutBuffer): removed (for now only with #ifdef) as this + is not needed anymore here! + (CutSelection): + (CopySelection): + (PasteSelection): redone (also with #ifdef) so that now this uses + the CutAndPaste-Class. + (SwitchLayoutsBetweenClasses): removed here and implemented in the + CutAndPaste-Class. + + * src/CutAndPaste.[Ch]: added this for clean handling of CutAndPaste + from/to text/insets. + + * src/paragraph.C (LyXParagraph): inserted new inset_owner pointer + so that the paragraph knows if it is inside an (text)-inset. + (InsertFromMinibuffer): changed return-value to bool as now it + may happen that an inset is not inserted in the paragraph. + (InsertInsetAllowed): this checks if it is allowed to insert an + inset in this paragraph. + (PasteParagraph): + (BreakParagraphConservative): + (BreakParagraph) : small change for the above change of the return + value of InsertFromMinibuffer. + + * src/lyxparagraph.h: added inset_owner and the functions to handle + this (SetInsetOwner(), InInset() and InsertInsetAllowed()). + 2000-04-10 Lars Gullik Bjønnes * src/BufferView.[Ch], src/BufferView_pimpl.[Ch]: move more diff --git a/po/POTFILES.in b/po/POTFILES.in index ca08ee0832..60b54c6d45 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -12,13 +12,14 @@ src/buffer.C src/bufferlist.C src/BufferView2.C -src/BufferView.C +src/BufferView_pimpl.C src/bullet_forms.C src/bullet_forms_cb.C src/Chktex.C src/combox.C src/credits.C src/credits_form.C +src/CutAndPaste.C src/filedlg.C src/FontLoader.C src/form1.C diff --git a/src/BufferView2.C b/src/BufferView2.C index 762050a3dd..b4b46aa653 100644 --- a/src/BufferView2.C +++ b/src/BufferView2.C @@ -771,6 +771,10 @@ int BufferView::unlockInset(UpdatableInset * inset) the_locking_inset = 0; text->FinishUndo(); return 0; + } else if (inset && the_locking_inset && + the_locking_inset->UnlockInsetInInset(this, inset)) { + text->FinishUndo(); + return 0; } return bufferlist.unlockInset(inset); } diff --git a/src/CutAndPaste.C b/src/CutAndPaste.C new file mode 100644 index 0000000000..006f3fc1cf --- /dev/null +++ b/src/CutAndPaste.C @@ -0,0 +1,423 @@ +/* This file is part of + * ====================================================== + * + * LyX, The Document Processor + * + * Copyright 1995-2000 The LyX Team. + * + * ====================================================== */ + +#include + +#include "CutAndPaste.h" +#include "lyxparagraph.h" +#include "insets/inseterror.h" +#include "lyx_gui_misc.h" + +#ifdef __GNUG__ +#pragma implementation +#endif + +static LyXParagraph * buf = 0; + +CutAndPaste::CutAndPaste() +{ +} + + +CutAndPaste::~CutAndPaste() +{ +} + +// for now here this should be in another Cut&Paste Class! +// +void CutAndPaste::DeleteBuffer() +{ + if (!buf) + return; + + LyXParagraph * tmppar; + + while (buf) { + tmppar = buf; + buf = buf->next; + delete tmppar; + } + buf = 0; +} + +bool CutAndPaste::cutSelection(LyXParagraph *startpar, LyXParagraph **endpar, + int start, int & end, char tc, bool doclear) +{ + if (!startpar || (start > startpar->Last())) + return false; + + DeleteBuffer(); + + textclass = tc; + + if (!(*endpar) || (startpar->ParFromPos(start) == + (*endpar)->ParFromPos(end))) { + // only within one paragraph + buf = new LyXParagraph; + LyXParagraph::size_type i = start; + if (end > startpar->Last()) + end = startpar->Last(); + for (; i < end; ++i) { + startpar->CopyIntoMinibuffer(start); + /* table stuff -- begin */ + if (startpar->table && startpar->IsNewline(start)) { + ++start; + } else { + /* table stuff -- end */ + startpar->Erase(start); + } + buf->InsertFromMinibuffer(buf->Last()); + } + } else { + // more than one paragraph + (*endpar)->BreakParagraphConservative(end); + *endpar = (*endpar)->Next(); + end = 0; + + startpar->BreakParagraphConservative(start); + + // store the selection + buf = startpar->ParFromPos(start)->next; + buf->previous = 0; + (*endpar)->previous->next = 0; + + // cut the selection + startpar->ParFromPos(start)->next = (*endpar); + + (*endpar)->previous = startpar->ParFromPos(start); + + // care about footnotes + if (buf->footnoteflag) { + LyXParagraph * tmppar = buf; + while (tmppar){ + tmppar->footnoteflag = LyXParagraph::NO_FOOTNOTE; + tmppar = tmppar->next; + } + } + + // the cut selection should begin with standard layout + buf->Clear(); + + // paste the paragraphs again, if possible + if (doclear) + startpar->Next()->ClearParagraph(); + if (startpar->FirstPhysicalPar()->HasSameLayout(startpar->Next()) || + !startpar->Next()->Last()) + startpar->ParFromPos(start)->PasteParagraph(); + } + return true; +} + +bool CutAndPaste::copySelection(LyXParagraph *startpar, LyXParagraph *endpar, + int start, int end, char tc) +{ + if (!startpar || (start > startpar->Last())) + return false; + + DeleteBuffer(); + + textclass = tc; + + if (!(endpar) || (startpar->ParFromPos(start) == + (endpar)->ParFromPos(end))) { + // only within one paragraph + buf = new LyXParagraph; + LyXParagraph::size_type i = start; + if (end > startpar->Last()) + end = startpar->Last(); + for (; i < end; ++i) { + startpar->CopyIntoMinibuffer(i); + buf->InsertFromMinibuffer(buf->Last()); + } + } else { + // copy more than one paragraph + // clone the paragraphs within the selection + LyXParagraph *tmppar = startpar->ParFromPos(start); + buf = tmppar->Clone(); + LyXParagraph *tmppar2 = buf; + + while (tmppar != endpar->ParFromPos(end) + && tmppar->next) { + tmppar = tmppar->next; + tmppar2->next = tmppar->Clone(); + tmppar2->next->previous = tmppar2; + tmppar2 = tmppar2->next; + } + tmppar2->next = 0; + + // care about footnotes + if (buf->footnoteflag) { + tmppar = buf; + while (tmppar){ + tmppar->footnoteflag = LyXParagraph::NO_FOOTNOTE; + tmppar = tmppar->next; + } + } + + // the buf paragraph is too big + LyXParagraph::size_type tmpi2 = startpar->PositionInParFromPos(start); + for (; tmpi2; --tmpi2) + buf->Erase(0); + + // now tmppar 2 is too big, delete all after end + + tmpi2 = endpar->PositionInParFromPos(end); + while (tmppar2->size() > tmpi2) { + tmppar2->Erase(tmppar2->size() - 1); + } + } + return true; +} + +bool CutAndPaste::pasteSelection(LyXParagraph **par, LyXParagraph **endpar, + int &pos, char tc) +{ + if (!checkPastePossible(*par, pos)) + return false; + + if (pos > (*par)->Last()) + pos = (*par)->Last(); + + LyXParagraph * tmpbuf; + LyXParagraph * tmppar = *par; + int tmppos = pos; + + // There are two cases: cutbuffer only one paragraph or many + if (!buf->next) { + // only within a paragraph + tmpbuf = buf->Clone(); + /* table stuff -- begin */ + bool table_too_small = false; + if ((*par)->table) { + while (buf->size() && !table_too_small) { + if (buf->IsNewline(0)){ + while((tmppos < tmppar->Last()) && + !tmppar->IsNewline(tmppos)) + tmppos++; + buf->Erase(0); + if (tmppos < tmppar->Last()) + tmppos++; + else + table_too_small = true; + } else { + // This is an attempt to fix the + // "never insert a space at the + // beginning of a paragraph" problem. + if (!tmppos && buf->IsLineSeparator(0)) { + buf->Erase(0); + } else { + buf->CutIntoMinibuffer(0); + buf->Erase(0); + if (tmppar->InsertFromMinibuffer(tmppos)) + ++tmppos; + } + } + } + } else { + /* table stuff -- end */ + // Some provisions should be done here for checking + // if we are inserting at the beginning of a + // paragraph. If there are a space at the beginning + // of the text to insert and we are inserting at + // the beginning of the paragraph the space should + // be removed. + while (buf->size()) { + // This is an attempt to fix the + // "never insert a space at the + // beginning of a paragraph" problem. + if (!tmppos && buf->IsLineSeparator(0)) { + buf->Erase(0); + } else { + buf->CutIntoMinibuffer(0); + buf->Erase(0); + if (tmppar->InsertFromMinibuffer(tmppos)) + ++tmppos; + } + } + } + delete buf; + buf = tmpbuf; + *endpar = tmppar->Next(); + pos = tmppos; + } else { + // many paragraphs + + // make a copy of the simple cut_buffer + tmpbuf = buf; + LyXParagraph * simple_cut_clone = tmpbuf->Clone(); + LyXParagraph * tmpbuf2 = simple_cut_clone; + if ((*par)->footnoteflag){ + tmpbuf->footnoteflag = (*par)->footnoteflag; + tmpbuf->footnotekind = (*par)->footnotekind; + } + while (tmpbuf->next) { + tmpbuf = tmpbuf->next; + tmpbuf2->next = tmpbuf->Clone(); + tmpbuf2->next->previous = tmpbuf2; + tmpbuf2 = tmpbuf2->next; + if ((*par)->footnoteflag){ + tmpbuf->footnoteflag = (*par)->footnoteflag; + tmpbuf->footnotekind = (*par)->footnotekind; + } + } + + // make sure there is no class difference + SwitchLayoutsBetweenClasses(textclass, tc, buf); + + // make the buf exactly the same layout than + // the cursor paragraph + buf->MakeSameLayout(*par); + + // find the end of the buffer + LyXParagraph * lastbuffer = buf; + while (lastbuffer->Next()) + lastbuffer = lastbuffer->Next(); + + bool paste_the_end = false; + + // open the paragraph for inserting the buf + // if necessary + if (((*par)->Last() > pos) || !(*par)->Next()) { + (*par)->BreakParagraphConservative(pos); + paste_the_end = true; + } + + // set the end for redoing later + *endpar = (*par)->ParFromPos(pos)->next->Next(); + + // paste it! + lastbuffer->ParFromPos(lastbuffer->Last())->next = + (*par)->ParFromPos(pos)->next; + (*par)->ParFromPos(pos)->next->previous = + lastbuffer->ParFromPos(lastbuffer->Last()); + + (*par)->ParFromPos(pos)->next = buf; + buf->previous = (*par)->ParFromPos(pos); + + if ((*par)->ParFromPos(pos)->Next() == lastbuffer) + lastbuffer = *par; + + (*par)->ParFromPos(pos)->PasteParagraph(); + + // store the new cursor position + tmppar = lastbuffer; + tmppos = lastbuffer->Last(); + + // maybe some pasting + if (lastbuffer->Next() && paste_the_end) { + if (lastbuffer->Next()->HasSameLayout(lastbuffer)) { + lastbuffer->ParFromPos(lastbuffer->Last())->PasteParagraph(); + } else if (!lastbuffer->Next()->Last()) { + lastbuffer->Next()->MakeSameLayout(lastbuffer); + lastbuffer->ParFromPos(lastbuffer->Last())->PasteParagraph(); + } else if (!lastbuffer->Last()) { + lastbuffer->MakeSameLayout(lastbuffer->next); + lastbuffer->ParFromPos(lastbuffer->Last())->PasteParagraph(); + } else + lastbuffer->Next()->ClearParagraph(); + } + // restore the simple cut buffer + buf = simple_cut_clone; + pos = tmppos; + } + + return true; +} + +int CutAndPaste::nrOfParagraphs() const +{ + if (!buf) + return 0; + + int n = 1; + LyXParagraph *tmppar = buf; + while(tmppar->next) { + ++n; + tmppar = tmppar->next; + } + return n; +} + +int CutAndPaste::SwitchLayoutsBetweenClasses(LyXTextClassList::size_type c1, + LyXTextClassList::size_type c2, + LyXParagraph * par) +{ + int ret = 0; + if (!par || c1 == c2) + return ret; + par = par->FirstPhysicalPar(); + while (par) { + string name = textclasslist.NameOfLayout(c1, par->layout); + int lay = 0; + pair pp = + textclasslist.NumberOfLayout(c2, name); + if (pp.first) { + lay = pp.second; + } else { // layout not found + // use default layout "Standard" (0) + lay = 0; + } + par->layout = lay; + + if (name != textclasslist.NameOfLayout(c2, par->layout)) { + ++ret; + string s = "Layout had to be changed from\n" + + name + " to " + + textclasslist.NameOfLayout(c2, par->layout) + + "\nbecause of class conversion from\n" + + textclasslist.NameOfClass(c1) + " to " + + textclasslist.NameOfClass(c2); + InsetError * new_inset = new InsetError(s); + par->InsertChar(0, LyXParagraph::META_INSET); + par->InsertInset(0, new_inset); + } + + par = par->next; + } + return ret; +} + +char CutAndPaste::getBufferTextClass() +{ + return textclass; +} + +bool CutAndPaste::checkPastePossible(LyXParagraph *par, int) +{ + if (!buf) + return false; + + LyXParagraph *tmppar; + + // be carefull with footnotes in footnotes + if (par->footnoteflag != LyXParagraph::NO_FOOTNOTE) { + // check whether the cut_buffer includes a footnote + tmppar = buf; + while (tmppar && tmppar->footnoteflag == LyXParagraph::NO_FOOTNOTE) + tmppar = tmppar->next; + + if (tmppar) { + WriteAlert(_("Impossible operation"), + _("Can't paste float into float!"), + _("Sorry.")); + return false; + } + } + /* table stuff -- begin */ + if (par->table) { + if (buf->next) { + WriteAlert(_("Impossible operation"), + _("Table cell cannot include more than one paragraph!"), + _("Sorry.")); + return false; + } + } + /* table stuff -- end */ + return true; +} diff --git a/src/CutAndPaste.h b/src/CutAndPaste.h new file mode 100644 index 0000000000..d2ff6e5d1f --- /dev/null +++ b/src/CutAndPaste.h @@ -0,0 +1,53 @@ +// -*- C++ -*- +/* This file is part of + * ====================================================== + * + * LyX, The Document Processor + * + * Copyright 1995-2000 the LyX Team. + * + * ====================================================== */ + +#ifndef CUTANDPASTE_H +#define CUTANDPASTE_H + +#ifdef __GNUG__ +#pragma interface +#endif + +#include "layout.h" + +class LyXParagraph; + +/// +class CutAndPaste { +public: + /// + CutAndPaste(); + ~CutAndPaste(); + bool cutSelection(LyXParagraph *startpar, LyXParagraph **endpar, + int start, int & end, char tc, bool doclear=false); + bool copySelection(LyXParagraph *startpar, LyXParagraph *endpar, + int start, int end, char tc); + bool pasteSelection(LyXParagraph **par, LyXParagraph **endpar, + int & pos, char tc); + int nrOfParagraphs() const; + /** needed to switch between different classes this works + for a list of paragraphs beginning with the specified par + return value is the number of wrong conversions + */ + int SwitchLayoutsBetweenClasses(LyXTextClassList::size_type class1, + LyXTextClassList::size_type class2, + LyXParagraph * par); + char getBufferTextClass(); + bool checkPastePossible(LyXParagraph *, int pos); + +private: + /// + void DeleteBuffer(); + /// + char textclass; + +}; + +#endif diff --git a/src/Makefile.am b/src/Makefile.am index 87a8e995a2..b098b89a2b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -20,6 +20,8 @@ lyx_SOURCES = \ Bullet.h \ Chktex.C \ Chktex.h \ + CutAndPaste.C \ + CutAndPaste.h \ DepTable.C \ DepTable.h \ FontInfo.C \ diff --git a/src/insets/insetcollapsable.C b/src/insets/insetcollapsable.C index a8d0254882..3cde4b52d5 100644 --- a/src/insets/insetcollapsable.C +++ b/src/insets/insetcollapsable.C @@ -36,7 +36,7 @@ InsetCollapsable::InsetCollapsable(Buffer * bf) Inset * InsetCollapsable::Clone() const { InsetCollapsable * result = new InsetCollapsable(buffer); - result->init(buffer, par); + result->init(buffer, this); result->collapsed = collapsed; return result; diff --git a/src/insets/insetert.C b/src/insets/insetert.C index 6042875484..bbbd43edc2 100644 --- a/src/insets/insetert.C +++ b/src/insets/insetert.C @@ -42,6 +42,7 @@ InsetERT::InsetERT(Buffer * bf) Inset * InsetERT::Clone() const { InsetERT * result = new InsetERT(buffer); + result->init(buffer, this); return result; } diff --git a/src/insets/insetfoot.C b/src/insets/insetfoot.C index e4504e48b9..fd775a3bad 100644 --- a/src/insets/insetfoot.C +++ b/src/insets/insetfoot.C @@ -39,7 +39,7 @@ InsetFoot::InsetFoot(Buffer * bf) Inset * InsetFoot::Clone() const { InsetFoot * result = new InsetFoot(buffer); - result->init(buffer, par); + result->init(buffer, this); result->collapsed = collapsed; return result; @@ -55,7 +55,7 @@ char const * InsetFoot::EditMessage() const int InsetFoot::Latex(ostream & os, signed char fragile, bool fp) const { if (fragile) - os << "\\footnotetext{"; + os << "\\footnote{"; // was footnotemark but that won't work else os << "\\footnote{"; @@ -93,10 +93,26 @@ void InsetFoot::Read(LyXLex & lex) bool InsetFoot::InsertInset(BufferView * bv, Inset * inset) +{ + if (!InsertInsetAllowed(inset)) + return false; + + return InsetText::InsertInset(bv, inset); +} + +bool InsetFoot::InsertInsetAllowed(Inset * inset) const { if ((inset->LyxCode() == Inset::FOOT_CODE) || (inset->LyxCode() == Inset::MARGIN_CODE)) { return false; } - return InsetText::InsertInset(bv, inset); + return true; +} + +LyXFont InsetFoot::GetDrawFont(LyXParagraph * par, int pos) const +{ + LyXFont fn = InsetCollapsable::GetDrawFont(par, pos); + fn.decSize(); + fn.decSize(); + return fn; } diff --git a/src/insets/insetfoot.h b/src/insets/insetfoot.h index 3ac1ee73bf..43faa6dd4a 100644 --- a/src/insets/insetfoot.h +++ b/src/insets/insetfoot.h @@ -46,6 +46,11 @@ public: const char * EditMessage() const; /// bool InsertInset(BufferView *, Inset * inset); + /// + bool InsertInsetAllowed(Inset * inset) const; + /// + LyXFont GetDrawFont(LyXParagraph * par, int pos) const; + /// }; #endif diff --git a/src/insets/insettext.C b/src/insets/insettext.C index b3f756ea9e..08da8ce5ab 100644 --- a/src/insets/insettext.C +++ b/src/insets/insettext.C @@ -51,6 +51,7 @@ #include "support/LAssert.h" #include "lyxtext.h" #include "lyxcursor.h" +#include "CutAndPaste.h" #include "font.h" using std::ostream; @@ -72,16 +73,12 @@ InsetText::InsetText(InsetText const & ins, Buffer * buf) { par = 0; widthOffset = 0; - init(buf, ins.par); + init(buf, &ins); + autoBreakRows = ins.autoBreakRows; } -void InsetText::init(Buffer * buf, LyXParagraph *p) +void InsetText::init(Buffer * buf, InsetText const * ins) { - if (p) { - if (par) - delete par; - par = p->Clone(); - } the_locking_inset = 0; buffer = buf; cursor_visible = false; @@ -93,6 +90,13 @@ void InsetText::init(Buffer * buf, LyXParagraph *p) maxAscent = maxDescent = insetWidth = 0; autoBreakRows = false; xpos = 0.0; + if (ins) { + if (par) + delete par; + par = ins->par->Clone(); + autoBreakRows = ins->autoBreakRows; + } + par->SetInsetOwner(this); } @@ -197,11 +201,11 @@ void InsetText::draw(Painter & pain, LyXFont const & f, int baseline, float & x) const { xpos = x; - computeTextRows(pain, x); UpdatableInset::draw(pain, f, baseline, x); top_x = int(x); top_baseline = baseline; + computeTextRows(pain, x); computeBaselines(baseline); for(RowList::size_type r = 0; r < rows.size() - 1; ++r) { drawRowSelection(pain, rows[r].pos, rows[r + 1].pos, r, @@ -239,7 +243,7 @@ void InsetText::drawRowSelection(Painter & pain, int startpos, int endpos, if ((p >= s_start) && (p <= s_end)) esel_x = int(x); char ch = par->GetChar(p); - font = GetFont(par,p); + font = GetDrawFont(par,p); if (IsFloatChar(ch)) { // skip for now } else if (ch == LyXParagraph::META_INSET) { @@ -269,7 +273,7 @@ void InsetText::drawRowText(Painter & pain, int startpos, int endpos, for(int p = startpos; p < endpos; ++p) { char ch = par->GetChar(p); - LyXFont font = GetFont(par,p); + LyXFont font = GetDrawFont(par,p); if (IsFloatChar(ch)) { // skip for now } else if (par->IsNewline(p)) { @@ -321,6 +325,7 @@ char const * InsetText::EditMessage() const void InsetText::Edit(BufferView * bv, int x, int y, unsigned int button) { + par->SetInsetOwner(this); UpdatableInset::Edit(bv, x, y, button); bv->lockInset(this); @@ -507,6 +512,7 @@ InsetText::LocalDispatch(BufferView * bv, moveRight(bv, false); selection_end = actpos; UpdateLocal(bv, false); + resetPos(bv, true); break; case LFUN_RIGHT: bv->text->FinishUndo(); @@ -517,12 +523,14 @@ InsetText::LocalDispatch(BufferView * bv, } else { selection_start = selection_end = actpos; } + resetPos(bv, true); break; case LFUN_LEFTSEL: bv->text->FinishUndo(); moveLeft(bv, false); selection_end = actpos; UpdateLocal(bv, false); + resetPos(bv, true); break; case LFUN_LEFT: bv->text->FinishUndo(); @@ -533,12 +541,14 @@ InsetText::LocalDispatch(BufferView * bv, } else { selection_start = selection_end = actpos; } + resetPos(bv, true); break; case LFUN_DOWNSEL: bv->text->FinishUndo(); moveDown(bv, false); selection_end = actpos; UpdateLocal(bv, false); + resetPos(bv, true); break; case LFUN_DOWN: bv->text->FinishUndo(); @@ -549,12 +559,14 @@ InsetText::LocalDispatch(BufferView * bv, } else { selection_start = selection_end = actpos; } + resetPos(bv, true); break; case LFUN_UPSEL: bv->text->FinishUndo(); moveUp(bv, false); selection_end = actpos; UpdateLocal(bv, false); + resetPos(bv, true); break; case LFUN_UP: bv->text->FinishUndo(); @@ -565,6 +577,7 @@ InsetText::LocalDispatch(BufferView * bv, } else { selection_start = selection_end = actpos; } + resetPos(bv, true); break; case LFUN_BACKSPACE: if (!actpos) { // || par->IsNewline(actpos-1)) { @@ -576,13 +589,17 @@ InsetText::LocalDispatch(BufferView * bv, } moveLeft(bv); case LFUN_DELETE: - bool ret; + { bv->text->SetUndo(Undo::DELETE, bv->text->cursor.par->ParFromPos(bv->text->cursor.pos)->previous, bv->text->cursor.par->ParFromPos(bv->text->cursor.pos)->next); - if (hasSelection()) - ret = cutSelection(); - else + bool ret = true; + if (hasSelection()) { + LyXParagraph::size_type i = selection_start; + for (; i < selection_end; ++i) { + par->Erase(selection_start); + } + } else ret = Delete(); if (ret) { // we need update selection_start = selection_end = actpos; @@ -591,22 +608,28 @@ InsetText::LocalDispatch(BufferView * bv, selection_start = selection_end = actpos; UpdateLocal(bv, false); } - break; + } + resetPos(bv, true); + break; case LFUN_CUT: - bv->text->SetUndo(Undo::DELETE, - bv->text->cursor.par->ParFromPos(bv->text->cursor.pos)->previous, - bv->text->cursor.par->ParFromPos(bv->text->cursor.pos)->next); - if (cutSelection()) { // we need update + bv->text->SetUndo(Undo::DELETE, + bv->text->cursor.par->ParFromPos(bv->text->cursor.pos)->previous, + bv->text->cursor.par->ParFromPos(bv->text->cursor.pos)->next); + + if (cutSelection()) { + // we need update actpos = selection_end = selection_start; UpdateLocal(bv, true); } else if (hasSelection()) { selection_start = selection_end = actpos; UpdateLocal(bv, false); } + resetPos(bv, true); break; case LFUN_COPY: bv->text->FinishUndo(); - if (copySelection()) { // we need update + if (copySelection()) { + // we need update selection_start = selection_end = actpos; UpdateLocal(bv, true); } else if (hasSelection()) { @@ -615,14 +638,17 @@ InsetText::LocalDispatch(BufferView * bv, } break; case LFUN_PASTE: + { 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); + 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; UpdateLocal(bv, true); } - break; + } + resetPos(bv, true); + break; case LFUN_HOME: bv->text->FinishUndo(); for(; actpos > rows[actrow].pos; --actpos) @@ -634,6 +660,7 @@ InsetText::LocalDispatch(BufferView * bv, } else { selection_start = selection_end = actpos; } + resetPos(bv, true); break; case LFUN_END: { @@ -650,6 +677,7 @@ InsetText::LocalDispatch(BufferView * bv, selection_start = selection_end = actpos; } } + resetPos(bv, true); break; case LFUN_MATH_MODE: // Open or create a math inset bv->text->SetUndo(Undo::INSERT, @@ -663,6 +691,7 @@ InsetText::LocalDispatch(BufferView * bv, selection_start = selection_end = actpos; } return DISPATCHED; + case LFUN_BREAKPARAGRAPH: case LFUN_BREAKLINE: bv->text->SetUndo(Undo::INSERT, bv->text->cursor.par->ParFromPos(bv->text->cursor.pos)->previous, @@ -704,7 +733,7 @@ void InsetText::Validate(LaTeXFeatures & features) const // Returns the width of a character at a certain spot int InsetText::SingleWidth(Painter & pain, LyXParagraph * par, int pos) const { - LyXFont font = GetFont(par, pos); + LyXFont font = GetDrawFont(par, pos); char c = par->GetChar(pos); if (IsPrintable(c)) { @@ -727,7 +756,7 @@ int InsetText::SingleWidth(Painter & pain, LyXParagraph * par, int pos) const void InsetText::SingleHeight(Painter & pain, LyXParagraph * par,int pos, int & asc, int & desc) const { - LyXFont font = GetFont(par, pos); + LyXFont font = GetDrawFont(par, pos); char c = par->GetChar(pos); asc = desc = 0; @@ -817,6 +846,11 @@ LyXFont InsetText::GetFont(LyXParagraph * par, int pos) const return tmpfont; } +// the font for drawing may be different from the real font +LyXFont InsetText::GetDrawFont(LyXParagraph * par, int pos) const +{ + return GetFont(par, pos); +} int InsetText::BeginningOfMainBody(LyXParagraph * par) const { @@ -852,7 +886,7 @@ void InsetText::ToggleInsetCursor(BufferView * bv) return; } - LyXFont font = GetFont(par, actpos); + LyXFont font = GetDrawFont(par, actpos); int asc = lyxfont::maxAscent(font); int desc = lyxfont::maxDescent(font); @@ -868,7 +902,7 @@ void InsetText::ToggleInsetCursor(BufferView * bv) void InsetText::ShowInsetCursor(BufferView * bv) { if (!cursor_visible) { - LyXFont font = GetFont(par, actpos); + LyXFont font = GetDrawFont(par, actpos); int asc = lyxfont::maxAscent(font); int desc = lyxfont::maxDescent(font); @@ -962,7 +996,7 @@ bool InsetText::moveLeft(BufferView * bv, bool activate_inset) inset_y = cy; inset_pos = actpos; the_locking_inset->Edit(bv, the_locking_inset-> - width(bv->painter(), GetFont(par,actpos)), + width(bv->painter(), GetDrawFont(par,actpos)), 0, 0); } else { resetPos(bv); @@ -991,8 +1025,11 @@ bool InsetText::moveDown(BufferView * bv, bool activate_inset) } -void InsetText::resetPos(BufferView * bv) +void InsetText::resetPos(BufferView * bv, bool setfont) { + if (setfont) { + real_current_font = current_font = GetDrawFont(par, actpos); + } if (!rows.size()) return; @@ -1315,75 +1352,43 @@ void InsetText::UpdateLocal(BufferView *bv, bool flag) ShowInsetCursor(bv); } -// this is for the simple cut and paste mechanism -// this then should be a global stuff so that cut'n'paste can work in and -// and outside text-insets -static LyXParagraph * simple_cut_buffer = 0; -// static char simple_cut_buffer_textclass = 0; - -// for now here this should be in another Cut&Paste Class! -// -static void DeleteSimpleCutBuffer() -{ - if (!simple_cut_buffer) - return; - LyXParagraph * tmppar; - - while (simple_cut_buffer) { - tmppar = simple_cut_buffer; - simple_cut_buffer = simple_cut_buffer->next; - delete tmppar; - } - simple_cut_buffer = 0; -} - bool InsetText::cutSelection() { if (!hasSelection()) return false; - DeleteSimpleCutBuffer(); - - // only within one paragraph - simple_cut_buffer = new LyXParagraph; - LyXParagraph::size_type i = selection_start; - for (; i < selection_end; ++i) { - par->CopyIntoMinibuffer(selection_start); - par->Erase(selection_start); - simple_cut_buffer->InsertFromMinibuffer(simple_cut_buffer->Last()); - } - return true; + + CutAndPaste cap; + + LyXParagraph *endpar = par; + + return cap.cutSelection(par, &endpar, selection_start, selection_end, + buffer->params.textclass); } bool InsetText::copySelection() { if (!hasSelection()) return false; - DeleteSimpleCutBuffer(); - - // only within one paragraph - simple_cut_buffer = new LyXParagraph; - LyXParagraph::size_type i = selection_start; - for (; i < selection_end; ++i) { - par->CopyIntoMinibuffer(i); - simple_cut_buffer->InsertFromMinibuffer(simple_cut_buffer->Last()); - } - return true; + + CutAndPaste cap; + + return cap.copySelection(par, par, selection_start, selection_end, + buffer->params.textclass); } bool InsetText::pasteSelection() { - if (!simple_cut_buffer) - return false; - - LyXParagraph * tmppar = simple_cut_buffer->Clone(); + CutAndPaste cap; - while (simple_cut_buffer->size()) { - simple_cut_buffer->CutIntoMinibuffer(0); - simple_cut_buffer->Erase(0); - par->InsertFromMinibuffer(actpos); - ++actpos; + if (cap.nrOfParagraphs() > 1) { + WriteAlert(_("Impossible operation"), + _("Cannot include more than one paragraph!"), + _("Sorry.")); + return false; } - delete simple_cut_buffer; - simple_cut_buffer = tmppar; - return true; + LyXParagraph *endpar; + LyXParagraph *actpar = par; + + return cap.pasteSelection(&actpar, &endpar, actpos, + buffer->params.textclass); } diff --git a/src/insets/insettext.h b/src/insets/insettext.h index 08d4814d61..a95523f834 100644 --- a/src/insets/insettext.h +++ b/src/insets/insettext.h @@ -100,7 +100,7 @@ public: /// void SetFont(BufferView *, LyXFont const &, bool toggleall = false); /// - void init(Buffer *, LyXParagraph * p = 0); + void init(Buffer *, InsetText const * ins = 0); LyXParagraph * par; @@ -110,7 +110,7 @@ protected: /// void WriteParagraphData(std::ostream &) const; /// - void resetPos(BufferView *); + void resetPos(BufferView *, bool setfont=false); /// void drawSelection(Painter &, int pos, int baseline, float x); /// @@ -120,6 +120,8 @@ protected: int SingleWidth(Painter &, LyXParagraph * par, int pos) const; /// LyXFont GetFont(LyXParagraph * par, int pos) const; + /// + virtual LyXFont GetDrawFont(LyXParagraph * par, int pos) const; Buffer * buffer; /// diff --git a/src/insets/lyxinset.h b/src/insets/lyxinset.h index 3a334ab900..debef0e87c 100644 --- a/src/insets/lyxinset.h +++ b/src/insets/lyxinset.h @@ -170,7 +170,8 @@ public: } /// virtual void init(BufferView *) {} - + /// + virtual bool InsertInsetAllowed(Inset *) const { return false; } }; @@ -260,6 +261,8 @@ public: /// virtual bool InsertInset(BufferView *, Inset *) { return false; } /// + virtual bool InsertInsetAllowed(Inset *) const { return true; } + /// virtual UpdatableInset * GetLockingInset() { return this; } /// virtual int InsetInInsetY() { return 0; } diff --git a/src/lyx_cb.C b/src/lyx_cb.C index 975c51f497..2a54f1128f 100644 --- a/src/lyx_cb.C +++ b/src/lyx_cb.C @@ -54,6 +54,7 @@ #include "gettext.h" #include "layout.h" #include "language.h" +#include "CutAndPaste.h" using std::ifstream; using std::copy; @@ -2710,13 +2711,13 @@ extern "C" void DocumentApplyCB(FL_OBJECT *, long) if (textclasslist.Load(new_class)) { // successfully loaded redo = true; - current_view->owner()->getMiniBuffer()->Set(_("Converting document to new document class...")); - int ret = current_view->text-> - SwitchLayoutsBetweenClasses(current_view->buffer()-> - params.textclass, - new_class, - current_view->buffer()-> - paragraph); + current_view->owner()->getMiniBuffer()-> + Set(_("Converting document to new document class...")); + CutAndPaste cap; + int ret = cap.SwitchLayoutsBetweenClasses( + current_view->buffer()->params.textclass, + new_class, + current_view->buffer()->paragraph); if (ret) { string s; diff --git a/src/lyxfunc.C b/src/lyxfunc.C index efc97ad917..9706810415 100644 --- a/src/lyxfunc.C +++ b/src/lyxfunc.C @@ -200,13 +200,17 @@ int LyXFunc::processKeyEvent(XEvent * ev) } // this function should be used always [asierra060396] - if (owner->view()->available() && - owner->view()->the_locking_inset && - keysym_return == XK_Escape) { - owner->view()->unlockInset(owner->view()->the_locking_inset); - owner->view()->text->CursorRight(); - moveCursorUpdate(false); - owner->getMiniBuffer()->Set(CurrentState()); + UpdatableInset * tli = owner->view()->the_locking_inset; + if (owner->view()->available() && tli && (keysym_return==XK_Escape)) { + if (tli == tli->GetLockingInset()) { + owner->view()->unlockInset(tli); + owner->view()->text->CursorRight(); + moveCursorUpdate(false); + owner->getMiniBuffer()->Set(CurrentState()); + } else { + tli->UnlockInsetInInset(owner->view(), + tli->GetLockingInset()); + } return 0; } diff --git a/src/lyxparagraph.h b/src/lyxparagraph.h index 17a8d11491..52c08a0f14 100644 --- a/src/lyxparagraph.h +++ b/src/lyxparagraph.h @@ -184,9 +184,15 @@ public: proof environment */ int GetEndLabel() const; + Inset * InInset() { return inset_owner; } + void SetInsetOwner(Inset *i) { inset_owner = i; } + private: /// TextContainer text; + /// + Inset * inset_owner; + public: /// size_type size() const { return text.size(); } @@ -401,6 +407,8 @@ public: /// void InsertInset(size_type pos, Inset * inset); /// + bool InsertInsetAllowed(Inset * inset); + /// Inset * GetInset(size_type pos); /// Inset const * GetInset(size_type pos) const; @@ -415,7 +423,7 @@ public: /// void CutIntoMinibuffer(size_type pos); /// - void InsertFromMinibuffer(size_type pos); + bool InsertFromMinibuffer(size_type pos); /// bool IsHfill(size_type pos) const; diff --git a/src/lyxtext.h b/src/lyxtext.h index 200fd75049..6683824104 100644 --- a/src/lyxtext.h +++ b/src/lyxtext.h @@ -391,14 +391,6 @@ public: /// just another feature :) bool GotoNextNote() const; - /** needed to switch between different classes this works - for a list of paragraphs beginning with the specified par - return value is the number of wrong conversions - */ - int SwitchLayoutsBetweenClasses(LyXTextClassList::size_type class1, - LyXTextClassList::size_type class2, - LyXParagraph * par); - /* for the greater insets */ /// returns 0 if inset wasn't found diff --git a/src/paragraph.C b/src/paragraph.C index 0841a945e5..28faee543a 100644 --- a/src/paragraph.C +++ b/src/paragraph.C @@ -77,6 +77,7 @@ LyXParagraph::LyXParagraph() /* table stuff -- begin*/ table = 0; /* table stuff -- end*/ + inset_owner = 0; id_ = paragraph_id++; bibkey = 0; // ale970302 Clear(); @@ -106,6 +107,7 @@ LyXParagraph::LyXParagraph(LyXParagraph * par) /* table stuff -- begin*/ table = 0; /* table stuff -- end*/ + inset_owner = 0; id_ = paragraph_id++; bibkey = 0; // ale970302 @@ -442,12 +444,16 @@ void LyXParagraph::CutIntoMinibuffer(LyXParagraph::size_type pos) } -void LyXParagraph::InsertFromMinibuffer(LyXParagraph::size_type pos) +bool LyXParagraph::InsertFromMinibuffer(LyXParagraph::size_type pos) { + if ((minibuffer_char == LyXParagraph::META_INSET) && + !InsertInsetAllowed(minibuffer_inset)) + return false; InsertChar(pos, minibuffer_char); SetFont(pos, minibuffer_font); if (minibuffer_char == LyXParagraph::META_INSET) InsertInset(pos, minibuffer_inset); + return true; } // end of minibuffer @@ -636,6 +642,15 @@ void LyXParagraph::InsertInset(LyXParagraph::size_type pos, } +bool LyXParagraph::InsertInsetAllowed(Inset *inset) +{ + if (inset_owner) { + printf("CODE:%d\n",inset->LyxCode()); + return inset_owner->InsertInsetAllowed(inset); + } + return true; +} + Inset * LyXParagraph::GetInset(LyXParagraph::size_type pos) { if (pos >= size()) { @@ -1335,7 +1350,7 @@ LyXParagraph const * LyXParagraph::Previous() const void LyXParagraph::BreakParagraph(LyXParagraph::size_type pos, int flag) { - size_type i, pos_end, pos_first; + size_type i, j, pos_end, pos_first; // create a new paragraph LyXParagraph * par = ParFromPos(pos); LyXParagraph * firstpar = FirstPhysicalPar(); @@ -1380,9 +1395,10 @@ void LyXParagraph::BreakParagraph(LyXParagraph::size_type pos, //if (pos_end > pos) // tmp->text.reserve(pos_end - pos); - for (i = pos; i <= pos_end; ++i) { + for (i = j = pos; i <= pos_end; ++i) { par->CutIntoMinibuffer(i - pos_first); - tmp->InsertFromMinibuffer(i - pos); + if (tmp->InsertFromMinibuffer(j - pos)) + ++j; } tmp->text.resize(tmp->text.size()); for (i = pos_end; i >= pos; --i) @@ -1472,6 +1488,8 @@ LyXParagraph * LyXParagraph::Clone() const else result->table = 0; /* table stuff -- end*/ + + result->inset_owner = inset_owner; // ale970302 result->bibkey = (bibkey) ? new InsetBibKey(bibkey): 0; @@ -1551,9 +1569,11 @@ void LyXParagraph::BreakParagraphConservative(LyXParagraph::size_type pos) //if (pos_end > pos) // tmp->text.reserve(pos_end - pos); - for (size_type i = pos; i <= pos_end; ++i) { + size_type i, j; + for (i = j = pos; i <= pos_end; ++i) { par->CutIntoMinibuffer(i - pos_first); - tmp->InsertFromMinibuffer(i - pos); + if (tmp->InsertFromMinibuffer(j - pos)) + ++j; } tmp->text.resize(tmp->text.size()); for (size_type i = pos_end; i >= pos; --i) @@ -1581,9 +1601,11 @@ void LyXParagraph::PasteParagraph() size_type pos_insert = Last(); // ok, now copy the paragraph - for (size_type i = 0; i <= pos_end; ++i) { + size_type i, j; + for (i = j = 0; i <= pos_end; ++i) { the_next->CutIntoMinibuffer(i); - InsertFromMinibuffer(pos_insert + i); + if (InsertFromMinibuffer(pos_insert + j)) + ++j; } // delete the next paragraph diff --git a/src/support/lyxstring.h b/src/support/lyxstring.h index e96e9f8206..8ed99ec079 100644 --- a/src/support/lyxstring.h +++ b/src/support/lyxstring.h @@ -163,7 +163,7 @@ public: lyxstring(value_type const *, size_type n); /// #lyxstring x("abc")# - explicit +// explicit lyxstring(value_type const *); /// lyxstring(5, 'n') -> "nnnnn" diff --git a/src/text2.C b/src/text2.C index 625d145f09..13774a60d5 100644 --- a/src/text2.C +++ b/src/text2.C @@ -35,11 +35,13 @@ #include "BufferView.h" #include "LyXView.h" #include "lyxrow.h" +#include "CutAndPaste.h" #include "Painter.h" #include "font.h" #include "debug.h" #define FIX_DOUBLE_SPACE 1 +//#define USE_OLD_CUT_AND_PASTE 1 using std::copy; using std::endl; @@ -1843,6 +1845,8 @@ void LyXText::UpdateCounters(Row * row) const /* insets an inset. */ void LyXText::InsertInset(Inset *inset) { + if (!cursor.par->InsertInsetAllowed(inset)) + return; SetUndo(Undo::INSERT, cursor.par->ParFromPos(cursor.pos)->previous, cursor.par->ParFromPos(cursor.pos)->next); @@ -1854,6 +1858,7 @@ void LyXText::InsertInset(Inset *inset) } +#ifdef USE_OLD_CUT_AND_PASTE // this is for the simple cut and paste mechanism static LyXParagraph * simple_cut_buffer = 0; static char simple_cut_buffer_textclass = 0; @@ -1871,7 +1876,7 @@ void DeleteSimpleCutBuffer() } simple_cut_buffer = 0; } - +#endif void LyXText::copyEnvironmentType() { @@ -1884,7 +1889,7 @@ void LyXText::pasteEnvironmentType() SetLayout(copylayouttype); } - +#ifdef USE_OLD_CUT_AND_PASTE void LyXText::CutSelection(bool doclear) { // This doesn't make sense, if there is no selection @@ -2140,7 +2145,98 @@ void LyXText::CutSelection(bool doclear) UpdateCounters(cursor.row); } +#else /////////////////////////////////////////////////////////////////// + +void LyXText::CutSelection(bool doclear) +{ + // This doesn't make sense, if there is no selection + if (!selection) + return; + + // OK, we have a selection. This is always between sel_start_cursor + // and sel_end cursor + LyXParagraph * tmppar; + + // Check whether there are half footnotes in the selection + if (sel_start_cursor.par->footnoteflag != LyXParagraph::NO_FOOTNOTE + || sel_end_cursor.par->footnoteflag != LyXParagraph::NO_FOOTNOTE) { + tmppar = sel_start_cursor.par; + while (tmppar != sel_end_cursor.par){ + if (tmppar->footnoteflag != sel_end_cursor.par->footnoteflag) { + WriteAlert(_("Impossible operation"), + _("Don't know what to do with half floats."), + _("sorry.")); + return; + } + tmppar = tmppar->Next(); + } + } + + /* table stuff -- begin */ + if (sel_start_cursor.par->table || sel_end_cursor.par->table) { + if ( sel_start_cursor.par != sel_end_cursor.par) { + WriteAlert(_("Impossible operation"), + _("Don't know what to do with half tables."), + _("sorry.")); + return; + } + sel_start_cursor.par->table->Reinit(); + } + /* table stuff -- end */ + // make sure that the depth behind the selection are restored, too + LyXParagraph * endpar = sel_end_cursor.par->LastPhysicalPar()->Next(); + LyXParagraph * undoendpar = endpar; + + if (endpar && endpar->GetDepth()) { + while (endpar && endpar->GetDepth()) { + endpar = endpar->LastPhysicalPar()->Next(); + undoendpar = endpar; + } + } else if (endpar) { + endpar = endpar->Next(); // because of parindents etc. + } + + SetUndo(Undo::DELETE, sel_start_cursor + .par->ParFromPos(sel_start_cursor.pos)->previous, undoendpar); + + CutAndPaste cap; + + // there are two cases: cut only within one paragraph or + // more than one paragraph + if (sel_start_cursor.par->ParFromPos(sel_start_cursor.pos) + == sel_end_cursor.par->ParFromPos(sel_end_cursor.pos)) { + // only within one paragraph + endpar = sel_start_cursor.par; + cap.cutSelection(sel_start_cursor.par, &endpar, + sel_start_cursor.pos, sel_end_cursor.pos, + parameters->textclass, doclear); + } else { + endpar = sel_end_cursor.par; + + cap.cutSelection(sel_start_cursor.par, &endpar, + sel_start_cursor.pos, sel_end_cursor.pos, + parameters->textclass, doclear); + cursor.par = sel_end_cursor.par = endpar; + cursor.pos = sel_end_cursor.pos; + } + endpar = sel_end_cursor.par->Next(); + + // sometimes necessary + if (doclear) + sel_start_cursor.par->ClearParagraph(); + + RedoParagraphs(sel_start_cursor, endpar); + + ClearSelection(); + cursor = sel_start_cursor; + SetCursor(cursor.par, cursor.pos); + sel_cursor = cursor; + UpdateCounters(cursor.row); +} +#endif + +#ifdef USE_OLD_CUT_AND_PASTE void LyXText::CopySelection() { // this doesnt make sense, if there is no selection @@ -2245,8 +2341,65 @@ void LyXText::CopySelection() } } } - +#else ////////////////////////////////////////////////////////////////////// + +void LyXText::CopySelection() +{ + // this doesnt make sense, if there is no selection + if (!selection) + return; + + // ok we have a selection. This is always between sel_start_cursor + // and sel_end cursor + LyXParagraph * tmppar; + + /* check wether there are half footnotes in the selection */ + if (sel_start_cursor.par->footnoteflag != LyXParagraph::NO_FOOTNOTE + || sel_end_cursor.par->footnoteflag != LyXParagraph::NO_FOOTNOTE) { + tmppar = sel_start_cursor.par; + while (tmppar != sel_end_cursor.par) { + if (tmppar->footnoteflag != + sel_end_cursor.par->footnoteflag) { + WriteAlert(_("Impossible operation"), + _("Don't know what to do" + " with half floats."), + _("sorry.")); + return; + } + tmppar = tmppar->Next(); + } + } + + /* table stuff -- begin */ + if (sel_start_cursor.par->table || sel_end_cursor.par->table){ + if ( sel_start_cursor.par != sel_end_cursor.par){ + WriteAlert(_("Impossible operation"), + _("Don't know what to do with half tables."), + _("sorry.")); + return; + } + } + /* table stuff -- end */ + +#ifdef FIX_DOUBLE_SPACE + // copy behind a space if there is one + while (sel_start_cursor.par->Last() > sel_start_cursor.pos + && sel_start_cursor.par->IsLineSeparator(sel_start_cursor.pos) + && (sel_start_cursor.par != sel_end_cursor.par + || sel_start_cursor.pos < sel_end_cursor.pos)) + sel_start_cursor.pos++; +#endif + + CutAndPaste cap; + + cap.copySelection(sel_start_cursor.par, sel_end_cursor.par, + sel_start_cursor.pos, sel_end_cursor.pos, + parameters->textclass); +} +#endif + +#ifdef USE_OLD_CUT_AND_PASTE void LyXText::PasteSelection() { // this does not make sense, if there is nothing to paste @@ -2373,6 +2526,7 @@ void LyXText::PasteSelection() endpar = tmpcursor.par->Next(); } else { // many paragraphs + CutAndPaste cap; // make a copy of the simple cut_buffer tmppar = simple_cut_buffer; @@ -2394,9 +2548,9 @@ void LyXText::PasteSelection() } // make sure there is no class difference - SwitchLayoutsBetweenClasses(simple_cut_buffer_textclass, - parameters->textclass, - simple_cut_buffer); + cap.SwitchLayoutsBetweenClasses(simple_cut_buffer_textclass, + parameters->textclass, + simple_cut_buffer); // make the simple_cut_buffer exactly the same layout than // the cursor paragraph @@ -2512,7 +2666,38 @@ void LyXText::PasteSelection() SetSelection(); UpdateCounters(cursor.row); } + +#else //////////////////////////////////////////////////////////////////// + +void LyXText::PasteSelection() +{ + CutAndPaste cap; + + // this does not make sense, if there is nothing to paste + if (!cap.checkPastePossible(cursor.par, cursor.pos)) + return; + + SetUndo(Undo::INSERT, + cursor.par->ParFromPos(cursor.pos)->previous, + cursor.par->ParFromPos(cursor.pos)->next); + + LyXParagraph *endpar; + LyXParagraph *actpar = cursor.par; + int endpos = cursor.pos; + + cap.pasteSelection(&actpar, &endpar, endpos, parameters->textclass); + + RedoParagraphs(cursor, endpar); + + SetCursor(cursor.par, cursor.pos); + ClearSelection(); + sel_cursor = cursor; + SetCursor(actpar, endpos); + SetSelection(); + UpdateCounters(cursor.row); +} +#endif // returns a pointer to the very first LyXParagraph LyXParagraph * LyXText::FirstParagraph() const @@ -2673,9 +2858,13 @@ void LyXText::InsertStringA(string const & str) #if 1 InsetSpecialChar * new_inset = new InsetSpecialChar(InsetSpecialChar::PROTECTED_SEPARATOR); - par->InsertChar(pos, LyXParagraph::META_INSET); - par->SetFont(pos, current_font); - par->InsertInset(pos, new_inset); + if (par->InsertInsetAllowed(new_inset)) { + par->InsertChar(pos, LyXParagraph::META_INSET); + par->SetFont(pos, current_font); + par->InsertInset(pos, new_inset); + } else { + delete new_inset; + } #else par->InsertChar(pos, LyXParagraph::META_PROTECTED_SEPARATOR); par->SetFont(pos, current_font); @@ -2686,9 +2875,13 @@ void LyXText::InsertStringA(string const & str) #if 1 InsetSpecialChar * new_inset = new InsetSpecialChar(InsetSpecialChar::PROTECTED_SEPARATOR); - par->InsertChar(pos, LyXParagraph::META_INSET); - par->SetFont(pos, current_font); - par->InsertInset(pos, new_inset); + if (par->InsertInsetAllowed(new_inset)) { + par->InsertChar(pos, LyXParagraph::META_INSET); + par->SetFont(pos, current_font); + par->InsertInset(pos, new_inset); + } else { + delete new_inset; + } #else par->InsertChar(a, LyXParagraph::META_PROTECTED_SEPARATOR); par->SetFont(a, current_font); @@ -2730,9 +2923,13 @@ void LyXText::InsertStringA(string const & str) #if 1 InsetSpecialChar * new_inset = new InsetSpecialChar(InsetSpecialChar::PROTECTED_SEPARATOR); - par->InsertChar(pos, LyXParagraph::META_INSET); - par->SetFont(pos, current_font); - par->InsertInset(pos, new_inset); + if (par->InsertInsetAllowed(new_inset)) { + par->InsertChar(pos, LyXParagraph::META_INSET); + par->SetFont(pos, current_font); + par->InsertInset(pos, new_inset); + } else { + delete new_inset; + } #else par->InsertChar(pos, LyXParagraph::META_PROTECTED_SEPARATOR); par->SetFont(pos, current_font); @@ -2838,45 +3035,6 @@ bool LyXText::GotoNextNote() const } -int LyXText::SwitchLayoutsBetweenClasses(LyXTextClassList::size_type class1, - LyXTextClassList::size_type class2, - LyXParagraph * par) -{ - int ret = 0; - if (!par || class1 == class2) - return ret; - par = par->FirstPhysicalPar(); - while (par) { - string name = textclasslist.NameOfLayout(class1, par->layout); - int lay = 0; - pair pp = - textclasslist.NumberOfLayout(class2, name); - if (pp.first) { - lay = pp.second; - } else { // layout not found - // use default layout "Standard" (0) - lay = 0; - } - par->layout = lay; - - if (name != textclasslist.NameOfLayout(class2, par->layout)) { - ++ret; - string s = "Layout had to be changed from\n" - + name + " to " + textclasslist.NameOfLayout(class2, par->layout) - + "\nbecause of class conversion from\n" - + textclasslist.NameOfClass(class1) + " to " - + textclasslist.NameOfClass(class2); - InsetError * new_inset = new InsetError(s); - par->InsertChar(0, LyXParagraph::META_INSET); - par->InsertInset(0, new_inset); - } - - par = par->next; - } - return ret; -} - - void LyXText::CheckParagraph(LyXParagraph * par, LyXParagraph::size_type pos) {