]> git.lyx.org Git - lyx.git/blob - src/BufferView2.C
b1a13b1097ade11635499792fdeda31724c6e368
[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 using std::count;
43
44 // Inserts a file into current document
45 bool BufferView::insertLyXFile(string const & filen)
46         //
47         // Copyright CHT Software Service GmbH
48         // Uwe C. Schroeder
49         //
50         // Insert a Lyxformat - file into current buffer
51         //
52         // Moved from lyx_cb.C (Lgb)
53 {
54         if (filen.empty()) return false;
55
56         string fname = MakeAbsPath(filen);
57
58         // check if file exist
59         FileInfo fi(fname);
60
61         if (!fi.readable()) {
62                 WriteAlert(_("Error!"),
63                            _("Specified file is unreadable: "),
64                            MakeDisplayPath(fname, 50));
65                 return false;
66         }
67         
68         beforeChange();
69
70         ifstream ifs(fname.c_str());
71         if (!ifs) {
72                 WriteAlert(_("Error!"),
73                            _("Cannot open specified file: "),
74                            MakeDisplayPath(fname, 50));
75                 return false;
76         }
77         
78         char c = ifs.peek();
79        
80         LyXLex lex(0, 0);
81         lex.setStream(ifs);
82
83         bool res = true;
84
85         if (c == '#') {
86                 lyxerr.debug() << "Will insert file with header" << endl;
87                 res = buffer()->readFile(lex, text->cursor.par());
88         } else {
89                 lyxerr.debug() << "Will insert file without header" << endl;
90                 res = buffer()->readLyXformat2(lex, text->cursor.par());
91         }
92
93         resize();
94         return res;
95 }
96
97 bool BufferView::removeAutoInsets()
98 {
99         LyXParagraph * par = buffer()->paragraph;
100
101         LyXCursor tmpcursor = text->cursor;
102         LyXCursor cursor;
103
104         bool a = false;
105         while (par) {
106                 // this has to be done before the delete
107 #ifndef NEW_INSETS
108                 if (par->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
109 #endif
110                         text->SetCursor(this, cursor, par, 0);
111                 if (par->AutoDeleteInsets()){
112                         a = true;
113 #ifndef NEW_INSETS
114                         if (par->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE){
115 #endif
116                                 text->RedoParagraphs(this, cursor,
117                                                      cursor.par()->Next());
118                                 text->FullRebreak(this);
119 #ifndef NEW_INSETS
120                         }
121 #endif
122                 }
123                 par = par->next;
124         }
125         // avoid forbidden cursor positions caused by error removing
126         if (tmpcursor.pos() > tmpcursor.par()->Last())
127                 tmpcursor.pos(tmpcursor.par()->Last());
128         text->SetCursorIntern(this, tmpcursor.par(), tmpcursor.pos());
129
130         return a;
131 }
132
133
134 void BufferView::insertErrors(TeXErrors & terr)
135 {
136         // Save the cursor position
137         LyXCursor cursor = text->cursor;
138
139 #ifndef NEW_INSETS
140         // This is drastic, but it's the only fix, I could find. (Asger)
141         allFloats(1, 0);
142         allFloats(1, 1);
143 #endif
144
145         for (TeXErrors::Errors::const_iterator cit = terr.begin();
146              cit != terr.end();
147              ++cit) {
148                 string desctext((*cit).error_desc);
149                 string errortext((*cit).error_text);
150                 string msgtxt = desctext + '\n' + errortext;
151                 int errorrow = (*cit).error_in_line;
152
153                 // Insert error string for row number
154                 int tmpid = -1; 
155                 int tmppos = -1;
156
157                 if (buffer()->texrow.getIdFromRow(errorrow, tmpid, tmppos)) {
158                         buffer()->texrow.increasePos(tmpid, tmppos);
159                 }
160                 
161                 LyXParagraph * texrowpar = 0;
162
163                 if (tmpid == -1) {
164                         texrowpar = text->FirstParagraph();
165                         tmppos = 0;
166                 } else {
167                         texrowpar = text->GetParFromID(tmpid);
168                 }
169
170                 if (texrowpar == 0)
171                         continue;
172
173                 InsetError * new_inset = new InsetError(msgtxt);
174                 text->SetCursorIntern(this, texrowpar, tmppos);
175                 text->InsertInset(this, new_inset);
176                 text->FullRebreak(this);
177         }
178         // Restore the cursor position
179         text->SetCursorIntern(this, cursor.par(), cursor.pos());
180 }
181
182
183 void BufferView::setCursorFromRow(int row)
184 {
185         int tmpid = -1; 
186         int tmppos = -1;
187
188         buffer()->texrow.getIdFromRow(row, tmpid, tmppos);
189
190         LyXParagraph * texrowpar;
191
192         if (tmpid == -1) {
193                 texrowpar = text->FirstParagraph();
194                 tmppos = 0;
195         } else {
196                 texrowpar = text->GetParFromID(tmpid);
197         }
198         text->SetCursor(this, texrowpar, tmppos);
199 }
200
201
202 bool BufferView::insertInset(Inset * inset, string const & lout,
203                              bool /*no_table*/)
204 {
205         // if we are in a locking inset we should try to insert the
206         // inset there otherwise this is a illegal function now
207         if (theLockingInset()) {
208                 if (theLockingInset()->InsertInsetAllowed(inset))
209                     return theLockingInset()->InsertInset(this, inset);
210                 return false;
211         }
212
213         // not quite sure if we want this...
214         text->SetCursorParUndo(buffer());
215         text->FreezeUndo();
216         
217         beforeChange();
218         if (!lout.empty()) {
219                 update(BufferView::SELECT|BufferView::FITCUR);
220                 text->BreakParagraph(this);
221                 update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
222                 
223                 if (text->cursor.par()->Last()) {
224                         text->CursorLeft(this);
225                         
226                         text->BreakParagraph(this);
227                         update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
228                 }
229
230                 pair<bool, LyXTextClass::size_type> lres =
231                         textclasslist.NumberOfLayout(buffer()->params
232                                                      .textclass, lout);
233                 LyXTextClass::size_type lay;
234                 if (lres.first != false) {
235                         // layout found
236                         lay = lres.second;
237                 } else {
238                         // layout not fount using default "Standard" (0)
239                         lay = 0;
240                 }
241                  
242                 text->SetLayout(this, lay);
243                 
244                 text->SetParagraph(this, 0, 0,
245                                    0, 0,
246                                    VSpace(VSpace::NONE), VSpace(VSpace::NONE),
247                                    LYX_ALIGN_LAYOUT, 
248                                    string(),
249                                    0);
250                 update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
251                 
252                 text->current_font.setLatex(LyXFont::OFF);
253         }
254         
255         text->InsertInset(this, inset);
256         update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
257
258         text->UnFreezeUndo();
259         return true;
260 }
261
262
263 // Open and lock an updatable inset
264 bool BufferView::open_new_inset(UpdatableInset * new_inset)
265 {
266         beforeChange();
267         text->FinishUndo();
268         if (!insertInset(new_inset)) {
269                 delete new_inset;
270                 return false;
271         }
272 //      text->CursorLeft(this);
273 //      update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
274         new_inset->Edit(this, 0, 0, 0);
275         return true;
276 }
277
278 /* This is also a buffer property (ale) */
279 // Not so sure about that. a goto Label function can not be buffer local, just
280 // think how this will work in a multiwindo/buffer environment, all the
281 // cursors in all the views showing this buffer will move. (Lgb)
282 // OK, then no cursor action should be allowed in buffer. (ale)
283 bool BufferView::gotoLabel(string const & label)
284
285 {
286         for (Buffer::inset_iterator it = buffer()->inset_iterator_begin();
287              it != buffer()->inset_iterator_end(); ++it) {
288                 vector<string> labels = (*it)->getLabelList();
289                 if (find(labels.begin(),labels.end(),label)
290                      != labels.end()) {
291                         beforeChange();
292                         text->SetCursor(this, it.getPar(), it.getPos());
293                         text->sel_cursor = text->cursor;
294                         update(BufferView::SELECT|BufferView::FITCUR);
295                         return true;
296                 }
297         }
298         return false;
299 }
300
301
302 #ifndef NEW_INSETS
303 void BufferView::allFloats(char flag, char figmar)
304 {
305         if (!available()) return;
306
307         LyXCursor cursor = text->cursor;
308
309         if (!flag
310             && cursor.par()->footnoteflag != LyXParagraph::NO_FOOTNOTE
311             && ((figmar 
312                  && cursor.par()->footnotekind != LyXParagraph::FOOTNOTE 
313                  && cursor.par()->footnotekind != LyXParagraph::MARGIN
314                     )
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(this, 
349                                                               par->previous,
350                                                               0);
351                                         text->OpenFootnote(this);
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(this, par, 0);
379                                 text->CloseFootnote(this);
380                         }
381                 }
382                 par = par->next;
383         }
384
385         text->SetCursorIntern(this, cursor.par(), cursor.pos());
386         redraw();
387         fitCursor(text);
388 }
389 #endif
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 #ifndef NEW_INSETS
401 void BufferView::openStuff()
402 {
403         if (available()) {
404                 owner()->getMiniBuffer()->Set(_("Open/Close..."));
405                 hideCursor();
406                 beforeChange();
407                 update(BufferView::SELECT|BufferView::FITCUR);
408                 text->OpenStuff(this);
409                 update(BufferView::SELECT|BufferView::FITCUR);
410                 setState();
411         }
412 }
413
414
415 void BufferView::toggleFloat()
416 {
417         if (available()) {
418                 owner()->getMiniBuffer()->Set(_("Open/Close..."));
419                 hideCursor();
420                 beforeChange();
421                 update(BufferView::SELECT|BufferView::FITCUR);
422                 text->ToggleFootnote(this);
423                 update(BufferView::SELECT|BufferView::FITCUR);
424                 setState();
425         }
426 }
427 #endif
428
429 void BufferView::menuUndo()
430 {
431         if (available()) {
432                 owner()->getMiniBuffer()->Set(_("Undo"));
433                 hideCursor();
434                 beforeChange();
435                 update(BufferView::SELECT|BufferView::FITCUR);
436                 if (!text->TextUndo(this))
437                         owner()->getMiniBuffer()->Set(_("No further undo information"));
438                 else
439                         update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
440                 setState();
441         }
442 }
443
444
445 void BufferView::menuRedo()
446 {
447         if (theLockingInset()) {
448                 owner()->getMiniBuffer()->Set(_("Redo not yet supported in math mode"));
449                 return;
450         }    
451    
452         if (available()) {
453                 owner()->getMiniBuffer()->Set(_("Redo"));
454                 hideCursor();
455                 beforeChange();
456                 update(BufferView::SELECT|BufferView::FITCUR);
457                 if (!text->TextRedo(this))
458                         owner()->getMiniBuffer()->Set(_("No further redo information"));
459                 else
460                         update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
461                 setState();
462         }
463 }
464
465
466 void BufferView::hyphenationPoint()
467 {
468         if (available()) {
469                 hideCursor();
470                 update(BufferView::SELECT|BufferView::FITCUR);
471                 InsetSpecialChar * new_inset = 
472                         new InsetSpecialChar(InsetSpecialChar::HYPHENATION);
473                 insertInset(new_inset);
474         }
475 }
476
477
478 void BufferView::ldots()
479 {
480         if (available())  {
481                 hideCursor();
482                 update(BufferView::SELECT|BufferView::FITCUR);
483                 InsetSpecialChar * new_inset = 
484                         new InsetSpecialChar(InsetSpecialChar::LDOTS);
485                 insertInset(new_inset);
486         }
487 }
488
489
490 void BufferView::endOfSentenceDot()
491 {
492         if (available()) {
493                 hideCursor();
494                 update(BufferView::SELECT|BufferView::FITCUR);
495                 InsetSpecialChar * new_inset = 
496                         new InsetSpecialChar(InsetSpecialChar::END_OF_SENTENCE);
497                 insertInset(new_inset);
498         }
499 }
500
501
502 void BufferView::menuSeparator()
503 {
504         if (available()) {
505                 hideCursor();
506                 update(BufferView::SELECT|BufferView::FITCUR);
507                 InsetSpecialChar * new_inset = 
508                         new InsetSpecialChar(InsetSpecialChar::MENU_SEPARATOR);
509                 insertInset(new_inset);
510         }
511 }
512
513
514 void BufferView::newline()
515 {
516         if (available()) {
517                 hideCursor();
518                 update(BufferView::SELECT|BufferView::FITCUR);
519                 text->InsertChar(this, LyXParagraph::META_NEWLINE);
520                 update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
521         }
522 }
523
524
525 void BufferView::protectedBlank()
526 {
527         if (available()) {
528                 hideCursor();
529                 update(BufferView::SELECT|BufferView::FITCUR);
530                 InsetSpecialChar * new_inset =
531                         new InsetSpecialChar(InsetSpecialChar::PROTECTED_SEPARATOR);
532                 insertInset(new_inset);
533         }
534 }
535
536
537 void BufferView::hfill()
538 {
539         if (available()) {
540                 hideCursor();
541                 update(BufferView::SELECT|BufferView::FITCUR);
542                 text->InsertChar(this, LyXParagraph::META_HFILL);
543                 update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
544         }
545 }
546
547 void BufferView::copyEnvironment()
548 {
549         if (available()) {
550                 text->copyEnvironmentType();
551                 // clear the selection, even if mark_set
552                 toggleSelection();
553                 text->ClearSelection();
554                 update(BufferView::SELECT|BufferView::FITCUR);
555                 owner()->getMiniBuffer()->Set(_("Paragraph environment type copied"));
556         }
557 }
558
559
560 void BufferView::pasteEnvironment()
561 {
562         if (available()) {
563                 text->pasteEnvironmentType(this);
564                 owner()->getMiniBuffer()->Set(_("Paragraph environment type set"));
565                 update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
566         }
567 }
568
569
570 void BufferView::copy()
571 {
572         if (available()) {
573                 text->CopySelection(this);
574                 // clear the selection, even if mark_set
575                 toggleSelection();
576                 text->ClearSelection();
577                 update(BufferView::SELECT|BufferView::FITCUR);
578                 owner()->getMiniBuffer()->Set(_("Copy"));
579         }
580 }
581
582 void BufferView::cut()
583 {
584         if (available()) {
585                 hideCursor();
586                 update(BufferView::SELECT|BufferView::FITCUR);
587                 text->CutSelection(this);
588                 update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
589                 owner()->getMiniBuffer()->Set(_("Cut"));
590         }
591 }
592
593
594 void BufferView::paste()
595 {
596         if (!available()) return;
597         
598         owner()->getMiniBuffer()->Set(_("Paste"));
599         hideCursor();
600         // clear the selection
601         toggleSelection();
602         text->ClearSelection();
603         update(BufferView::SELECT|BufferView::FITCUR);
604         
605         // paste
606         text->PasteSelection(this);
607         update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
608         
609         // clear the selection 
610         toggleSelection();
611         text->ClearSelection();
612         update(BufferView::SELECT|BufferView::FITCUR);
613 }
614
615
616 void BufferView::gotoNote()
617 {
618         if (!available()) return;
619    
620         hideCursor();
621         beforeChange();
622         update(BufferView::SELECT|BufferView::FITCUR);
623         LyXCursor tmp;
624    
625         if (!text->GotoNextNote(this)) {
626                 if (text->cursor.pos() 
627                     || text->cursor.par() != text->FirstParagraph()) {
628                                 tmp = text->cursor;
629                                 text->cursor.par(text->FirstParagraph());
630                                 text->cursor.pos(0);
631                                 if (!text->GotoNextNote(this)) {
632                                         text->cursor = tmp;
633                                         owner()->getMiniBuffer()->Set(_("No more notes"));
634                                         LyXBell();
635                                 }
636                         } else {
637                                 owner()->getMiniBuffer()->Set(_("No more notes"));
638                                 LyXBell();
639                         }
640         }
641         update(BufferView::SELECT|BufferView::FITCUR);
642         text->sel_cursor = text->cursor;
643 }
644
645
646 void BufferView::insertCorrectQuote()
647 {
648         char c;
649
650         if (text->cursor.pos())
651                 c = text->cursor.par()->GetChar(text->cursor.pos() - 1);
652         else 
653                 c = ' ';
654
655         insertInset(new InsetQuotes(c, buffer()->params));
656 }
657
658
659 /* these functions are for the spellchecker */ 
660 string const BufferView::nextWord(float & value)
661 {
662         if (!available()) {
663                 value = 1;
664                 return string();
665         }
666
667         return text->SelectNextWord(this, value);
668 }
669
670   
671 void BufferView::selectLastWord()
672 {
673         if (!available()) return;
674    
675         hideCursor();
676         beforeChange();
677         text->SelectSelectedWord(this);
678         toggleSelection(false);
679         update(BufferView::SELECT|BufferView::FITCUR);
680 }
681
682
683 void BufferView::endOfSpellCheck()
684 {
685         if (!available()) return;
686    
687         hideCursor();
688         beforeChange();
689         text->SelectSelectedWord(this);
690         text->ClearSelection();
691         update(BufferView::SELECT|BufferView::FITCUR);
692 }
693
694
695 void BufferView::replaceWord(string const & replacestring)
696 {
697         if (!available()) return;
698
699         hideCursor();
700         update(BufferView::SELECT|BufferView::FITCUR);
701    
702         /* clear the selection (if there is any) */ 
703         toggleSelection(false);
704         update(BufferView::SELECT|BufferView::FITCUR);
705    
706         /* clear the selection (if there is any) */ 
707         toggleSelection(false);
708         text->ReplaceSelectionWithString(this, replacestring);
709    
710         text->SetSelectionOverString(this, replacestring);
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->CursorLeft(this);
715         }
716         update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
717 }
718 // End of spellchecker stuff
719
720
721 bool BufferView::lockInset(UpdatableInset * inset)
722 {
723         if (!theLockingInset() && inset) {
724                 theLockingInset(inset);
725                 return true;
726         } else if (inset) {
727             return theLockingInset()->LockInsetInInset(this, inset);
728         }
729         return false;
730 }
731
732
733 void BufferView::showLockedInsetCursor(int x, int y, int asc, int desc)
734 {
735         if (theLockingInset() && 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                      theLockingInset()->GetLockingInset()))
742                         text->SetCursor(this, cursor,
743                                         cursor.par(), cursor.pos() - 1);
744                 LyXScreen::Cursor_Shape shape = LyXScreen::BAR_SHAPE;
745                 LyXText * txt = getLyXText();
746                 if (theLockingInset()->GetLockingInset()->LyxCode() ==
747                     Inset::TEXT_CODE &&
748                     (txt->real_current_font.language() !=
749                      buffer()->params.language
750                      || txt->real_current_font.isVisibleRightToLeft()
751                      != buffer()->params.language->RightToLeft()))
752                         shape = (txt->real_current_font.isVisibleRightToLeft())
753                                 ? LyXScreen::REVERSED_L_SHAPE
754                                 : LyXScreen::L_SHAPE;
755                 y += cursor.y() + theLockingInset()->InsetInInsetY();
756                 pimpl_->screen_->ShowManualCursor(text, x, y, asc, desc,
757                                                   shape);
758         }
759 }
760
761
762 void BufferView::hideLockedInsetCursor()
763 {
764         if (theLockingInset() && available()) {
765                 pimpl_->screen_->HideCursor();
766         }
767 }
768
769
770 void BufferView::fitLockedInsetCursor(int x, int y, int asc, int desc)
771 {
772         if (theLockingInset() && available()){
773                 y += text->cursor.y() + theLockingInset()->InsetInInsetY();
774                 if (pimpl_->screen_->FitManualCursor(text, x, y, asc, desc))
775                         updateScrollbar();
776         }
777 }
778
779
780 int BufferView::unlockInset(UpdatableInset * inset)
781 {
782         if (inset && theLockingInset() == inset) {
783                 inset->InsetUnlock(this);
784                 theLockingInset(0);
785                 text->FinishUndo();
786                 return 0;
787         } else if (inset && theLockingInset() &&
788                    theLockingInset()->UnlockInsetInInset(this, inset)) {
789                 text->FinishUndo();
790                 return 0;
791         }
792         return bufferlist.unlockInset(inset);
793 }
794
795
796 void BufferView::lockedInsetStoreUndo(Undo::undo_kind kind)
797 {
798         if (!theLockingInset())
799                 return; // shouldn't happen
800         if (kind == Undo::EDIT) // in this case insets would not be stored!
801                 kind = Undo::FINISH;
802         text->SetUndo(buffer(), kind,
803 #ifndef NEW_INSETS
804                       text->cursor.par()->
805                       ParFromPos(text->cursor.pos())->previous, 
806                       text->cursor.par()->
807                       ParFromPos(text->cursor.pos())->next
808 #else
809                       text->cursor.par()->previous, 
810                       text->cursor.par()->next
811 #endif
812                 );
813 }
814
815
816 void BufferView::updateInset(Inset * inset, bool mark_dirty)
817 {
818         if (!inset)
819                 return;
820
821         // first check for locking insets
822         if (theLockingInset()) {
823                 if (theLockingInset() == inset) {
824                         if (text->UpdateInset(this, inset)){
825                                 update();
826                                 if (mark_dirty){
827                                         if (buffer()->isLyxClean())
828                                                 owner()->getMiniBuffer()->
829                                                         setTimer(4);
830                                         buffer()->markDirty();
831                                 }
832                                 updateScrollbar();
833                                 return;
834                         }
835                 } else if (theLockingInset()->UpdateInsetInInset(this,inset)) {
836                         if (text->UpdateInset(this, theLockingInset())) {
837                                 update();
838                                 if (mark_dirty){
839                                         if (buffer()->isLyxClean())
840                                                 owner()->getMiniBuffer()->
841                                                         setTimer(4);
842                                         buffer()->markDirty();
843                                 }
844                                 updateScrollbar();
845                                 return;
846                         }
847                 }
848         }
849   
850         // then check the current buffer
851         if (available()) {
852                 hideCursor();
853                 update(BufferView::UPDATE);
854                 if (text->UpdateInset(this, inset)){
855                         if (mark_dirty)
856                                 update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
857                         else 
858                                 update(SELECT);
859                         return;
860                 }
861         }
862 }
863
864 bool BufferView::ChangeRefs(string const & from, string const & to)
865 {
866         bool flag = false;
867         LyXParagraph * par = buffer()->paragraph;
868         LyXCursor cursor = text->cursor;
869         LyXCursor tmpcursor = cursor;
870 #ifndef NEW_INSETS
871         cursor.par(tmpcursor.par()->ParFromPos(tmpcursor.pos()));
872         cursor.pos(tmpcursor.par()->PositionInParFromPos(tmpcursor.pos()));
873 #else
874         cursor.par(tmpcursor.par());
875         cursor.pos(tmpcursor.pos());
876 #endif
877
878         while (par) {
879                 bool flag2 = false;
880                 for (LyXParagraph::inset_iterator it = par->inset_iterator_begin();
881                      it != par->inset_iterator_end(); ++it) {
882                         if ((*it)->LyxCode() == Inset::REF_CODE) {
883                                 InsetCommand * inset = static_cast<InsetCommand *>(*it);
884                                 if (inset->getContents() == from) {
885                                         inset->setContents(to);
886                                         flag2 = true;
887                                 }
888                         }
889                 }
890                 if (flag2) {
891                         flag = true;
892 #ifndef NEW_INSETS
893                         if (par->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE){
894 #endif
895                                 // this is possible now, since SetCursor takes
896                                 // care about footnotes
897                                 text->SetCursorIntern(this, par, 0);
898                                 text->RedoParagraphs(this, text->cursor,
899                                                      text->cursor.par()->Next());
900                                 text->FullRebreak(this);
901 #ifndef NEW_INSETS
902                         }
903 #endif
904                 }
905                 par = par->next;
906         }
907         text->SetCursorIntern(this, cursor.par(), cursor.pos());
908         return flag;
909 }
910
911
912 bool BufferView::ChangeRefsIfUnique(string const & from, string const & to)
913 {
914         // Check if the label 'from' appears more than once
915         vector<string> labels = buffer()->getLabelList();
916         if (count(labels.begin(), labels.end(), from) > 1)
917                 return false;
918
919         return ChangeRefs(from, to);
920 }
921
922 UpdatableInset * BufferView::theLockingInset() const
923 {
924         // If NULL is not allowed we should put an Assert here. (Lgb)
925         if (text)
926                 return text->the_locking_inset;
927         return 0;
928 }
929
930
931 void BufferView::theLockingInset(UpdatableInset * inset)
932 {
933     text->the_locking_inset = inset;
934 }
935
936
937 LyXText * BufferView::getLyXText() const
938 {
939         if (theLockingInset()) {
940                 LyXText * txt = theLockingInset()->getLyXText(this);
941                 if (txt)
942                         return txt;
943         }
944         return text;
945 }
946