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