2 /* This file is part of
3 * ======================================================
5 * LyX, The Document Processor
7 * Copyright 1995 Matthias Ettrich
8 * Copyright 1995-2000 The LyX Team.
10 * ====================================================== */
14 #include "BufferView.h"
16 #include "lyxcursor.h"
18 #include "insets/inseterror.h"
19 #include "insets/insetinfo.h"
20 #include "insets/insetspecialchar.h"
22 #include "minibuffer.h"
23 #include "bufferlist.h"
24 #include "support/FileInfo.h"
25 #include "lyxscreen.h"
27 extern BufferList bufferlist;
31 // Inserts a file into current document
32 bool BufferView::insertLyXFile(string const & filen)
34 // Copyright CHT Software Service GmbH
37 // Insert a Lyxformat - file into current buffer
39 // Moved from lyx_cb.C (Lgb)
41 if (filen.empty()) return false;
43 string fname = MakeAbsPath(filen);
45 // check if file exist
49 WriteAlert(_("Error!"),
50 _("Specified file is unreadable: "),
51 MakeDisplayPath(fname, 50));
57 ifstream ifs(fname.c_str());
59 WriteAlert(_("Error!"),
60 _("Cannot open specified file: "),
61 MakeDisplayPath(fname, 50));
72 lyxerr.debug() << "Will insert file with header" << endl;
73 res = buffer()->readFile(lex, text->cursor.par);
75 lyxerr.debug() << "Will insert file without header" << endl;
76 res = buffer()->readLyXformat2(lex, text->cursor.par);
83 bool BufferView::removeAutoInsets()
85 LyXParagraph * par = buffer()->paragraph;
87 LyXCursor cursor = text->cursor;
88 LyXCursor tmpcursor = cursor;
89 cursor.par = tmpcursor.par->ParFromPos(tmpcursor.pos);
90 cursor.pos = tmpcursor.par->PositionInParFromPos(tmpcursor.pos);
94 if (par->AutoDeleteInsets()){
96 if (par->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE){
97 // this is possible now, since SetCursor takes
98 // care about footnotes
99 text->SetCursorIntern(par, 0);
100 text->RedoParagraphs(text->cursor,
101 text->cursor.par->Next());
107 // avoid forbidden cursor positions caused by error removing
108 if (cursor.pos > cursor.par->Last())
109 cursor.pos = cursor.par->Last();
110 text->SetCursorIntern(cursor.par, cursor.pos);
116 void BufferView::insertErrors(TeXErrors & terr)
118 // Save the cursor position
119 LyXCursor cursor = text->cursor;
121 // This is drastic, but it's the only fix, I could find. (Asger)
125 for (TeXErrors::Errors::const_iterator cit = terr.begin();
128 string desctext((*cit).error_desc);
129 string errortext((*cit).error_text);
130 string msgtxt = desctext + '\n' + errortext;
131 int errorrow = (*cit).error_in_line;
133 // Insert error string for row number
137 buffer()->texrow.getIdFromRow(errorrow, tmpid, tmppos);
139 LyXParagraph * texrowpar = 0;
142 texrowpar = text->FirstParagraph();
145 texrowpar = text->GetParFromID(tmpid);
151 InsetError * new_inset = new InsetError(msgtxt);
152 text->SetCursorIntern(texrowpar, tmppos);
153 text->InsertInset(new_inset);
156 // Restore the cursor position
157 text->SetCursorIntern(cursor.par, cursor.pos);
161 void BufferView::setCursorFromRow(int row)
166 buffer()->texrow.getIdFromRow(row, tmpid, tmppos);
168 LyXParagraph * texrowpar;
171 texrowpar = text->FirstParagraph();
174 texrowpar = text->GetParFromID(tmpid);
176 text->SetCursor(texrowpar, tmppos);
179 void BufferView::insertInset(Inset * inset, string const & lout,
182 // check for table/list in tables
183 if (no_table && text->cursor.par->table){
184 WriteAlert(_("Impossible Operation!"),
185 _("Cannot insert table/list in table."),
189 // not quite sure if we want this...
190 text->SetCursorParUndo();
196 text->BreakParagraph();
199 if (text->cursor.par->Last()) {
202 text->BreakParagraph();
206 pair<bool, LyXTextClass::size_type> lres =
207 textclasslist.NumberOfLayout(buffer()->params
209 LyXTextClass::size_type lay;
210 if (lres.first != false) {
214 // layout not fount using default "Standard" (0)
218 text->SetLayout(lay);
220 text->SetParagraph(0, 0,
222 VSpace(VSpace::NONE), VSpace(VSpace::NONE),
228 text->current_font.setLatex(LyXFont::OFF);
231 text->InsertInset(inset);
234 text->UnFreezeUndo();
238 // Open and lock an updatable inset
239 void BufferView::open_new_inset(UpdatableInset * new_inset)
243 insertInset(new_inset);
246 new_inset->Edit(this, 0, 0, 0);
249 /* This is also a buffer property (ale) */
250 // Not so sure about that. a goto Label function can not be buffer local, just
251 // think how this will work in a multiwindo/buffer environment, all the
252 // cursors in all the views showing this buffer will move. (Lgb)
253 // OK, then no cursor action should be allowed in buffer. (ale)
254 bool BufferView::gotoLabel(string const & label)
257 LyXParagraph * par = buffer()->paragraph;
258 LyXParagraph::size_type pos;
262 while ((inset = par->ReturnNextInsetPointer(pos))){
263 for (int i = 0; i < inset->GetNumberOfLabels(); ++i) {
264 if (label == inset->getLabel(i)) {
266 text->SetCursor(par, pos);
267 text->sel_cursor = text->cursor;
279 void BufferView::allFloats(char flag, char figmar)
281 if (!available()) return;
283 LyXCursor cursor = text->cursor;
285 if (!flag && cursor.par->footnoteflag != LyXParagraph::NO_FOOTNOTE
287 && cursor.par->footnotekind != LyXParagraph::FOOTNOTE
288 && cursor.par->footnotekind != LyXParagraph::MARGIN)
290 && cursor.par->footnotekind != LyXParagraph::FIG
291 && cursor.par->footnotekind != LyXParagraph::TAB
292 && cursor.par->footnotekind != LyXParagraph::WIDE_FIG
293 && cursor.par->footnotekind != LyXParagraph::WIDE_TAB
294 && cursor.par->footnotekind != LyXParagraph::ALGORITHM)))
299 LyXCursor tmpcursor = cursor;
300 cursor.par = tmpcursor.par->ParFromPos(tmpcursor.pos);
301 cursor.pos = tmpcursor.par->PositionInParFromPos(tmpcursor.pos);
303 LyXParagraph *par = buffer()->paragraph;
306 if (par->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE
308 && par->footnotekind != LyXParagraph::FOOTNOTE
309 && par->footnotekind != LyXParagraph::MARGIN)
311 && par->footnotekind != LyXParagraph::FIG
312 && par->footnotekind != LyXParagraph::TAB
313 && par->footnotekind != LyXParagraph::WIDE_FIG
314 && par->footnotekind != LyXParagraph::WIDE_TAB
315 && par->footnotekind != LyXParagraph::ALGORITHM
320 && par->previous->footnoteflag !=
321 LyXParagraph::CLOSED_FOOTNOTE){ /* should be */
322 text->SetCursorIntern(par->previous,
324 text->OpenFootnote();
328 if (par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE
332 par->footnotekind != LyXParagraph::FOOTNOTE
334 par->footnotekind != LyXParagraph::MARGIN
339 par->footnotekind != LyXParagraph::FIG
341 par->footnotekind != LyXParagraph::TAB
343 par->footnotekind != LyXParagraph::WIDE_FIG
345 par->footnotekind != LyXParagraph::WIDE_TAB
347 par->footnotekind != LyXParagraph::ALGORITHM
351 text->SetCursorIntern(par, 0);
352 text->CloseFootnote();
358 text->SetCursorIntern(cursor.par, cursor.pos);
365 void BufferView::insertNote()
367 InsetInfo * new_inset = new InsetInfo();
368 insertInset(new_inset);
369 new_inset->Edit(this, 0, 0, 0);
373 void BufferView::openStuff()
376 owner()->getMiniBuffer()->Set(_("Open/Close..."));
387 void BufferView::toggleFloat()
390 owner()->getMiniBuffer()->Set(_("Open/Close..."));
394 text->ToggleFootnote();
400 void BufferView::menuUndo()
403 owner()->getMiniBuffer()->Set(_("Undo"));
407 if (!text->TextUndo())
408 owner()->getMiniBuffer()->Set(_("No further undo information"));
416 void BufferView::menuRedo()
418 if (the_locking_inset) {
419 owner()->getMiniBuffer()->Set(_("Redo not yet supported in math mode"));
424 owner()->getMiniBuffer()->Set(_("Redo"));
428 if (!text->TextRedo())
429 owner()->getMiniBuffer()->Set(_("No further redo information"));
437 void BufferView::hyphenationPoint()
442 InsetSpecialChar * new_inset =
443 new InsetSpecialChar(InsetSpecialChar::HYPHENATION);
444 insertInset(new_inset);
449 void BufferView::ldots()
454 InsetSpecialChar * new_inset =
455 new InsetSpecialChar(InsetSpecialChar::LDOTS);
456 insertInset(new_inset);
461 void BufferView::endOfSentenceDot()
466 InsetSpecialChar * new_inset =
467 new InsetSpecialChar(InsetSpecialChar::END_OF_SENTENCE);
468 insertInset(new_inset);
473 void BufferView::menuSeparator()
478 InsetSpecialChar * new_inset =
479 new InsetSpecialChar(InsetSpecialChar::MENU_SEPARATOR);
480 insertInset(new_inset);
485 void BufferView::newline()
491 InsetSpecialChar * new_inset =
492 new InsetSpecialChar(InsetSpecialChar::NEWLINE);
493 insertInset(new_inset);
495 text->InsertChar(LyXParagraph::META_NEWLINE);
502 void BufferView::protectedBlank()
508 InsetSpecialChar * new_inset =
509 new InsetSpecialChar(InsetSpecialChar::PROTECTED_SEPARATOR);
510 insertInset(new_inset);
512 text->InsertChar(LyXParagraph::META_PROTECTED_SEPARATOR);
519 void BufferView::hfill()
524 text->InsertChar(LyXParagraph::META_HFILL);
529 void BufferView::copyEnvironment()
532 text->copyEnvironmentType();
533 // clear the selection, even if mark_set
535 text->ClearSelection();
537 owner()->getMiniBuffer()->Set(_("Paragraph environment type copied"));
542 void BufferView::pasteEnvironment()
545 text->pasteEnvironmentType();
546 owner()->getMiniBuffer()->Set(_("Paragraph environment type set"));
552 void BufferView::copy()
555 text->CopySelection();
556 // clear the selection, even if mark_set
558 text->ClearSelection();
560 owner()->getMiniBuffer()->Set(_("Copy"));
564 void BufferView::cut()
569 text->CutSelection();
571 owner()->getMiniBuffer()->Set(_("Cut"));
576 void BufferView::paste()
578 if (!available()) return;
580 owner()->getMiniBuffer()->Set(_("Paste"));
582 // clear the selection
584 text->ClearSelection();
588 text->PasteSelection();
591 // clear the selection
593 text->ClearSelection();
598 void BufferView::gotoNote()
600 if (!available()) return;
607 if (!text->GotoNextNote()) {
609 || text->cursor.par != text->FirstParagraph()) {
611 text->cursor.par = text->FirstParagraph();
612 text->cursor.pos = 0;
613 if (!text->GotoNextNote()) {
615 owner()->getMiniBuffer()->Set(_("No more notes"));
619 owner()->getMiniBuffer()->Set(_("No more notes"));
624 text->sel_cursor = text->cursor;
628 void BufferView::insertCorrectQuote()
632 if (text->cursor.pos)
633 c = text->cursor.par->GetChar(text->cursor.pos - 1);
637 insertInset(new InsetQuotes(c, buffer()->params));
641 /* these functions are for the spellchecker */
642 char * BufferView::nextWord(float & value)
649 char * string = text->SelectNextWord(value);
655 void BufferView::selectLastWord()
657 if (!available()) return;
661 text->SelectSelectedWord();
662 toggleSelection(false);
667 void BufferView::endOfSpellCheck()
669 if (!available()) return;
673 text->SelectSelectedWord();
674 text->ClearSelection();
679 void BufferView::replaceWord(string const & replacestring)
681 if (!available()) return;
686 /* clear the selection (if there is any) */
687 toggleSelection(false);
690 /* clear the selection (if there is any) */
691 toggleSelection(false);
692 text->ReplaceSelectionWithString(replacestring.c_str());
694 text->SetSelectionOverString(replacestring.c_str());
696 // Go back so that replacement string is also spellchecked
697 for (string::size_type i = 0; i < replacestring.length() + 1; ++i) {
698 text->CursorLeftIntern();
702 // End of spellchecker stuff
706 /* these functions return 1 if an error occured,
708 int BufferView::lockInset(UpdatableInset * inset)
710 if (!the_locking_inset && inset){
711 the_locking_inset = inset;
718 void BufferView::showLockedInsetCursor(long x, long y, int asc, int desc)
720 if (the_locking_inset && available()) {
722 screen->ShowManualCursor(x, y, asc, desc,
723 LyXScreen::BAR_SHAPE);
728 void BufferView::hideLockedInsetCursor()
730 if (the_locking_inset && available()) {
731 screen->HideCursor();
736 void BufferView::fitLockedInsetCursor(long x, long y, int asc, int desc)
738 if (the_locking_inset && available()){
740 if (screen->FitManualCursor(x, y, asc, desc))
746 int BufferView::unlockInset(UpdatableInset * inset)
748 if (inset && the_locking_inset == inset) {
749 inset->InsetUnlock(this);
750 the_locking_inset = 0;
754 return bufferlist.unlockInset(inset);
758 void BufferView::lockedInsetStoreUndo(Undo::undo_kind kind)
760 if (!the_locking_inset)
761 return; // shouldn't happen
762 if (kind == Undo::EDIT) // in this case insets would not be stored!
766 ParFromPos(text->cursor.pos)->previous,
768 ParFromPos(text->cursor.pos)->next);
772 void BufferView::updateInset(Inset * inset, bool mark_dirty)
777 // first check for locking insets
778 if (the_locking_inset) {
779 if (the_locking_inset == inset) {
780 if (text->UpdateInset(inset)){
783 if (buffer()->isLyxClean())
784 owner()->getMiniBuffer()->
786 buffer()->markDirty();
791 } else if (the_locking_inset->UpdateInsetInInset(this,inset)) {
792 if (text->UpdateInset(the_locking_inset)) {
795 if (buffer()->isLyxClean())
796 owner()->getMiniBuffer()->
798 buffer()->markDirty();
806 // then check the current buffer
810 if (text->UpdateInset(inset)){