]> git.lyx.org Git - lyx.git/blob - src/BufferView2.C
Fix the line-delete-forward bug?
[lyx.git] / src / BufferView2.C
1 // -*- C++ -*-
2 /* This file is part of
3  * ====================================================== 
4  * 
5  *           LyX, The Document Processor
6  *        
7  *           Copyright 1995 Matthias Ettrich
8  *           Copyright 1995-2000 The LyX Team.
9  *
10  * ====================================================== */
11
12 #include <config.h>
13
14 #include <fstream>
15 #include <algorithm>
16
17 #include "BufferView.h"
18 #include "buffer.h"
19 #include "lyxcursor.h"
20 #include "lyxtext.h"
21 #include "insets/inseterror.h"
22 #include "insets/insetinfo.h"
23 #include "insets/insetspecialchar.h"
24 #include "LyXView.h"
25 #include "minibuffer.h"
26 #include "bufferlist.h"
27 #include "support/FileInfo.h"
28 #include "lyxscreen.h"
29 #include "support/filetools.h"
30 #include "lyx_gui_misc.h"
31 #include "LaTeX.h"
32 #include "BufferView_pimpl.h"
33 #include "insets/insetcommand.h" //ChangeRefs
34
35 extern BufferList bufferlist;
36
37 using std::pair;
38 using std::endl;
39 using std::ifstream;
40 using std::vector;
41 using std::find;
42
43 // Inserts a file into current document
44 bool BufferView::insertLyXFile(string const & filen)
45         //
46         // Copyright CHT Software Service GmbH
47         // Uwe C. Schroeder
48         //
49         // Insert a Lyxformat - file into current buffer
50         //
51         // Moved from lyx_cb.C (Lgb)
52 {
53         if (filen.empty()) return false;
54
55         string fname = MakeAbsPath(filen);
56
57         // check if file exist
58         FileInfo fi(fname);
59
60         if (!fi.readable()) {
61                 WriteAlert(_("Error!"),
62                            _("Specified file is unreadable: "),
63                            MakeDisplayPath(fname, 50));
64                 return false;
65         }
66         
67         beforeChange();
68
69         ifstream ifs(fname.c_str());
70         if (!ifs) {
71                 WriteAlert(_("Error!"),
72                            _("Cannot open specified file: "),
73                            MakeDisplayPath(fname, 50));
74                 return false;
75         }
76         LyXLex lex(0, 0);
77         lex.setStream(ifs);
78         char c; ifs.get(c);
79         ifs.putback(c);
80
81         bool res = true;
82
83         if (c == '#') {
84                 lyxerr.debug() << "Will insert file with header" << endl;
85                 res = buffer()->readFile(lex, text->cursor.par);
86         } else {
87                 lyxerr.debug() << "Will insert file without header" << endl;
88                 res = buffer()->readLyXformat2(lex, text->cursor.par);
89         }
90
91         resize();
92         return res;
93 }
94
95 bool BufferView::removeAutoInsets()
96 {
97         LyXParagraph * par = buffer()->paragraph;
98
99         LyXCursor tmpcursor = text->cursor;
100         LyXCursor cursor;
101
102         bool a = false;
103         while (par) {
104                 // this has to be done before the delete
105                 text->SetCursor(cursor, par, 0);
106                 if (par->AutoDeleteInsets()){
107                         a = true;
108                         if (par->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE){
109                                 text->RedoParagraphs(cursor,
110                                                      cursor.par->Next());
111                                 text->FullRebreak();
112                         }
113                 }
114                 par = par->next;
115         }
116         // avoid forbidden cursor positions caused by error removing
117         if (tmpcursor.pos > tmpcursor.par->Last())
118                 tmpcursor.pos = tmpcursor.par->Last();
119         text->SetCursorIntern(tmpcursor.par, tmpcursor.pos);
120
121         return a;
122 }
123
124
125 void BufferView::insertErrors(TeXErrors & terr)
126 {
127         // Save the cursor position
128         LyXCursor cursor = text->cursor;
129
130         // This is drastic, but it's the only fix, I could find. (Asger)
131         allFloats(1, 0);
132         allFloats(1, 1);
133
134         for (TeXErrors::Errors::const_iterator cit = terr.begin();
135              cit != terr.end();
136              ++cit) {
137                 string desctext((*cit).error_desc);
138                 string errortext((*cit).error_text);
139                 string msgtxt = desctext + '\n' + errortext;
140                 int errorrow = (*cit).error_in_line;
141
142                 // Insert error string for row number
143                 int tmpid = -1; 
144                 int tmppos = -1;
145
146                 buffer()->texrow.getIdFromRow(errorrow, tmpid, tmppos);
147
148                 LyXParagraph * texrowpar = 0;
149
150                 if (tmpid == -1) {
151                         texrowpar = text->FirstParagraph();
152                         tmppos = 0;
153                 } else {
154                         texrowpar = text->GetParFromID(tmpid);
155                 }
156
157                 if (texrowpar == 0)
158                         continue;
159
160                 InsetError * new_inset = new InsetError(msgtxt);
161                 text->SetCursorIntern(texrowpar, tmppos);
162                 text->InsertInset(new_inset);
163                 text->FullRebreak();
164         }
165         // Restore the cursor position
166         text->SetCursorIntern(cursor.par, cursor.pos);
167 }
168
169
170 void BufferView::setCursorFromRow(int row)
171 {
172         int tmpid = -1; 
173         int tmppos = -1;
174
175         buffer()->texrow.getIdFromRow(row, tmpid, tmppos);
176
177         LyXParagraph * texrowpar;
178
179         if (tmpid == -1) {
180                 texrowpar = text->FirstParagraph();
181                 tmppos = 0;
182         } else {
183                 texrowpar = text->GetParFromID(tmpid);
184         }
185         text->SetCursor(texrowpar, tmppos);
186 }
187
188 bool BufferView::insertInset(Inset * inset, string const & lout,
189                          bool no_table)
190 {
191         // if we are in a locking inset we should try to insert the
192         // inset there otherwise this is a illegal function now
193         if (the_locking_inset) {
194                 if (the_locking_inset->InsertInsetAllowed(inset) &&
195                     the_locking_inset->InsertInset(this, inset))
196                         return true;
197                 return false;
198         }
199
200         // check for table/list in tables
201         if (no_table && text->cursor.par->table){
202                 WriteAlert(_("Impossible Operation!"),
203                            _("Cannot insert table/list in table."),
204                            _("Sorry."));
205                 return false;
206         }
207
208         // not quite sure if we want this...
209         text->SetCursorParUndo();
210         text->FreezeUndo();
211         
212         beforeChange();
213         if (!lout.empty()) {
214                 update(-2);
215                 text->BreakParagraph();
216                 update(-1);
217                 
218                 if (text->cursor.par->Last()) {
219                         text->CursorLeft();
220                         
221                         text->BreakParagraph();
222                         update(-1);
223                 }
224
225                 pair<bool, LyXTextClass::size_type> lres =
226                         textclasslist.NumberOfLayout(buffer()->params
227                                                      .textclass, lout);
228                 LyXTextClass::size_type lay;
229                 if (lres.first != false) {
230                         // layout found
231                         lay = lres.second;
232                 } else {
233                         // layout not fount using default "Standard" (0)
234                         lay = 0;
235                 }
236                  
237                 text->SetLayout(lay);
238                 
239                 text->SetParagraph(0, 0,
240                                    0, 0,
241                                    VSpace(VSpace::NONE), VSpace(VSpace::NONE),
242                                    LYX_ALIGN_LAYOUT, 
243                                    string(),
244                                    0);
245                 update(-1);
246                 
247                 text->current_font.setLatex(LyXFont::OFF);
248         }
249         
250         text->InsertInset(inset);
251 #if 1
252         // if we enter a text-inset the cursor should be to the left side
253         // of it! This couldn't happen before as Undo was not handled inside
254         // inset now after the Undo LyX tries to call inset->Edit(...) again
255         // and cannot do this as the cursor is behind the inset and GetInset
256         // does not return the inset!
257         if (inset->IsTextInset()) {
258                 if (text->cursor.par->isRightToLeftPar())
259                         text->CursorRight();
260                 else
261                         text->CursorLeft();
262         }
263 #endif
264         update(-1);
265
266         text->UnFreezeUndo();
267         return true;
268 }
269
270
271 // Open and lock an updatable inset
272 void BufferView::open_new_inset(UpdatableInset * new_inset)
273 {
274         beforeChange();
275         text->FinishUndo();
276         insertInset(new_inset);
277         text->CursorLeft();
278         update(1);
279         new_inset->Edit(this, 0, 0, 0);
280 }
281
282 /* This is also a buffer property (ale) */
283 // Not so sure about that. a goto Label function can not be buffer local, just
284 // think how this will work in a multiwindo/buffer environment, all the
285 // cursors in all the views showing this buffer will move. (Lgb)
286 // OK, then no cursor action should be allowed in buffer. (ale)
287 bool BufferView::gotoLabel(string const & label)
288
289 {
290         for (Buffer::inset_iterator it = buffer()->inset_iterator_begin();
291              it != buffer()->inset_iterator_end(); ++it) {
292                 vector<string> labels = (*it)->getLabelList();
293                 if ( find(labels.begin(),labels.end(),label)
294                      != labels.end()) {
295                         beforeChange();
296                         text->SetCursor(it.getPar(), it.getPos());
297                         text->sel_cursor = text->cursor;
298                         update(0);
299                         return true;
300                 }
301         }
302         return false;
303 }
304
305 void BufferView::allFloats(char flag, char figmar)
306 {
307         if (!available()) return;
308
309         LyXCursor cursor = text->cursor;
310
311         if (!flag && cursor.par->footnoteflag != LyXParagraph::NO_FOOTNOTE
312             && ((figmar 
313                  && cursor.par->footnotekind != LyXParagraph::FOOTNOTE 
314                  && cursor.par->footnotekind != LyXParagraph::MARGIN)
315                 || (!figmar
316                     && cursor.par->footnotekind != LyXParagraph::FIG 
317                     && cursor.par->footnotekind != LyXParagraph::TAB
318                     && cursor.par->footnotekind != LyXParagraph::WIDE_FIG 
319                     && cursor.par->footnotekind != LyXParagraph::WIDE_TAB
320                     && cursor.par->footnotekind != LyXParagraph::ALGORITHM)))
321                 toggleFloat();
322         else
323                 beforeChange();
324
325         LyXCursor tmpcursor = cursor;
326         cursor.par = tmpcursor.par->ParFromPos(tmpcursor.pos);
327         cursor.pos = tmpcursor.par->PositionInParFromPos(tmpcursor.pos);
328
329         LyXParagraph *par = buffer()->paragraph;
330         while (par) {
331                 if (flag) {
332                         if (par->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE
333                             && ((figmar 
334                                  && par->footnotekind != LyXParagraph::FOOTNOTE 
335                                  && par->footnotekind !=  LyXParagraph::MARGIN)
336                                 || (!figmar
337                                     && par->footnotekind != LyXParagraph::FIG 
338                                     && par->footnotekind != LyXParagraph::TAB
339                                     && par->footnotekind != LyXParagraph::WIDE_FIG 
340                                     && par->footnotekind != LyXParagraph::WIDE_TAB
341                                     && par->footnotekind != LyXParagraph::ALGORITHM
342                                         )
343                                     )
344                                 ) {
345                                 if (par->previous
346                                     && par->previous->footnoteflag != 
347                                     LyXParagraph::CLOSED_FOOTNOTE){ /* should be */ 
348                                         text->SetCursorIntern(par->previous,
349                                                               0);
350                                         text->OpenFootnote();
351                                 }
352                         }
353                 } else {
354                         if (par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE
355                             && (
356                                     (figmar 
357                                      &&
358                                      par->footnotekind != LyXParagraph::FOOTNOTE 
359                                      &&
360                                      par->footnotekind !=  LyXParagraph::MARGIN
361                                             )
362                                     ||
363                                     (!figmar
364                                      &&
365                                      par->footnotekind != LyXParagraph::FIG 
366                                      &&
367                                      par->footnotekind != LyXParagraph::TAB
368                                      &&
369                                      par->footnotekind != LyXParagraph::WIDE_FIG 
370                                      &&
371                                      par->footnotekind != LyXParagraph::WIDE_TAB
372                                      &&
373                                      par->footnotekind != LyXParagraph::ALGORITHM
374                                             )
375                                     )
376                                 ) {
377                                 text->SetCursorIntern(par, 0);
378                                 text->CloseFootnote();
379                         }
380                 }
381                 par = par->next;
382         }
383
384         text->SetCursorIntern(cursor.par, cursor.pos);
385         redraw();
386         fitCursor();
387         //updateScrollbar();
388 }
389
390
391 void BufferView::insertNote()
392 {
393         InsetInfo * new_inset = new InsetInfo();
394         insertInset(new_inset);
395         new_inset->Edit(this, 0, 0, 0);
396 }
397
398
399 void BufferView::openStuff()
400 {
401         if (available()) {
402                 owner()->getMiniBuffer()->Set(_("Open/Close..."));
403                 hideCursor();
404                 beforeChange();
405                 update(-2);
406                 text->OpenStuff();
407                 update(0);
408                 setState();
409         }
410 }
411
412
413 void BufferView::toggleFloat()
414 {
415         if (available()) {
416                 owner()->getMiniBuffer()->Set(_("Open/Close..."));
417                 hideCursor();
418                 beforeChange();
419                 update(-2);
420                 text->ToggleFootnote();
421                 update(0);
422                 setState();
423         }
424 }
425
426 void BufferView::menuUndo()
427 {
428         if (available()) {
429                 owner()->getMiniBuffer()->Set(_("Undo"));
430                 hideCursor();
431                 beforeChange();
432                 update(-2);
433                 if (!text->TextUndo())
434                         owner()->getMiniBuffer()->Set(_("No further undo information"));
435                 else
436                         update(-1);
437                 setState();
438         }
439 }
440
441
442 void BufferView::menuRedo()
443 {
444         if (the_locking_inset) {
445                 owner()->getMiniBuffer()->Set(_("Redo not yet supported in math mode"));
446                 return;
447         }    
448    
449         if (available()) {
450                 owner()->getMiniBuffer()->Set(_("Redo"));
451                 hideCursor();
452                 beforeChange();
453                 update(-2);
454                 if (!text->TextRedo())
455                         owner()->getMiniBuffer()->Set(_("No further redo information"));
456                 else
457                         update(-1);
458                 setState();
459         }
460 }
461
462
463 void BufferView::hyphenationPoint()
464 {
465         if (available()) {
466                 hideCursor();
467                 update(-2);
468                 InsetSpecialChar * new_inset = 
469                         new InsetSpecialChar(InsetSpecialChar::HYPHENATION);
470                 insertInset(new_inset);
471         }
472 }
473
474
475 void BufferView::ldots()
476 {
477         if (available())  {
478                 hideCursor();
479                 update(-2);
480                 InsetSpecialChar * new_inset = 
481                         new InsetSpecialChar(InsetSpecialChar::LDOTS);
482                 insertInset(new_inset);
483         }
484 }
485
486
487 void BufferView::endOfSentenceDot()
488 {
489         if (available()) {
490                 hideCursor();
491                 update(-2);
492                 InsetSpecialChar * new_inset = 
493                         new InsetSpecialChar(InsetSpecialChar::END_OF_SENTENCE);
494                 insertInset(new_inset);
495         }
496 }
497
498
499 void BufferView::menuSeparator()
500 {
501         if (available()) {
502                 hideCursor();
503                 update(-2);
504                 InsetSpecialChar * new_inset = 
505                         new InsetSpecialChar(InsetSpecialChar::MENU_SEPARATOR);
506                 insertInset(new_inset);
507         }
508 }
509
510
511 void BufferView::newline()
512 {
513         if (available()) {
514                 hideCursor();
515                 update(-2);
516                 text->InsertChar(LyXParagraph::META_NEWLINE);
517                 update(-1);
518         }
519 }
520
521
522 void BufferView::protectedBlank()
523 {
524         if (available()) {
525                 hideCursor();
526                 update(-2);
527                 InsetSpecialChar * new_inset =
528                         new InsetSpecialChar(InsetSpecialChar::PROTECTED_SEPARATOR);
529                 insertInset(new_inset);
530         }
531 }
532
533
534 void BufferView::hfill()
535 {
536         if (available()) {
537                 hideCursor();
538                 update(-2);
539                 text->InsertChar(LyXParagraph::META_HFILL);
540                 update(-1);
541         }
542 }
543
544 void BufferView::copyEnvironment()
545 {
546         if (available()) {
547                 text->copyEnvironmentType();
548                 // clear the selection, even if mark_set
549                 toggleSelection();
550                 text->ClearSelection();
551                 update(-2);
552                 owner()->getMiniBuffer()->Set(_("Paragraph environment type copied"));
553         }
554 }
555
556
557 void BufferView::pasteEnvironment()
558 {
559         if (available()) {
560                 text->pasteEnvironmentType();
561                 owner()->getMiniBuffer()->Set(_("Paragraph environment type set"));
562                 update(1);
563         }
564 }
565
566
567 void BufferView::copy()
568 {
569         if (available()) {
570                 text->CopySelection();
571                 // clear the selection, even if mark_set
572                 toggleSelection();
573                 text->ClearSelection();
574                 update(-2);
575                 owner()->getMiniBuffer()->Set(_("Copy"));
576         }
577 }
578
579 void BufferView::cut()
580 {
581         if (available()) {
582                 hideCursor();
583                 update(-2);
584                 text->CutSelection();
585                 update(1);
586                 owner()->getMiniBuffer()->Set(_("Cut"));
587         }
588 }
589
590
591 void BufferView::paste()
592 {
593         if (!available()) return;
594         
595         owner()->getMiniBuffer()->Set(_("Paste"));
596         hideCursor();
597         // clear the selection
598         toggleSelection();
599         text->ClearSelection();
600         update(-2);
601         
602         // paste
603         text->PasteSelection();
604         update(1);
605         
606         // clear the selection 
607         toggleSelection();
608         text->ClearSelection();
609         update(-2);
610 }
611
612
613 void BufferView::gotoNote()
614 {
615         if (!available()) return;
616    
617         hideCursor();
618         beforeChange();
619         update(-2);
620         LyXCursor tmp;
621    
622         if (!text->GotoNextNote()) {
623                 if (text->cursor.pos 
624                     || text->cursor.par != text->FirstParagraph()) {
625                                 tmp = text->cursor;
626                                 text->cursor.par = text->FirstParagraph();
627                                 text->cursor.pos = 0;
628                                 if (!text->GotoNextNote()) {
629                                         text->cursor = tmp;
630                                         owner()->getMiniBuffer()->Set(_("No more notes"));
631                                         LyXBell();
632                                 }
633                         } else {
634                                 owner()->getMiniBuffer()->Set(_("No more notes"));
635                                 LyXBell();
636                         }
637         }
638         update(0);
639         text->sel_cursor = text->cursor;
640 }
641
642
643 void BufferView::insertCorrectQuote()
644 {
645         char c;
646
647         if (text->cursor.pos)
648                 c = text->cursor.par->GetChar(text->cursor.pos - 1);
649         else 
650                 c = ' ';
651
652         insertInset(new InsetQuotes(c, buffer()->params));
653 }
654
655
656 /* these functions are for the spellchecker */ 
657 char * BufferView::nextWord(float & value)
658 {
659         if (!available()) {
660                 value = 1;
661                 return 0;
662         }
663
664         char * string = text->SelectNextWord(value);
665
666         return string;
667 }
668
669   
670 void BufferView::selectLastWord()
671 {
672         if (!available()) return;
673    
674         hideCursor();
675         beforeChange();
676         text->SelectSelectedWord();
677         toggleSelection(false);
678         update(0);
679 }
680
681
682 void BufferView::endOfSpellCheck()
683 {
684         if (!available()) return;
685    
686         hideCursor();
687         beforeChange();
688         text->SelectSelectedWord();
689         text->ClearSelection();
690         update(0);
691 }
692
693
694 void BufferView::replaceWord(string const & replacestring)
695 {
696         if (!available()) return;
697
698         hideCursor();
699         update(-2);
700    
701         /* clear the selection (if there is any) */ 
702         toggleSelection(false);
703         update(-2);
704    
705         /* clear the selection (if there is any) */ 
706         toggleSelection(false);
707         text->ReplaceSelectionWithString(replacestring.c_str());
708    
709         text->SetSelectionOverString(replacestring.c_str());
710
711         // Go back so that replacement string is also spellchecked
712         for (string::size_type i = 0; i < replacestring.length() + 1; ++i) {
713                 text->CursorLeftIntern();
714         }
715         update(1);
716 }
717 // End of spellchecker stuff
718
719
720 bool BufferView::lockInset(UpdatableInset * inset)
721 {
722         if (!the_locking_inset && inset) {
723                 the_locking_inset = inset;
724                 return true;
725         } else if (inset) {
726             return the_locking_inset->LockInsetInInset(this, inset);
727         }
728         return false;
729 }
730
731
732 void BufferView::showLockedInsetCursor(long x, long y, int asc, int desc)
733 {
734         if (the_locking_inset && available()) {
735                 LyXCursor cursor = text->cursor;
736                 if ((cursor.pos - 1 >= 0) &&
737                     (cursor.par->GetChar(cursor.pos-1) ==
738                      LyXParagraph::META_INSET) &&
739                     (cursor.par->GetInset(cursor.pos - 1) ==
740                      the_locking_inset->GetLockingInset()))
741                         text->SetCursor(cursor, cursor.par, cursor.pos-1);
742                 y += cursor.y + the_locking_inset->InsetInInsetY();
743                 pimpl_->screen->ShowManualCursor(x, y, asc, desc,
744                                          LyXScreen::BAR_SHAPE);
745         }
746 }
747
748
749 void BufferView::hideLockedInsetCursor()
750 {
751         if (the_locking_inset && available()) {
752                 pimpl_->screen->HideCursor();
753         }
754 }
755
756
757 void BufferView::fitLockedInsetCursor(long x, long y, int asc, int desc)
758 {
759         if (the_locking_inset && available()){
760                 y += text->cursor.y + the_locking_inset->InsetInInsetY();
761                 if (pimpl_->screen->FitManualCursor(x, y, asc, desc))
762                         updateScrollbar();
763         }
764 }
765
766
767 int BufferView::unlockInset(UpdatableInset * inset)
768 {
769         if (inset && the_locking_inset == inset) {
770                 inset->InsetUnlock(this);
771                 the_locking_inset = 0;
772                 text->FinishUndo();
773                 return 0;
774         } else if (inset && the_locking_inset &&
775                    the_locking_inset->UnlockInsetInInset(this, inset)) {
776                 text->FinishUndo();
777                 return 0;
778         }
779         return bufferlist.unlockInset(inset);
780 }
781
782
783 void BufferView::lockedInsetStoreUndo(Undo::undo_kind kind)
784 {
785         if (!the_locking_inset)
786                 return; // shouldn't happen
787         if (kind == Undo::EDIT) // in this case insets would not be stored!
788                 kind = Undo::FINISH;
789         text->SetUndo(kind,
790                       text->cursor.par->
791                       ParFromPos(text->cursor.pos)->previous, 
792                       text->cursor.par->
793                       ParFromPos(text->cursor.pos)->next);
794 }
795
796
797 void BufferView::updateInset(Inset * inset, bool mark_dirty)
798 {
799         if (!inset)
800                 return;
801
802         // first check for locking insets
803         if (the_locking_inset) {
804                 if (the_locking_inset == inset) {
805                         if (text->UpdateInset(inset)){
806                                 update();
807                                 if (mark_dirty){
808                                         if (buffer()->isLyxClean())
809                                                 owner()->getMiniBuffer()->
810                                                         setTimer(4);
811                                         buffer()->markDirty();
812                                 }
813                                 updateScrollbar();
814                                 return;
815                         }
816                 } else if (the_locking_inset->UpdateInsetInInset(this,inset)) {
817                         if (text->UpdateInset(the_locking_inset)) {
818                                 update();
819                                 if (mark_dirty){
820                                         if (buffer()->isLyxClean())
821                                                 owner()->getMiniBuffer()->
822                                                         setTimer(4);
823                                         buffer()->markDirty();
824                                 }
825                                 updateScrollbar();
826                                 return;
827                         }
828                 }
829         }
830   
831         // then check the current buffer
832         if (available()) {
833                 hideCursor();
834                 update(-3);
835                 if (text->UpdateInset(inset)){
836                         if (mark_dirty)
837                                 update(1);
838                         else 
839                                 update(3);
840                         return;
841                 }
842         }
843 }
844
845 bool BufferView::ChangeRefs(string const & from, string const & to)
846 {
847         bool flag = false;
848         LyXParagraph * par = buffer()->paragraph;
849         LyXCursor cursor = text->cursor;
850         LyXCursor tmpcursor = cursor;
851         cursor.par = tmpcursor.par->ParFromPos(tmpcursor.pos);
852         cursor.pos = tmpcursor.par->PositionInParFromPos(tmpcursor.pos);
853
854         while (par) {
855                 bool flag2 = false;
856                 for (LyXParagraph::inset_iterator it = par->inset_iterator_begin();
857                      it != par->inset_iterator_end(); ++it) {
858                         if ((*it)->LyxCode() == Inset::REF_CODE) {
859                                 InsetCommand * inset = static_cast<InsetCommand *>(*it);
860                                 if (inset->getContents() == from) {
861                                         inset->setContents(to);
862                                         flag2 = true;
863                                 }
864                         }
865                 }
866                 if (flag2) {
867                         flag = true;
868                         if (par->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE){
869                                 // this is possible now, since SetCursor takes
870                                 // care about footnotes
871                                 text->SetCursorIntern(par, 0);
872                                 text->RedoParagraphs(text->cursor,
873                                                      text->cursor.par->Next());
874                                 text->FullRebreak();
875                         }
876                 }
877                 par = par->next;
878         }
879         text->SetCursorIntern(cursor.par, cursor.pos);
880         return flag;
881 }