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