1 /* This file is part of
2 * ======================================================
4 * LyX, The Document Processor
6 * Copyright 1998-2001 The LyX Team.
8 * ======================================================
20 #pragma implementation
23 #include "insettext.h"
24 #include "paragraph.h"
28 #include "commandtags.h"
31 #include "BufferView.h"
33 #include "LaTeXFeatures.h"
35 #include "frontends/Alert.h"
37 #include "lyxcursor.h"
38 #include "CutAndPaste.h"
41 #include "support/textutils.h"
42 #include "support/LAssert.h"
43 #include "support/lstrings.h"
47 #include "trans_mgr.h"
48 #include "lyxscreen.h"
52 #include "ParagraphParameters.h"
53 #include "undo_funcs.h"
66 extern unsigned char getCurrentTextClass(Buffer *);
67 extern bool math_insert_greek(BufferView *, char);
68 extern int greek_kb_flag;
71 // These functions should probably go into bufferview_funcs somehow (Jug)
73 void InsetText::saveLyXTextState(LyXText * t) const
75 // check if my paragraphs are still valid
78 if (p == t->cursor.par())
83 if (p && t->cursor.pos() <= p->size()) {
84 sstate.lpar = t->cursor.par();
85 sstate.pos = t->cursor.pos();
86 sstate.boundary = t->cursor.boundary();
87 sstate.selstartpar = t->selection.start.par();
88 sstate.selstartpos = t->selection.start.pos();
89 sstate.selstartboundary = t->selection.start.boundary();
90 sstate.selendpar = t->selection.end.par();
91 sstate.selendpos = t->selection.end.pos();
92 sstate.selendboundary = t->selection.end.boundary();
93 sstate.selection = t->selection.set();
94 sstate.mark_set = t->selection.mark();
95 sstate.refresh = t->refresh_row != 0;
101 void InsetText::restoreLyXTextState(BufferView * bv, LyXText * t) const
104 t->selection.set(true);
105 /* at this point just to avoid the Delete-Empty-Paragraph
106 * Mechanism when setting the cursor */
107 t->selection.mark(sstate.mark_set);
108 if (sstate.selection) {
109 t->setCursor(bv, sstate.selstartpar, sstate.selstartpos,
110 true, sstate.selstartboundary);
111 t->selection.cursor = t->cursor;
112 t->setCursor(bv, sstate.selendpar, sstate.selendpos,
113 true, sstate.selendboundary);
115 t->setCursor(bv, sstate.lpar, sstate.pos);
117 t->setCursor(bv, sstate.lpar, sstate.pos, true, sstate.boundary);
118 t->selection.cursor = t->cursor;
119 t->selection.set(false);
121 if (sstate.refresh) {
127 InsetText::InnerCache::InnerCache(boost::shared_ptr<LyXText> t)
134 InsetText::InsetText()
135 : UpdatableInset(), lt(0), in_update(false), do_resize(0),
143 InsetText::InsetText(InsetText const & in, bool same_id)
144 : UpdatableInset(in, same_id), lt(0), in_update(false), do_resize(0),
152 InsetText & InsetText::operator=(InsetText const & it)
159 void InsetText::init(InsetText const * ins, bool same_id)
162 setParagraphData(ins->par);
163 autoBreakRows = ins->autoBreakRows;
164 drawFrame_ = ins->drawFrame_;
165 frame_color = ins->frame_color;
171 p->setInsetOwner(this);
174 the_locking_inset = 0;
176 frame_color = LColor::insetframe;
177 autoBreakRows = false;
186 no_selection = false;
193 last_drawn_width = -1;
194 frame_is_visible = false;
200 InsetText::~InsetText()
207 Paragraph * tmp = par->next();
214 void InsetText::clear()
217 Paragraph * tmp = par->next();
226 Inset * InsetText::clone(Buffer const &, bool same_id) const
228 return new InsetText(*this, same_id);
232 void InsetText::write(Buffer const * buf, ostream & os) const
235 writeParagraphData(buf, os);
239 void InsetText::writeParagraphData(Buffer const * buf, ostream & os) const
241 par->writeFile(buf, os, buf->params, 0);
245 void InsetText::read(Buffer const * buf, LyXLex & lex)
249 Paragraph * return_par = 0;
250 Paragraph::depth_type depth = 0;
251 LyXFont font(LyXFont::ALL_INHERIT);
257 token = lex.getString();
260 if (token == "\\end_inset") {
261 #ifndef NO_COMPABILITY
262 const_cast<Buffer*>(buf)->insertErtContents(par, pos, font, false);
267 if (const_cast<Buffer*>(buf)->
268 parseSingleLyXformat2Token(lex, par, return_par,
269 token, pos, depth, font)) {
270 // the_end read this should NEVER happen
271 lex.printError("\\the_end read in inset! Error in document!");
279 return_par->setInsetOwner(this);
280 return_par = return_par->next();
283 if (token != "\\end_inset") {
284 lex.printError("Missing \\end_inset at this point. "
291 int InsetText::ascent(BufferView * bv, LyXFont const &) const
294 Row * row = getLyXText(bv)->getRowNearY(y_temp);
295 insetAscent = row->ascent_of_text() + TEXT_TO_INSET_OFFSET;
300 int InsetText::descent(BufferView * bv, LyXFont const &) const
308 Row * row = lt->getRowNearY(y_temp);
309 insetDescent = lt->height - row->ascent_of_text() +
310 TEXT_TO_INSET_OFFSET;
317 int InsetText::width(BufferView * bv, LyXFont const &) const
319 insetWidth = max(textWidth(bv), (int)getLyXText(bv)->width) +
320 (2 * TEXT_TO_INSET_OFFSET);
321 insetWidth = max(insetWidth, 10);
326 int InsetText::textWidth(BufferView * bv, bool fordraw) const
329 if (!autoBreakRows) {
332 w = getMaxWidth(bv, this);
335 return max(w - (2 * TEXT_TO_INSET_OFFSET),
336 (int)getLyXText(bv)->width);
340 return w - (2 * TEXT_TO_INSET_OFFSET);
344 void InsetText::draw(BufferView * bv, LyXFont const & f,
345 int baseline, float & x, bool cleared) const
350 Painter & pain = bv->painter();
352 // this is the first thing we have to ask because if the x pos
353 // changed we have to do a complete rebreak of the text as we
354 // may have few space to draw in. Well we should check on this too
356 if (top_x != int(x)) {
358 int nw = getMaxWidth(bv, this);
359 if (nw > 0 && old_max_width != nw) {
362 bv->text->status(bv, LyXText::CHANGED_IN_DRAW);
370 // repaint the background if needed
371 if (cleared && backgroundColor() != LColor::background) {
373 clearInset(pain, baseline, cleared);
377 // no draw is necessary !!!
378 if ((drawFrame_ == LOCKED) && !locked && !par->size()) {
381 top_baseline = baseline;
383 if (need_update & CLEAR_FRAME)
384 clearFrame(pain, cleared);
391 x += static_cast<float>(scroll());
393 // if top_x differs we did it already
394 if (!cleared && (top_x == int(x)) &&
395 ((need_update&(INIT|FULL)) || (top_baseline!=baseline) ||
396 (last_drawn_width!=insetWidth))) {
397 clearInset(pain, baseline, cleared);
403 frame_is_visible = false;
405 if (!cleared && (need_update == NONE)) {
407 drawFrame(pain, cleared);
411 top_baseline = baseline;
412 top_y = baseline - ascent(bv, f);
413 last_width = width(bv, f);
414 last_height = ascent(bv, f) + descent(bv, f);
416 if (cleared || (last_drawn_width != insetWidth)) {
418 clearInset(pain, baseline, cleared);
420 last_drawn_width = insetWidth;
423 if (the_locking_inset && (cpar(bv) == inset_par)
424 && (cpos(bv) == inset_pos)) {
425 inset_x = cx(bv) - top_x + drawTextXOffset;
426 inset_y = cy(bv) + drawTextYOffset;
428 if (!cleared && (need_update == CURSOR)
429 && !getLyXText(bv)->selection.set()) {
430 drawFrame(pain, cleared);
431 x += last_width; // was width(bv, f);
440 x += TEXT_TO_INSET_OFFSET;
443 Row * row = lt->getRowNearY(y);
444 int y_offset = baseline - row->ascent_of_text();
445 int ph = pain.paperHeight();
448 while ((row != 0) && ((y+row->height()) <= 0)) {
450 first += row->height();
456 if (cleared || (need_update&(INIT|FULL))) {
459 while ((row != 0) && (yf < ph)) {
460 lt->getVisibleRow(bv, y+y_offset, int(x), row,
466 } else if (!locked) {
467 if (need_update & CURSOR) {
468 bv->screen()->toggleSelection(lt, bv, true, y_offset,int(x));
469 lt->clearSelection();
470 lt->selection.cursor = lt->cursor;
472 bv->screen()->update(lt, bv, y_offset, int(x));
475 if (need_update & SELECTION) {
476 bv->screen()->toggleToggle(lt, bv, y_offset, int(x));
477 } else if (need_update & CURSOR) {
478 bv->screen()->toggleSelection(lt, bv, true, y_offset,int(x));
479 lt->clearSelection();
480 lt->selection.cursor = lt->cursor;
482 bv->screen()->update(lt, bv, y_offset, int(x));
487 lt->status(bv, LyXText::UNCHANGED);
488 if ((need_update != CURSOR_PAR) &&
489 ((drawFrame_ == ALWAYS) || ((drawFrame_ == LOCKED) && locked))) {
490 drawFrame(pain, cleared);
491 } else if (need_update & CLEAR_FRAME) {
492 clearFrame(pain, cleared);
495 x += last_width /* was width(bv, f) */ - TEXT_TO_INSET_OFFSET;
497 if (bv->text->status() == LyXText::CHANGED_IN_DRAW) {
499 } else if (need_update != INIT) {
508 void InsetText::drawFrame(Painter & pain, bool cleared) const
510 static int const ttoD2 = TEXT_TO_INSET_OFFSET / 2;
511 if (!frame_is_visible || cleared) {
512 frame_x = top_x + ttoD2;
513 frame_y = top_baseline - insetAscent + ttoD2;
514 frame_w = last_width - TEXT_TO_INSET_OFFSET;
515 frame_h = insetAscent + insetDescent - TEXT_TO_INSET_OFFSET;
516 pain.rectangle(frame_x, frame_y,
519 frame_is_visible = true;
524 void InsetText::clearFrame(Painter & pain, bool cleared) const
526 if (frame_is_visible) {
528 pain.rectangle(frame_x, frame_y, frame_w, frame_h,
531 frame_is_visible = false;
536 void InsetText::update(BufferView * bv, LyXFont const & font, bool reinit)
539 if (reinit && owner()) {
541 owner()->update(bv, font, true);
546 if (reinit || need_update == INIT) {
550 owner()->update(bv, font, true);
554 if (the_locking_inset) {
555 inset_x = cx(bv) - top_x + drawTextXOffset;
556 inset_y = cy(bv) + drawTextYOffset;
557 the_locking_inset->update(bv, font, reinit);
566 int oldw = insetWidth;
567 insetWidth = lt->width + (2 * TEXT_TO_INSET_OFFSET);
568 if (oldw != insetWidth) {
577 if ((need_update & CURSOR_PAR) && (lt->status() == LyXText::UNCHANGED) &&
580 lt->updateInset(bv, the_locking_inset);
582 if (lt->status() == LyXText::NEED_MORE_REFRESH)
590 void InsetText::setUpdateStatus(BufferView * bv, int what) const
598 // we have to redraw us full if our LyXText NEEDS_MORE_REFRES or
599 // if we don't break row so that we only have one row to update!
600 if ((lt->status() == LyXText::NEED_MORE_REFRESH) ||
602 (lt->status() == LyXText::NEED_VERY_LITTLE_REFRESH)))
605 } else if (lt->status() == LyXText::NEED_VERY_LITTLE_REFRESH) {
606 need_update |= CURSOR_PAR;
609 // this to not draw a selection when we redraw all of it!
610 if (need_update & CURSOR && !(need_update & SELECTION)) {
611 if (lt->selection.set())
613 lt->clearSelection();
620 void InsetText::updateLocal(BufferView * bv, int what, bool mark_dirty) const
628 setUpdateStatus(bv, what);
629 if (((need_update != CURSOR) && (need_update != NONE)) ||
630 (lt->status() != LyXText::UNCHANGED) || lt->selection.set())
632 bv->updateInset(const_cast<InsetText *>(this), mark_dirty);
634 if (need_update == CURSOR)
636 bv->owner()->showState();
637 if (old_par != cpar(bv)) {
638 bv->owner()->setLayout(cpar(bv)->getLayout());
646 string const InsetText::editMessage() const
648 return _("Opened Text Inset");
652 void InsetText::edit(BufferView * bv, int x, int y, unsigned int button)
654 UpdatableInset::edit(bv, x, y, button);
656 if (!bv->lockInset(this)) {
657 lyxerr[Debug::INSETS] << "Cannot lock inset" << endl;
661 the_locking_inset = 0;
662 inset_pos = inset_x = inset_y = 0;
663 inset_boundary = false;
666 int tmp_y = (y < 0) ? 0 : y;
673 if (!checkAndActivateInset(bv, x, tmp_y, button))
674 lt->setCursorFromCoordinates(bv, x - drawTextXOffset,
676 lt->clearSelection();
679 updateLocal(bv, CURSOR, false);
681 // If the inset is empty set the language of the current font to the
682 // language to the surronding text (if different).
683 if (par->size() == 0 && !par->next() &&
684 bv->getParentLanguage(this) != lt->current_font.language()) {
685 LyXFont font(LyXFont::ALL_IGNORE);
686 font.setLanguage(bv->getParentLanguage(this));
687 setFont(bv, font, false);
694 void InsetText::edit(BufferView * bv, bool front)
696 UpdatableInset::edit(bv, front);
698 if (!bv->lockInset(this)) {
699 lyxerr[Debug::INSETS] << "Cannot lock inset" << endl;
703 the_locking_inset = 0;
704 inset_pos = inset_x = inset_y = 0;
705 inset_boundary = false;
714 lt->setCursor(bv, par, 0);
719 // int const pos = (p->size() ? p->size()-1 : p->size());
720 lt->setCursor(bv, p, p->size());
722 lt->clearSelection();
725 updateLocal(bv, CURSOR, false);
727 // If the inset is empty set the language of the current font to the
728 // language to the surronding text (if different).
729 if (par->size() == 0 && !par->next() &&
730 bv->getParentLanguage(this) != lt->current_font.language()) {
731 LyXFont font(LyXFont::ALL_IGNORE);
732 font.setLanguage(bv->getParentLanguage(this));
733 setFont(bv, font, false);
740 void InsetText::insetUnlock(BufferView * bv)
742 if (the_locking_inset) {
743 the_locking_inset->insetUnlock(bv);
744 the_locking_inset = 0;
747 no_selection = false;
750 if (drawFrame_ == LOCKED)
751 code = CURSOR|CLEAR_FRAME;
759 if (lt->selection.set()) {
760 lt->clearSelection();
762 } else if (owner()) {
763 bv->owner()->setLayout(owner()->getLyXText(bv)
764 ->cursor.par()->getLayout());
766 bv->owner()->setLayout(bv->text->cursor.par()->getLayout());
767 // hack for deleteEmptyParMech
768 lt->setCursor(bv, par, 0);
769 updateLocal(bv, code, false);
775 bool InsetText::lockInsetInInset(BufferView * bv, UpdatableInset * inset)
777 lyxerr[Debug::INSETS] << "InsetText::LockInsetInInset("
781 if (inset == cpar(bv)->getInset(cpos(bv))) {
782 lyxerr[Debug::INSETS] << "OK" << endl;
783 the_locking_inset = inset;
784 inset_x = cx(bv) - top_x + drawTextXOffset;
785 inset_y = cy(bv) + drawTextYOffset;
786 inset_pos = cpos(bv);
787 inset_par = cpar(bv);
788 inset_boundary = cboundary(bv);
789 updateLocal(bv, CURSOR, false);
791 } else if (the_locking_inset && (the_locking_inset == inset)) {
792 if (cpar(bv) == inset_par && cpos(bv) == inset_pos) {
793 lyxerr[Debug::INSETS] << "OK" << endl;
794 inset_x = cx(bv) - top_x + drawTextXOffset;
795 inset_y = cy(bv) + drawTextYOffset;
797 lyxerr[Debug::INSETS] << "cursor.pos != inset_pos" << endl;
799 } else if (the_locking_inset) {
800 lyxerr[Debug::INSETS] << "MAYBE" << endl;
801 return the_locking_inset->lockInsetInInset(bv, inset);
803 lyxerr[Debug::INSETS] << "NOT OK" << endl;
808 bool InsetText::unlockInsetInInset(BufferView * bv, UpdatableInset * inset,
811 if (!the_locking_inset)
813 if (the_locking_inset == inset) {
814 the_locking_inset->insetUnlock(bv);
815 getLyXText(bv)->updateInset(bv, inset);
816 the_locking_inset = 0;
818 moveRight(bv, false);
819 old_par = 0; // force layout setting
823 updateLocal(bv, CURSOR, false);
826 return the_locking_inset->unlockInsetInInset(bv, inset, lr);
830 bool InsetText::updateInsetInInset(BufferView * bv, Inset * inset)
832 if (!the_locking_inset)
834 if (the_locking_inset != inset) {
835 getLyXText(bv)->updateInset(bv, the_locking_inset);
836 setUpdateStatus(bv, CURSOR_PAR);
837 return the_locking_inset->updateInsetInInset(bv, inset);
839 if (getLyXText(bv)->updateInset(bv, inset))
840 updateLocal(bv, CURSOR_PAR, false);
841 if (cpar(bv) == inset_par && cpos(bv) == inset_pos) {
842 inset_x = cx(bv) - top_x + drawTextXOffset;
843 inset_y = cy(bv) + drawTextYOffset;
849 void InsetText::insetButtonPress(BufferView * bv, int x, int y, int button)
853 int tmp_x = x - drawTextXOffset;
854 int tmp_y = y + insetAscent - getLyXText(bv)->first;
855 Inset * inset = bv->checkInsetHit(getLyXText(bv), tmp_x, tmp_y, button);
858 if (the_locking_inset) {
859 if (the_locking_inset == inset) {
860 the_locking_inset->insetButtonPress(bv,x-inset_x,y-inset_y,button);
861 no_selection = false;
864 // otherwise unlock the_locking_inset and lock the new inset
865 the_locking_inset->insetUnlock(bv);
866 inset_x = cx(bv) - top_x + drawTextXOffset;
867 inset_y = cy(bv) + drawTextYOffset;
868 the_locking_inset = static_cast<UpdatableInset*>(inset);
869 inset->insetButtonPress(bv, x - inset_x, y - inset_y, button);
870 inset->edit(bv, x - inset_x, y - inset_y, button);
871 if (the_locking_inset)
872 updateLocal(bv, CURSOR, false);
873 no_selection = false;
876 // otherwise only unlock the_locking_inset
877 the_locking_inset->insetUnlock(bv);
878 the_locking_inset = 0;
880 if (bv->theLockingInset()) {
881 if (isHighlyEditableInset(inset)) {
882 UpdatableInset * uinset = static_cast<UpdatableInset*>(inset);
883 inset_x = cx(bv) - top_x + drawTextXOffset;
884 inset_y = cy(bv) + drawTextYOffset;
885 inset_pos = cpos(bv);
886 inset_par = cpar(bv);
887 inset_boundary = cboundary(bv);
888 the_locking_inset = uinset;
889 uinset->insetButtonPress(bv, x - inset_x, y - inset_y,
891 uinset->edit(bv, x - inset_x, y - inset_y, 0);
892 if (the_locking_inset)
893 updateLocal(bv, CURSOR, false);
894 no_selection = false;
898 if (!inset) { // && (button == 2)) {
899 bool paste_internally = false;
900 if ((button == 2) && getLyXText(bv)->selection.set()) {
901 localDispatch(bv, LFUN_COPY, "");
902 paste_internally = true;
909 lt->setCursorFromCoordinates(bv, x-drawTextXOffset, y + insetAscent);
910 if (lt->selection.set()) {
911 lt->clearSelection();
912 updateLocal(bv, FULL, false);
914 lt->clearSelection();
916 bv->owner()->setLayout(cpar(bv)->getLayout());
918 // Insert primary selection with middle mouse
919 // if there is a local selection in the current buffer,
922 if (paste_internally)
923 localDispatch(bv, LFUN_PASTE, "");
925 localDispatch(bv, LFUN_PASTESELECTION,
932 no_selection = false;
936 void InsetText::insetButtonRelease(BufferView * bv, int x, int y, int button)
938 UpdatableInset * inset = 0;
940 if (the_locking_inset) {
941 the_locking_inset->insetButtonRelease(bv,
942 x - inset_x, y - inset_y,
945 if (cpar(bv)->isInset(cpos(bv))) {
946 inset = static_cast<UpdatableInset*>(cpar(bv)->getInset(cpos(bv)));
947 if (isHighlyEditableInset(inset)) {
948 inset->insetButtonRelease(bv,
950 y - inset_y, button);
952 inset_x = cx(bv) - top_x + drawTextXOffset;
953 inset_y = cy(bv) + drawTextYOffset;
954 inset->insetButtonRelease(bv,
956 y - inset_y, button);
958 x - inset_x, y - inset_y, button);
960 updateLocal(bv, CURSOR_PAR, false);
963 no_selection = false;
967 void InsetText::insetMotionNotify(BufferView * bv, int x, int y, int state)
971 if (the_locking_inset) {
972 the_locking_inset->insetMotionNotify(bv, x - inset_x,
976 LyXText * t = getLyXText(bv);
978 t->setCursorFromCoordinates(bv, x - drawTextXOffset, y + insetAscent);
980 if (t->toggle_cursor.par() != t->toggle_end_cursor.par() ||
981 t->toggle_cursor.pos() != t->toggle_end_cursor.pos())
982 updateLocal(bv, SELECTION, false);
987 void InsetText::insetKeyPress(XKeyEvent * xke)
989 if (the_locking_inset) {
990 the_locking_inset->insetKeyPress(xke);
996 UpdatableInset::RESULT
997 InsetText::localDispatch(BufferView * bv,
998 kb_action action, string const & arg)
1000 bool was_empty = par->size() == 0 && !par->next();
1001 no_selection = false;
1002 UpdatableInset::RESULT
1003 result= UpdatableInset::localDispatch(bv, action, arg);
1004 if (result != UNDISPATCHED) {
1008 result = DISPATCHED;
1009 if ((action < 0) && arg.empty())
1012 if (the_locking_inset) {
1013 result = the_locking_inset->localDispatch(bv, action, arg);
1014 if (result == DISPATCHED_NOUPDATE)
1016 else if (result == DISPATCHED) {
1017 updateLocal(bv, CURSOR_PAR, false);
1019 } else if (result >= FINISHED) {
1021 case FINISHED_RIGHT:
1022 moveRightIntern(bv, false, false);
1023 result = DISPATCHED;
1026 if ((result = moveUp(bv)) >= FINISHED) {
1027 updateLocal(bv, CURSOR, false);
1028 bv->unlockInset(this);
1032 if ((result = moveDown(bv)) >= FINISHED) {
1033 updateLocal(bv, CURSOR, false);
1034 bv->unlockInset(this);
1038 result = DISPATCHED;
1041 the_locking_inset = 0;
1042 #ifdef WITH_WARNINGS
1043 #warning I changed this to always return Dispatched maybe it is wrong (20011001 Jug)
1048 hideInsetCursor(bv);
1051 lt = getLyXText(bv);
1056 case LFUN_SELFINSERT:
1057 if (bv->buffer()->isReadonly()) {
1058 // setErrorMessage(N_("Document is read only"));
1062 /* Automatically delete the currently selected
1063 * text and replace it with what is being
1064 * typed in now. Depends on lyxrc settings
1065 * "auto_region_delete", which defaults to
1068 setUndo(bv, Undo::INSERT,
1069 lt->cursor.par(), lt->cursor.par()->next());
1071 if (lyxrc.auto_region_delete) {
1072 if (lt->selection.set()) {
1073 lt->cutSelection(bv, false);
1076 lt->clearSelection();
1077 for (string::size_type i = 0; i < arg.length(); ++i) {
1078 bv->owner()->getIntl()->getTrans().TranslateAndInsert(arg[i], lt);
1081 lt->selection.cursor = lt->cursor;
1082 updateLocal(bv, CURSOR_PAR, true);
1083 result = DISPATCHED_NOUPDATE;
1085 // --- Cursor Movements -----------------------------------
1088 moveRight(bv, false, true);
1089 lt->setSelection(bv);
1090 updateLocal(bv, SELECTION, false);
1093 result = moveRight(bv);
1095 updateLocal(bv, CURSOR, false);
1099 moveLeft(bv, false, true);
1100 lt->setSelection(bv);
1101 updateLocal(bv, SELECTION, false);
1105 result = moveLeft(bv);
1106 updateLocal(bv, CURSOR, false);
1111 lt->setSelection(bv);
1112 updateLocal(bv, SELECTION, false);
1116 result = moveDown(bv);
1117 updateLocal(bv, CURSOR, false);
1122 lt->setSelection(bv);
1123 updateLocal(bv, SELECTION, false);
1127 result = moveUp(bv);
1128 updateLocal(bv, CURSOR, false);
1133 updateLocal(bv, CURSOR, false);
1137 updateLocal(bv, CURSOR, false);
1139 case LFUN_BACKSPACE: {
1140 setUndo(bv, Undo::DELETE,
1141 lt->cursor.par(), lt->cursor.par()->next());
1142 if (lt->selection.set())
1143 lt->cutSelection(bv);
1146 updateLocal(bv, CURSOR_PAR, true);
1151 setUndo(bv, Undo::DELETE,
1152 lt->cursor.par(), lt->cursor.par()->next());
1153 if (lt->selection.set()) {
1154 lt->cutSelection(bv);
1158 updateLocal(bv, CURSOR_PAR, true);
1163 setUndo(bv, Undo::DELETE,
1164 lt->cursor.par(), lt->cursor.par()->next());
1165 lt->cutSelection(bv);
1166 updateLocal(bv, CURSOR_PAR, true);
1172 lt->copySelection(bv);
1173 updateLocal(bv, CURSOR_PAR, false);
1175 case LFUN_PASTESELECTION:
1177 string const clip(bv->getClipboard());
1181 if (arg == "paragraph") {
1182 lt->insertStringAsParagraphs(bv, clip);
1184 lt->insertStringAsLines(bv, clip);
1186 updateLocal(bv, CURSOR_PAR, true);
1190 if (!autoBreakRows) {
1192 if (CutAndPaste::nrOfParagraphs() > 1) {
1193 Alert::alert(_("Impossible operation"),
1194 _("Cannot include more than one paragraph!"),
1199 setUndo(bv, Undo::INSERT,
1200 lt->cursor.par(), lt->cursor.par()->next());
1201 lt->pasteSelection(bv);
1202 updateLocal(bv, CURSOR_PAR, true);
1206 case LFUN_BREAKPARAGRAPH:
1207 if (!autoBreakRows) {
1208 result = DISPATCHED;
1211 lt->breakParagraph(bv, 0);
1212 updateLocal(bv, FULL, true);
1214 case LFUN_BREAKPARAGRAPHKEEPLAYOUT:
1215 if (!autoBreakRows) {
1216 result = DISPATCHED;
1219 lt->breakParagraph(bv, 1);
1220 updateLocal(bv, FULL, true);
1223 case LFUN_BREAKLINE: {
1224 if (!autoBreakRows) {
1225 result = DISPATCHED;
1228 setUndo(bv, Undo::INSERT,
1229 lt->cursor.par(), lt->cursor.par()->next());
1230 lt->insertChar(bv, Paragraph::META_NEWLINE);
1231 updateLocal(bv, CURSOR_PAR, true);
1236 // do not set layouts on non breakable textinsets
1237 if (autoBreakRows) {
1238 LyXTextClass::size_type cur_layout = cpar(bv)->layout;
1240 // Derive layout number from given argument (string)
1241 // and current buffer's textclass (number). */
1242 LyXTextClassList::ClassList::size_type tclass =
1243 bv->buffer()->params.textclass;
1244 std::pair <bool, LyXTextClass::size_type> layout =
1245 textclasslist.NumberOfLayout(tclass, arg);
1247 // If the entry is obsolete, use the new one instead.
1249 string obs = textclasslist.Style(tclass,layout.second).
1252 layout = textclasslist.NumberOfLayout(tclass, obs);
1255 // see if we found the layout number:
1256 if (!layout.first) {
1257 string const msg = string(N_("Layout ")) + arg + N_(" not known");
1258 bv->owner()->getLyXFunc()->dispatch(LFUN_MESSAGE, msg);
1262 if (cur_layout != layout.second) {
1263 cur_layout = layout.second;
1264 lt->setLayout(bv, layout.second);
1265 bv->owner()->setLayout(cpar(bv)->getLayout());
1266 updateLocal(bv, CURSOR_PAR, true);
1269 // reset the layout box
1270 bv->owner()->setLayout(cpar(bv)->getLayout());
1273 case LFUN_PARAGRAPH_SPACING:
1274 // This one is absolutely not working. When fiddling with this
1275 // it also seems to me that the paragraphs inside the insettext
1276 // inherit bufferparams/paragraphparams in a strange way. (Lgb)
1278 Paragraph * par = lt->cursor.par();
1279 Spacing::Space cur_spacing = par->params().spacing().getSpace();
1280 float cur_value = 1.0;
1281 if (cur_spacing == Spacing::Other) {
1282 cur_value = par->params().spacing().getValue();
1285 istringstream istr(arg.c_str());
1288 Spacing::Space new_spacing = cur_spacing;
1289 float new_value = cur_value;
1291 lyxerr << "Missing argument to `paragraph-spacing'"
1293 } else if (tmp == "single") {
1294 new_spacing = Spacing::Single;
1295 } else if (tmp == "onehalf") {
1296 new_spacing = Spacing::Onehalf;
1297 } else if (tmp == "double") {
1298 new_spacing = Spacing::Double;
1299 } else if (tmp == "other") {
1300 new_spacing = Spacing::Other;
1303 lyxerr << "new_value = " << tmpval << endl;
1306 } else if (tmp == "default") {
1307 new_spacing = Spacing::Default;
1309 lyxerr << _("Unknown spacing argument: ")
1312 if (cur_spacing != new_spacing || cur_value != new_value) {
1313 par->params().spacing(Spacing(new_spacing, new_value));
1314 updateLocal(bv, CURSOR_PAR, true);
1320 if (!bv->Dispatch(action, arg))
1321 result = UNDISPATCHED;
1325 /// If the action has deleted all text in the inset, we need to change the
1326 // language to the language of the surronding text.
1327 if (!was_empty && par->size() == 0 && !par->next()) {
1328 LyXFont font(LyXFont::ALL_IGNORE);
1329 font.setLanguage(bv->getParentLanguage(this));
1330 setFont(bv, font, false);
1333 if (result < FINISHED) {
1334 showInsetCursor(bv);
1336 bv->unlockInset(this);
1343 int InsetText::latex(Buffer const * buf, ostream & os, bool, bool) const
1346 buf->latexParagraphs(os, par, 0, texrow);
1347 return texrow.rows();
1351 int InsetText::ascii(Buffer const * buf, ostream & os, int linelen) const
1353 Paragraph * p = par;
1354 unsigned int lines = 0;
1357 string const tmp = buf->asciiParagraph(p, linelen);
1358 lines += countChar(tmp, '\n');
1366 int InsetText::docbook(Buffer const * buf, ostream & os) const
1368 Paragraph * p = par;
1369 unsigned int lines = 0;
1371 vector<string> environment_stack(10);
1372 vector<string> environment_inner(10);
1374 int const command_depth = 0;
1377 Paragraph::depth_type depth = 0; // paragraph depth
1381 int desc_on = 0; // description mode
1383 LyXLayout const & style =
1384 textclasslist.Style(buf->params.textclass,
1387 // environment tag closing
1388 for (; depth > p->params().depth(); --depth) {
1389 if (environment_inner[depth] != "!-- --") {
1390 item_name = "listitem";
1391 buf->sgmlCloseTag(os, command_depth + depth,
1393 if (environment_inner[depth] == "varlistentry")
1394 buf->sgmlCloseTag(os, depth+command_depth,
1395 environment_inner[depth]);
1397 buf->sgmlCloseTag(os, depth + command_depth,
1398 environment_stack[depth]);
1399 environment_stack[depth].erase();
1400 environment_inner[depth].erase();
1403 if (depth == p->params().depth()
1404 && environment_stack[depth] != style.latexname()
1405 && !environment_stack[depth].empty()) {
1406 if (environment_inner[depth] != "!-- --") {
1407 item_name= "listitem";
1408 buf->sgmlCloseTag(os, command_depth+depth,
1410 if (environment_inner[depth] == "varlistentry")
1411 buf->sgmlCloseTag(os,
1412 depth + command_depth,
1413 environment_inner[depth]);
1416 buf->sgmlCloseTag(os, depth + command_depth,
1417 environment_stack[depth]);
1419 environment_stack[depth].erase();
1420 environment_inner[depth].erase();
1423 // Write opening SGML tags.
1424 switch (style.latextype) {
1425 case LATEX_PARAGRAPH:
1426 buf->sgmlOpenTag(os, depth + command_depth,
1431 buf->sgmlError(p, 0,
1432 _("Error : LatexType Command not allowed here.\n"));
1436 case LATEX_ENVIRONMENT:
1437 case LATEX_ITEM_ENVIRONMENT:
1438 if (depth < p->params().depth()) {
1439 depth = p->params().depth();
1440 environment_stack[depth].erase();
1443 if (environment_stack[depth] != style.latexname()) {
1444 if(environment_stack.size() == depth + 1) {
1445 environment_stack.push_back("!-- --");
1446 environment_inner.push_back("!-- --");
1448 environment_stack[depth] = style.latexname();
1449 environment_inner[depth] = "!-- --";
1450 buf->sgmlOpenTag(os, depth + command_depth,
1451 environment_stack[depth]);
1453 if (environment_inner[depth] != "!-- --") {
1454 item_name= "listitem";
1455 buf->sgmlCloseTag(os,
1456 command_depth + depth,
1458 if (environment_inner[depth] == "varlistentry")
1459 buf->sgmlCloseTag(os,
1460 depth + command_depth,
1461 environment_inner[depth]);
1465 if (style.latextype == LATEX_ENVIRONMENT) {
1466 if (!style.latexparam().empty()) {
1467 if(style.latexparam() == "CDATA")
1470 buf->sgmlOpenTag(os, depth + command_depth,
1471 style.latexparam());
1476 desc_on = (style.labeltype == LABEL_MANUAL);
1479 environment_inner[depth]= "varlistentry";
1481 environment_inner[depth]= "listitem";
1483 buf->sgmlOpenTag(os, depth + 1 + command_depth,
1484 environment_inner[depth]);
1488 buf->sgmlOpenTag(os, depth + 1 + command_depth,
1492 buf->sgmlOpenTag(os, depth + 1 + command_depth,
1497 buf->sgmlOpenTag(os, depth + command_depth,
1502 buf->simpleDocBookOnePar(os, p, desc_on,
1503 depth + 1 + command_depth);
1507 // write closing SGML tags
1508 switch (style.latextype) {
1509 case LATEX_ENVIRONMENT:
1510 if (!style.latexparam().empty()) {
1511 if(style.latexparam() == "CDATA")
1514 buf->sgmlCloseTag(os, depth + command_depth,
1515 style.latexparam());
1518 case LATEX_ITEM_ENVIRONMENT:
1519 if (desc_on == 1) break;
1521 buf->sgmlCloseTag(os, depth + 1 + command_depth, end_tag);
1523 case LATEX_PARAGRAPH:
1524 buf->sgmlCloseTag(os, depth + command_depth, style.latexname());
1527 buf->sgmlCloseTag(os, depth + command_depth, style.latexname());
1533 for (int d = depth; d >= 0; --d) {
1534 if (!environment_stack[depth].empty()) {
1535 if (environment_inner[depth] != "!-- --") {
1536 item_name = "listitem";
1537 buf->sgmlCloseTag(os, command_depth + depth,
1539 if (environment_inner[depth] == "varlistentry")
1540 buf->sgmlCloseTag(os, depth + command_depth,
1541 environment_inner[depth]);
1544 buf->sgmlCloseTag(os, depth + command_depth,
1545 environment_stack[depth]);
1553 void InsetText::validate(LaTeXFeatures & features) const
1555 Paragraph * p = par;
1557 p->validate(features);
1563 int InsetText::beginningOfMainBody(Buffer const * buf, Paragraph * p) const
1565 if (textclasslist.Style(buf->params.textclass,
1566 p->getLayout()).labeltype != LABEL_MANUAL)
1569 return p->beginningOfMainBody();
1573 void InsetText::getCursorPos(BufferView * bv,
1574 int & x, int & y) const
1576 if (the_locking_inset) {
1577 the_locking_inset->getCursorPos(bv, x, y);
1585 unsigned int InsetText::insetInInsetY()
1587 if (!the_locking_inset)
1590 return (inset_y + the_locking_inset->insetInInsetY());
1594 void InsetText::toggleInsetCursor(BufferView * bv)
1596 if (the_locking_inset) {
1597 the_locking_inset->toggleInsetCursor(bv);
1601 LyXFont const font(getLyXText(bv)->getFont(bv->buffer(), cpar(bv), cpos(bv)));
1603 int const asc = lyxfont::maxAscent(font);
1604 int const desc = lyxfont::maxDescent(font);
1606 if (isCursorVisible())
1607 bv->hideLockedInsetCursor();
1609 bv->showLockedInsetCursor(cx(bv), cy(bv), asc, desc);
1610 toggleCursorVisible();
1614 void InsetText::showInsetCursor(BufferView * bv, bool show)
1616 if (the_locking_inset) {
1617 the_locking_inset->showInsetCursor(bv, show);
1620 if (!isCursorVisible()) {
1621 LyXFont const font =
1622 getLyXText(bv)->getFont(bv->buffer(), cpar(bv), cpos(bv));
1624 int const asc = lyxfont::maxAscent(font);
1625 int const desc = lyxfont::maxDescent(font);
1627 bv->fitLockedInsetCursor(cx(bv), cy(bv), asc, desc);
1629 bv->showLockedInsetCursor(cx(bv), cy(bv), asc, desc);
1630 setCursorVisible(true);
1635 void InsetText::hideInsetCursor(BufferView * bv)
1637 if (isCursorVisible()) {
1638 bv->hideLockedInsetCursor();
1639 setCursorVisible(false);
1641 if (the_locking_inset)
1642 the_locking_inset->hideInsetCursor(bv);
1646 void InsetText::fitInsetCursor(BufferView * bv) const
1648 if (the_locking_inset) {
1649 the_locking_inset->fitInsetCursor(bv);
1652 LyXFont const font =
1653 getLyXText(bv)->getFont(bv->buffer(), cpar(bv), cpos(bv));
1655 int const asc = lyxfont::maxAscent(font);
1656 int const desc = lyxfont::maxDescent(font);
1658 bv->fitLockedInsetCursor(cx(bv), cy(bv), asc, desc);
1662 UpdatableInset::RESULT
1663 InsetText::moveRight(BufferView * bv, bool activate_inset, bool selecting)
1665 if (getLyXText(bv)->cursor.par()->isRightToLeftPar(bv->buffer()->params))
1666 return moveLeftIntern(bv, false, activate_inset, selecting);
1668 return moveRightIntern(bv, false, activate_inset, selecting);
1672 UpdatableInset::RESULT
1673 InsetText::moveLeft(BufferView * bv, bool activate_inset, bool selecting)
1675 if (getLyXText(bv)->cursor.par()->isRightToLeftPar(bv->buffer()->params))
1676 return moveRightIntern(bv, true, activate_inset, selecting);
1678 return moveLeftIntern(bv, true, activate_inset, selecting);
1682 UpdatableInset::RESULT
1683 InsetText::moveRightIntern(BufferView * bv, bool behind,
1684 bool activate_inset, bool selecting)
1686 if (!cpar(bv)->next() && (cpos(bv) >= cpar(bv)->size()))
1687 return FINISHED_RIGHT;
1688 if (activate_inset && checkAndActivateInset(bv, behind))
1690 getLyXText(bv)->cursorRight(bv);
1692 getLyXText(bv)->selection.cursor = getLyXText(bv)->cursor;
1693 return DISPATCHED_NOUPDATE;
1697 UpdatableInset::RESULT
1698 InsetText::moveLeftIntern(BufferView * bv, bool behind,
1699 bool activate_inset, bool selecting)
1701 if (!cpar(bv)->previous() && (cpos(bv) <= 0))
1703 getLyXText(bv)->cursorLeft(bv);
1705 getLyXText(bv)->selection.cursor = getLyXText(bv)->cursor;
1706 if (activate_inset && checkAndActivateInset(bv, behind))
1708 return DISPATCHED_NOUPDATE;
1712 UpdatableInset::RESULT
1713 InsetText::moveUp(BufferView * bv)
1715 if (!crow(bv)->previous())
1717 getLyXText(bv)->cursorUp(bv);
1718 return DISPATCHED_NOUPDATE;
1722 UpdatableInset::RESULT
1723 InsetText::moveDown(BufferView * bv)
1725 if (!crow(bv)->next())
1726 return FINISHED_DOWN;
1727 getLyXText(bv)->cursorDown(bv);
1728 return DISPATCHED_NOUPDATE;
1732 bool InsetText::insertInset(BufferView * bv, Inset * inset)
1734 if (the_locking_inset) {
1735 if (the_locking_inset->insetAllowed(inset))
1736 return the_locking_inset->insertInset(bv, inset);
1739 inset->setOwner(this);
1740 hideInsetCursor(bv);
1744 lt = getLyXText(bv);
1747 lt->insertInset(bv, inset);
1749 if ((!cpar(bv)->isInset(cpos(bv))) ||
1750 (cpar(bv)->getInset(cpos(bv)) != inset))
1754 updateLocal(bv, CURSOR_PAR|CURSOR, true);
1755 showInsetCursor(bv);
1762 bool InsetText::insetAllowed(Inset::Code code) const
1764 if (the_locking_inset)
1765 return the_locking_inset->insetAllowed(code);
1770 UpdatableInset * InsetText::getLockingInset() const
1772 return the_locking_inset ? the_locking_inset->getLockingInset() :
1773 const_cast<InsetText *>(this);
1777 UpdatableInset * InsetText::getFirstLockingInsetOfType(Inset::Code c)
1781 if (the_locking_inset)
1782 return the_locking_inset->getFirstLockingInsetOfType(c);
1787 bool InsetText::showInsetDialog(BufferView * bv) const
1789 if (the_locking_inset)
1790 return the_locking_inset->showInsetDialog(bv);
1795 std::vector<string> const InsetText::getLabelList() const
1797 std::vector<string> label_list;
1799 Paragraph * tpar = par;
1801 Paragraph::inset_iterator beg = tpar->inset_iterator_begin();
1802 Paragraph::inset_iterator end = tpar->inset_iterator_end();
1803 for (; beg != end; ++beg) {
1804 std::vector<string> const l = (*beg)->getLabelList();
1805 label_list.insert(label_list.end(), l.begin(), l.end());
1807 tpar = tpar->next();
1813 void InsetText::setFont(BufferView * bv, LyXFont const & font, bool toggleall,
1816 if (the_locking_inset) {
1817 the_locking_inset->setFont(bv, font, toggleall, selectall);
1820 if ((!par->next() && !par->size()) || !cpar(bv)->size()) {
1821 getLyXText(bv)->setFont(bv, font, toggleall);
1826 lt = getLyXText(bv);
1829 if (lt->selection.set()) {
1830 setUndo(bv, Undo::EDIT, lt->cursor.par(), lt->cursor.par()->next());
1834 lt->toggleFree(bv, font, toggleall);
1836 lt->clearSelection();
1838 if (selectall || lt->selection.set())
1839 updateLocal(bv, FULL, true);
1841 updateLocal(bv, CURSOR_PAR, true);
1847 bool InsetText::checkAndActivateInset(BufferView * bv, bool behind)
1849 if (cpar(bv)->isInset(cpos(bv))) {
1853 static_cast<UpdatableInset*>(cpar(bv)->getInset(cpos(bv)));
1854 if (!isHighlyEditableInset(inset))
1856 LyXFont const font =
1857 getLyXText(bv)->getFont(bv->buffer(), cpar(bv), cpos(bv));
1859 x = inset->width(bv, font);
1860 y = font.isRightToLeft() ? 0 : inset->descent(bv, font);
1863 y = font.isRightToLeft() ? inset->descent(bv, font) : 0;
1865 //inset_x = cx(bv) - top_x + drawTextXOffset;
1866 //inset_y = cy(bv) + drawTextYOffset;
1867 inset->edit(bv, x, y, 0);
1868 if (!the_locking_inset)
1870 updateLocal(bv, CURSOR, false);
1877 bool InsetText::checkAndActivateInset(BufferView * bv, int x, int y,
1880 x -= drawTextXOffset;
1882 int dummyy = y + insetAscent;
1883 Inset * inset = bv->checkInsetHit(getLyXText(bv), dummyx, dummyy, button);
1890 inset_x = cx(bv) - top_x + drawTextXOffset;
1891 inset_y = cy(bv) + drawTextYOffset;
1892 inset->edit(bv, x - inset_x, y - inset_y, button);
1893 if (!the_locking_inset)
1895 updateLocal(bv, CURSOR, false);
1902 int InsetText::getMaxWidth(BufferView * bv, UpdatableInset const * inset) const
1905 int w = UpdatableInset::getMaxWidth(bv, inset);
1910 w = w - top_x + owner()->x();
1913 w -= (2 * TEXT_TO_INSET_OFFSET);
1916 return UpdatableInset::getMaxWidth(bv, inset);
1921 void InsetText::setParagraphData(Paragraph * p)
1923 // we have to unlock any locked inset otherwise we're in troubles
1924 the_locking_inset = 0;
1926 Paragraph * tmp = par->next();
1931 par = new Paragraph(*p, false);
1932 par->setInsetOwner(this);
1933 Paragraph * np = par;
1936 np->next(new Paragraph(*p, false));
1937 np->next()->previous(np);
1939 np->setInsetOwner(this);
1945 void InsetText::setText(string const & data)
1948 LyXFont font(LyXFont::ALL_SANE);
1949 for (unsigned int i=0; i < data.length(); ++i)
1950 par->insertChar(i, data[i], font);
1954 void InsetText::setAutoBreakRows(bool flag)
1956 if (flag != autoBreakRows) {
1957 autoBreakRows = flag;
1965 void InsetText::setDrawFrame(BufferView * bv, DrawFrame how)
1967 if (how != drawFrame_) {
1970 updateLocal(bv, DRAW_FRAME, false);
1975 void InsetText::setFrameColor(BufferView * bv, LColor::color col)
1977 if (frame_color != col) {
1980 updateLocal(bv, DRAW_FRAME, false);
1985 int InsetText::cx(BufferView * bv) const
1989 lt = getLyXText(bv);
1992 int x = lt->cursor.x() + top_x + TEXT_TO_INSET_OFFSET;
1993 if (the_locking_inset) {
1994 LyXFont font = lt->getFont(bv->buffer(),
1997 if (font.isVisibleRightToLeft())
1998 x -= the_locking_inset->width(bv, font);
2006 int InsetText::cy(BufferView * bv) const
2009 return getLyXText(bv)->cursor.y() - ascent(bv, font) + TEXT_TO_INSET_OFFSET;
2013 pos_type InsetText::cpos(BufferView * bv) const
2015 return getLyXText(bv)->cursor.pos();
2019 Paragraph * InsetText::cpar(BufferView * bv) const
2021 return getLyXText(bv)->cursor.par();
2025 bool InsetText::cboundary(BufferView * bv) const
2027 return getLyXText(bv)->cursor.boundary();
2031 Row * InsetText::crow(BufferView * bv) const
2033 return getLyXText(bv)->cursor.row();
2037 LyXText * InsetText::getLyXText(BufferView const * lbv,
2038 bool const recursive) const
2040 if (!recursive && (cached_bview == lbv))
2041 return cached_text.get();
2043 // Super UGLY! (Lgb)
2044 BufferView * bv = const_cast<BufferView *>(lbv);
2047 Cache::iterator it = cache.find(bv);
2049 if (it != cache.end()) {
2053 resizeLyXText(do_resize);
2054 if (lt || !it->second.remove) {
2055 lyx::Assert(it->second.text.get());
2056 cached_text = it->second.text;
2057 if (recursive && the_locking_inset) {
2058 return the_locking_inset->getLyXText(bv, true);
2060 return cached_text.get();
2061 } else if (it->second.remove) {
2063 saveLyXTextState(it->second.text.get());
2070 cached_text.reset(new LyXText(const_cast<InsetText *>(this)));
2071 cached_text->init(bv);
2072 restoreLyXTextState(bv, cached_text.get());
2074 cache.insert(make_pair(bv, cached_text));
2076 if (the_locking_inset && recursive) {
2077 return the_locking_inset->getLyXText(bv);
2079 return cached_text.get();
2083 void InsetText::deleteLyXText(BufferView * bv, bool recursive) const
2087 Cache::iterator it = cache.find(bv);
2089 if (it == cache.end()) {
2093 lyx::Assert(it->second.text.get());
2095 it->second.remove = true;
2097 /// then remove all LyXText in text-insets
2098 Paragraph * p = par;
2099 for (; p; p = p->next()) {
2100 p->deleteInsetsLyXText(bv);
2106 void InsetText::resizeLyXText(BufferView * bv, bool force) const
2109 // we cannot resize this because we are in use!
2110 // so do this on the next possible getLyXText()
2115 // lyxerr << "InsetText::resizeLyXText\n";
2116 if (!par->next() && !par->size()) // no data, resize not neccessary!
2118 // one endless line, resize normally not necessary
2119 if (!force && getMaxWidth(bv, this) < 0)
2122 Cache::iterator it = cache.find(bv);
2123 if (it == cache.end()) {
2126 lyx::Assert(it->second.text.get());
2128 LyXText * t = it->second.text.get();
2129 saveLyXTextState(t);
2130 for (Paragraph * p = par; p; p = p->next()) {
2131 p->resizeInsetsLyXText(bv);
2134 restoreLyXTextState(bv, t);
2135 if (the_locking_inset) {
2136 inset_x = cx(bv) - top_x + drawTextXOffset;
2137 inset_y = cy(bv) + drawTextYOffset;
2141 t->first = bv->screen()->topCursorVisible(t);
2144 updateLocal(bv, FULL, false);
2145 // this will scroll the screen such that the cursor becomes visible
2146 bv->updateScrollbar();
2148 need_update |= FULL;
2153 void InsetText::reinitLyXText() const
2156 // we cannot resize this because we are in use!
2157 // so do this on the next possible getLyXText()
2163 // lyxerr << "InsetText::reinitLyXText\n";
2164 for(Cache::iterator it = cache.begin(); it != cache.end(); ++it) {
2165 lyx::Assert(it->second.text.get());
2167 LyXText * t = it->second.text.get();
2168 BufferView * bv = it->first;
2170 saveLyXTextState(t);
2171 for (Paragraph * p = par; p; p = p->next()) {
2172 p->resizeInsetsLyXText(bv);
2175 restoreLyXTextState(bv, t);
2176 if (the_locking_inset) {
2177 inset_x = cx(bv) - top_x + drawTextXOffset;
2178 inset_y = cy(bv) + drawTextYOffset;
2181 t->first = bv->screen()->topCursorVisible(t);
2184 updateLocal(bv, FULL, false);
2185 // this will scroll the screen such that the cursor becomes visible
2186 bv->updateScrollbar();
2194 void InsetText::removeNewlines()
2196 for (Paragraph * p = par; p; p = p->next()) {
2197 for (int i = 0; i < p->size(); ++i) {
2198 if (p->getChar(i) == Paragraph::META_NEWLINE)
2205 bool InsetText::nodraw() const
2207 if (the_locking_inset)
2208 return the_locking_inset->nodraw();
2209 return UpdatableInset::nodraw();
2213 int InsetText::scroll(bool recursive) const
2215 int sx = UpdatableInset::scroll(false);
2217 if (recursive && the_locking_inset)
2218 sx += the_locking_inset->scroll(recursive);
2224 bool InsetText::doClearArea() const
2226 return !locked || (need_update & (FULL|INIT));
2230 void InsetText::selectAll(BufferView * bv)
2232 getLyXText(bv)->cursorTop(bv);
2233 getLyXText(bv)->selection.cursor = getLyXText(bv)->cursor;
2234 getLyXText(bv)->cursorBottom(bv);
2235 getLyXText(bv)->setSelection(bv);
2239 void InsetText::clearSelection(BufferView * bv)
2241 getLyXText(bv)->clearSelection();
2245 void InsetText::clearInset(Painter & pain, int baseline, bool & cleared) const
2248 int h = insetAscent + insetDescent;
2249 int ty = baseline - insetAscent;
2255 if ((ty + h) > pain.paperHeight())
2256 h = pain.paperHeight();
2257 if ((top_x + drawTextXOffset + w) > pain.paperWidth())
2258 w = pain.paperWidth();
2259 // w -= TEXT_TO_INSET_OFFSET;
2260 pain.fillRectangle(top_x, ty, w+1, h+1, backgroundColor());
2263 frame_is_visible = false;
2267 Paragraph * InsetText::getParFromID(int id) const
2270 Paragraph * result = par;
2271 Paragraph * ires = 0;
2272 while (result && result->id() != id) {
2273 if ((ires = result->getParFromID(id)))
2275 result = result->next();
2279 Paragraph * tmp = par;
2281 int tmp_id = tmp->id();
2282 lyxerr << "Looking at paragraph: " << tmp_id << endl;
2283 if (tmp->id() == id) {
2286 Paragraph * tmp2 = tmp->getParFromID(id);
2297 Paragraph * InsetText::firstParagraph() const
2300 if (the_locking_inset)
2301 if ((result = the_locking_inset->firstParagraph()))
2307 Paragraph * InsetText::getFirstParagraph(int i) const
2309 return (i == 0) ? par : 0;
2313 LyXCursor const & InsetText::cursor(BufferView * bv) const
2315 if (the_locking_inset)
2316 return the_locking_inset->cursor(bv);
2317 return getLyXText(bv)->cursor;
2321 Paragraph * InsetText::paragraph() const
2327 void InsetText::paragraph(Paragraph * p)
2331 // we now have to update/redraw all instances
2332 for (Cache::iterator cit = cache.begin(); cit != cache.end(); ++cit) {
2337 // redraw myself when asked for
2342 Inset * InsetText::getInsetFromID(int id_arg) const
2345 return const_cast<InsetText *>(this);
2347 Paragraph * lp = par;
2350 for (Paragraph::inset_iterator it = lp->inset_iterator_begin(),
2351 en = lp->inset_iterator_end();
2354 if ((*it)->id() == id_arg)
2356 Inset * in = (*it)->getInsetFromID(id_arg);
2366 string const InsetText::selectNextWordToSpellcheck(BufferView * bv, float & value) const
2372 lt = getLyXText(bv);
2375 if (the_locking_inset) {
2376 str = the_locking_inset->selectNextWordToSpellcheck(bv, value);
2383 #warning Dekel please have a look on this one RTL? (Jug)
2385 // we have to go on checking so move cusor to the right
2386 lt->cursor.pos(lt->cursor.pos() + 1);
2388 str = lt->selectNextWordToSpellcheck(bv, value);
2390 bv->unlockInset(const_cast<InsetText *>(this));
2399 void InsetText::selectSelectedWord(BufferView * bv)
2401 if (the_locking_inset) {
2402 the_locking_inset->selectSelectedWord(bv);
2405 getLyXText(bv)->selectSelectedWord(bv);
2406 updateLocal(bv, SELECTION, false);
2410 void InsetText::toggleSelection(BufferView * bv, bool kill_selection)
2412 if (the_locking_inset) {
2413 the_locking_inset->toggleSelection(bv, kill_selection);
2417 lt = getLyXText(bv);
2421 int x = top_x + TEXT_TO_INSET_OFFSET;
2424 Row * row = lt->getRowNearY(y);
2425 int y_offset = top_baseline - row->ascent_of_text();
2427 while ((row != 0) && ((y+row->height()) <= 0)) {
2434 if (need_update & SELECTION)
2436 bv->screen()->toggleSelection(lt, bv, kill_selection, y_offset, x);
2442 bool InsetText::searchForward(BufferView * bv, string const & str,
2443 bool const & cs, bool const & mw)
2445 if (the_locking_inset) {
2446 if (the_locking_inset->searchForward(bv, str, cs, mw))
2450 lt = getLyXText(bv);
2453 Paragraph * lpar = lt->cursor.par();
2454 pos_type pos = lt->cursor.pos();
2455 if (pos < lpar->size() - 1)
2459 lpar = lpar->next();
2464 // we have to unlock ourself in this function by default!
2465 bv->unlockInset(const_cast<InsetText *>(this));
2468 lt->setCursor(bv, lpar, pos);
2472 if (LyXFind(bv, str, true, true, cs , mw)) {
2475 // we have to unlock ourself in this function by default!
2476 bv->unlockInset(const_cast<InsetText *>(this));
2480 bool InsetText::searchBackward(BufferView * bv, string const & str,
2481 bool const & cs, bool const & mw)
2483 if (the_locking_inset)
2484 if (the_locking_inset->searchBackward(bv, str, cs, mw))
2486 if (LyXFind(bv, str, false, true, cs, mw)) {
2489 // we have to unlock ourself in this function by default!
2490 bv->unlockInset(const_cast<InsetText *>(this));
2495 bool InsetText::checkInsertChar(LyXFont & font)
2498 return owner()->checkInsertChar(font);