1 /* This file is part of
2 * ======================================================
4 * LyX, The Document Processor
6 * Copyright 1998-2001 The LyX Team.
8 * ======================================================
14 #pragma implementation
17 #include "insettext.h"
18 #include "paragraph.h"
22 #include "commandtags.h"
25 #include "BufferView.h"
26 #include "lyxtextclasslist.h"
27 #include "LaTeXFeatures.h"
30 #include "lyxcursor.h"
31 #include "CutAndPaste.h"
37 #include "trans_mgr.h"
38 #include "lyxscreen.h"
42 #include "ParagraphParameters.h"
43 #include "undo_funcs.h"
46 #include "frontends/Alert.h"
48 #include "support/textutils.h"
49 #include "support/LAssert.h"
50 #include "support/lstrings.h"
66 using lyx::layout_type;
67 using lyx::textclass_type;
69 extern unsigned char getCurrentTextClass(Buffer *);
70 extern bool math_insert_greek(BufferView *, char);
71 extern int greek_kb_flag;
74 // These functions should probably go into bufferview_funcs somehow (Jug)
76 void InsetText::saveLyXTextState(LyXText * t) const
78 // check if my paragraphs are still valid
81 if (p == t->cursor.par())
86 if (p && t->cursor.pos() <= p->size()) {
87 sstate.lpar = t->cursor.par();
88 sstate.pos = t->cursor.pos();
89 sstate.boundary = t->cursor.boundary();
90 sstate.selstartpar = t->selection.start.par();
91 sstate.selstartpos = t->selection.start.pos();
92 sstate.selstartboundary = t->selection.start.boundary();
93 sstate.selendpar = t->selection.end.par();
94 sstate.selendpos = t->selection.end.pos();
95 sstate.selendboundary = t->selection.end.boundary();
96 sstate.selection = t->selection.set();
97 sstate.mark_set = t->selection.mark();
98 sstate.refresh = t->refresh_row != 0;
104 void InsetText::restoreLyXTextState(BufferView * bv, LyXText * t) const
107 t->selection.set(true);
108 /* at this point just to avoid the Delete-Empty-Paragraph
109 * Mechanism when setting the cursor */
110 t->selection.mark(sstate.mark_set);
111 if (sstate.selection) {
112 t->setCursor(bv, sstate.selstartpar, sstate.selstartpos,
113 true, sstate.selstartboundary);
114 t->selection.cursor = t->cursor;
115 t->setCursor(bv, sstate.selendpar, sstate.selendpos,
116 true, sstate.selendboundary);
118 t->setCursor(bv, sstate.lpar, sstate.pos);
120 t->setCursor(bv, sstate.lpar, sstate.pos, true, sstate.boundary);
121 t->selection.cursor = t->cursor;
122 t->selection.set(false);
124 if (sstate.refresh) {
130 InsetText::InnerCache::InnerCache(boost::shared_ptr<LyXText> t)
137 InsetText::InsetText()
138 : UpdatableInset(), lt(0), in_update(false), do_resize(0),
146 InsetText::InsetText(InsetText const & in, bool same_id)
147 : UpdatableInset(in, same_id), lt(0), in_update(false), do_resize(0),
155 InsetText & InsetText::operator=(InsetText const & it)
162 void InsetText::init(InsetText const * ins, bool same_id)
165 setParagraphData(ins->par, same_id);
166 autoBreakRows = ins->autoBreakRows;
167 drawFrame_ = ins->drawFrame_;
168 frame_color = ins->frame_color;
174 p->setInsetOwner(this);
177 the_locking_inset = 0;
179 frame_color = LColor::insetframe;
180 autoBreakRows = false;
187 no_selection = false;
194 last_drawn_width = -1;
195 frame_is_visible = false;
198 in_insetAllowed = false;
202 InsetText::~InsetText()
209 Paragraph * tmp = par->next();
216 void InsetText::clear()
219 Paragraph * tmp = par->next();
229 Inset * InsetText::clone(Buffer const &, bool same_id) const
231 return new InsetText(*this, same_id);
235 void InsetText::write(Buffer const * buf, ostream & os) const
238 writeParagraphData(buf, os);
242 void InsetText::writeParagraphData(Buffer const * buf, ostream & os) const
244 par->writeFile(buf, os, buf->params, 0);
248 void InsetText::read(Buffer const * buf, LyXLex & lex)
252 Paragraph * return_par = 0;
253 Paragraph::depth_type depth = 0;
254 LyXFont font(LyXFont::ALL_INHERIT);
260 token = lex.getString();
263 if (token == "\\end_inset") {
264 #ifndef NO_COMPABILITY
265 const_cast<Buffer*>(buf)->insertErtContents(par, pos, font, false);
270 if (const_cast<Buffer*>(buf)->
271 parseSingleLyXformat2Token(lex, par, return_par,
272 token, pos, depth, font)) {
273 // the_end read this should NEVER happen
274 lex.printError("\\the_end read in inset! Error in document!");
282 return_par->setInsetOwner(this);
283 return_par = return_par->next();
286 if (token != "\\end_inset") {
287 lex.printError("Missing \\end_inset at this point. "
294 int InsetText::ascent(BufferView * bv, LyXFont const &) const
296 insetAscent = getLyXText(bv)->firstRow()->ascent_of_text() +
297 TEXT_TO_INSET_OFFSET;
302 int InsetText::descent(BufferView * bv, LyXFont const &) const
304 LyXText * llt = getLyXText(bv);
305 insetDescent = llt->height - llt->firstRow()->ascent_of_text() +
306 TEXT_TO_INSET_OFFSET;
311 int InsetText::width(BufferView * bv, LyXFont const &) const
313 insetWidth = max(textWidth(bv), (int)getLyXText(bv)->width) +
314 (2 * TEXT_TO_INSET_OFFSET);
315 insetWidth = max(insetWidth, 10);
320 int InsetText::textWidth(BufferView * bv, bool fordraw) const
323 if (!autoBreakRows) {
326 w = getMaxWidth(bv, this);
329 return max(w - (2 * TEXT_TO_INSET_OFFSET),
330 (int)getLyXText(bv)->width);
334 return w - (2 * TEXT_TO_INSET_OFFSET);
338 void InsetText::draw(BufferView * bv, LyXFont const & f,
339 int baseline, float & x, bool cleared) const
344 Painter & pain = bv->painter();
346 // this is the first thing we have to ask because if the x pos
347 // changed we have to do a complete rebreak of the text as we
348 // may have few space to draw in. Well we should check on this too
350 if (top_x != int(x)) {
352 int nw = getMaxWidth(bv, this);
353 if (nw > 0 && old_max_width != nw) {
356 bv->text->status(bv, LyXText::CHANGED_IN_DRAW);
364 // call these methods so that insetWidth, insetAscent and
365 // insetDescent have the right values.
370 // repaint the background if needed
371 if (cleared && backgroundColor() != LColor::background) {
373 clearInset(bv, 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(bv, 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 - insetAscent;
414 if (last_drawn_width != insetWidth) {
416 clearInset(bv, baseline, cleared);
418 last_drawn_width = insetWidth;
421 if (the_locking_inset && (cpar(bv) == inset_par)
422 && (cpos(bv) == inset_pos)) {
423 inset_x = cx(bv) - top_x + drawTextXOffset;
424 inset_y = cy(bv) + drawTextYOffset;
426 if (!cleared && (need_update == CURSOR)
427 && !getLyXText(bv)->selection.set()) {
428 drawFrame(pain, cleared);
438 x += TEXT_TO_INSET_OFFSET;
440 Row * row = lt->firstRow();
441 int y_offset = baseline - row->ascent_of_text();
442 int ph = pain.paperHeight();
445 while ((row != 0) && ((y+row->height()) <= 0)) {
447 first += row->height();
453 if (cleared || (need_update&(INIT|FULL))) {
456 while ((row != 0) && (yf < ph)) {
457 lt->getVisibleRow(bv, y+y_offset, int(x), row,
463 } else if (!locked) {
464 if (need_update & CURSOR) {
465 bv->screen()->toggleSelection(lt, bv, true, y_offset,int(x));
466 lt->clearSelection();
467 lt->selection.cursor = lt->cursor;
469 bv->screen()->update(lt, bv, y_offset, int(x));
472 if (need_update & SELECTION) {
473 bv->screen()->toggleToggle(lt, bv, y_offset, int(x));
474 } else if (need_update & CURSOR) {
475 bv->screen()->toggleSelection(lt, bv, true, y_offset,int(x));
476 lt->clearSelection();
477 lt->selection.cursor = lt->cursor;
479 bv->screen()->update(lt, bv, y_offset, int(x));
484 lt->status(bv, LyXText::UNCHANGED);
485 if ((need_update != CURSOR_PAR) &&
486 ((drawFrame_ == ALWAYS) || ((drawFrame_ == LOCKED) && locked))) {
487 drawFrame(pain, cleared);
488 } else if (need_update & CLEAR_FRAME) {
489 clearFrame(pain, cleared);
492 x += insetWidth - TEXT_TO_INSET_OFFSET;
494 if (bv->text->status() == LyXText::CHANGED_IN_DRAW) {
496 } else if (need_update != INIT) {
504 void InsetText::drawFrame(Painter & pain, bool cleared) const
506 static int const ttoD2 = TEXT_TO_INSET_OFFSET / 2;
507 if (!frame_is_visible || cleared) {
508 frame_x = top_x + ttoD2;
509 frame_y = top_baseline - insetAscent + ttoD2;
510 frame_w = insetWidth - TEXT_TO_INSET_OFFSET;
511 frame_h = insetAscent + insetDescent - TEXT_TO_INSET_OFFSET;
512 pain.rectangle(frame_x, frame_y, frame_w, frame_h,
514 frame_is_visible = true;
519 void InsetText::clearFrame(Painter & pain, bool cleared) const
521 if (frame_is_visible) {
523 pain.rectangle(frame_x, frame_y, frame_w, frame_h,
526 frame_is_visible = false;
531 void InsetText::update(BufferView * bv, LyXFont const & font, bool reinit)
534 if (reinit && owner()) {
536 owner()->update(bv, font, true);
541 if (reinit || need_update == INIT) {
543 // we should put this call where we set need_update to INIT!
546 owner()->update(bv, font, true);
550 if (the_locking_inset) {
551 inset_x = cx(bv) - top_x + drawTextXOffset;
552 inset_y = cy(bv) + drawTextYOffset;
553 the_locking_inset->update(bv, font, reinit);
561 if ((need_update & CURSOR_PAR) && (lt->status() == LyXText::UNCHANGED) &&
564 lt->updateInset(bv, the_locking_inset);
566 if (lt->status() == LyXText::NEED_MORE_REFRESH)
574 void InsetText::setUpdateStatus(BufferView * bv, int what) const
576 // this does nothing dangerous so use only a localized buffer
577 LyXText * llt = getLyXText(bv);
580 // we have to redraw us full if our LyXText NEEDS_MORE_REFRES or
581 // if we don't break row so that we only have one row to update!
582 if ((llt->status() == LyXText::NEED_MORE_REFRESH) ||
584 (llt->status() == LyXText::NEED_VERY_LITTLE_REFRESH)))
587 } else if (llt->status() == LyXText::NEED_VERY_LITTLE_REFRESH) {
588 need_update |= CURSOR_PAR;
591 // this to not draw a selection when we redraw all of it!
592 if (need_update & CURSOR && !(need_update & SELECTION)) {
593 if (llt->selection.set())
595 llt->clearSelection();
600 void InsetText::updateLocal(BufferView * bv, int what, bool mark_dirty) const
602 if (!autoBreakRows && par->next())
603 collapseParagraphs(bv->buffer()->params);
610 setUpdateStatus(bv, what);
611 bool flag = (((need_update != CURSOR) && (need_update != NONE)) ||
612 (lt->status() != LyXText::UNCHANGED) || lt->selection.set());
616 bv->updateInset(const_cast<InsetText *>(this), mark_dirty);
617 if (need_update == CURSOR)
619 bv->owner()->showState();
620 if (old_par != cpar(bv)) {
621 bv->owner()->setLayout(cpar(bv)->getLayout());
627 string const InsetText::editMessage() const
629 return _("Opened Text Inset");
633 void InsetText::edit(BufferView * bv, int x, int y, unsigned int button)
635 UpdatableInset::edit(bv, x, y, button);
637 if (!bv->lockInset(this)) {
638 lyxerr[Debug::INSETS] << "Cannot lock inset" << endl;
642 the_locking_inset = 0;
643 inset_pos = inset_x = inset_y = 0;
644 inset_boundary = false;
647 int tmp_y = (y < 0) ? 0 : y;
653 if (!checkAndActivateInset(bv, x, tmp_y, button))
654 lt->setCursorFromCoordinates(bv, x - drawTextXOffset,
656 lt->clearSelection();
658 // If the inset is empty set the language of the current font to the
659 // language to the surronding text (if different).
660 if (par->size() == 0 && !par->next() &&
661 bv->getParentLanguage(this) != lt->current_font.language())
663 LyXFont font(LyXFont::ALL_IGNORE);
664 font.setLanguage(bv->getParentLanguage(this));
665 setFont(bv, font, false);
670 updateLocal(bv, CURSOR, false);
674 void InsetText::edit(BufferView * bv, bool front)
676 UpdatableInset::edit(bv, front);
678 if (!bv->lockInset(this)) {
679 lyxerr[Debug::INSETS] << "Cannot lock inset" << endl;
683 the_locking_inset = 0;
684 inset_pos = inset_x = inset_y = 0;
685 inset_boundary = false;
694 lt->setCursor(bv, par, 0);
699 // int const pos = (p->size() ? p->size()-1 : p->size());
700 lt->setCursor(bv, p, p->size());
702 lt->clearSelection();
704 // If the inset is empty set the language of the current font to the
705 // language to the surronding text (if different).
706 if (par->size() == 0 && !par->next() &&
707 bv->getParentLanguage(this) != lt->current_font.language()) {
708 LyXFont font(LyXFont::ALL_IGNORE);
709 font.setLanguage(bv->getParentLanguage(this));
710 setFont(bv, font, false);
715 updateLocal(bv, CURSOR, false);
719 void InsetText::insetUnlock(BufferView * bv)
721 if (the_locking_inset) {
722 the_locking_inset->insetUnlock(bv);
723 the_locking_inset = 0;
726 no_selection = false;
729 if (drawFrame_ == LOCKED)
730 code = CURSOR|CLEAR_FRAME;
738 if (lt->selection.set()) {
739 lt->clearSelection();
741 } else if (owner()) {
742 bv->owner()->setLayout(owner()->getLyXText(bv)
743 ->cursor.par()->getLayout());
745 bv->owner()->setLayout(bv->text->cursor.par()->getLayout());
746 // hack for deleteEmptyParMech
747 lt->setCursor(bv, par, 0);
750 updateLocal(bv, code, false);
753 void InsetText::lockInset(BufferView * bv, UpdatableInset * inset)
755 the_locking_inset = inset;
756 inset_x = cx(bv) - top_x + drawTextXOffset;
757 inset_y = cy(bv) + drawTextYOffset;
758 inset_pos = cpos(bv);
759 inset_par = cpar(bv);
760 inset_boundary = cboundary(bv);
761 updateLocal(bv, CURSOR, false);
765 bool InsetText::lockInsetInInset(BufferView * bv, UpdatableInset * inset)
767 lyxerr[Debug::INSETS] << "InsetText::LockInsetInInset("
771 if (!the_locking_inset) {
773 int const id = inset->id();
775 Paragraph::inset_iterator it =
776 p->inset_iterator_begin();
777 Paragraph::inset_iterator const end =
778 p->inset_iterator_end();
779 for (; it != end; ++it) {
780 if ((*it) == inset) {
781 getLyXText(bv)->setCursorIntern(bv, p, it.getPos());
782 lockInset(bv, inset);
785 if ((*it)->getInsetFromID(id)) {
786 getLyXText(bv)->setCursorIntern(bv, p, it.getPos());
787 lockInset(bv, static_cast<UpdatableInset *>(*it));
788 return the_locking_inset->lockInsetInInset(bv, inset);
795 if (inset == cpar(bv)->getInset(cpos(bv))) {
796 lyxerr[Debug::INSETS] << "OK" << endl;
797 lockInset(bv, inset);
799 } else if (the_locking_inset && (the_locking_inset == inset)) {
800 if (cpar(bv) == inset_par && cpos(bv) == inset_pos) {
801 lyxerr[Debug::INSETS] << "OK" << endl;
802 inset_x = cx(bv) - top_x + drawTextXOffset;
803 inset_y = cy(bv) + drawTextYOffset;
805 lyxerr[Debug::INSETS] << "cursor.pos != inset_pos" << endl;
807 } else if (the_locking_inset) {
808 lyxerr[Debug::INSETS] << "MAYBE" << endl;
809 return the_locking_inset->lockInsetInInset(bv, inset);
811 lyxerr[Debug::INSETS] << "NOT OK" << endl;
816 bool InsetText::unlockInsetInInset(BufferView * bv, UpdatableInset * inset,
819 if (!the_locking_inset)
821 if (the_locking_inset == inset) {
822 the_locking_inset->insetUnlock(bv);
823 getLyXText(bv)->updateInset(bv, inset);
824 the_locking_inset = 0;
826 moveRight(bv, false);
827 old_par = 0; // force layout setting
831 updateLocal(bv, CURSOR, false);
834 return the_locking_inset->unlockInsetInInset(bv, inset, lr);
838 bool InsetText::updateInsetInInset(BufferView * bv, Inset * inset)
840 if (!autoBreakRows && par->next())
841 collapseParagraphs(bv->buffer()->params);
849 if (!the_locking_inset) {
850 bool found = lt->updateInset(bv, inset);
854 setUpdateStatus(bv, NONE);
857 if (the_locking_inset != inset) {
858 bool found = the_locking_inset->updateInsetInInset(bv, inset);
862 setUpdateStatus(bv, CURSOR_PAR);
865 bool found = lt->updateInset(bv, inset);
869 setUpdateStatus(bv, CURSOR_PAR);
870 if (cpar(bv) == inset_par && cpos(bv) == inset_pos) {
871 inset_x = cx(bv) - top_x + drawTextXOffset;
872 inset_y = cy(bv) + drawTextYOffset;
879 void InsetText::insetButtonPress(BufferView * bv, int x, int y, int button)
883 // use this to check mouse motion for selection!
887 int tmp_x = x - drawTextXOffset;
888 int tmp_y = y + insetAscent - getLyXText(bv)->first;
889 Inset * inset = bv->checkInsetHit(getLyXText(bv), tmp_x, tmp_y);
892 if (the_locking_inset) {
893 if (the_locking_inset == inset) {
894 the_locking_inset->insetButtonPress(bv,
898 no_selection = false;
901 // otherwise unlock the_locking_inset and lock the new inset
902 the_locking_inset->insetUnlock(bv);
903 inset_x = cx(bv) - top_x + drawTextXOffset;
904 inset_y = cy(bv) + drawTextYOffset;
905 the_locking_inset = static_cast<UpdatableInset*>(inset);
906 inset->insetButtonPress(bv, x - inset_x,
907 y - inset_y, button);
908 inset->edit(bv, x - inset_x, y - inset_y, button);
909 if (the_locking_inset)
910 updateLocal(bv, CURSOR, false);
911 no_selection = false;
914 // otherwise only unlock the_locking_inset
915 the_locking_inset->insetUnlock(bv);
916 the_locking_inset = 0;
918 if (bv->theLockingInset()) {
919 if (isHighlyEditableInset(inset)) {
920 UpdatableInset * uinset = static_cast<UpdatableInset*>(inset);
921 inset_x = cx(bv) - top_x + drawTextXOffset;
922 inset_y = cy(bv) + drawTextYOffset;
923 inset_pos = cpos(bv);
924 inset_par = cpar(bv);
925 inset_boundary = cboundary(bv);
926 the_locking_inset = uinset;
927 uinset->insetButtonPress(bv, x - inset_x, y - inset_y,
929 uinset->edit(bv, x - inset_x, y - inset_y, 0);
930 if (the_locking_inset)
931 updateLocal(bv, CURSOR, false);
932 no_selection = false;
936 if (!inset) { // && (button == 2)) {
937 bool paste_internally = false;
938 if ((button == 2) && getLyXText(bv)->selection.set()) {
939 localDispatch(bv, LFUN_COPY, "");
940 paste_internally = true;
948 lt->setCursorFromCoordinates(bv, x - drawTextXOffset,
950 // set the selection cursor!
951 lt->selection.cursor = lt->cursor;
952 lt->cursor.x_fix(lt->cursor.x());
954 if (lt->selection.set()) {
955 lt->clearSelection();
958 updateLocal(bv, FULL, false);
960 lt->clearSelection();
964 bv->owner()->setLayout(cpar(bv)->getLayout());
966 // Insert primary selection with middle mouse
967 // if there is a local selection in the current buffer,
970 if (paste_internally)
971 localDispatch(bv, LFUN_PASTE, "");
973 localDispatch(bv, LFUN_PASTESELECTION,
977 getLyXText(bv)->clearSelection();
980 no_selection = false;
984 bool InsetText::insetButtonRelease(BufferView * bv, int x, int y, int button)
986 if (the_locking_inset) {
987 return the_locking_inset->insetButtonRelease(bv,
988 x - inset_x, y - inset_y,
991 int tmp_x = x - drawTextXOffset;
992 int tmp_y = y + insetAscent - getLyXText(bv)->first;
993 Inset * inset = bv->checkInsetHit(getLyXText(bv), tmp_x, tmp_y);
996 if (isHighlyEditableInset(inset)) {
997 ret = inset->insetButtonRelease(bv, x - inset_x,
998 y - inset_y, button);
1000 inset_x = cx(bv) - top_x + drawTextXOffset;
1001 inset_y = cy(bv) + drawTextYOffset;
1002 ret = inset->insetButtonRelease(bv, x - inset_x,
1003 y - inset_y, button);
1004 inset->edit(bv, x - inset_x,
1005 y - inset_y, button);
1007 updateLocal(bv, CURSOR_PAR, false);
1013 void InsetText::insetMotionNotify(BufferView * bv, int x, int y, int state)
1015 if (no_selection || ((mouse_x == x) && (mouse_y == y)))
1017 if (the_locking_inset) {
1018 the_locking_inset->insetMotionNotify(bv, x - inset_x,
1024 lt = getLyXText(bv);
1027 hideInsetCursor(bv);
1028 LyXCursor cur = lt->cursor;
1029 lt->setCursorFromCoordinates(bv, x - drawTextXOffset, y + insetAscent);
1030 if (cur == lt->cursor) {
1035 lt->setSelection(bv);
1036 bool flag = (lt->toggle_cursor.par() != lt->toggle_end_cursor.par() ||
1037 lt->toggle_cursor.pos() != lt->toggle_end_cursor.pos());
1041 updateLocal(bv, SELECTION, false);
1043 showInsetCursor(bv);
1047 void InsetText::insetKeyPress(XKeyEvent * xke)
1049 if (the_locking_inset) {
1050 the_locking_inset->insetKeyPress(xke);
1056 UpdatableInset::RESULT
1057 InsetText::localDispatch(BufferView * bv,
1058 kb_action action, string const & arg)
1060 bool was_empty = par->size() == 0 && !par->next();
1061 no_selection = false;
1062 UpdatableInset::RESULT
1063 result= UpdatableInset::localDispatch(bv, action, arg);
1064 if (result != UNDISPATCHED) {
1068 result = DISPATCHED;
1069 if ((action < 0) && arg.empty())
1072 if (the_locking_inset) {
1073 result = the_locking_inset->localDispatch(bv, action, arg);
1074 if (result == DISPATCHED_NOUPDATE)
1076 else if (result == DISPATCHED) {
1077 updateLocal(bv, CURSOR_PAR, false);
1079 } else if (result >= FINISHED) {
1081 case FINISHED_RIGHT:
1082 moveRightIntern(bv, false, false);
1083 result = DISPATCHED;
1086 if ((result = moveUp(bv)) >= FINISHED) {
1087 updateLocal(bv, CURSOR, false);
1088 bv->unlockInset(this);
1092 if ((result = moveDown(bv)) >= FINISHED) {
1093 updateLocal(bv, CURSOR, false);
1094 bv->unlockInset(this);
1098 result = DISPATCHED;
1101 the_locking_inset = 0;
1102 #ifdef WITH_WARNINGS
1103 #warning I changed this to always return Dispatched maybe it is wrong (20011001 Jug)
1108 hideInsetCursor(bv);
1111 lt = getLyXText(bv);
1115 int updflag = false;
1118 case LFUN_SELFINSERT:
1119 if (bv->buffer()->isReadonly()) {
1120 // setErrorMessage(N_("Document is read only"));
1124 /* Automatically delete the currently selected
1125 * text and replace it with what is being
1126 * typed in now. Depends on lyxrc settings
1127 * "auto_region_delete", which defaults to
1130 setUndo(bv, Undo::INSERT,
1131 lt->cursor.par(), lt->cursor.par()->next());
1133 if (lyxrc.auto_region_delete) {
1134 if (lt->selection.set()) {
1135 lt->cutSelection(bv, false);
1138 lt->clearSelection();
1139 for (string::size_type i = 0; i < arg.length(); ++i) {
1140 bv->owner()->getIntl()->getTrans().TranslateAndInsert(arg[i], lt);
1143 lt->selection.cursor = lt->cursor;
1144 updwhat = CURSOR_PAR;
1146 result = DISPATCHED_NOUPDATE;
1148 // --- Cursor Movements -----------------------------------
1151 moveRight(bv, false, true);
1152 lt->setSelection(bv);
1153 updwhat = SELECTION;
1156 result = moveRight(bv);
1162 moveLeft(bv, false, true);
1163 lt->setSelection(bv);
1164 updwhat = SELECTION;
1168 result = moveLeft(bv);
1174 lt->setSelection(bv);
1175 updwhat = SELECTION;
1179 result = moveDown(bv);
1185 lt->setSelection(bv);
1186 updwhat = SELECTION;
1190 result = moveUp(bv);
1202 case LFUN_BACKSPACE: {
1203 setUndo(bv, Undo::DELETE,
1204 lt->cursor.par(), lt->cursor.par()->next());
1205 if (lt->selection.set())
1206 lt->cutSelection(bv);
1209 updwhat = CURSOR_PAR;
1215 setUndo(bv, Undo::DELETE,
1216 lt->cursor.par(), lt->cursor.par()->next());
1217 if (lt->selection.set()) {
1218 lt->cutSelection(bv);
1222 updwhat = CURSOR_PAR;
1228 setUndo(bv, Undo::DELETE,
1229 lt->cursor.par(), lt->cursor.par()->next());
1230 lt->cutSelection(bv);
1231 updwhat = CURSOR_PAR;
1238 lt->copySelection(bv);
1239 updwhat = CURSOR_PAR;
1241 case LFUN_PASTESELECTION:
1243 string const clip(bv->getClipboard());
1247 if (arg == "paragraph") {
1248 lt->insertStringAsParagraphs(bv, clip);
1250 lt->insertStringAsLines(bv, clip);
1252 updwhat = CURSOR_PAR;
1257 if (!autoBreakRows) {
1259 if (CutAndPaste::nrOfParagraphs() > 1) {
1260 Alert::alert(_("Impossible operation"),
1261 _("Cannot include more than one paragraph!"),
1266 setUndo(bv, Undo::INSERT,
1267 lt->cursor.par(), lt->cursor.par()->next());
1268 lt->pasteSelection(bv);
1269 updwhat = CURSOR_PAR;
1274 case LFUN_BREAKPARAGRAPH:
1275 if (!autoBreakRows) {
1276 result = DISPATCHED;
1279 lt->breakParagraph(bv, 0);
1283 case LFUN_BREAKPARAGRAPHKEEPLAYOUT:
1284 if (!autoBreakRows) {
1285 result = DISPATCHED;
1288 lt->breakParagraph(bv, 1);
1293 case LFUN_BREAKLINE: {
1294 if (!autoBreakRows) {
1295 result = DISPATCHED;
1298 setUndo(bv, Undo::INSERT,
1299 lt->cursor.par(), lt->cursor.par()->next());
1300 lt->insertChar(bv, Paragraph::META_NEWLINE);
1301 updwhat = CURSOR_PAR;
1307 // do not set layouts on non breakable textinsets
1308 if (autoBreakRows) {
1309 layout_type cur_layout = cpar(bv)->layout;
1311 // Derive layout number from given argument (string)
1312 // and current buffer's textclass (number). */
1313 textclass_type tclass = bv->buffer()->params.textclass;
1314 std::pair <bool, layout_type> layout =
1315 textclasslist.NumberOfLayout(tclass, arg);
1317 // If the entry is obsolete, use the new one instead.
1319 string obs = textclasslist.Style(tclass,layout.second).
1322 layout = textclasslist.NumberOfLayout(tclass, obs);
1325 // see if we found the layout number:
1326 if (!layout.first) {
1327 string const msg = string(N_("Layout ")) + arg + N_(" not known");
1328 bv->owner()->getLyXFunc()->dispatch(LFUN_MESSAGE, msg);
1332 if (cur_layout != layout.second) {
1333 cur_layout = layout.second;
1334 lt->setLayout(bv, layout.second);
1335 bv->owner()->setLayout(cpar(bv)->getLayout());
1336 updwhat = CURSOR_PAR;
1340 // reset the layout box
1341 bv->owner()->setLayout(cpar(bv)->getLayout());
1344 case LFUN_PARAGRAPH_SPACING:
1345 // This one is absolutely not working. When fiddling with this
1346 // it also seems to me that the paragraphs inside the insettext
1347 // inherit bufferparams/paragraphparams in a strange way. (Lgb)
1349 Paragraph * par = lt->cursor.par();
1350 Spacing::Space cur_spacing = par->params().spacing().getSpace();
1351 float cur_value = 1.0;
1352 if (cur_spacing == Spacing::Other) {
1353 cur_value = par->params().spacing().getValue();
1356 istringstream istr(arg.c_str());
1359 Spacing::Space new_spacing = cur_spacing;
1360 float new_value = cur_value;
1362 lyxerr << "Missing argument to `paragraph-spacing'"
1364 } else if (tmp == "single") {
1365 new_spacing = Spacing::Single;
1366 } else if (tmp == "onehalf") {
1367 new_spacing = Spacing::Onehalf;
1368 } else if (tmp == "double") {
1369 new_spacing = Spacing::Double;
1370 } else if (tmp == "other") {
1371 new_spacing = Spacing::Other;
1374 lyxerr << "new_value = " << tmpval << endl;
1377 } else if (tmp == "default") {
1378 new_spacing = Spacing::Default;
1380 lyxerr << _("Unknown spacing argument: ")
1383 if (cur_spacing != new_spacing || cur_value != new_value) {
1384 par->params().spacing(Spacing(new_spacing, new_value));
1385 updwhat = CURSOR_PAR;
1392 if (!bv->Dispatch(action, arg))
1393 result = UNDISPATCHED;
1400 updateLocal(bv, updwhat, updflag);
1401 /// If the action has deleted all text in the inset, we need to change the
1402 // language to the language of the surronding text.
1403 if (!was_empty && par->size() == 0 && !par->next()) {
1404 LyXFont font(LyXFont::ALL_IGNORE);
1405 font.setLanguage(bv->getParentLanguage(this));
1406 setFont(bv, font, false);
1409 if (result < FINISHED) {
1410 showInsetCursor(bv);
1412 bv->unlockInset(this);
1417 int InsetText::latex(Buffer const * buf, ostream & os, bool, bool) const
1420 buf->latexParagraphs(os, par, 0, texrow);
1421 return texrow.rows();
1425 int InsetText::ascii(Buffer const * buf, ostream & os, int linelen) const
1427 Paragraph * p = par;
1428 unsigned int lines = 0;
1431 string const tmp = buf->asciiParagraph(p, linelen, p->previous()==0);
1432 lines += countChar(tmp, '\n');
1440 int InsetText::docbook(Buffer const * buf, ostream & os) const
1442 Paragraph * p = par;
1443 unsigned int lines = 0;
1445 vector<string> environment_stack(10);
1446 vector<string> environment_inner(10);
1448 int const command_depth = 0;
1451 Paragraph::depth_type depth = 0; // paragraph depth
1455 int desc_on = 0; // description mode
1457 LyXLayout const & style =
1458 textclasslist.Style(buf->params.textclass,
1461 // environment tag closing
1462 for (; depth > p->params().depth(); --depth) {
1463 if (environment_inner[depth] != "!-- --") {
1464 item_name = "listitem";
1465 buf->sgmlCloseTag(os, command_depth + depth,
1467 if (environment_inner[depth] == "varlistentry")
1468 buf->sgmlCloseTag(os, depth+command_depth,
1469 environment_inner[depth]);
1471 buf->sgmlCloseTag(os, depth + command_depth,
1472 environment_stack[depth]);
1473 environment_stack[depth].erase();
1474 environment_inner[depth].erase();
1477 if (depth == p->params().depth()
1478 && environment_stack[depth] != style.latexname()
1479 && !environment_stack[depth].empty()) {
1480 if (environment_inner[depth] != "!-- --") {
1481 item_name= "listitem";
1482 buf->sgmlCloseTag(os, command_depth+depth,
1484 if (environment_inner[depth] == "varlistentry")
1485 buf->sgmlCloseTag(os,
1486 depth + command_depth,
1487 environment_inner[depth]);
1490 buf->sgmlCloseTag(os, depth + command_depth,
1491 environment_stack[depth]);
1493 environment_stack[depth].erase();
1494 environment_inner[depth].erase();
1497 // Write opening SGML tags.
1498 switch (style.latextype) {
1499 case LATEX_PARAGRAPH:
1500 buf->sgmlOpenTag(os, depth + command_depth,
1505 buf->sgmlError(p, 0,
1506 _("Error : LatexType Command not allowed here.\n"));
1510 case LATEX_ENVIRONMENT:
1511 case LATEX_ITEM_ENVIRONMENT:
1512 if (depth < p->params().depth()) {
1513 depth = p->params().depth();
1514 environment_stack[depth].erase();
1517 if (environment_stack[depth] != style.latexname()) {
1518 if(environment_stack.size() == depth + 1) {
1519 environment_stack.push_back("!-- --");
1520 environment_inner.push_back("!-- --");
1522 environment_stack[depth] = style.latexname();
1523 environment_inner[depth] = "!-- --";
1524 buf->sgmlOpenTag(os, depth + command_depth,
1525 environment_stack[depth]);
1527 if (environment_inner[depth] != "!-- --") {
1528 item_name= "listitem";
1529 buf->sgmlCloseTag(os,
1530 command_depth + depth,
1532 if (environment_inner[depth] == "varlistentry")
1533 buf->sgmlCloseTag(os,
1534 depth + command_depth,
1535 environment_inner[depth]);
1539 if (style.latextype == LATEX_ENVIRONMENT) {
1540 if (!style.latexparam().empty()) {
1541 if(style.latexparam() == "CDATA")
1544 buf->sgmlOpenTag(os, depth + command_depth,
1545 style.latexparam());
1550 desc_on = (style.labeltype == LABEL_MANUAL);
1553 environment_inner[depth]= "varlistentry";
1555 environment_inner[depth]= "listitem";
1557 buf->sgmlOpenTag(os, depth + 1 + command_depth,
1558 environment_inner[depth]);
1562 buf->sgmlOpenTag(os, depth + 1 + command_depth,
1566 buf->sgmlOpenTag(os, depth + 1 + command_depth,
1571 buf->sgmlOpenTag(os, depth + command_depth,
1576 buf->simpleDocBookOnePar(os, p, desc_on,
1577 depth + 1 + command_depth);
1581 // write closing SGML tags
1582 switch (style.latextype) {
1583 case LATEX_ENVIRONMENT:
1584 if (!style.latexparam().empty()) {
1585 if(style.latexparam() == "CDATA")
1588 buf->sgmlCloseTag(os, depth + command_depth,
1589 style.latexparam());
1592 case LATEX_ITEM_ENVIRONMENT:
1593 if (desc_on == 1) break;
1595 buf->sgmlCloseTag(os, depth + 1 + command_depth, end_tag);
1597 case LATEX_PARAGRAPH:
1598 buf->sgmlCloseTag(os, depth + command_depth, style.latexname());
1601 buf->sgmlCloseTag(os, depth + command_depth, style.latexname());
1607 for (int d = depth; d >= 0; --d) {
1608 if (!environment_stack[depth].empty()) {
1609 if (environment_inner[depth] != "!-- --") {
1610 item_name = "listitem";
1611 buf->sgmlCloseTag(os, command_depth + depth,
1613 if (environment_inner[depth] == "varlistentry")
1614 buf->sgmlCloseTag(os, depth + command_depth,
1615 environment_inner[depth]);
1618 buf->sgmlCloseTag(os, depth + command_depth,
1619 environment_stack[depth]);
1627 void InsetText::validate(LaTeXFeatures & features) const
1629 Paragraph * p = par;
1631 p->validate(features);
1637 int InsetText::beginningOfMainBody(Buffer const * buf, Paragraph * p) const
1639 if (textclasslist.Style(buf->params.textclass,
1640 p->getLayout()).labeltype != LABEL_MANUAL)
1643 return p->beginningOfMainBody();
1647 void InsetText::getCursorPos(BufferView * bv,
1648 int & x, int & y) const
1650 if (the_locking_inset) {
1651 the_locking_inset->getCursorPos(bv, x, y);
1659 unsigned int InsetText::insetInInsetY()
1661 if (!the_locking_inset)
1664 return (inset_y + the_locking_inset->insetInInsetY());
1668 void InsetText::toggleInsetCursor(BufferView * bv)
1670 if (the_locking_inset) {
1671 the_locking_inset->toggleInsetCursor(bv);
1675 LyXFont const font(getLyXText(bv)->getFont(bv->buffer(), cpar(bv), cpos(bv)));
1677 int const asc = lyxfont::maxAscent(font);
1678 int const desc = lyxfont::maxDescent(font);
1680 if (isCursorVisible())
1681 bv->hideLockedInsetCursor();
1683 bv->showLockedInsetCursor(cx(bv), cy(bv), asc, desc);
1684 toggleCursorVisible();
1688 void InsetText::showInsetCursor(BufferView * bv, bool show)
1690 if (the_locking_inset) {
1691 the_locking_inset->showInsetCursor(bv, show);
1694 if (!isCursorVisible()) {
1695 LyXFont const font =
1696 getLyXText(bv)->getFont(bv->buffer(), cpar(bv), cpos(bv));
1698 int const asc = lyxfont::maxAscent(font);
1699 int const desc = lyxfont::maxDescent(font);
1701 bv->fitLockedInsetCursor(cx(bv), cy(bv), asc, desc);
1703 bv->showLockedInsetCursor(cx(bv), cy(bv), asc, desc);
1704 setCursorVisible(true);
1709 void InsetText::hideInsetCursor(BufferView * bv)
1711 if (isCursorVisible()) {
1712 bv->hideLockedInsetCursor();
1713 setCursorVisible(false);
1715 if (the_locking_inset)
1716 the_locking_inset->hideInsetCursor(bv);
1720 void InsetText::fitInsetCursor(BufferView * bv) const
1722 if (the_locking_inset) {
1723 the_locking_inset->fitInsetCursor(bv);
1726 LyXFont const font =
1727 getLyXText(bv)->getFont(bv->buffer(), cpar(bv), cpos(bv));
1729 int const asc = lyxfont::maxAscent(font);
1730 int const desc = lyxfont::maxDescent(font);
1732 bv->fitLockedInsetCursor(cx(bv), cy(bv), asc, desc);
1736 UpdatableInset::RESULT
1737 InsetText::moveRight(BufferView * bv, bool activate_inset, bool selecting)
1739 if (getLyXText(bv)->cursor.par()->isRightToLeftPar(bv->buffer()->params))
1740 return moveLeftIntern(bv, false, activate_inset, selecting);
1742 return moveRightIntern(bv, false, activate_inset, selecting);
1746 UpdatableInset::RESULT
1747 InsetText::moveLeft(BufferView * bv, bool activate_inset, bool selecting)
1749 if (getLyXText(bv)->cursor.par()->isRightToLeftPar(bv->buffer()->params))
1750 return moveRightIntern(bv, true, activate_inset, selecting);
1752 return moveLeftIntern(bv, true, activate_inset, selecting);
1756 UpdatableInset::RESULT
1757 InsetText::moveRightIntern(BufferView * bv, bool behind,
1758 bool activate_inset, bool selecting)
1760 if (!cpar(bv)->next() && (cpos(bv) >= cpar(bv)->size()))
1761 return FINISHED_RIGHT;
1762 if (activate_inset && checkAndActivateInset(bv, behind))
1764 getLyXText(bv)->cursorRight(bv);
1766 getLyXText(bv)->selection.cursor = getLyXText(bv)->cursor;
1767 return DISPATCHED_NOUPDATE;
1771 UpdatableInset::RESULT
1772 InsetText::moveLeftIntern(BufferView * bv, bool behind,
1773 bool activate_inset, bool selecting)
1775 if (!cpar(bv)->previous() && (cpos(bv) <= 0))
1777 getLyXText(bv)->cursorLeft(bv);
1779 getLyXText(bv)->selection.cursor = getLyXText(bv)->cursor;
1780 if (activate_inset && checkAndActivateInset(bv, behind))
1782 return DISPATCHED_NOUPDATE;
1786 UpdatableInset::RESULT
1787 InsetText::moveUp(BufferView * bv)
1789 if (!crow(bv)->previous())
1791 getLyXText(bv)->cursorUp(bv);
1792 return DISPATCHED_NOUPDATE;
1796 UpdatableInset::RESULT
1797 InsetText::moveDown(BufferView * bv)
1799 if (!crow(bv)->next())
1800 return FINISHED_DOWN;
1801 getLyXText(bv)->cursorDown(bv);
1802 return DISPATCHED_NOUPDATE;
1806 bool InsetText::insertInset(BufferView * bv, Inset * inset)
1808 if (the_locking_inset) {
1809 if (the_locking_inset->insetAllowed(inset))
1810 return the_locking_inset->insertInset(bv, inset);
1815 lt = getLyXText(bv);
1818 setUndo(bv, Undo::FINISH, lt->cursor.par(), lt->cursor.par()->next());
1820 inset->setOwner(this);
1821 hideInsetCursor(bv);
1822 lt->insertInset(bv, inset);
1826 updateLocal(bv, CURSOR_PAR|CURSOR, true);
1832 bool InsetText::insetAllowed(Inset::Code code) const
1834 // in_insetAllowed is a really gross hack,
1835 // to allow us to call the owner's insetAllowed
1836 // without stack overflow, which can happen
1837 // when the owner uses InsetCollapsable::insetAllowed()
1839 if (in_insetAllowed)
1841 in_insetAllowed = true;
1842 if (the_locking_inset)
1843 ret = the_locking_inset->insetAllowed(code);
1845 ret = owner()->insetAllowed(code);
1846 in_insetAllowed = false;
1851 UpdatableInset * InsetText::getLockingInset() const
1853 return the_locking_inset ? the_locking_inset->getLockingInset() :
1854 const_cast<InsetText *>(this);
1858 UpdatableInset * InsetText::getFirstLockingInsetOfType(Inset::Code c)
1862 if (the_locking_inset)
1863 return the_locking_inset->getFirstLockingInsetOfType(c);
1868 bool InsetText::showInsetDialog(BufferView * bv) const
1870 if (the_locking_inset)
1871 return the_locking_inset->showInsetDialog(bv);
1876 std::vector<string> const InsetText::getLabelList() const
1878 std::vector<string> label_list;
1880 Paragraph * tpar = par;
1882 Paragraph::inset_iterator beg = tpar->inset_iterator_begin();
1883 Paragraph::inset_iterator end = tpar->inset_iterator_end();
1884 for (; beg != end; ++beg) {
1885 std::vector<string> const l = (*beg)->getLabelList();
1886 label_list.insert(label_list.end(), l.begin(), l.end());
1888 tpar = tpar->next();
1894 void InsetText::setFont(BufferView * bv, LyXFont const & font, bool toggleall,
1897 if (the_locking_inset) {
1898 the_locking_inset->setFont(bv, font, toggleall, selectall);
1901 if ((!par->next() && !par->size()) || !cpar(bv)->size()) {
1902 getLyXText(bv)->setFont(bv, font, toggleall);
1907 lt = getLyXText(bv);
1910 if (lt->selection.set()) {
1911 setUndo(bv, Undo::EDIT, lt->cursor.par(), lt->cursor.par()->next());
1915 lt->toggleFree(bv, font, toggleall);
1917 lt->clearSelection();
1919 bool flag = (selectall || lt->selection.set());
1923 updateLocal(bv, FULL, true);
1925 updateLocal(bv, CURSOR_PAR, true);
1929 bool InsetText::checkAndActivateInset(BufferView * bv, bool behind)
1931 if (cpar(bv)->isInset(cpos(bv))) {
1935 static_cast<UpdatableInset*>(cpar(bv)->getInset(cpos(bv)));
1936 if (!isHighlyEditableInset(inset))
1938 LyXFont const font =
1939 getLyXText(bv)->getFont(bv->buffer(), cpar(bv), cpos(bv));
1941 x = inset->width(bv, font);
1942 y = font.isRightToLeft() ? 0 : inset->descent(bv, font);
1945 y = font.isRightToLeft() ? inset->descent(bv, font) : 0;
1947 //inset_x = cx(bv) - top_x + drawTextXOffset;
1948 //inset_y = cy(bv) + drawTextYOffset;
1949 inset->edit(bv, x, y, 0);
1950 if (!the_locking_inset)
1952 updateLocal(bv, CURSOR, false);
1959 bool InsetText::checkAndActivateInset(BufferView * bv, int x, int y,
1962 x -= drawTextXOffset;
1964 int dummyy = y + insetAscent;
1965 Inset * inset = bv->checkInsetHit(getLyXText(bv), dummyx, dummyy);
1972 inset_x = cx(bv) - top_x + drawTextXOffset;
1973 inset_y = cy(bv) + drawTextYOffset;
1974 inset->edit(bv, x - inset_x, y - inset_y, button);
1975 if (!the_locking_inset)
1977 updateLocal(bv, CURSOR, false);
1984 int InsetText::getMaxWidth(BufferView * bv, UpdatableInset const * inset) const
1987 int w = UpdatableInset::getMaxWidth(bv, inset);
1992 w = w - top_x + owner()->x();
1995 w -= (2 * TEXT_TO_INSET_OFFSET);
1998 return UpdatableInset::getMaxWidth(bv, inset);
2003 void InsetText::setParagraphData(Paragraph * p, bool same_id)
2005 // we have to unlock any locked inset otherwise we're in troubles
2006 the_locking_inset = 0;
2008 Paragraph * tmp = par->next();
2013 par = new Paragraph(*p, same_id);
2014 par->setInsetOwner(this);
2015 Paragraph * np = par;
2018 np->next(new Paragraph(*p, same_id));
2019 np->next()->previous(np);
2021 np->setInsetOwner(this);
2028 void InsetText::setText(string const & data)
2031 LyXFont font(LyXFont::ALL_SANE);
2032 for (unsigned int i=0; i < data.length(); ++i)
2033 par->insertChar(i, data[i], font);
2037 void InsetText::setAutoBreakRows(bool flag)
2039 if (flag != autoBreakRows) {
2040 autoBreakRows = flag;
2048 void InsetText::setDrawFrame(BufferView * bv, DrawFrame how)
2050 if (how != drawFrame_) {
2053 updateLocal(bv, DRAW_FRAME, false);
2058 void InsetText::setFrameColor(BufferView * bv, LColor::color col)
2060 if (frame_color != col) {
2063 updateLocal(bv, DRAW_FRAME, false);
2068 int InsetText::cx(BufferView * bv) const
2070 // we do nothing dangerous so we use a local cache
2071 LyXText * llt = getLyXText(bv);
2072 int x = llt->cursor.x() + top_x + TEXT_TO_INSET_OFFSET;
2073 if (the_locking_inset) {
2074 LyXFont font = llt->getFont(bv->buffer(), llt->cursor.par(),
2076 if (font.isVisibleRightToLeft())
2077 x -= the_locking_inset->width(bv, font);
2083 int InsetText::cy(BufferView * bv) const
2086 return getLyXText(bv)->cursor.y() - ascent(bv, font) + TEXT_TO_INSET_OFFSET;
2090 pos_type InsetText::cpos(BufferView * bv) const
2092 return getLyXText(bv)->cursor.pos();
2096 Paragraph * InsetText::cpar(BufferView * bv) const
2098 return getLyXText(bv)->cursor.par();
2102 bool InsetText::cboundary(BufferView * bv) const
2104 return getLyXText(bv)->cursor.boundary();
2108 Row * InsetText::crow(BufferView * bv) const
2110 return getLyXText(bv)->cursor.row();
2114 LyXText * InsetText::getLyXText(BufferView const * lbv,
2115 bool const recursive) const
2117 if (!recursive && (cached_bview == lbv)) {
2118 LyXText * lt = cached_text.get();
2119 lyx::Assert(lt && lt->firstRow()->par() == par);
2120 return cached_text.get();
2123 // Super UGLY! (Lgb)
2124 BufferView * bv = const_cast<BufferView *>(lbv);
2127 Cache::iterator it = cache.find(bv);
2129 if (it != cache.end()) {
2133 resizeLyXText(do_resize);
2134 if (lt || !it->second.remove) {
2135 lyx::Assert(it->second.text.get());
2136 cached_text = it->second.text;
2137 if (recursive && the_locking_inset) {
2138 return the_locking_inset->getLyXText(bv, true);
2140 return cached_text.get();
2141 } else if (it->second.remove) {
2143 saveLyXTextState(it->second.text.get());
2150 cached_text.reset(new LyXText(const_cast<InsetText *>(this)));
2151 cached_text->init(bv);
2152 restoreLyXTextState(bv, cached_text.get());
2154 cache.insert(make_pair(bv, cached_text));
2156 if (the_locking_inset && recursive) {
2157 return the_locking_inset->getLyXText(bv);
2159 return cached_text.get();
2163 void InsetText::deleteLyXText(BufferView * bv, bool recursive) const
2167 Cache::iterator it = cache.find(bv);
2169 if (it == cache.end()) {
2173 lyx::Assert(it->second.text.get());
2175 it->second.remove = true;
2177 /// then remove all LyXText in text-insets
2178 Paragraph * p = par;
2179 for (; p; p = p->next()) {
2180 p->deleteInsetsLyXText(bv);
2186 void InsetText::resizeLyXText(BufferView * bv, bool force) const
2189 // we cannot resize this because we are in use!
2190 // so do this on the next possible getLyXText()
2195 // lyxerr << "InsetText::resizeLyXText\n";
2196 if (!par->next() && !par->size()) { // no data, resize not neccessary!
2197 // we have to do this as a fixed width may have changed!
2198 LyXText * t = getLyXText(bv);
2199 saveLyXTextState(t);
2201 restoreLyXTextState(bv, t);
2204 // one endless line, resize normally not necessary
2205 if (!force && getMaxWidth(bv, this) < 0)
2208 Cache::iterator it = cache.find(bv);
2209 if (it == cache.end()) {
2212 lyx::Assert(it->second.text.get());
2214 LyXText * t = it->second.text.get();
2215 saveLyXTextState(t);
2216 for (Paragraph * p = par; p; p = p->next()) {
2217 p->resizeInsetsLyXText(bv);
2220 restoreLyXTextState(bv, t);
2221 if (the_locking_inset) {
2222 inset_x = cx(bv) - top_x + drawTextXOffset;
2223 inset_y = cy(bv) + drawTextYOffset;
2227 t->first = bv->screen()->topCursorVisible(t);
2230 updateLocal(bv, FULL, false);
2231 // this will scroll the screen such that the cursor becomes visible
2232 bv->updateScrollbar();
2234 need_update |= FULL;
2239 void InsetText::reinitLyXText() const
2242 // we cannot resize this because we are in use!
2243 // so do this on the next possible getLyXText()
2249 // lyxerr << "InsetText::reinitLyXText\n";
2250 for(Cache::iterator it = cache.begin(); it != cache.end(); ++it) {
2251 lyx::Assert(it->second.text.get());
2253 LyXText * t = it->second.text.get();
2254 BufferView * bv = it->first;
2256 saveLyXTextState(t);
2257 for (Paragraph * p = par; p; p = p->next()) {
2258 p->resizeInsetsLyXText(bv);
2261 restoreLyXTextState(bv, t);
2262 if (the_locking_inset) {
2263 inset_x = cx(bv) - top_x + drawTextXOffset;
2264 inset_y = cy(bv) + drawTextYOffset;
2267 t->first = bv->screen()->topCursorVisible(t);
2270 updateLocal(bv, FULL, false);
2271 // this will scroll the screen such that the cursor becomes visible
2272 bv->updateScrollbar();
2280 void InsetText::removeNewlines()
2282 bool changed = false;
2284 for (Paragraph * p = par; p; p = p->next()) {
2285 for (int i = 0; i < p->size(); ++i) {
2286 if (p->getChar(i) == Paragraph::META_NEWLINE) {
2297 bool InsetText::nodraw() const
2299 if (the_locking_inset)
2300 return the_locking_inset->nodraw();
2301 return UpdatableInset::nodraw();
2305 int InsetText::scroll(bool recursive) const
2307 int sx = UpdatableInset::scroll(false);
2309 if (recursive && the_locking_inset)
2310 sx += the_locking_inset->scroll(recursive);
2316 bool InsetText::doClearArea() const
2318 return !locked || (need_update & (FULL|INIT));
2322 void InsetText::selectAll(BufferView * bv)
2324 getLyXText(bv)->cursorTop(bv);
2325 getLyXText(bv)->selection.cursor = getLyXText(bv)->cursor;
2326 getLyXText(bv)->cursorBottom(bv);
2327 getLyXText(bv)->setSelection(bv);
2331 void InsetText::clearSelection(BufferView * bv)
2333 getLyXText(bv)->clearSelection();
2337 void InsetText::clearInset(BufferView * bv, int baseline, bool & cleared) const
2339 Painter & pain = bv->painter();
2341 int h = insetAscent + insetDescent;
2342 int ty = baseline - insetAscent;
2348 if ((ty + h) > pain.paperHeight())
2349 h = pain.paperHeight();
2350 if ((top_x + drawTextXOffset + w) > pain.paperWidth())
2351 w = pain.paperWidth();
2352 // w -= TEXT_TO_INSET_OFFSET;
2353 pain.fillRectangle(top_x, ty, w+1, h+1, backgroundColor());
2356 frame_is_visible = false;
2360 Paragraph * InsetText::getParFromID(int id) const
2363 Paragraph * result = par;
2364 Paragraph * ires = 0;
2365 while (result && result->id() != id) {
2366 if ((ires = result->getParFromID(id)))
2368 result = result->next();
2372 Paragraph * tmp = par;
2374 if (tmp->id() == id) {
2377 Paragraph * tmp2 = tmp->getParFromID(id);
2388 Paragraph * InsetText::firstParagraph() const
2391 if (the_locking_inset)
2392 if ((result = the_locking_inset->firstParagraph()))
2398 Paragraph * InsetText::getFirstParagraph(int i) const
2400 return (i == 0) ? par : 0;
2404 LyXCursor const & InsetText::cursor(BufferView * bv) const
2406 if (the_locking_inset)
2407 return the_locking_inset->cursor(bv);
2408 return getLyXText(bv)->cursor;
2412 Paragraph * InsetText::paragraph() const
2418 void InsetText::paragraph(Paragraph * p)
2420 // GENERAL COMMENT: We don't have to free the old paragraphs as the
2421 // caller of this function has to take care of it. This IS important
2422 // as we could have to insert a paragraph before this one and just
2423 // link the actual to a new ones next and set it with this function
2426 // set ourself as owner for all the paragraphs inserted!
2427 Paragraph * np = par;
2429 np->setInsetOwner(this);
2433 // redraw myself when asked for
2438 Inset * InsetText::getInsetFromID(int id_arg) const
2441 return const_cast<InsetText *>(this);
2443 Paragraph * lp = par;
2446 for (Paragraph::inset_iterator it = lp->inset_iterator_begin(),
2447 en = lp->inset_iterator_end();
2450 if ((*it)->id() == id_arg)
2452 Inset * in = (*it)->getInsetFromID(id_arg);
2462 string const InsetText::selectNextWordToSpellcheck(BufferView * bv, float & value) const
2468 lt = getLyXText(bv);
2471 if (the_locking_inset) {
2472 str = the_locking_inset->selectNextWordToSpellcheck(bv, value);
2479 #warning Dekel please have a look on this one RTL? (Jug)
2481 // we have to go on checking so move cusor to the right
2482 lt->cursor.pos(lt->cursor.pos() + 1);
2484 str = lt->selectNextWordToSpellcheck(bv, value);
2486 bv->unlockInset(const_cast<InsetText *>(this));
2495 void InsetText::selectSelectedWord(BufferView * bv)
2497 if (the_locking_inset) {
2498 the_locking_inset->selectSelectedWord(bv);
2501 getLyXText(bv)->selectSelectedWord(bv);
2502 updateLocal(bv, SELECTION, false);
2506 void InsetText::toggleSelection(BufferView * bv, bool kill_selection)
2508 if (the_locking_inset) {
2509 the_locking_inset->toggleSelection(bv, kill_selection);
2513 lt = getLyXText(bv);
2517 int x = top_x + TEXT_TO_INSET_OFFSET;
2519 Row * row = lt->firstRow();
2520 int y_offset = top_baseline - row->ascent_of_text();
2522 while ((row != 0) && ((y+row->height()) <= 0)) {
2529 if (need_update & SELECTION)
2531 bv->screen()->toggleSelection(lt, bv, kill_selection, y_offset, x);
2537 bool InsetText::searchForward(BufferView * bv, string const & str,
2540 if (the_locking_inset) {
2541 if (the_locking_inset->searchForward(bv, str, cs, mw))
2545 lt = getLyXText(bv);
2548 Paragraph * lpar = lt->cursor.par();
2549 pos_type pos = lt->cursor.pos();
2550 if (pos < lpar->size() - 1)
2554 lpar = lpar->next();
2559 // we have to unlock ourself in this function by default!
2560 bv->unlockInset(const_cast<InsetText *>(this));
2563 lt->setCursor(bv, lpar, pos);
2567 if (LyXFind(bv, str, true, true, cs , mw)) {
2570 // we have to unlock ourself in this function by default!
2571 bv->unlockInset(const_cast<InsetText *>(this));
2575 bool InsetText::searchBackward(BufferView * bv, string const & str,
2578 if (the_locking_inset)
2579 if (the_locking_inset->searchBackward(bv, str, cs, mw))
2581 if (LyXFind(bv, str, false, true, cs, mw)) {
2584 // we have to unlock ourself in this function by default!
2585 bv->unlockInset(const_cast<InsetText *>(this));
2590 bool InsetText::checkInsertChar(LyXFont & font)
2593 return owner()->checkInsertChar(font);
2598 void InsetText::collapseParagraphs(BufferParams const & bparams) const
2600 while(par->next()) {
2601 if (!par->isSeparator(par->size()-1))
2602 par->insertChar(par->size()-1, ' ');
2603 par->pasteParagraph(bparams);