2 /* This file is part of
3 * ======================================================
5 * LyX, The Document Processor
7 * Copyright 1998-2000 The LyX Team.
9 * ======================================================
20 #pragma implementation
23 #include "insettext.h"
24 #include "lyxparagraph.h"
28 #include "commandtags.h"
31 #include "BufferView.h"
33 #include "LaTeXFeatures.h"
35 #include "lyx_gui_misc.h"
37 #include "lyxcursor.h"
38 #include "CutAndPaste.h"
40 #include "minibuffer.h"
42 #include "support/textutils.h"
43 #include "support/LAssert.h"
47 #include "trans_mgr.h"
48 #include "lyxscreen.h"
57 extern unsigned char getCurrentTextClass(Buffer *);
59 InsetText::InsetText()
61 par = new LyXParagraph();
66 InsetText::InsetText(InsetText const & ins)
71 autoBreakRows = ins.autoBreakRows;
75 InsetText & InsetText::operator=(InsetText const & it)
78 autoBreakRows = it.autoBreakRows;
83 void InsetText::init(InsetText const * ins)
85 top_y = last_width = last_height = 0;
86 insetAscent = insetDescent = insetWidth = 0;
87 the_locking_inset = 0;
88 cursor_visible = false;
92 drawTextXOffset = drawTextYOffset = 0;
93 autoBreakRows = false;
97 SetParagraphData(ins->par);
98 autoBreakRows = ins->autoBreakRows;
99 drawFrame = ins->drawFrame;
101 par->SetInsetOwner(this);
102 frame_color = LColor::insetframe;
108 InsetText::~InsetText()
110 for(Cache::const_iterator cit=cache.begin(); cit != cache.end(); ++cit)
111 delete (*cit).second;
112 // deleteLyXText((*cit).first);
113 LyXParagraph * p = par->next;
123 void InsetText::clear()
125 LyXParagraph * p = par->next;
132 par = new LyXParagraph();
136 Inset * InsetText::Clone() const
138 InsetText * t = new InsetText(*this);
143 void InsetText::Write(Buffer const * buf, ostream & os) const
146 WriteParagraphData(buf, os);
150 void InsetText::WriteParagraphData(Buffer const * buf, ostream & os) const
152 par->writeFile(buf, os, buf->params, 0, 0);
156 void InsetText::Read(Buffer const * buf, LyXLex & lex)
160 LyXParagraph * return_par = 0;
161 char depth = 0; // signed or unsigned?
163 LyXParagraph::footnote_flag footnoteflag = LyXParagraph::NO_FOOTNOTE;
164 LyXParagraph::footnote_kind footnotekind = LyXParagraph::FOOTNOTE;
166 LyXFont font(LyXFont::ALL_INHERIT);
168 LyXParagraph * p = par->next;
175 par = new LyXParagraph;
178 token = lex.GetString();
181 if (token == "\\end_inset")
183 if (const_cast<Buffer*>(buf)->
184 parseSingleLyXformat2Token(lex, par, return_par,token, pos, depth,
187 , footnoteflag, footnotekind
191 // the_end read this should NEVER happen
192 lex.printError("\\the_end read in inset! Error in document!");
200 return_par->SetInsetOwner(this);
201 return_par = return_par->next;
204 if (token != "\\end_inset") {
205 lex.printError("Missing \\end_inset at this point. "
212 int InsetText::ascent(BufferView * bv, LyXFont const &) const
215 Row * row = TEXT(bv)->GetRowNearY(y_temp);
216 insetAscent = row->ascent_of_text() + TEXT_TO_INSET_OFFSET;
221 int InsetText::descent(BufferView * bv, LyXFont const &) const
224 Row * row = TEXT(bv)->GetRowNearY(y_temp);
225 insetDescent = TEXT(bv)->height - row->ascent_of_text() +
226 TEXT_TO_INSET_OFFSET;
231 int InsetText::width(BufferView * bv, LyXFont const &) const
233 insetWidth = TEXT(bv)->width + (2 * TEXT_TO_INSET_OFFSET);
238 int InsetText::textWidth(Painter & pain) const
240 int w = getMaxWidth(pain, this);
245 void InsetText::draw(BufferView * bv, LyXFont const & f,
246 int baseline, float & x, bool cleared) const
248 Painter & pain = bv->painter();
250 // no draw is necessary !!!
251 if ((drawFrame == LOCKED) && !locked && !par->size()) {
252 if (!cleared && (need_update == CLEAR_FRAME)) {
253 pain.rectangle(top_x + 1, baseline - insetAscent + 1,
255 insetAscent + insetDescent - 1,
259 top_baseline = baseline;
266 UpdatableInset::draw(bv, f, baseline, x, cleared);
268 if (!cleared && ((need_update==FULL) || (top_x!=int(x)) ||
269 (top_baseline!=baseline))) {
271 int h = insetAscent + insetDescent;
272 int ty = baseline - insetAscent;
278 if ((ty + h) > pain.paperHeight())
279 h = pain.paperHeight();
280 if ((top_x + drawTextXOffset + w) > pain.paperWidth())
281 w = pain.paperWidth();
282 pain.fillRectangle(top_x+drawTextXOffset, ty, w, h);
286 if (!cleared && (need_update == NONE))
289 if (top_x != int(x)) {
292 bv->text->status = LyXText::CHANGED_IN_DRAW;
296 top_baseline = baseline;
297 top_y = baseline - ascent(bv, f);
298 last_width = width(bv, f);
299 last_height = ascent(bv, f) + descent(bv, f);
301 if (the_locking_inset && (cpar(bv) == inset_par) && (cpos(bv) == inset_pos)) {
302 inset_x = cx(bv) - top_x + drawTextXOffset;
303 inset_y = cy(bv) + drawTextYOffset;
305 if (!cleared && (need_update == CURSOR) && !TEXT(bv)->selection) {
310 x += TEXT_TO_INSET_OFFSET;
312 Row * row = TEXT(bv)->GetRowNearY(y);
313 y += baseline - row->ascent_of_text();
314 if (cleared || !locked || (need_update == FULL)) {
316 TEXT(bv)->GetVisibleRow(bv, y, int(x), row, y, cleared);
320 } else if (need_update == SELECTION) {
321 bv->screen()->ToggleToggle(TEXT(bv), y, int(x));
324 if (need_update == CURSOR) {
325 bv->screen()->ToggleSelection(TEXT(bv), true, y, int(x));
326 TEXT(bv)->ClearSelection();
327 TEXT(bv)->sel_cursor = TEXT(bv)->cursor;
329 bv->screen()->Update(TEXT(bv), y, int(x));
332 TEXT(bv)->refresh_y = 0;
333 TEXT(bv)->status = LyXText::UNCHANGED;
334 if ((drawFrame == ALWAYS) || ((drawFrame == LOCKED) && locked)) {
335 pain.rectangle(top_x + 1, baseline - insetAscent + 1,
336 width(bv, f) - 1, insetAscent + insetDescent - 1,
338 } else if (need_update == CLEAR_FRAME) {
339 pain.rectangle(top_x + 1, baseline - insetAscent + 1,
340 width(bv, f) - 1, insetAscent + insetDescent - 1,
343 x += width(bv, f) - TEXT_TO_INSET_OFFSET;
344 if (bv->text->status==LyXText::CHANGED_IN_DRAW)
346 else if (need_update != INIT)
351 void InsetText::update(BufferView * bv, LyXFont const & font, bool reinit)
353 if (reinit) { // && (need_update != CURSOR)) {
357 owner()->update(bv, font, true);
360 if (the_locking_inset) {
361 inset_x = cx(bv) - top_x + drawTextXOffset;
362 inset_y = cy(bv) + drawTextYOffset;
363 the_locking_inset->update(bv, font, reinit);
365 if (need_update == INIT) {
368 // if (!owner() && bv->text)
369 // bv->text->UpdateInset(bv, this);
371 int oldw = insetWidth;
373 insetWidth = TEXT(bv)->width + (2 * TEXT_TO_INSET_OFFSET);
374 // max(textWidth(bv->painter()),
375 // static_cast<int>(TEXT(bv)->width) + drawTextXOffset) +
376 // (2 * TEXT_TO_INSET_OFFSET);
378 insetWidth = textWidth(bv->painter());
380 insetWidth = static_cast<int>(TEXT(bv)->width);
382 if (oldw != insetWidth) {
383 // printf("TW(%p): %d-%d-%d-%d\n",this,insetWidth, oldw,
384 // textWidth(bv->painter()),static_cast<int>(TEXT(bv)->width));
389 owner()->update(bv, font, reinit);
392 update(bv, font, reinit);
396 update(bv, font, reinit);
398 UpdateLocal(bv, INIT, false);
403 if ((need_update==CURSOR_PAR) && (TEXT(bv)->status==LyXText::UNCHANGED) &&
406 TEXT(bv)->UpdateInset(bv, the_locking_inset);
409 if (TEXT(bv)->status == LyXText::NEED_MORE_REFRESH)
413 Row * row = TEXT(bv)->GetRowNearY(y_temp);
414 insetAscent = row->ascent_of_text() + TEXT_TO_INSET_OFFSET;
415 insetDescent = TEXT(bv)->height - row->ascent_of_text() +
416 TEXT_TO_INSET_OFFSET;
420 void InsetText::UpdateLocal(BufferView * bv, UpdateCodes what, bool mark_dirty)
422 TEXT(bv)->FullRebreak(bv);
423 if (need_update != INIT) {
424 if (TEXT(bv)->status == LyXText::NEED_MORE_REFRESH)
426 else if (!the_locking_inset || (what != CURSOR))
429 if ((need_update != CURSOR) || (TEXT(bv)->status != LyXText::UNCHANGED) ||
431 bv->updateInset(this, mark_dirty);
432 bv->owner()->showState();
433 if (old_par != cpar(bv)) {
434 bv->owner()->setLayout(cpar(bv)->GetLayout());
440 string const InsetText::EditMessage() const
442 return _("Opened Text Inset");
446 void InsetText::Edit(BufferView * bv, int x, int y, unsigned int button)
448 // par->SetInsetOwner(this);
449 UpdatableInset::Edit(bv, x, y, button);
451 if (!bv->lockInset(this)) {
452 lyxerr[Debug::INSETS] << "Cannot lock inset" << endl;
456 the_locking_inset = 0;
457 inset_pos = inset_x = inset_y = 0;
460 if (!checkAndActivateInset(bv, x, y, button))
461 TEXT(bv)->SetCursorFromCoordinates(bv, x-drawTextXOffset,
462 y+TEXT(bv)->first+insetAscent);
463 TEXT(bv)->sel_cursor = TEXT(bv)->cursor;
464 bv->text->FinishUndo();
465 UpdateLocal(bv, FULL, false);
469 void InsetText::InsetUnlock(BufferView * bv)
471 if (the_locking_inset) {
472 the_locking_inset->InsetUnlock(bv);
473 the_locking_inset = 0;
476 no_selection = false;
478 TEXT(bv)->selection = 0;
479 UpdateLocal(bv, CLEAR_FRAME, false);
481 bv->owner()->setLayout(owner()->getLyXText(bv)
482 ->cursor.par()->GetLayout());
484 bv->owner()->setLayout(bv->text->cursor.par()->GetLayout());
488 bool InsetText::LockInsetInInset(BufferView * bv, UpdatableInset * inset)
490 lyxerr[Debug::INSETS] << "InsetText::LockInsetInInset(" << inset << "): ";
493 if (inset == cpar(bv)->GetInset(cpos(bv))) {
494 lyxerr[Debug::INSETS] << "OK" << endl;
495 the_locking_inset = inset;
496 inset_x = cx(bv) - top_x + drawTextXOffset;
497 inset_y = cy(bv) + drawTextYOffset;
498 inset_pos = cpos(bv);
499 inset_par = cpar(bv);
500 TEXT(bv)->UpdateInset(bv, the_locking_inset);
502 } else if (the_locking_inset && (the_locking_inset == inset)) {
503 if (cpar(bv) == inset_par && cpos(bv) == inset_pos) {
504 lyxerr[Debug::INSETS] << "OK" << endl;
505 inset_x = cx(bv) - top_x + drawTextXOffset;
506 inset_y = cy(bv) + drawTextYOffset;
508 lyxerr[Debug::INSETS] << "cursor.pos != inset_pos" << endl;
510 } else if (the_locking_inset) {
511 lyxerr[Debug::INSETS] << "MAYBE" << endl;
512 return the_locking_inset->LockInsetInInset(bv, inset);
514 lyxerr[Debug::INSETS] << "NOT OK" << endl;
519 bool InsetText::UnlockInsetInInset(BufferView * bv, UpdatableInset * inset,
522 if (!the_locking_inset)
524 if (the_locking_inset == inset) {
525 the_locking_inset->InsetUnlock(bv);
526 TEXT(bv)->UpdateInset(bv, inset);
527 the_locking_inset = 0;
529 moveRight(bv, false);
530 old_par = 0; // force layout setting
531 UpdateLocal(bv, CURSOR_PAR, false);
534 return the_locking_inset->UnlockInsetInInset(bv, inset, lr);
538 bool InsetText::UpdateInsetInInset(BufferView * bv, Inset * inset)
540 if (!the_locking_inset)
542 if (the_locking_inset != inset) {
543 TEXT(bv)->UpdateInset(bv, the_locking_inset);
544 need_update = CURSOR_PAR;
545 return the_locking_inset->UpdateInsetInInset(bv, inset);
547 // UpdateLocal(bv, FULL, false);
548 if (TEXT(bv)->UpdateInset(bv, inset))
549 UpdateLocal(bv, CURSOR_PAR, false);
550 if (cpar(bv) == inset_par && cpos(bv) == inset_pos) {
551 inset_x = cx(bv) - top_x + drawTextXOffset;
552 inset_y = cy(bv) + drawTextYOffset;
558 void InsetText::InsetButtonPress(BufferView * bv, int x, int y, int button)
560 no_selection = false;
562 int tmp_x = x - drawTextXOffset;
563 int tmp_y = y + insetAscent;
564 Inset * inset = bv->checkInsetHit(TEXT(bv), tmp_x, tmp_y, button);
567 if (the_locking_inset) {
568 if (the_locking_inset == inset) {
569 the_locking_inset->InsetButtonPress(bv,x-inset_x,y-inset_y,button);
572 // otherwise unlock the_locking_inset and lock the new inset
573 the_locking_inset->InsetUnlock(bv);
574 inset_x = cx(bv) - top_x + drawTextXOffset;
575 inset_y = cy(bv) + drawTextYOffset;
576 inset->InsetButtonPress(bv, x - inset_x, y - inset_y, button);
577 inset->Edit(bv, x - inset_x, y - inset_y, button);
578 if (the_locking_inset) {
579 UpdateLocal(bv, CURSOR_PAR, false);
583 // otherwise only unlock the_locking_inset
584 the_locking_inset->InsetUnlock(bv);
585 the_locking_inset = 0;
587 if (bv->the_locking_inset) {
588 if (inset && inset->Editable() == Inset::HIGHLY_EDITABLE) {
589 UpdatableInset * uinset = static_cast<UpdatableInset*>(inset);
590 inset_x = cx(bv) - top_x + drawTextXOffset;
591 inset_y = cy(bv) + drawTextYOffset;
592 inset_pos = cpos(bv);
593 inset_par = cpar(bv);
594 uinset->InsetButtonPress(bv, x - inset_x, y - inset_y, button);
595 uinset->Edit(bv, x - inset_x, y - inset_y, 0);
596 if (the_locking_inset) {
597 UpdateLocal(bv, CURSOR_PAR, false);
603 bool paste_internally = false;
604 if ((button == 2) && TEXT(bv)->selection) {
605 LocalDispatch(bv, LFUN_COPY, "");
606 paste_internally = true;
608 TEXT(bv)->SetCursorFromCoordinates(bv, x-drawTextXOffset,
609 y+TEXT(bv)->first+insetAscent);
610 TEXT(bv)->sel_cursor = TEXT(bv)->cursor;
611 UpdateLocal(bv, CURSOR, false);
612 bv->owner()->setLayout(cpar(bv)->GetLayout());
614 // Insert primary selection with middle mouse
615 // if there is a local selection in the current buffer,
618 if (paste_internally)
619 LocalDispatch(bv, LFUN_PASTE, "");
621 LocalDispatch(bv, LFUN_PASTESELECTION, "paragraph");
628 void InsetText::InsetButtonRelease(BufferView * bv, int x, int y, int button)
630 UpdatableInset * inset = 0;
632 if (the_locking_inset) {
633 the_locking_inset->InsetButtonRelease(bv,
634 x - inset_x, y - inset_y,
637 if (cpar(bv)->GetChar(cpos(bv)) == LyXParagraph::META_INSET) {
638 inset = static_cast<UpdatableInset*>(cpar(bv)->GetInset(cpos(bv)));
639 if (inset->Editable() == Inset::HIGHLY_EDITABLE) {
640 inset->InsetButtonRelease(bv, x - inset_x, y - inset_y,button);
642 inset_x = cx(bv) - top_x + drawTextXOffset;
643 inset_y = cy(bv) + drawTextYOffset;
644 inset->InsetButtonRelease(bv, x - inset_x, y - inset_y,button);
645 inset->Edit(bv, x - inset_x, y - inset_y, button);
647 UpdateLocal(bv, CURSOR_PAR, false);
650 no_selection = false;
654 void InsetText::InsetMotionNotify(BufferView * bv, int x, int y, int state)
656 if (the_locking_inset) {
657 the_locking_inset->InsetMotionNotify(bv, x - inset_x,
663 TEXT(bv)->SetCursorFromCoordinates(bv, x-drawTextXOffset,
664 y+TEXT(bv)->first+insetAscent);
665 TEXT(bv)->SetSelection();
666 if (TEXT(bv)->toggle_cursor.par()!=TEXT(bv)->toggle_end_cursor.par() ||
667 TEXT(bv)->toggle_cursor.pos()!=TEXT(bv)->toggle_end_cursor.pos())
668 UpdateLocal(bv, SELECTION, false);
671 no_selection = false;
675 void InsetText::InsetKeyPress(XKeyEvent * xke)
677 if (the_locking_inset) {
678 the_locking_inset->InsetKeyPress(xke);
684 UpdatableInset::RESULT
685 InsetText::LocalDispatch(BufferView * bv,
686 int action, string const & arg)
688 no_selection = false;
689 UpdatableInset::RESULT
690 result= UpdatableInset::LocalDispatch(bv, action, arg);
691 if (result != UNDISPATCHED) {
696 if ((action < 0) && arg.empty())
699 if (the_locking_inset) {
700 result = the_locking_inset->LocalDispatch(bv, action, arg);
701 if (result == DISPATCHED_NOUPDATE)
703 else if (result == DISPATCHED) {
704 UpdateLocal(bv, CURSOR_PAR, false);
706 } else if (result == FINISHED) {
710 moveRight(bv, false);
716 the_locking_inset = 0;
724 if (bv->buffer()->isReadonly()) {
726 // setErrorMessage(N_("Document is read only"));
730 /* Automatically delete the currently selected
731 * text and replace it with what is being
732 * typed in now. Depends on lyxrc settings
733 * "auto_region_delete", which defaults to
736 bv->text->SetUndo(bv->buffer(), Undo::INSERT,
738 bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->previous,
739 bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->next
741 bv->text->cursor.par()->previous,
742 bv->text->cursor.par()->next
745 if (lyxrc.auto_region_delete) {
746 if (TEXT(bv)->selection){
747 TEXT(bv)->CutSelection(bv, false);
750 TEXT(bv)->ClearSelection();
751 for (string::size_type i = 0; i < arg.length(); ++i) {
752 bv->owner()->getIntl()->getTrans()->TranslateAndInsert(arg[i], TEXT(bv));
755 UpdateLocal(bv, CURSOR_PAR, true);
757 // --- Cursor Movements ---------------------------------------------
759 bv->text->FinishUndo();
760 moveRight(bv, false, true);
761 TEXT(bv)->SetSelection();
762 UpdateLocal(bv, SELECTION, false);
765 result = moveRight(bv);
766 bv->text->FinishUndo();
767 UpdateLocal(bv, CURSOR, false);
770 bv->text->FinishUndo();
771 moveLeft(bv, false, true);
772 TEXT(bv)->SetSelection();
773 UpdateLocal(bv, SELECTION, false);
776 bv->text->FinishUndo();
777 result= moveLeft(bv);
778 UpdateLocal(bv, CURSOR, false);
781 bv->text->FinishUndo();
783 TEXT(bv)->SetSelection();
784 UpdateLocal(bv, SELECTION, false);
787 bv->text->FinishUndo();
788 result = moveDown(bv);
789 UpdateLocal(bv, CURSOR, false);
792 bv->text->FinishUndo();
794 TEXT(bv)->SetSelection();
795 UpdateLocal(bv, SELECTION, false);
798 bv->text->FinishUndo();
800 UpdateLocal(bv, CURSOR, false);
803 bv->text->FinishUndo();
804 TEXT(bv)->CursorHome(bv);
805 UpdateLocal(bv, CURSOR, false);
808 TEXT(bv)->CursorEnd(bv);
809 UpdateLocal(bv, CURSOR, false);
812 bv->text->SetUndo(bv->buffer(), Undo::DELETE,
814 bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->previous,
815 bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->next
817 bv->text->cursor.par()->previous,
818 bv->text->cursor.par()->next
821 if (TEXT(bv)->selection)
822 TEXT(bv)->CutSelection(bv);
824 TEXT(bv)->Backspace(bv);
825 UpdateLocal(bv, CURSOR_PAR, true);
828 bv->text->SetUndo(bv->buffer(), Undo::DELETE,
830 bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->previous,
831 bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->next
833 bv->text->cursor.par()->previous,
834 bv->text->cursor.par()->next
837 if (TEXT(bv)->selection)
838 TEXT(bv)->CutSelection(bv);
840 TEXT(bv)->Delete(bv);
841 UpdateLocal(bv, CURSOR_PAR, true);
844 bv->text->SetUndo(bv->buffer(), Undo::DELETE,
846 bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->previous,
847 bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->next
849 bv->text->cursor.par()->previous,
850 bv->text->cursor.par()->next
853 TEXT(bv)->CutSelection(bv);
854 UpdateLocal(bv, CURSOR_PAR, true);
857 bv->text->FinishUndo();
858 TEXT(bv)->CopySelection(bv);
859 UpdateLocal(bv, CURSOR_PAR, false);
861 case LFUN_PASTESELECTION:
863 string clip(bv->workarea()->getClipboard());
867 if (arg == "paragraph") {
868 TEXT(bv)->InsertStringB(bv, clip);
870 TEXT(bv)->InsertStringA(bv, clip);
872 UpdateLocal(bv, CURSOR_PAR, true);
876 if (!autoBreakRows) {
879 if (cap.nrOfParagraphs() > 1) {
880 WriteAlert(_("Impossible operation"),
881 _("Cannot include more than one paragraph!"),
886 bv->text->SetUndo(bv->buffer(), Undo::INSERT,
888 bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->previous,
889 bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->next
891 bv->text->cursor.par()->previous,
892 bv->text->cursor.par()->next
895 TEXT(bv)->PasteSelection(bv);
896 UpdateLocal(bv, CURSOR_PAR, true);
898 case LFUN_BREAKPARAGRAPH:
901 TEXT(bv)->BreakParagraph(bv, 0);
902 UpdateLocal(bv, FULL, true);
907 bv->text->SetUndo(bv->buffer(), Undo::INSERT,
909 bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->previous,
910 bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->next
912 bv->text->cursor.par()->previous,
913 bv->text->cursor.par()->next
916 TEXT(bv)->InsertChar(bv, LyXParagraph::META_NEWLINE);
917 UpdateLocal(bv, CURSOR_PAR, true);
920 // do not set layouts on non breakable textinsets
922 LyXTextClass::size_type cur_layout = cpar(bv)->layout;
924 // Derive layout number from given argument (string)
925 // and current buffer's textclass (number). */
926 LyXTextClassList::ClassList::size_type tclass =
927 bv->buffer()->params.textclass;
928 std::pair <bool, LyXTextClass::size_type> layout =
929 textclasslist.NumberOfLayout(tclass, arg);
931 // If the entry is obsolete, use the new one instead.
933 string obs = textclasslist.Style(tclass,layout.second).
936 layout = textclasslist.NumberOfLayout(tclass, obs);
939 // see if we found the layout number:
941 string msg = string(N_("Layout ")) + arg + N_(" not known");
943 bv->owner()->getMiniBuffer()->Set(msg);
947 if (cur_layout != layout.second) {
948 cur_layout = layout.second;
949 TEXT(bv)->SetLayout(bv, layout.second);
950 bv->owner()->setLayout(cpar(bv)->GetLayout());
951 UpdateLocal(bv, CURSOR_PAR, true);
954 // reset the layout box
955 bv->owner()->setLayout(cpar(bv)->GetLayout());
958 case LFUN_PARAGRAPH_SPACING:
959 // This one is absolutely not working. When fiddling with this
960 // it also seems to me that the paragraphs inside the insettext
961 // inherit bufferparams/paragraphparams in a strange way. (Lgb)
963 LyXParagraph * par = TEXT(bv)->cursor.par();
964 Spacing::Space cur_spacing = par->spacing.getSpace();
965 float cur_value = 1.0;
966 if (cur_spacing == Spacing::Other) {
967 cur_value = par->spacing.getValue();
970 std::istringstream istr(arg.c_str());
973 Spacing::Space new_spacing = cur_spacing;
974 float new_value = cur_value;
976 lyxerr << "Missing argument to `paragraph-spacing'"
978 } else if (tmp == "single") {
979 new_spacing = Spacing::Single;
980 } else if (tmp == "onehalf") {
981 new_spacing = Spacing::Onehalf;
982 } else if (tmp == "double") {
983 new_spacing = Spacing::Double;
984 } else if (tmp == "other") {
985 new_spacing = Spacing::Other;
988 lyxerr << "new_value = " << tmpval << endl;
991 } else if (tmp == "default") {
992 new_spacing = Spacing::Default;
994 lyxerr << _("Unknown spacing argument: ")
997 if (cur_spacing != new_spacing || cur_value != new_value) {
998 par->spacing.set(new_spacing, new_value);
999 //TEXT(bv)->RedoParagraph(owner->view());
1000 UpdateLocal(bv, CURSOR_PAR, true);
1001 //bv->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
1007 result = UNDISPATCHED;
1010 if (result != FINISHED) {
1011 ShowInsetCursor(bv);
1013 bv->unlockInset(this);
1018 int InsetText::Latex(Buffer const * buf, ostream & os, bool, bool) const
1021 buf->latexParagraphs(os, par, 0, texrow);
1022 return texrow.rows();
1026 int InsetText::Ascii(Buffer const * buf, ostream & os, int linelen) const
1028 LyXParagraph * p = par;
1029 unsigned int lines = 0;
1032 string const tmp = buf->asciiParagraph(p, linelen);
1033 lines += countChar(tmp, '\n');
1043 void InsetText::Validate(LaTeXFeatures & features) const
1045 LyXParagraph * p = par;
1047 p->validate(features);
1053 int InsetText::BeginningOfMainBody(Buffer const * buf, LyXParagraph * p) const
1055 if (textclasslist.Style(buf->params.textclass,
1056 p->GetLayout()).labeltype != LABEL_MANUAL)
1059 return p->BeginningOfMainBody();
1063 void InsetText::GetCursorPos(BufferView * bv, int & x, int & y) const
1070 int InsetText::InsetInInsetY()
1072 if (!the_locking_inset)
1075 return (inset_y + the_locking_inset->InsetInInsetY());
1079 void InsetText::ToggleInsetCursor(BufferView * bv)
1081 if (the_locking_inset) {
1082 the_locking_inset->ToggleInsetCursor(bv);
1086 LyXFont font = TEXT(bv)->GetFont(bv->buffer(), cpar(bv), cpos(bv));
1088 int asc = lyxfont::maxAscent(font);
1089 int desc = lyxfont::maxDescent(font);
1092 bv->hideLockedInsetCursor();
1094 bv->showLockedInsetCursor(cx(bv), cy(bv), asc, desc);
1095 cursor_visible = !cursor_visible;
1099 void InsetText::ShowInsetCursor(BufferView * bv)
1101 if (the_locking_inset) {
1102 the_locking_inset->ShowInsetCursor(bv);
1105 if (!cursor_visible) {
1106 LyXFont font = TEXT(bv)->GetFont(bv->buffer(), cpar(bv), cpos(bv));
1108 int asc = lyxfont::maxAscent(font);
1109 int desc = lyxfont::maxDescent(font);
1111 bv->fitLockedInsetCursor(cx(bv), cy(bv), asc, desc);
1112 bv->showLockedInsetCursor(cx(bv), cy(bv), asc, desc);
1113 cursor_visible = true;
1118 void InsetText::HideInsetCursor(BufferView * bv)
1120 if (cursor_visible) {
1121 bv->hideLockedInsetCursor();
1122 cursor_visible = false;
1124 if (the_locking_inset)
1125 the_locking_inset->HideInsetCursor(bv);
1129 UpdatableInset::RESULT
1130 InsetText::moveRight(BufferView * bv, bool activate_inset, bool selecting)
1132 if (!cpar(bv)->next && (cpos(bv) >= cpar(bv)->Last()))
1134 if (activate_inset && checkAndActivateInset(bv, false))
1136 TEXT(bv)->CursorRight(bv, selecting);
1137 return DISPATCHED_NOUPDATE;
1141 UpdatableInset::RESULT
1142 InsetText::moveLeft(BufferView * bv, bool activate_inset, bool selecting)
1144 if (!cpar(bv)->previous && (cpos(bv) <= 0))
1146 TEXT(bv)->CursorLeft(bv, selecting);
1147 if (activate_inset && checkAndActivateInset(bv, true))
1149 return DISPATCHED_NOUPDATE;
1153 UpdatableInset::RESULT
1154 InsetText::moveUp(BufferView * bv)
1156 if (!crow(bv)->previous())
1158 TEXT(bv)->CursorUp(bv);
1159 return DISPATCHED_NOUPDATE;
1163 UpdatableInset::RESULT
1164 InsetText::moveDown(BufferView * bv)
1166 if (!crow(bv)->next())
1168 TEXT(bv)->CursorDown(bv);
1169 return DISPATCHED_NOUPDATE;
1173 bool InsetText::InsertInset(BufferView * bv, Inset * inset)
1175 if (the_locking_inset) {
1176 if (the_locking_inset->InsertInsetAllowed(inset))
1177 return the_locking_inset->InsertInset(bv, inset);
1180 bv->text->SetUndo(bv->buffer(), Undo::INSERT,
1182 bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->previous,
1183 bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->next
1185 bv->text->cursor.par()->previous,
1186 bv->text->cursor.par()->next
1189 if (inset->Editable() == Inset::IS_EDITABLE) {
1190 UpdatableInset * i = static_cast<UpdatableInset *>(inset);
1191 i->setOwner(static_cast<UpdatableInset *>(this));
1193 TEXT(bv)->InsertInset(bv, inset);
1194 TEXT(bv)->selection = 0;
1195 UpdateLocal(bv, CURSOR_PAR, true);
1196 static_cast<UpdatableInset*>(inset)->Edit(bv, 0, 0, 0);
1201 UpdatableInset * InsetText::GetLockingInset()
1203 return the_locking_inset ? the_locking_inset->GetLockingInset() : this;
1207 UpdatableInset * InsetText::GetFirstLockingInsetOfType(Inset::Code c)
1211 if (the_locking_inset)
1212 return the_locking_inset->GetFirstLockingInsetOfType(c);
1217 void InsetText::SetFont(BufferView * bv, LyXFont const & font, bool toggleall)
1219 TEXT(bv)->SetFont(bv, font, toggleall);
1223 bool InsetText::checkAndActivateInset(BufferView * bv, bool behind)
1225 if (cpar(bv)->GetChar(cpos(bv)) == LyXParagraph::META_INSET) {
1228 static_cast<UpdatableInset*>(cpar(bv)->GetInset(cpos(bv)));
1229 if (!inset || inset->Editable() != Inset::HIGHLY_EDITABLE)
1231 LyXFont font = TEXT(bv)->GetFont(bv->buffer(), cpar(bv), cpos(bv));
1233 x = inset->width(bv, font);
1234 y = inset->descent(bv, font);
1238 inset_x = cx(bv) - top_x + drawTextXOffset;
1239 inset_y = cy(bv) + drawTextYOffset;
1240 inset->Edit(bv, x-inset_x, y-inset_y, 0);
1241 if (!the_locking_inset)
1243 UpdateLocal(bv, CURSOR_PAR, false);
1250 bool InsetText::checkAndActivateInset(BufferView * bv, int x, int y,
1253 int tmp_x = x - drawTextXOffset;
1254 int tmp_y = y + insetAscent;
1255 Inset * inset = bv->checkInsetHit(TEXT(bv), tmp_x, tmp_y, button);
1262 inset_x = cx(bv) - top_x + drawTextXOffset;
1263 inset_y = cy(bv) + drawTextYOffset;
1264 inset->Edit(bv, x - inset_x, y - inset_y, button);
1265 if (!the_locking_inset)
1267 UpdateLocal(bv, CURSOR_PAR, false);
1274 int InsetText::getMaxWidth(Painter & pain, UpdatableInset const * inset) const
1276 int w = UpdatableInset::getMaxWidth(pain, inset);
1281 w = w - top_x + owner()->x();
1284 w -= (2 * TEXT_TO_INSET_OFFSET);
1286 // return w - (2*TEXT_TO_INSET_OFFSET);
1290 void InsetText::SetParagraphData(LyXParagraph *p)
1304 par->SetInsetOwner(this);
1308 np->next = p->Clone();
1309 np->next->previous = np;
1311 np->SetInsetOwner(this);
1317 void InsetText::SetAutoBreakRows(bool flag)
1319 if (flag != autoBreakRows) {
1320 autoBreakRows = flag;
1328 void InsetText::SetDrawFrame(BufferView * bv, DrawFrame how)
1330 if (how != drawFrame) {
1333 UpdateLocal(bv, DRAW_FRAME, false);
1338 void InsetText::SetFrameColor(BufferView * bv, LColor::color col)
1340 if (frame_color != col) {
1343 UpdateLocal(bv, DRAW_FRAME, false);
1348 LyXFont InsetText::GetDrawFont(BufferView * bv, LyXParagraph * p, int pos) const
1350 return TEXT(bv)->GetFont(bv->buffer(), p, pos);
1354 int InsetText::cx(BufferView * bv) const
1356 return TEXT(bv)->cursor.x() + top_x + TEXT_TO_INSET_OFFSET;
1360 int InsetText::cy(BufferView * bv) const
1363 return TEXT(bv)->cursor.y() - ascent(bv, font) + TEXT_TO_INSET_OFFSET;
1367 int InsetText::cpos(BufferView * bv) const
1369 return TEXT(bv)->cursor.pos();
1373 LyXParagraph * InsetText::cpar(BufferView * bv) const
1375 return TEXT(bv)->cursor.par();
1379 Row * InsetText::crow(BufferView * bv) const
1381 return TEXT(bv)->cursor.row();
1385 LyXText * InsetText::getLyXText(BufferView * bv) const
1387 if (cache.find(bv) != cache.end())
1389 LyXText * lt = new LyXText(const_cast<InsetText *>(this));
1392 if (the_locking_inset) {
1393 lt->SetCursor(bv, inset_par, inset_pos);
1399 void InsetText::deleteLyXText(BufferView * bv, bool recursive) const
1401 if (cache.find(bv) == cache.end())
1406 /// then remove all LyXText in text-insets
1407 LyXParagraph * p = par;
1408 for(;p;p = p->next) {
1409 p->deleteInsetsLyXText(bv);
1415 void InsetText::resizeLyXText(BufferView * bv) const
1417 if (!par->next && !par->size()) // resize not neccessary!
1419 if (cache.find(bv) == cache.end())
1422 LyXParagraph * lpar = 0;
1423 LyXParagraph * selstartpar = 0;
1424 LyXParagraph * selendpar = 0;
1426 int selstartpos = 0;
1431 // ProhibitInput(bv);
1434 lpar = TEXT(bv)->cursor.par();
1435 pos = TEXT(bv)->cursor.pos();
1436 selstartpar = TEXT(bv)->sel_start_cursor.par();
1437 selstartpos = TEXT(bv)->sel_start_cursor.pos();
1438 selendpar = TEXT(bv)->sel_end_cursor.par();
1439 selendpos = TEXT(bv)->sel_end_cursor.pos();
1440 selection = TEXT(bv)->selection;
1441 mark_set = TEXT(bv)->mark_set;
1443 deleteLyXText(bv, (the_locking_inset == 0));
1446 TEXT(bv)->selection = true;
1447 /* at this point just to avoid the Delete-Empty-Paragraph
1448 * Mechanism when setting the cursor */
1449 TEXT(bv)->mark_set = mark_set;
1451 TEXT(bv)->SetCursor(bv, selstartpar, selstartpos);
1452 TEXT(bv)->sel_cursor = TEXT(bv)->cursor;
1453 TEXT(bv)->SetCursor(bv, selendpar, selendpos);
1454 TEXT(bv)->SetSelection();
1455 TEXT(bv)->SetCursor(bv, lpar, pos);
1457 TEXT(bv)->SetCursor(bv, lpar, pos);
1458 TEXT(bv)->sel_cursor = TEXT(bv)->cursor;
1459 TEXT(bv)->selection = false;
1463 TEXT(bv)->first = bv->screen()->TopCursorVisible(TEXT(bv));
1464 // this will scroll the screen such that the cursor becomes visible
1465 bv->updateScrollbar();
1467 if (the_locking_inset) {
1468 /// then resize all LyXText in text-insets
1469 inset_x = cx(bv) - top_x + drawTextXOffset;
1470 inset_y = cy(bv) + drawTextYOffset;
1471 for(LyXParagraph * p = par; p; p = p->next) {
1472 p->resizeInsetsLyXText(bv);
1479 void InsetText::removeNewlines()
1481 for(LyXParagraph * p = par; p; p = p->next) {
1482 for(int i = 0; i < p->Last(); ++i) {
1483 if (p->GetChar(i) == LyXParagraph::META_NEWLINE)