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