2 /* This file is part of
3 * ======================================================
5 * LyX, The Document Processor
7 * Copyright 1998 The LyX Team.
9 * ======================================================
23 #pragma implementation
26 #include "insettext.h"
31 #include "commandtags.h"
34 #include "BufferView.h"
35 #include "support/textutils.h"
37 #include "insetlatexaccent.h"
38 #include "insetquotes.h"
39 #include "mathed/formulamacro.h"
41 #include "insetinfo.h"
42 #include "insetinclude.h"
44 #include "insetcommand.h"
45 #include "insetindex.h"
46 #include "insetlabel.h"
48 //#include "insettabular.h"
50 #include "insetspecialchar.h"
51 #include "LaTeXFeatures.h"
53 #include "lyx_gui_misc.h"
54 #include "support/LAssert.h"
56 extern unsigned char getCurrentTextClass(Buffer *);
58 InsetText::InsetText(Buffer * buf)
60 par = new LyXParagraph();
61 the_locking_inset = 0;
63 cursor_visible = false;
64 maxWidth = old_x = -1;
65 actpos = selection_start = selection_end = 0;
69 maxAscent = maxDescent = insetWidth = widthOffset = 0;
70 autoBreakRows = false;
75 InsetText::InsetText(InsetText const & ins, Buffer * buf)
77 par = new LyXParagraph(ins.par);
78 the_locking_inset = 0;
80 cursor_visible = false;
81 maxWidth = old_x = -1;
82 actpos = selection_start = selection_end = 0;
86 maxAscent = maxDescent = insetWidth = widthOffset = 0;
87 autoBreakRows = false;
92 InsetText::~InsetText()
98 Inset * InsetText::Clone() const
100 InsetText * t = new InsetText(*this, buffer);
105 void InsetText::Write(ostream & os) const
108 WriteParagraphData(os);
112 void InsetText::WriteParagraphData(ostream & os) const
114 par->writeFile(os, buffer->params, 0, 0);
118 void InsetText::Read(LyXLex & lex)
120 string token, tmptok;
122 LyXParagraph * return_par = 0;
123 char depth = 0; // signed or unsigned?
124 LyXParagraph::footnote_flag footnoteflag = LyXParagraph::NO_FOOTNOTE;
125 LyXParagraph::footnote_kind footnotekind = LyXParagraph::FOOTNOTE;
126 LyXFont font(LyXFont::ALL_INHERIT);
129 par = new LyXParagraph;
133 token = lex.GetString();
136 if (token == "\\end_inset")
138 if (buffer->parseSingleLyXformat2Token(lex, par, return_par,
142 // the_end read this should NEVER happen
143 lex.printError("\\the_end read in inset! Error in document!");
147 if (token != "\\end_inset") {
148 lex.printError("Missing \\end_inset at this point. "
155 int InsetText::ascent(Painter & pain, LyXFont const & font) const
158 computeTextRows(pain, xpos);
163 return font.maxAscent();
167 int InsetText::descent(Painter & pain, LyXFont const & font) const
170 computeTextRows(pain, xpos);
175 return font.maxDescent();
179 int InsetText::width(Painter & pain, LyXFont const &) const
182 computeTextRows(pain, xpos);
189 void InsetText::draw(Painter & pain, LyXFont const & f,
190 int baseline, float & x) const
193 computeTextRows(pain, x);
194 UpdatableInset::draw(pain, f, baseline, x);
197 top_baseline = baseline;
198 computeBaselines(baseline);
199 for(RowList::size_type r = 0; r < rows.size() - 1; ++r) {
200 drawRowSelection(pain, rows[r].pos, rows[r + 1].pos, r,
201 rows[r].baseline, x);
202 drawRowText(pain, rows[r].pos, rows[r + 1].pos, rows[r].baseline, x);
208 void InsetText::drawRowSelection(Painter & pain, int startpos, int endpos,
209 int row, int baseline, float x) const
215 if (selection_start > selection_end) {
216 s_start = selection_end;
217 s_end = selection_start;
219 s_start = selection_start;
220 s_end = selection_end;
222 if ((s_start > endpos) || (s_end < startpos))
226 int ssel_x = esel_x = int(x);
229 for(; p < endpos; ++p) {
232 if ((p >= s_start) && (p <= s_end))
234 char ch = par->GetChar(p);
235 font = GetFont(par,p);
236 if (IsFloatChar(ch)) {
238 } else if (ch == LyXParagraph::META_INSET) {
239 Inset const * tmpinset = par->GetInset(p);
240 x += tmpinset->width(pain, font);
242 x += pain.width(ch,font);
247 if ((p >= s_start) && (p <= s_end))
249 if (ssel_x < esel_x) {
250 pain.fillRectangle(int(ssel_x), baseline-rows[row].asc,
251 int(esel_x - ssel_x),
252 rows[row].asc + rows[row].desc,
258 void InsetText::drawRowText(Painter & pain, int startpos, int endpos,
259 int baseline, float x) const
261 Assert(endpos <= par->Last());
263 for(int p = startpos; p < endpos; ++p) {
264 char ch = par->GetChar(p);
265 LyXFont font = GetFont(par,p);
266 if (IsFloatChar(ch)) {
268 } else if (par->IsNewline(p)) {
269 // Draw end-of-line marker
270 int wid = font.width('n');
271 int asc = font.maxAscent();
275 xp[0] = int(x + wid * 0.375);
276 yp[0] = int(y - 0.875 * asc * 0.75);
279 yp[1] = int(y - 0.500 * asc * 0.75);
281 xp[2] = int(x + wid * 0.375);
282 yp[2] = int(y - 0.125 * asc * 0.75);
284 pain.lines(xp, yp, 3, LColor::eolmarker);
287 yp[0] = int(y - 0.500 * asc * 0.75);
289 xp[1] = int(x + wid);
290 yp[1] = int(y - 0.500 * asc * 0.75);
292 xp[2] = int(x + wid);
293 yp[2] = int(y - asc * 0.75);
295 pain.lines(xp, yp, 3, LColor::eolmarker);
297 } else if (ch == LyXParagraph::META_INSET) {
298 Inset * tmpinset = par->GetInset(p);
300 tmpinset->draw(pain, font, baseline, x);
302 pain.text(int(x), baseline, ch, font);
303 x += pain.width(ch,font);
309 char const * InsetText::EditMessage() const
311 return _("Opened Text Inset");
315 void InsetText::Edit(BufferView * bv, int x, int y, unsigned int button)
317 UpdatableInset::Edit(bv, x, y, button);
320 the_locking_inset = 0;
321 inset_pos = inset_x = inset_y = 0;
324 selection_start = selection_end = actpos;
325 current_font = real_current_font = GetFont(par, actpos);
329 void InsetText::InsetUnlock(BufferView * bv)
331 if (the_locking_inset)
332 the_locking_inset->InsetUnlock(bv);
334 if (hasSelection()) {
335 selection_start = selection_end = actpos;
336 UpdateLocal(bv, false);
338 the_locking_inset = 0;
339 no_selection = false;
343 bool InsetText::UnlockInsetInInset(BufferView * bv, Inset * inset, bool lr)
345 if (!the_locking_inset)
347 if (the_locking_inset == inset) {
348 the_locking_inset->InsetUnlock(bv);
349 the_locking_inset = 0;
351 moveRight(bv, false);
354 return the_locking_inset->UnlockInsetInInset(bv, inset,lr);
358 bool InsetText::UpdateInsetInInset(BufferView * bv, Inset * inset)
360 if (!the_locking_inset)
362 if (the_locking_inset != inset)
363 return the_locking_inset->UpdateInsetInInset(bv, inset);
365 inset->draw(bv->getPainter(), real_current_font, inset_y, x);
366 UpdateLocal(bv, true);
371 void InsetText::InsetButtonRelease(BufferView * bv, int x, int y, int button)
373 if (the_locking_inset) {
374 the_locking_inset->InsetButtonRelease(bv, x-inset_x, y-inset_y,button);
377 no_selection = false;
381 void InsetText::InsetButtonPress(BufferView * bv, int x, int y, int button)
383 if (hasSelection()) {
384 selection_start = selection_end = actpos;
385 UpdateLocal(bv, false);
387 no_selection = false;
388 if (the_locking_inset) {
389 setPos(bv, x, y, false);
392 if (par->GetChar(actpos) == LyXParagraph::META_INSET)
393 inset = static_cast<UpdatableInset*>(par->GetInset(actpos));
394 if (the_locking_inset == inset) {
395 the_locking_inset->InsetButtonPress(bv,x-inset_x,y-inset_y,button);
398 // otherwise unlock the_locking_inset and lock the new inset
402 the_locking_inset->InsetUnlock(bv);
403 the_locking_inset = inset;
404 the_locking_inset->Edit(bv, x - inset_x, y - inset_y, button);
407 // otherwise only unlock the_locking_inset
408 the_locking_inset->InsetUnlock(bv);
411 the_locking_inset = 0;
413 selection_start = selection_end = actpos;
414 if (!the_locking_inset)
419 void InsetText::InsetMotionNotify(BufferView * bv, int x, int y, int button)
421 if (the_locking_inset) {
422 the_locking_inset->InsetMotionNotify(bv, x - inset_x,
427 int old = selection_end;
428 setPos(bv, x, y, false);
429 selection_end = actpos;
430 if (old != selection_end)
431 UpdateLocal(bv, false);
433 no_selection = false;
437 void InsetText::InsetKeyPress(XKeyEvent * xke)
439 if (the_locking_inset) {
440 the_locking_inset->InsetKeyPress(xke);
446 UpdatableInset::RESULT
447 InsetText::LocalDispatch(BufferView * bv,
448 int action, string const & arg)
450 no_selection = false;
451 if (UpdatableInset::LocalDispatch(bv, action, arg)) {
456 UpdatableInset::RESULT
459 if ((action < 0) && arg.empty())
462 if ((action != LFUN_DOWN) && (action != LFUN_UP) &&
463 (action != LFUN_DOWNSEL) && (action != LFUN_UPSEL))
465 if (the_locking_inset) {
466 result = the_locking_inset->LocalDispatch(bv, action, arg);
467 if (result == DISPATCHED) {
468 the_locking_inset->ToggleInsetCursor(bv);
469 UpdateLocal(bv, false);
470 the_locking_inset->ToggleInsetCursor(bv);
472 } else if (result == FINISHED) {
473 if ((action == LFUN_RIGHT) || (action == -1)) {
474 actpos = inset_pos + 1;
477 the_locking_inset = 0;
486 actpos = selection_start;
487 par->InsertChar(actpos,arg[0]);
488 par->SetFont(actpos,real_current_font);
490 selection_start = selection_end = actpos;
491 UpdateLocal(bv, true);
493 // --- Cursor Movements ---------------------------------------------
495 moveRight(bv, false);
496 selection_end = actpos;
497 UpdateLocal(bv, false);
500 result= DISPATCH_RESULT(moveRight(bv));
501 if (hasSelection()) {
502 selection_start = selection_end = actpos;
503 UpdateLocal(bv, false);
505 selection_start = selection_end = actpos;
510 selection_end = actpos;
511 UpdateLocal(bv, false);
514 result= DISPATCH_RESULT(moveLeft(bv));
515 if (hasSelection()) {
516 selection_start = selection_end = actpos;
517 UpdateLocal(bv, false);
519 selection_start = selection_end = actpos;
524 selection_end = actpos;
525 UpdateLocal(bv, false);
528 result= DISPATCH_RESULT(moveDown(bv));
529 if (hasSelection()) {
530 selection_start = selection_end = actpos;
531 UpdateLocal(bv, false);
533 selection_start = selection_end = actpos;
538 selection_end = actpos;
539 UpdateLocal(bv, false);
542 result= DISPATCH_RESULT(moveUp(bv));
543 if (hasSelection()) {
544 selection_start = selection_end = actpos;
545 UpdateLocal(bv, false);
547 selection_start = selection_end = actpos;
551 if (!actpos || par->IsNewline(actpos-1)) {
552 if (hasSelection()) {
553 selection_start = selection_end = actpos;
554 UpdateLocal(bv, false);
562 ret = cutSelection();
565 if (ret) { // we need update
566 selection_start = selection_end = actpos;
567 UpdateLocal(bv, true);
568 } else if (hasSelection()) {
569 selection_start = selection_end = actpos;
570 UpdateLocal(bv, false);
574 if (cutSelection()) { // we need update
575 actpos = selection_end = selection_start;
576 UpdateLocal(bv, true);
577 } else if (hasSelection()) {
578 selection_start = selection_end = actpos;
579 UpdateLocal(bv, false);
583 if (copySelection()) { // we need update
584 selection_start = selection_end = actpos;
585 UpdateLocal(bv, true);
586 } else if (hasSelection()) {
587 selection_start = selection_end = actpos;
588 UpdateLocal(bv, false);
592 if (pasteSelection()) {
593 selection_start = selection_end = actpos;
594 UpdateLocal(bv, true);
598 for(; actpos > rows[actrow].pos; --actpos)
599 cx -= SingleWidth(bv->getPainter(), par, actpos);
600 cx -= SingleWidth(bv->getPainter(), par, actpos);
601 if (hasSelection()) {
602 selection_start = selection_end = actpos;
603 UpdateLocal(bv, false);
605 selection_start = selection_end = actpos;
610 int checkpos = (int)rows[actrow + 1].pos;
611 if ((actrow + 2) < (int)rows.size())
613 for(; actpos < checkpos; ++actpos)
614 cx += SingleWidth(bv->getPainter(), par, actpos);
615 if (hasSelection()) {
616 selection_start = selection_end = actpos;
617 UpdateLocal(bv, false);
619 selection_start = selection_end = actpos;
623 case LFUN_MATH_MODE: // Open or create a math inset
624 InsertInset(bv, new InsetFormula);
625 if (hasSelection()) {
626 selection_start = selection_end = actpos;
627 UpdateLocal(bv, false);
629 selection_start = selection_end = actpos;
633 par->InsertChar(actpos,LyXParagraph::META_NEWLINE);
634 par->SetFont(actpos,real_current_font);
635 UpdateLocal(bv, true);
637 selection_start = selection_end = actpos;
641 result = UNDISPATCHED;
644 if (result != FINISHED) {
645 if (!the_locking_inset)
648 bv->unlockInset(this);
653 int InsetText::Latex(ostream & os, signed char /*fragile*/, bool) const
656 int ret = par->SimpleTeXOnePar(os, texrow);
661 void InsetText::Validate(LaTeXFeatures & features) const
663 par->validate(features);
667 // Returns the width of a character at a certain spot
668 int InsetText::SingleWidth(Painter & pain, LyXParagraph * par, int pos) const
670 LyXFont font = GetFont(par, pos);
671 char c = par->GetChar(pos);
673 if (IsPrintable(c)) {
674 return font.width(c);
675 } else if (c == LyXParagraph::META_INSET) {
676 Inset const * tmpinset = par->GetInset(pos);
678 return tmpinset->width(pain, font);
681 } else if (IsSeparatorChar(c))
683 else if (IsNewlineChar(c))
685 return font.width(c);
689 // Returns the width of a character at a certain spot
690 void InsetText::SingleHeight(Painter & pain, LyXParagraph * par,int pos,
691 int & asc, int & desc) const
693 LyXFont font = GetFont(par, pos);
694 char c = par->GetChar(pos);
697 if (c == LyXParagraph::META_INSET) {
698 Inset const * tmpinset=par->GetInset(pos);
700 asc = tmpinset->ascent(pain, font);
701 desc = tmpinset->descent(pain, font);
704 asc = font.maxAscent();
705 desc = font.maxDescent();
711 // Gets the fully instantiated font at a given position in a paragraph
712 // Basically the same routine as LyXParagraph::getFont() in paragraph.C.
713 // The difference is that this one is used for displaying, and thus we
714 // are allowed to make cosmetic improvements. For instance make footnotes
716 // If position is -1, we get the layout font of the paragraph.
717 // If position is -2, we get the font of the manual label of the paragraph.
718 LyXFont InsetText::GetFont(LyXParagraph * par, int pos) const
720 char par_depth = par->GetDepth();
722 LyXLayout const & layout =
723 textclasslist.Style(buffer->params.textclass, par->GetLayout());
725 // We specialize the 95% common case:
726 if (par->footnoteflag == LyXParagraph::NO_FOOTNOTE && !par_depth) {
729 if (layout.labeltype == LABEL_MANUAL
730 && pos < BeginningOfMainBody(par)) {
732 return par->GetFontSettings(pos).realize(layout.reslabelfont);
734 return par->GetFontSettings(pos).realize(layout.resfont);
737 // process layoutfont for pos == -1 and labelfont for pos < -1
739 return layout.resfont;
741 return layout.reslabelfont;
744 // The uncommon case need not be optimized as much
746 LyXFont layoutfont, tmpfont;
750 if (pos < BeginningOfMainBody(par)) {
752 layoutfont = layout.labelfont;
755 layoutfont = layout.font;
757 tmpfont = par->GetFontSettings(pos);
758 tmpfont.realize(layoutfont);
761 // process layoutfont for pos == -1 and labelfont for pos < -1
763 tmpfont = layout.font;
765 tmpfont = layout.labelfont;
768 // Resolve against environment font information
769 //if (par->GetDepth()){ // already in while condition
770 while (par && par_depth && !tmpfont.resolved()) {
771 par = par->DepthHook(par_depth - 1);
773 tmpfont.realize(textclasslist.Style(buffer->params.textclass,
774 par->GetLayout()).font);
775 par_depth = par->GetDepth();
778 tmpfont.realize((textclasslist.TextClass(buffer->params.textclass).
784 int InsetText::BeginningOfMainBody(LyXParagraph * par) const
786 if (textclasslist.Style(buffer->params.textclass,
787 par->GetLayout()).labeltype != LABEL_MANUAL)
790 return par->BeginningOfMainBody();
794 void InsetText::GetCursorPos(int & x, int & y) const
801 int InsetText::InsetInInsetY()
803 if (!the_locking_inset)
807 return (y + the_locking_inset->InsetInInsetY());
811 void InsetText::ToggleInsetCursor(BufferView * bv)
813 if (the_locking_inset) {
814 the_locking_inset->ToggleInsetCursor(bv);
818 LyXFont font = GetFont(par, actpos);
820 int asc = font.maxAscent();
821 int desc = font.maxDescent();
824 bv->hideLockedInsetCursor();
826 bv->showLockedInsetCursor(cx, cy, asc, desc);
827 cursor_visible = !cursor_visible;
831 void InsetText::ShowInsetCursor(BufferView * bv)
833 if (!cursor_visible) {
834 LyXFont font = GetFont(par, actpos);
836 int asc = font.maxAscent();
837 int desc = font.maxDescent();
838 bv->fitLockedInsetCursor(cx, cy, asc, desc);
839 bv->showLockedInsetCursor(cx, cy, asc, desc);
840 cursor_visible = true;
845 void InsetText::HideInsetCursor(BufferView * bv)
848 ToggleInsetCursor(bv);
852 void InsetText::setPos(BufferView * bv, int x, int y, bool activate_inset)
857 // search right X-pos x==0 -> top_x
861 for(unsigned int i = 1;
862 ((cy + rows[i - 1].desc) < y) && (i < rows.size() - 1); ++i) {
863 cy = rows[i].baseline;
864 actpos = rows[i].pos;
875 sw = swh = SingleWidth(bv->getPainter(), par,actpos);
876 if (par->GetChar(actpos)!=LyXParagraph::META_INSET)
878 checkpos = rows[actrow + 1].pos;
879 if ((actrow+2) < (int)rows.size())
881 while ((actpos < checkpos) && ((cx + swh) < x)) {
884 sw = swh = SingleWidth(bv->getPainter(), par,actpos);
885 if (par->GetChar(actpos)!=LyXParagraph::META_INSET)
888 if (activate_inset && par->GetChar(actpos)==LyXParagraph::META_INSET) {
890 static_cast<UpdatableInset*>(par->GetInset(actpos));
891 inset_x = cx - top_x;
894 the_locking_inset->Edit(bv, ox - inset_x, oy - inset_y, 0);
899 bool InsetText::moveRight(BufferView * bv, bool activate_inset)
901 if (actpos >= par->Last())
903 if (activate_inset && par->GetChar(actpos)==LyXParagraph::META_INSET) {
905 static_cast<UpdatableInset*>(par->GetInset(actpos));
906 inset_x = cx - top_x;
909 the_locking_inset->Edit(bv, 0, 0, 0);
918 bool InsetText::moveLeft(BufferView * bv, bool activate_inset)
923 if (activate_inset && par->GetChar(actpos)==LyXParagraph::META_INSET) {
925 static_cast<UpdatableInset*>(par->GetInset(actpos));
927 inset_x = cx - top_x;
930 the_locking_inset->Edit(bv, the_locking_inset->
931 width(bv->getPainter(), GetFont(par,actpos)),
940 bool InsetText::moveUp(BufferView * bv, bool activate_inset)
944 cy = rows[actrow - 1].baseline - top_baseline;
945 setPos(bv, cx - top_x, cy, activate_inset);
950 bool InsetText::moveDown(BufferView * bv, bool activate_inset)
952 if (actrow >= int(rows.size() - 2))
954 cy = rows[actrow + 1].baseline - top_baseline;
955 setPos(bv, cx - top_x, cy, activate_inset);
960 void InsetText::resetPos(BufferView * bv)
965 int old_pos = actpos;
969 for(unsigned int i = 0; (i < (rows.size()-1)) && (rows[i].pos <= actpos);
971 cy = rows[i].baseline;
975 setPos(bv, 0, cy, false);
977 while(actpos < old_pos) {
978 cx += SingleWidth(bv->getPainter(), par,actpos);
984 bool InsetText::Delete()
986 /* some insets are undeletable here */
987 if (par->GetChar(actpos)==LyXParagraph::META_INSET) {
988 /* force complete redo when erasing display insets */
989 /* this is a cruel method but save..... Matthias */
990 if (par->GetInset(actpos)->Deletable() &&
991 par->GetInset(actpos)->display()) {
1002 bool InsetText::InsertInset(BufferView * bv, Inset * inset)
1004 if (inset->Editable() == Inset::IS_EDITABLE) {
1005 UpdatableInset *i = (UpdatableInset *)inset;
1006 i->setOwner((UpdatableInset *)this);
1008 par->InsertChar(actpos, LyXParagraph::META_INSET);
1009 par->InsertInset(actpos, inset);
1010 UpdateLocal(bv, true);
1011 the_locking_inset = static_cast<UpdatableInset*>(inset);
1012 inset_x = cx - top_x;
1015 inset->Edit(bv, 0, 0, 0);
1020 UpdatableInset * InsetText::GetLockingInset()
1022 return the_locking_inset ? the_locking_inset->GetLockingInset() : this;
1026 void InsetText::SetFont(BufferView * bv, LyXFont const & font, bool toggleall)
1028 // if there is no selection just set the current_font
1029 if (!hasSelection()) {
1030 // Determine basis font
1032 if (actpos < BeginningOfMainBody(par))
1033 layoutfont = GetFont(par, -2);
1035 layoutfont = GetFont(par, -1);
1037 // Update current font
1038 real_current_font.update(font, bv->buffer()->params.language_info,
1041 // Reduce to implicit settings
1042 current_font = real_current_font;
1043 current_font.reduce(layoutfont);
1044 // And resolve it completely
1045 real_current_font.realize(layoutfont);
1050 if (selection_start > selection_end) {
1051 s_start = selection_end;
1052 s_end = selection_start;
1054 s_start = selection_start;
1055 s_end = selection_end;
1058 while(s_start < s_end) {
1059 newfont = GetFont(par,s_start);
1060 newfont.update(font, bv->buffer()->params.language_info, toggleall);
1061 SetCharFont(s_start, newfont);
1064 UpdateLocal(bv, true);
1068 void InsetText::SetCharFont(int pos, LyXFont const & f)
1070 /* let the insets convert their font */
1073 if (par->GetChar(pos) == LyXParagraph::META_INSET) {
1074 if (par->GetInset(pos))
1075 font = par->GetInset(pos)->ConvertFont(font);
1077 LyXLayout const & layout =
1078 textclasslist.Style(buffer->params.textclass,par->GetLayout());
1080 // Get concrete layout font to reduce against
1083 if (pos < BeginningOfMainBody(par))
1084 layoutfont = layout.labelfont;
1086 layoutfont = layout.font;
1089 layoutfont.realize((textclasslist.TextClass(buffer->params.textclass).
1092 // Now, reduce font against full layout font
1093 font.reduce(layoutfont);
1095 par->SetFont(pos, font);
1099 void InsetText::computeTextRows(Painter & pain, float x) const
1114 int width = wordAscent = wordDescent = 0;
1115 insetWidth = maxAscent = maxDescent = 0;
1120 rows.push_back(row);
1121 if (!autoBreakRows) {
1122 for(p = 0; p < par->Last(); ++p) {
1123 insetWidth += SingleWidth(pain, par, p);
1124 SingleHeight(pain, par, p, asc, desc);
1125 maxAscent = max(maxAscent, asc);
1126 maxDescent = max(maxDescent, desc);
1128 rows[0].asc = maxAscent;
1129 rows[0].desc = maxDescent;
1130 // alocate a dummy row for the endpos
1131 row.pos = par->Last();
1132 rows.push_back(row);
1136 bool is_first_word_in_row = true;
1138 int cw, lastWordWidth = 0;
1140 maxWidth = getMaxWidth(pain) - widthOffset;
1141 for(p = 0; p < par->Last(); ++p) {
1142 cw = SingleWidth(pain, par, p);
1144 lastWordWidth += cw;
1145 SingleHeight(pain, par, p, asc, desc);
1146 wordAscent = max(wordAscent, asc);
1147 wordDescent = max(wordDescent, desc);
1148 if (par->IsNewline(p)) {
1149 rows.back().asc = wordAscent;
1150 rows.back().desc = wordDescent;
1152 rows.push_back(row);
1153 SingleHeight(pain, par, p, oasc, odesc);
1154 width = lastWordWidth = 0;
1155 is_first_word_in_row = true;
1156 wordAscent = wordDescent = 0;
1159 Inset const * inset = 0;
1160 if (((p + 1) < par->Last()) &&
1161 (par->GetChar(p + 1)==LyXParagraph::META_INSET))
1162 inset = par->GetInset(p + 1);
1163 if (inset && inset->display()) {
1164 if (!is_first_word_in_row && (width >= (maxWidth - x))) {
1165 // we have to split also the row above
1166 rows.back().asc = oasc;
1167 rows.back().desc = odesc;
1169 rows.push_back(row);
1171 odesc = wordDescent;
1172 insetWidth = max(insetWidth, owidth);
1173 width = lastWordWidth;
1176 oasc = max(oasc, wordAscent);
1177 odesc = max(odesc, wordDescent);
1179 rows.back().asc = oasc;
1180 rows.back().desc = odesc;
1182 rows.push_back(row);
1183 SingleHeight(pain, par, p, asc, desc);
1184 rows.back().asc = asc;
1185 rows.back().desc = desc;
1186 row.pos = nwp = p + 1;
1187 rows.push_back(row);
1188 oasc = odesc = width = lastWordWidth = 0;
1189 is_first_word_in_row = true;
1190 wordAscent = wordDescent = 0;
1192 } else if (par->IsSeparator(p)) {
1193 if (width >= maxWidth - x) {
1194 if (is_first_word_in_row) {
1195 rows.back().asc = wordAscent;
1196 rows.back().desc = wordDescent;
1198 rows.push_back(row);
1199 oasc = odesc = width = 0;
1201 rows.back().asc = oasc;
1202 rows.back().desc = odesc;
1204 rows.push_back(row);
1206 odesc = wordDescent;
1207 insetWidth = max(insetWidth, owidth);
1208 width = lastWordWidth;
1210 wordAscent = wordDescent = lastWordWidth = 0;
1215 oasc = max(oasc, wordAscent);
1216 odesc = max(odesc, wordDescent);
1217 wordAscent = wordDescent = lastWordWidth = 0;
1219 is_first_word_in_row = false;
1222 // if we have some data in the paragraph we have ascent/descent
1224 if (width >= (maxWidth - x)) {
1226 rows.back().asc = oasc;
1227 rows.back().desc = odesc;
1228 // assign and allocate lower row
1230 rows.push_back(row);
1231 rows.back().asc = wordAscent;
1232 rows.back().desc = wordDescent;
1233 width -= lastWordWidth;
1235 // assign last row data
1236 // width = lastWordWidth;
1237 // lastWordWidth = 0;
1238 rows.back().asc = max(oasc, wordAscent);
1239 rows.back().desc = max(odesc, wordDescent);
1242 insetWidth = max(insetWidth, width);
1243 // alocate a dummy row for the endpos
1244 row.pos = par->Last();
1245 rows.push_back(row);
1246 // calculate maxAscent/Descent
1247 maxAscent = rows[0].asc;
1248 maxDescent = rows[0].desc;
1249 for (RowList::size_type i = 1; i < rows.size() - 1; ++i) {
1250 maxDescent += rows[i].asc + rows[i].desc + interline_space;
1253 if (the_locking_inset) {
1254 computeBaselines(top_baseline);
1257 inset_x = cx - top_x;
1264 void InsetText::computeBaselines(int baseline) const
1266 rows[0].baseline = baseline;
1267 for (unsigned int i = 1; i < rows.size() - 1; i++) {
1268 rows[i].baseline = rows[i - 1].baseline + rows[i - 1].desc +
1269 rows[i].asc + interline_space;
1273 void InsetText::UpdateLocal(BufferView *bv, bool flag)
1275 HideInsetCursor(bv);
1277 computeTextRows(bv->painter(), xpos);
1278 computeBaselines(top_baseline);
1281 bv->updateInset(this, flag);
1282 ShowInsetCursor(bv);
1285 // this is for the simple cut and paste mechanism
1286 // this then should be a global stuff so that cut'n'paste can work in and
1287 // and outside text-insets
1288 static LyXParagraph * simple_cut_buffer = 0;
1289 // static char simple_cut_buffer_textclass = 0;
1291 // for now here this should be in another Cut&Paste Class!
1293 static void DeleteSimpleCutBuffer()
1295 if (!simple_cut_buffer)
1297 LyXParagraph * tmppar;
1299 while (simple_cut_buffer) {
1300 tmppar = simple_cut_buffer;
1301 simple_cut_buffer = simple_cut_buffer->next;
1304 simple_cut_buffer = 0;
1307 bool InsetText::cutSelection()
1309 if (!hasSelection())
1311 DeleteSimpleCutBuffer();
1313 // only within one paragraph
1314 simple_cut_buffer = new LyXParagraph;
1315 LyXParagraph::size_type i = selection_start;
1316 for (; i < selection_end; ++i) {
1317 par->CopyIntoMinibuffer(selection_start);
1318 par->Erase(selection_start);
1319 simple_cut_buffer->InsertFromMinibuffer(simple_cut_buffer->Last());
1324 bool InsetText::copySelection()
1326 if (!hasSelection())
1328 DeleteSimpleCutBuffer();
1330 // only within one paragraph
1331 simple_cut_buffer = new LyXParagraph;
1332 LyXParagraph::size_type i = selection_start;
1333 for (; i < selection_end; ++i) {
1334 par->CopyIntoMinibuffer(i);
1335 simple_cut_buffer->InsertFromMinibuffer(simple_cut_buffer->Last());
1340 bool InsetText::pasteSelection()
1342 if (!simple_cut_buffer)
1345 LyXParagraph * tmppar = simple_cut_buffer->Clone();
1347 while (simple_cut_buffer->size()) {
1348 simple_cut_buffer->CutIntoMinibuffer(0);
1349 simple_cut_buffer->Erase(0);
1350 par->InsertFromMinibuffer(actpos);
1353 delete simple_cut_buffer;
1354 simple_cut_buffer = tmppar;