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 // (c) 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 int lay = textclasslist.NumberOfLayout(buffer()->params.textclass,
208 if (lay == -1) // layout not found
209 // use default layout "Standard" (0)
212 text->SetLayout(lay);
214 text->SetParagraph(0, 0,
216 VSpace(VSpace::NONE), VSpace(VSpace::NONE),
222 text->current_font.setLatex(LyXFont::OFF);
225 text->InsertInset(inset);
228 text->UnFreezeUndo();
232 // Open and lock an updatable inset
233 void BufferView::open_new_inset(UpdatableInset * new_inset)
237 insertInset(new_inset);
240 new_inset->Edit(this, 0, 0);
243 /* This is also a buffer property (ale) */
244 // Not so sure about that. a goto Label function can not be buffer local, just
245 // think how this will work in a multiwindo/buffer environment, all the
246 // cursors in all the views showing this buffer will move. (Lgb)
247 // OK, then no cursor action should be allowed in buffer. (ale)
248 bool BufferView::gotoLabel(string const & label)
251 LyXParagraph * par = buffer()->paragraph;
252 LyXParagraph::size_type pos;
256 while ((inset = par->ReturnNextInsetPointer(pos))){
257 for (int i = 0; i < inset->GetNumberOfLabels(); ++i) {
258 if (label == inset->getLabel(i)) {
260 text->SetCursor(par, pos);
261 text->sel_cursor = text->cursor;
273 void BufferView::allFloats(char flag, char figmar)
275 if (!available()) return;
277 LyXCursor cursor = text->cursor;
279 if (!flag && cursor.par->footnoteflag != LyXParagraph::NO_FOOTNOTE
281 && cursor.par->footnotekind != LyXParagraph::FOOTNOTE
282 && cursor.par->footnotekind != LyXParagraph::MARGIN)
284 && cursor.par->footnotekind != LyXParagraph::FIG
285 && cursor.par->footnotekind != LyXParagraph::TAB
286 && cursor.par->footnotekind != LyXParagraph::WIDE_FIG
287 && cursor.par->footnotekind != LyXParagraph::WIDE_TAB
288 && cursor.par->footnotekind != LyXParagraph::ALGORITHM)))
293 LyXCursor tmpcursor = cursor;
294 cursor.par = tmpcursor.par->ParFromPos(tmpcursor.pos);
295 cursor.pos = tmpcursor.par->PositionInParFromPos(tmpcursor.pos);
297 LyXParagraph *par = buffer()->paragraph;
300 if (par->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE
302 && par->footnotekind != LyXParagraph::FOOTNOTE
303 && par->footnotekind != LyXParagraph::MARGIN)
305 && par->footnotekind != LyXParagraph::FIG
306 && par->footnotekind != LyXParagraph::TAB
307 && par->footnotekind != LyXParagraph::WIDE_FIG
308 && par->footnotekind != LyXParagraph::WIDE_TAB
309 && par->footnotekind != LyXParagraph::ALGORITHM
314 && par->previous->footnoteflag !=
315 LyXParagraph::CLOSED_FOOTNOTE){ /* should be */
316 text->SetCursorIntern(par->previous,
318 text->OpenFootnote();
322 if (par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE
326 par->footnotekind != LyXParagraph::FOOTNOTE
328 par->footnotekind != LyXParagraph::MARGIN
333 par->footnotekind != LyXParagraph::FIG
335 par->footnotekind != LyXParagraph::TAB
337 par->footnotekind != LyXParagraph::WIDE_FIG
339 par->footnotekind != LyXParagraph::WIDE_TAB
341 par->footnotekind != LyXParagraph::ALGORITHM
345 text->SetCursorIntern(par, 0);
346 text->CloseFootnote();
352 text->SetCursorIntern(cursor.par, cursor.pos);
359 void BufferView::insertNote()
361 InsetInfo * new_inset = new InsetInfo();
362 insertInset(new_inset);
363 new_inset->Edit(this, 0, 0);
367 void BufferView::openStuff()
370 owner()->getMiniBuffer()->Set(_("Open/Close..."));
381 void BufferView::toggleFloat()
384 owner()->getMiniBuffer()->Set(_("Open/Close..."));
388 text->ToggleFootnote();
394 void BufferView::menuUndo()
397 owner()->getMiniBuffer()->Set(_("Undo"));
401 if (!text->TextUndo())
402 owner()->getMiniBuffer()->Set(_("No further undo information"));
410 void BufferView::menuRedo()
412 if (the_locking_inset) {
413 owner()->getMiniBuffer()->Set(_("Redo not yet supported in math mode"));
418 owner()->getMiniBuffer()->Set(_("Redo"));
422 if (!text->TextRedo())
423 owner()->getMiniBuffer()->Set(_("No further redo information"));
431 void BufferView::hyphenationPoint()
436 InsetSpecialChar * new_inset =
437 new InsetSpecialChar(InsetSpecialChar::HYPHENATION);
438 insertInset(new_inset);
443 void BufferView::ldots()
448 InsetSpecialChar * new_inset =
449 new InsetSpecialChar(InsetSpecialChar::LDOTS);
450 insertInset(new_inset);
455 void BufferView::endOfSentenceDot()
460 InsetSpecialChar * new_inset =
461 new InsetSpecialChar(InsetSpecialChar::END_OF_SENTENCE);
462 insertInset(new_inset);
467 void BufferView::menuSeparator()
472 InsetSpecialChar * new_inset =
473 new InsetSpecialChar(InsetSpecialChar::MENU_SEPARATOR);
474 insertInset(new_inset);
479 void BufferView::newline()
484 text->InsertChar(LyXParagraph::META_NEWLINE);
490 void BufferView::protectedBlank()
495 text->InsertChar(LyXParagraph::META_PROTECTED_SEPARATOR);
501 void BufferView::hfill()
506 text->InsertChar(LyXParagraph::META_HFILL);
511 void BufferView::copyEnvironment()
514 text->copyEnvironmentType();
515 // clear the selection, even if mark_set
517 text->ClearSelection();
519 owner()->getMiniBuffer()->Set(_("Paragraph environment type copied"));
524 void BufferView::pasteEnvironment()
527 text->pasteEnvironmentType();
528 owner()->getMiniBuffer()->Set(_("Paragraph environment type set"));
534 void BufferView::copy()
537 text->CopySelection();
538 // clear the selection, even if mark_set
540 text->ClearSelection();
542 owner()->getMiniBuffer()->Set(_("Copy"));
546 void BufferView::cut()
551 text->CutSelection();
553 owner()->getMiniBuffer()->Set(_("Cut"));
558 void BufferView::paste()
560 if (!available()) return;
562 owner()->getMiniBuffer()->Set(_("Paste"));
564 // clear the selection
566 text->ClearSelection();
570 text->PasteSelection();
573 // clear the selection
575 text->ClearSelection();
580 void BufferView::gotoNote()
582 if (!available()) return;
589 if (!text->GotoNextNote()) {
591 || text->cursor.par != text->FirstParagraph()) {
593 text->cursor.par = text->FirstParagraph();
594 text->cursor.pos = 0;
595 if (!text->GotoNextNote()) {
597 owner()->getMiniBuffer()->Set(_("No more notes"));
601 owner()->getMiniBuffer()->Set(_("No more notes"));
606 text->sel_cursor = text->cursor;
610 void BufferView::insertCorrectQuote()
614 if (text->cursor.pos)
615 c = text->cursor.par->GetChar(text->cursor.pos - 1);
619 insertInset(new InsetQuotes(c, buffer()->params));
623 /* these functions are for the spellchecker */
624 char * BufferView::nextWord(float & value)
631 char * string = text->SelectNextWord(value);
637 void BufferView::selectLastWord()
639 if (!available()) return;
643 text->SelectSelectedWord();
644 toggleSelection(false);
649 void BufferView::endOfSpellCheck()
651 if (!available()) return;
655 text->SelectSelectedWord();
656 text->ClearSelection();
661 void BufferView::replaceWord(string const & replacestring)
663 if (!available()) return;
668 /* clear the selection (if there is any) */
669 toggleSelection(false);
672 /* clear the selection (if there is any) */
673 toggleSelection(false);
674 text->ReplaceSelectionWithString(replacestring.c_str());
676 text->SetSelectionOverString(replacestring.c_str());
678 // Go back so that replacement string is also spellchecked
679 for (string::size_type i = 0; i < replacestring.length() + 1; ++i) {
680 text->CursorLeftIntern();
684 // End of spellchecker stuff
687 /* these functions return 1 if an error occured,
689 int BufferView::lockInset(UpdatableInset * inset)
691 if (!the_locking_inset && inset){
692 the_locking_inset = inset;
699 void BufferView::showLockedInsetCursor(long x, long y, int asc, int desc)
701 if (the_locking_inset && available()) {
703 screen->ShowManualCursor(x, y,
709 void BufferView::hideLockedInsetCursor()
711 if (the_locking_inset && available()) {
712 screen->HideCursor();
717 void BufferView::fitLockedInsetCursor(long x, long y, int asc, int desc)
719 if (the_locking_inset && available()){
721 if (screen->FitManualCursor(x, y, asc, desc))
727 int BufferView::unlockInset(UpdatableInset * inset)
729 if (inset && the_locking_inset == inset) {
730 inset->InsetUnlock(this);
731 the_locking_inset = 0;
735 return bufferlist.unlockInset(inset);
739 void BufferView::lockedInsetStoreUndo(Undo::undo_kind kind)
741 if (!the_locking_inset)
742 return; // shouldn't happen
743 if (kind == Undo::EDIT) // in this case insets would not be stored!
747 ParFromPos(text->cursor.pos)->previous,
749 ParFromPos(text->cursor.pos)->next);
753 void BufferView::updateInset(Inset * inset, bool mark_dirty)
758 // first check for locking insets
759 if (the_locking_inset == inset) {
760 if (text->UpdateInset(inset)){
763 if (buffer()->isLyxClean())
764 owner()->getMiniBuffer()->setTimer(4);
765 buffer()->markDirty();
772 // then check the current buffer
776 if (text->UpdateInset(inset)){