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