1 /* This file is part of
2 * ======================================================
4 * LyX, The Document Processor
6 * Copyright 1995-2000 The LyX Team.
8 * ====================================================== */
12 #include "CutAndPaste.h"
13 #include "lyxparagraph.h"
14 #include "insets/inseterror.h"
15 #include "lyx_gui_misc.h"
18 #pragma implementation
21 static LyXParagraph * buf = 0;
23 CutAndPaste::CutAndPaste()
28 CutAndPaste::~CutAndPaste()
32 // for now here this should be in another Cut&Paste Class!
34 void CutAndPaste::DeleteBuffer()
39 LyXParagraph * tmppar;
49 bool CutAndPaste::cutSelection(LyXParagraph *startpar, LyXParagraph **endpar,
50 int start, int & end, char tc, bool doclear)
52 if (!startpar || (start > startpar->Last()))
59 if (!(*endpar) || (startpar->ParFromPos(start) ==
60 (*endpar)->ParFromPos(end))) {
61 // only within one paragraph
62 buf = new LyXParagraph;
63 LyXParagraph::size_type i = start;
64 if (end > startpar->Last())
65 end = startpar->Last();
66 for (; i < end; ++i) {
67 startpar->CopyIntoMinibuffer(start);
68 /* table stuff -- begin */
69 if (startpar->table && startpar->IsNewline(start)) {
72 /* table stuff -- end */
73 startpar->Erase(start);
75 buf->InsertFromMinibuffer(buf->Last());
78 // more than one paragraph
79 (*endpar)->BreakParagraphConservative(end);
80 *endpar = (*endpar)->Next();
83 startpar->BreakParagraphConservative(start);
85 // store the selection
86 buf = startpar->ParFromPos(start)->next;
88 (*endpar)->previous->next = 0;
91 startpar->ParFromPos(start)->next = (*endpar);
93 (*endpar)->previous = startpar->ParFromPos(start);
95 // care about footnotes
96 if (buf->footnoteflag) {
97 LyXParagraph * tmppar = buf;
99 tmppar->footnoteflag = LyXParagraph::NO_FOOTNOTE;
100 tmppar = tmppar->next;
104 // the cut selection should begin with standard layout
107 // paste the paragraphs again, if possible
109 startpar->Next()->ClearParagraph();
110 if (startpar->FirstPhysicalPar()->HasSameLayout(startpar->Next()) ||
111 !startpar->Next()->Last())
112 startpar->ParFromPos(start)->PasteParagraph();
117 bool CutAndPaste::copySelection(LyXParagraph *startpar, LyXParagraph *endpar,
118 int start, int end, char tc)
120 if (!startpar || (start > startpar->Last()))
127 if (!(endpar) || (startpar->ParFromPos(start) ==
128 (endpar)->ParFromPos(end))) {
129 // only within one paragraph
130 buf = new LyXParagraph;
131 LyXParagraph::size_type i = start;
132 if (end > startpar->Last())
133 end = startpar->Last();
134 for (; i < end; ++i) {
135 startpar->CopyIntoMinibuffer(i);
136 buf->InsertFromMinibuffer(buf->Last());
139 // copy more than one paragraph
140 // clone the paragraphs within the selection
141 LyXParagraph *tmppar = startpar->ParFromPos(start);
142 buf = tmppar->Clone();
143 LyXParagraph *tmppar2 = buf;
145 while (tmppar != endpar->ParFromPos(end)
147 tmppar = tmppar->next;
148 tmppar2->next = tmppar->Clone();
149 tmppar2->next->previous = tmppar2;
150 tmppar2 = tmppar2->next;
154 // care about footnotes
155 if (buf->footnoteflag) {
158 tmppar->footnoteflag = LyXParagraph::NO_FOOTNOTE;
159 tmppar = tmppar->next;
163 // the buf paragraph is too big
164 LyXParagraph::size_type tmpi2 = startpar->PositionInParFromPos(start);
165 for (; tmpi2; --tmpi2)
168 // now tmppar 2 is too big, delete all after end
170 tmpi2 = endpar->PositionInParFromPos(end);
171 while (tmppar2->size() > tmpi2) {
172 tmppar2->Erase(tmppar2->size() - 1);
178 bool CutAndPaste::pasteSelection(LyXParagraph **par, LyXParagraph **endpar,
181 if (!checkPastePossible(*par, pos))
184 if (pos > (*par)->Last())
185 pos = (*par)->Last();
187 LyXParagraph * tmpbuf;
188 LyXParagraph * tmppar = *par;
191 // There are two cases: cutbuffer only one paragraph or many
193 // only within a paragraph
194 tmpbuf = buf->Clone();
195 /* table stuff -- begin */
196 bool table_too_small = false;
198 while (buf->size() && !table_too_small) {
199 if (buf->IsNewline(0)){
200 while((tmppos < tmppar->Last()) &&
201 !tmppar->IsNewline(tmppos))
204 if (tmppos < tmppar->Last())
207 table_too_small = true;
209 // This is an attempt to fix the
210 // "never insert a space at the
211 // beginning of a paragraph" problem.
212 if (!tmppos && buf->IsLineSeparator(0)) {
215 buf->CutIntoMinibuffer(0);
217 if (tmppar->InsertFromMinibuffer(tmppos))
223 /* table stuff -- end */
224 // Some provisions should be done here for checking
225 // if we are inserting at the beginning of a
226 // paragraph. If there are a space at the beginning
227 // of the text to insert and we are inserting at
228 // the beginning of the paragraph the space should
230 while (buf->size()) {
231 // This is an attempt to fix the
232 // "never insert a space at the
233 // beginning of a paragraph" problem.
234 if (!tmppos && buf->IsLineSeparator(0)) {
237 buf->CutIntoMinibuffer(0);
239 if (tmppar->InsertFromMinibuffer(tmppos))
246 *endpar = tmppar->Next();
251 // make a copy of the simple cut_buffer
253 LyXParagraph * simple_cut_clone = tmpbuf->Clone();
254 LyXParagraph * tmpbuf2 = simple_cut_clone;
255 if ((*par)->footnoteflag){
256 tmpbuf->footnoteflag = (*par)->footnoteflag;
257 tmpbuf->footnotekind = (*par)->footnotekind;
259 while (tmpbuf->next) {
260 tmpbuf = tmpbuf->next;
261 tmpbuf2->next = tmpbuf->Clone();
262 tmpbuf2->next->previous = tmpbuf2;
263 tmpbuf2 = tmpbuf2->next;
264 if ((*par)->footnoteflag){
265 tmpbuf->footnoteflag = (*par)->footnoteflag;
266 tmpbuf->footnotekind = (*par)->footnotekind;
270 // make sure there is no class difference
271 SwitchLayoutsBetweenClasses(textclass, tc, buf);
273 // make the buf exactly the same layout than
274 // the cursor paragraph
275 buf->MakeSameLayout(*par);
277 // find the end of the buffer
278 LyXParagraph * lastbuffer = buf;
279 while (lastbuffer->Next())
280 lastbuffer = lastbuffer->Next();
282 bool paste_the_end = false;
284 // open the paragraph for inserting the buf
286 if (((*par)->Last() > pos) || !(*par)->Next()) {
287 (*par)->BreakParagraphConservative(pos);
288 paste_the_end = true;
291 // set the end for redoing later
292 *endpar = (*par)->ParFromPos(pos)->next->Next();
295 lastbuffer->ParFromPos(lastbuffer->Last())->next =
296 (*par)->ParFromPos(pos)->next;
297 (*par)->ParFromPos(pos)->next->previous =
298 lastbuffer->ParFromPos(lastbuffer->Last());
300 (*par)->ParFromPos(pos)->next = buf;
301 buf->previous = (*par)->ParFromPos(pos);
303 if ((*par)->ParFromPos(pos)->Next() == lastbuffer)
306 (*par)->ParFromPos(pos)->PasteParagraph();
308 // store the new cursor position
310 tmppos = lastbuffer->Last();
312 // maybe some pasting
313 if (lastbuffer->Next() && paste_the_end) {
314 if (lastbuffer->Next()->HasSameLayout(lastbuffer)) {
315 lastbuffer->ParFromPos(lastbuffer->Last())->PasteParagraph();
316 } else if (!lastbuffer->Next()->Last()) {
317 lastbuffer->Next()->MakeSameLayout(lastbuffer);
318 lastbuffer->ParFromPos(lastbuffer->Last())->PasteParagraph();
319 } else if (!lastbuffer->Last()) {
320 lastbuffer->MakeSameLayout(lastbuffer->next);
321 lastbuffer->ParFromPos(lastbuffer->Last())->PasteParagraph();
323 lastbuffer->Next()->ClearParagraph();
325 // restore the simple cut buffer
326 buf = simple_cut_clone;
333 int CutAndPaste::nrOfParagraphs() const
339 LyXParagraph *tmppar = buf;
340 while(tmppar->next) {
342 tmppar = tmppar->next;
347 int CutAndPaste::SwitchLayoutsBetweenClasses(LyXTextClassList::size_type c1,
348 LyXTextClassList::size_type c2,
352 if (!par || c1 == c2)
354 par = par->FirstPhysicalPar();
356 string name = textclasslist.NameOfLayout(c1, par->layout);
358 pair<bool, LyXTextClass::LayoutList::size_type> pp =
359 textclasslist.NumberOfLayout(c2, name);
362 } else { // layout not found
363 // use default layout "Standard" (0)
368 if (name != textclasslist.NameOfLayout(c2, par->layout)) {
370 string s = "Layout had to be changed from\n"
372 + textclasslist.NameOfLayout(c2, par->layout)
373 + "\nbecause of class conversion from\n"
374 + textclasslist.NameOfClass(c1) + " to "
375 + textclasslist.NameOfClass(c2);
376 InsetError * new_inset = new InsetError(s);
377 par->InsertChar(0, LyXParagraph::META_INSET);
378 par->InsertInset(0, new_inset);
386 char CutAndPaste::getBufferTextClass()
391 bool CutAndPaste::checkPastePossible(LyXParagraph *par, int)
396 LyXParagraph *tmppar;
398 // be carefull with footnotes in footnotes
399 if (par->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
400 // check whether the cut_buffer includes a footnote
402 while (tmppar && tmppar->footnoteflag == LyXParagraph::NO_FOOTNOTE)
403 tmppar = tmppar->next;
406 WriteAlert(_("Impossible operation"),
407 _("Can't paste float into float!"),
412 /* table stuff -- begin */
415 WriteAlert(_("Impossible operation"),
416 _("Table cell cannot include more than one paragraph!"),
421 /* table stuff -- end */