2 /* This file is part of
3 * ======================================================
5 * LyX, The Document Processor
7 * Copyright 1998 The LyX Team.
9 * ======================================================
20 #pragma implementation
23 #include "insettext.h"
28 #include "commandtags.h"
31 #include "BufferView.h"
32 #include "support/textutils.h"
34 #include "insetlatexaccent.h"
35 #include "insetquotes.h"
36 #include "mathed/formulamacro.h"
38 #include "insetinfo.h"
39 #include "insetinclude.h"
41 #include "insetcommand.h"
42 #include "insetindex.h"
43 #include "insetlabel.h"
45 //#include "insettabular.h"
47 #include "insetspecialchar.h"
48 #include "LaTeXFeatures.h"
50 #include "lyx_gui_misc.h"
51 #include "support/LAssert.h"
53 extern unsigned char getCurrentTextClass(Buffer *);
55 InsetText::InsetText(Buffer * buf)
57 par = new LyXParagraph();
58 the_locking_inset = 0;
60 cursor_visible = false;
61 maxWidth = old_x = -1;
62 actpos = selection_start = selection_end = 0;
69 InsetText::InsetText(InsetText const & ins, Buffer * buf)
71 par = new LyXParagraph(ins.par);
72 the_locking_inset = 0;
74 cursor_visible = false;
75 maxWidth = old_x = -1;
76 actpos = selection_start = selection_end = 0;
83 InsetText::~InsetText()
89 Inset * InsetText::Clone() const
91 InsetText * t = new InsetText(*this, buffer);
96 void InsetText::Write(ostream & os) const
99 WriteParagraphData(os);
103 void InsetText::WriteParagraphData(ostream & os) const
105 par->writeFile(os, buffer->params, 0, 0);
109 void InsetText::Read(LyXLex & lex)
111 string token, tmptok;
113 LyXParagraph * return_par = 0;
114 char depth = 0; // signed or unsigned?
115 LyXParagraph::footnote_flag footnoteflag = LyXParagraph::NO_FOOTNOTE;
116 LyXParagraph::footnote_kind footnotekind = LyXParagraph::FOOTNOTE;
117 LyXFont font(LyXFont::ALL_INHERIT);
120 par = new LyXParagraph;
124 token = lex.GetString();
127 if (token == "\\end_inset")
129 if (buffer->parseSingleLyXformat2Token(lex, par, return_par,
133 // the_end read this should NEVER happen
134 lex.printError("\\the_end read in inset! Error in document!");
138 if (token != "\\end_inset") {
139 lex.printError("Missing \\end_inset at this point. "
146 int InsetText::ascent(Painter & pain, LyXFont const & font) const
149 computeTextRows(pain);
154 return font.maxAscent();
158 int InsetText::descent(Painter & pain, LyXFont const & font) const
161 computeTextRows(pain);
166 return font.maxDescent();
170 int InsetText::width(Painter & pain, LyXFont const &) const
173 computeTextRows(pain);
180 int InsetText::getMaxWidth(UpdatableInset * inset) const
182 if (!the_locking_inset) {
183 lyxerr << "Text: No locking inset in this inset.\n";
187 if (the_locking_inset == inset)
190 return the_locking_inset->getMaxWidth(inset);
194 void InsetText::draw(Painter & pain, LyXFont const & f,
195 int baseline, float & x) const
198 computeTextRows(pain);
199 // init_inset = false;
201 UpdatableInset::draw(pain, f, baseline, x);
203 bool do_reset_pos = (x != top_x) || (baseline != top_baseline);
205 top_baseline = baseline;
206 computeBaselines(baseline);
207 for(unsigned int r = 0; r < rows.size() - 1; ++r) {
208 drawRowSelection(pain, rows[r].pos, rows[r + 1].pos, r,
209 rows[r].baseline, x);
210 drawRowText(pain, rows[r].pos, rows[r + 1].pos, rows[r].baseline, x);
213 if (!the_locking_inset && do_reset_pos) {
214 // HideInsetCursor(bv);
216 // ShowInsetCursor(bv);
221 void InsetText::drawRowSelection(Painter & pain, int startpos, int endpos,
222 int row, int baseline, float x) const
228 if (selection_start > selection_end) {
229 s_start = selection_end;
230 s_end = selection_start;
232 s_start = selection_start;
233 s_end = selection_end;
235 if ((s_start > endpos) || (s_end < startpos))
239 int ssel_x = esel_x = int(x);
242 for(; p < endpos; ++p) {
245 if ((p >= s_start) && (p <= s_end))
247 char ch = par->GetChar(p);
248 font = GetFont(par,p);
249 if (IsFloatChar(ch)) {
251 } else if (ch == LyXParagraph::META_INSET) {
252 Inset const * tmpinset = par->GetInset(p);
253 x += tmpinset->width(pain, font);
255 x += pain.width(ch,font);
260 if ((p >= s_start) && (p <= s_end))
262 if (ssel_x < esel_x) {
263 pain.fillRectangle(int(ssel_x), baseline-rows[row].asc,
264 int(esel_x - ssel_x),
265 rows[row].asc + rows[row].desc,
271 void InsetText::drawRowText(Painter & pain, int startpos, int endpos,
272 int baseline, float x) const
274 Assert(endpos <= par->Last());
276 for(int p = startpos; p < endpos; ++p) {
277 char ch = par->GetChar(p);
278 LyXFont font = GetFont(par,p);
279 if (IsFloatChar(ch)) {
281 } else if (ch == LyXParagraph::META_INSET) {
282 Inset * tmpinset = par->GetInset(p);
284 tmpinset->draw(pain, font, baseline, x);
286 pain.text(int(x), baseline, ch, font);
287 x += pain.width(ch,font);
293 char const * InsetText::EditMessage() const
295 return _("Opened Text Inset");
299 void InsetText::Edit(BufferView * bv, int x, int y, unsigned int button)
301 UpdatableInset::Edit(bv, x, y, button);
304 the_locking_inset = 0;
305 inset_pos = inset_x = inset_y = 0;
308 selection_start = selection_end = actpos;
309 current_font = real_current_font = GetFont(par, actpos);
313 void InsetText::InsetUnlock(BufferView * bv)
315 if (the_locking_inset)
316 the_locking_inset->InsetUnlock(bv);
318 if (hasSelection()) {
319 selection_start = selection_end = actpos;
320 bv->updateInset(this, false);
322 the_locking_inset = 0;
323 no_selection = false;
327 bool InsetText::UnlockInsetInInset(BufferView * bv, Inset * inset, bool lr)
329 if (!the_locking_inset)
331 if (the_locking_inset == inset) {
332 the_locking_inset->InsetUnlock(bv);
333 the_locking_inset = 0;
335 moveRight(bv, false);
338 return the_locking_inset->UnlockInsetInInset(bv, inset,lr);
342 bool InsetText::UpdateInsetInInset(BufferView * bv, Inset * inset)
344 if (!the_locking_inset)
346 if (the_locking_inset != inset)
347 return the_locking_inset->UpdateInsetInInset(bv, inset);
349 inset->draw(bv->getPainter(), real_current_font, inset_y, x);
350 bv->updateInset(this, true);
355 void InsetText::InsetButtonRelease(BufferView * bv, int x, int y, int button)
357 if (the_locking_inset) {
358 the_locking_inset->InsetButtonRelease(bv, x-inset_x, y-inset_y,button);
361 no_selection = false;
365 void InsetText::InsetButtonPress(BufferView * bv, int x, int y, int button)
367 if (hasSelection()) {
368 selection_start = selection_end = actpos;
369 bv->updateInset(this, false);
371 no_selection = false;
372 if (the_locking_inset) {
373 setPos(bv, x, y, false);
376 if (par->GetChar(actpos) == LyXParagraph::META_INSET)
377 inset = static_cast<UpdatableInset*>(par->GetInset(actpos));
378 if (the_locking_inset == inset) {
379 the_locking_inset->InsetButtonPress(bv,x-inset_x,y-inset_y,button);
382 // otherwise unlock the_locking_inset and lock the new inset
386 the_locking_inset->InsetUnlock(bv);
387 the_locking_inset = inset;
388 the_locking_inset->Edit(bv, x - inset_x, y - inset_y, button);
391 // otherwise only unlock the_locking_inset
392 the_locking_inset->InsetUnlock(bv);
395 the_locking_inset = 0;
397 selection_start = selection_end = actpos;
398 if (!the_locking_inset)
403 void InsetText::InsetMotionNotify(BufferView * bv, int x, int y, int button)
405 if (the_locking_inset) {
406 the_locking_inset->InsetMotionNotify(bv, x - inset_x,
411 int old = selection_end;
412 setPos(bv, x, y, false);
413 selection_end = actpos;
414 if (old != selection_end)
415 bv->updateInset(this, false);
417 no_selection = false;
421 void InsetText::InsetKeyPress(XKeyEvent * xke)
423 if (the_locking_inset) {
424 the_locking_inset->InsetKeyPress(xke);
430 UpdatableInset::RESULT
431 InsetText::LocalDispatch(BufferView * bv,
432 int action, string const & arg)
434 no_selection = false;
435 if (UpdatableInset::LocalDispatch(bv, action, arg)) {
440 UpdatableInset::RESULT
443 if ((action < 0) && arg.empty())
446 if ((action != LFUN_DOWN) && (action != LFUN_UP) &&
447 (action != LFUN_DOWNSEL) && (action != LFUN_UPSEL))
449 if (the_locking_inset) {
450 result = the_locking_inset->LocalDispatch(bv, action, arg);
451 if (result == DISPATCHED) {
452 the_locking_inset->ToggleInsetCursor(bv);
453 bv->updateInset(this, false);
454 the_locking_inset->ToggleInsetCursor(bv);
456 } else if (result == FINISHED) {
457 if ((action == LFUN_RIGHT) || (action == -1)) {
458 actpos = inset_pos + 1;
461 the_locking_inset = 0;
469 par->InsertChar(actpos,arg[0]);
470 par->SetFont(actpos,real_current_font);
471 computeTextRows(bv->getPainter());
472 bv->updateInset(this, true);
474 selection_start = selection_end = actpos;
477 // --- Cursor Movements ---------------------------------------------
479 moveRight(bv, false);
480 selection_end = actpos;
481 bv->updateInset(this, false);
484 result= DISPATCH_RESULT(moveRight(bv));
485 if (hasSelection()) {
486 selection_start = selection_end = actpos;
487 bv->updateInset(this, false);
489 selection_start = selection_end = actpos;
494 selection_end = actpos;
495 bv->updateInset(this, false);
498 result= DISPATCH_RESULT(moveLeft(bv));
499 if (hasSelection()) {
500 selection_start = selection_end = actpos;
501 bv->updateInset(this, false);
503 selection_start = selection_end = actpos;
508 selection_end = actpos;
509 bv->updateInset(this, false);
512 result= DISPATCH_RESULT(moveDown(bv));
513 if (hasSelection()) {
514 selection_start = selection_end = actpos;
515 bv->updateInset(this, false);
517 selection_start = selection_end = actpos;
522 selection_end = actpos;
523 bv->updateInset(this, false);
526 result= DISPATCH_RESULT(moveUp(bv));
527 if (hasSelection()) {
528 selection_start = selection_end = actpos;
529 bv->updateInset(this, false);
531 selection_start = selection_end = actpos;
535 if (!actpos || par->IsNewline(actpos-1)) {
536 if (hasSelection()) {
537 selection_start = selection_end = actpos;
538 bv->updateInset(this, false);
544 if (Delete()) { // we need update
545 selection_start = selection_end = actpos;
546 computeTextRows(bv->getPainter());
547 bv->updateInset(this, true);
548 } else if (hasSelection()) {
549 selection_start = selection_end = actpos;
550 bv->updateInset(this, false);
554 for(; actpos > rows[actrow].pos; --actpos)
555 cx -= SingleWidth(bv->getPainter(), par, actpos);
556 cx -= SingleWidth(bv->getPainter(), par, actpos);
557 if (hasSelection()) {
558 selection_start = selection_end = actpos;
559 bv->updateInset(this, false);
561 selection_start = selection_end = actpos;
565 for(; actpos < rows[actrow + 1].pos; ++actpos)
566 cx += SingleWidth(bv->getPainter(), par, actpos);
567 if (hasSelection()) {
568 selection_start = selection_end = actpos;
569 bv->updateInset(this, false);
571 selection_start = selection_end = actpos;
574 case LFUN_MATH_MODE: // Open or create a math inset
575 InsertInset(bv, new InsetFormula);
576 if (hasSelection()) {
577 selection_start = selection_end = actpos;
578 bv->updateInset(this, false);
580 selection_start = selection_end = actpos;
584 result = UNDISPATCHED;
587 if (result != FINISHED) {
588 if (!the_locking_inset)
591 bv->unlockInset(this);
596 int InsetText::Latex(ostream & os, signed char /*fragile*/) const
598 #ifdef USE_OSTREAM_ONLY
601 int ret = par->SimpleTeXOnePar(fstr, texrow);
607 int i = Latex(fstr, fragile);
614 #ifndef USE_OSTREAM_ONLY
615 int InsetText::Latex(string & file, signed char /* fragile */) const
619 return par->SimpleTeXOnePar(file, texrow);
624 void InsetText::Validate(LaTeXFeatures & features) const
626 par->validate(features);
630 // Returns the width of a character at a certain spot
631 int InsetText::SingleWidth(Painter & pain, LyXParagraph * par, int pos) const
633 LyXFont font = GetFont(par, pos);
634 char c = par->GetChar(pos);
636 if (IsPrintable(c)) {
637 return font.width(c);
638 } else if (c == LyXParagraph::META_INSET) {
639 Inset const * tmpinset = par->GetInset(pos);
641 return tmpinset->width(pain, font);
644 } else if (IsSeparatorChar(c))
646 else if (IsNewlineChar(c))
648 return font.width(c);
652 // Returns the width of a character at a certain spot
653 void InsetText::SingleHeight(Painter & pain, LyXParagraph * par,int pos,
654 int & asc, int & desc) const
656 LyXFont font = GetFont(par, pos);
657 char c = par->GetChar(pos);
660 if (c == LyXParagraph::META_INSET) {
661 Inset const * tmpinset=par->GetInset(pos);
663 asc = tmpinset->ascent(pain, font);
664 desc = tmpinset->descent(pain, font);
667 asc = font.maxAscent();
668 desc = font.maxDescent();
674 // Gets the fully instantiated font at a given position in a paragraph
675 // Basically the same routine as LyXParagraph::getFont() in paragraph.C.
676 // The difference is that this one is used for displaying, and thus we
677 // are allowed to make cosmetic improvements. For instance make footnotes
679 // If position is -1, we get the layout font of the paragraph.
680 // If position is -2, we get the font of the manual label of the paragraph.
681 LyXFont InsetText::GetFont(LyXParagraph * par, int pos) const
683 char par_depth = par->GetDepth();
685 LyXLayout const & layout =
686 textclasslist.Style(buffer->params.textclass, par->GetLayout());
688 // We specialize the 95% common case:
689 if (par->footnoteflag == LyXParagraph::NO_FOOTNOTE && !par_depth) {
692 if (layout.labeltype == LABEL_MANUAL
693 && pos < BeginningOfMainBody(par)) {
695 return par->GetFontSettings(pos).realize(layout.reslabelfont);
697 return par->GetFontSettings(pos).realize(layout.resfont);
700 // process layoutfont for pos == -1 and labelfont for pos < -1
702 return layout.resfont;
704 return layout.reslabelfont;
707 // The uncommon case need not be optimized as much
709 LyXFont layoutfont, tmpfont;
713 if (pos < BeginningOfMainBody(par)) {
715 layoutfont = layout.labelfont;
718 layoutfont = layout.font;
720 tmpfont = par->GetFontSettings(pos);
721 tmpfont.realize(layoutfont);
724 // process layoutfont for pos == -1 and labelfont for pos < -1
726 tmpfont = layout.font;
728 tmpfont = layout.labelfont;
731 // Resolve against environment font information
732 //if (par->GetDepth()){ // already in while condition
733 while (par && par_depth && !tmpfont.resolved()) {
734 par = par->DepthHook(par_depth - 1);
736 tmpfont.realize(textclasslist.Style(buffer->params.textclass,
737 par->GetLayout()).font);
738 par_depth = par->GetDepth();
741 tmpfont.realize((textclasslist.TextClass(buffer->params.textclass).
747 int InsetText::BeginningOfMainBody(LyXParagraph * par) const
749 if (textclasslist.Style(buffer->params.textclass,
750 par->GetLayout()).labeltype != LABEL_MANUAL)
753 return par->BeginningOfMainBody();
757 void InsetText::GetCursorPos(int & x, int & y) const
764 int InsetText::InsetInInsetY()
766 if (!the_locking_inset)
770 return (y + the_locking_inset->InsetInInsetY());
774 void InsetText::ToggleInsetCursor(BufferView * bv)
776 if (the_locking_inset) {
777 the_locking_inset->ToggleInsetCursor(bv);
781 LyXFont font = GetFont(par, actpos);
783 int asc = font.maxAscent();
784 int desc = font.maxDescent();
787 bv->hideLockedInsetCursor();
789 bv->showLockedInsetCursor(cx, cy, asc, desc);
790 cursor_visible = !cursor_visible;
794 void InsetText::ShowInsetCursor(BufferView * bv)
796 if (!cursor_visible) {
797 LyXFont font = GetFont(par, actpos);
799 int asc = font.maxAscent();
800 int desc = font.maxDescent();
801 bv->fitLockedInsetCursor(cx, cy, asc, desc);
802 bv->showLockedInsetCursor(cx, cy, asc, desc);
803 cursor_visible = true;
808 void InsetText::HideInsetCursor(BufferView * bv)
811 ToggleInsetCursor(bv);
815 void InsetText::setPos(BufferView * bv, int x, int y, bool activate_inset)
820 // search right X-pos x==0 -> top_x
824 for(unsigned int i = 1;
825 ((cy + rows[i - 1].desc) < y) && (i < rows.size() - 1); ++i) {
826 cy = rows[i].baseline;
827 actpos = rows[i].pos;
835 int sw = swh = SingleWidth(bv->getPainter(), par,actpos);
836 if (par->GetChar(actpos)!=LyXParagraph::META_INSET)
838 while ((actpos < (rows[actrow + 1].pos - 1)) && ((cx + swh) < x)) {
841 sw = swh = SingleWidth(bv->getPainter(), par,actpos);
842 if (par->GetChar(actpos)!=LyXParagraph::META_INSET)
845 if (activate_inset && par->GetChar(actpos)==LyXParagraph::META_INSET) {
847 static_cast<UpdatableInset*>(par->GetInset(actpos));
848 inset_x = cx - top_x;
851 the_locking_inset->Edit(bv, ox - inset_x, oy - inset_y, 0);
856 bool InsetText::moveRight(BufferView * bv, bool activate_inset)
858 if (actpos >= par->Last())
860 if (activate_inset && par->GetChar(actpos)==LyXParagraph::META_INSET) {
862 static_cast<UpdatableInset*>(par->GetInset(actpos));
863 inset_x = cx - top_x;
866 the_locking_inset->Edit(bv, 0, 0, 0);
875 bool InsetText::moveLeft(BufferView * bv, bool activate_inset)
880 if (activate_inset && par->GetChar(actpos)==LyXParagraph::META_INSET) {
882 static_cast<UpdatableInset*>(par->GetInset(actpos));
884 inset_x = cx - top_x;
887 the_locking_inset->Edit(bv, the_locking_inset->
888 width(bv->getPainter(), GetFont(par,actpos)),
897 bool InsetText::moveUp(BufferView * bv, bool activate_inset)
901 cy = rows[actrow - 1].baseline - top_baseline;
902 setPos(bv, cx - top_x, cy, activate_inset);
907 bool InsetText::moveDown(BufferView * bv, bool activate_inset)
909 if (actrow >= int(rows.size() - 2))
911 cy = rows[actrow + 1].baseline - top_baseline;
912 setPos(bv, cx - top_x, cy, activate_inset);
917 void InsetText::resetPos(BufferView * bv)
919 int old_pos = actpos;
923 for(int i = 0; rows[i].pos <= actpos; ++i) {
924 cy = rows[i].baseline;
928 setPos(bv, 0, cy, false);
930 while(actpos < old_pos) {
931 cx += SingleWidth(bv->getPainter(), par,actpos);
937 bool InsetText::Delete()
939 /* some insets are undeletable here */
940 if (par->GetChar(actpos)==LyXParagraph::META_INSET) {
941 /* force complete redo when erasing display insets */
942 /* this is a cruel mathod but save..... Matthias */
943 if (par->GetInset(actpos)->Deletable() &&
944 par->GetInset(actpos)->display()) {
955 bool InsetText::InsertInset(BufferView * bv, Inset * inset)
957 par->InsertChar(actpos, LyXParagraph::META_INSET);
958 par->InsertInset(actpos, inset);
959 computeTextRows(bv->getPainter());
960 bv->updateInset(this, true);
961 the_locking_inset = static_cast<UpdatableInset*>(inset);
962 inset_x = cx - top_x;
965 inset->Edit(bv, 0, 0, 0);
970 UpdatableInset * InsetText::GetLockingInset()
972 return the_locking_inset ? the_locking_inset->GetLockingInset() : this;
976 void InsetText::SetFont(BufferView * bv, LyXFont const & font, bool toggleall)
978 // if there is no selection just set the current_font
979 if (!hasSelection()) {
980 // Determine basis font
982 if (actpos < BeginningOfMainBody(par))
983 layoutfont = GetFont(par, -2);
985 layoutfont = GetFont(par, -1);
987 // Update current font
988 real_current_font.update(font, toggleall);
990 // Reduce to implicit settings
991 current_font = real_current_font;
992 current_font.reduce(layoutfont);
993 // And resolve it completely
994 real_current_font.realize(layoutfont);
999 if (selection_start > selection_end) {
1000 s_start = selection_end;
1001 s_end = selection_start;
1003 s_start = selection_start;
1004 s_end = selection_end;
1007 while(s_start < s_end) {
1008 newfont = GetFont(par,s_start);
1009 newfont.update(font, toggleall);
1010 SetCharFont(s_start, newfont);
1013 computeTextRows(bv->getPainter());
1014 bv->updateInset(this, true);
1018 void InsetText::SetCharFont(int pos, LyXFont const & f)
1020 /* let the insets convert their font */
1023 if (par->GetChar(pos) == LyXParagraph::META_INSET) {
1024 if (par->GetInset(pos))
1025 font = par->GetInset(pos)->ConvertFont(font);
1027 LyXLayout const & layout =
1028 textclasslist.Style(buffer->params.textclass,par->GetLayout());
1030 // Get concrete layout font to reduce against
1033 if (pos < BeginningOfMainBody(par))
1034 layoutfont = layout.labelfont;
1036 layoutfont = layout.font;
1039 layoutfont.realize((textclasslist.TextClass(buffer->params.textclass).
1042 // Now, reduce font against full layout font
1043 font.reduce(layoutfont);
1045 par->SetFont(pos, font);
1049 void InsetText::computeTextRows(Painter & pain) const
1063 rows.erase(rows.begin(),rows.end());
1064 int width = wordAscent = wordDescent = 0;
1065 insetWidth = maxAscent = maxDescent = 0;
1070 rows.push_back(row);
1072 for(p = 0; p < par->Last(); ++p) {
1073 insetWidth += SingleWidth(pain, par, p);
1074 SingleHeight(pain, par, p, asc, desc);
1075 if (asc > maxAscent)
1077 if (desc > maxDescent)
1080 rows[0].asc = maxAscent;
1081 rows[0].desc = maxDescent;
1082 // alocate a dummy row for the endpos
1083 row.pos = par->Last();
1084 rows.push_back(row);
1087 bool is_first_word_in_row = true;
1092 for(p = 0; p < par->Last(); ++p) {
1093 cw = SingleWidth(pain, par, p);
1095 lastWordWidth += cw;
1096 SingleHeight(pain, par, p, asc, desc);
1097 if (asc > wordAscent)
1099 if (desc > wordDescent)
1101 Inset const * inset = 0;
1102 if (((p + 1) < par->Last()) &&
1103 (par->GetChar(p + 1)==LyXParagraph::META_INSET))
1104 inset = par->GetInset(p + 1);
1105 if (inset && inset->display()) {
1106 if (!is_first_word_in_row && (width >= maxWidth)) {
1107 // we have to split also the row above
1108 rows[rows.size() - 1].asc = oasc;
1109 rows[rows.size() - 1].desc = odesc;
1111 rows.push_back(row);
1113 odesc = wordDescent;
1114 if (insetWidth < owidth)
1115 insetWidth = owidth;
1116 width = lastWordWidth;
1119 if (oasc < wordAscent)
1121 if (odesc < wordDescent)
1122 odesc = wordDescent;
1124 rows[rows.size() - 1].asc = oasc;
1125 rows[rows.size() - 1].desc = odesc;
1127 rows.push_back(row);
1128 SingleHeight(pain, par, p, asc, desc);
1129 rows[rows.size() - 1].asc = asc;
1130 rows[rows.size() - 1].desc = desc;
1131 row.pos = nwp = p + 1;
1132 rows.push_back(row);
1133 oasc = odesc = width = lastWordWidth = 0;
1134 is_first_word_in_row = true;
1135 wordAscent = wordDescent = 0;
1137 } else if (par->IsSeparator(p)) {
1138 if (width >= maxWidth) {
1139 if (is_first_word_in_row) {
1140 rows[rows.size() - 1].asc = wordAscent;
1141 rows[rows.size() - 1].desc = wordDescent;
1143 rows.push_back(row);
1144 oasc = odesc = width = 0;
1146 rows[rows.size() - 1].asc = oasc;
1147 rows[rows.size() - 1].desc = odesc;
1149 rows.push_back(row);
1151 odesc = wordDescent;
1152 if (insetWidth < owidth)
1153 insetWidth = owidth;
1154 width = lastWordWidth;
1156 wordAscent = wordDescent = lastWordWidth = 0;
1161 if (oasc < wordAscent)
1163 if (odesc < wordDescent)
1164 odesc = wordDescent;
1165 wordAscent = wordDescent = lastWordWidth = 0;
1167 is_first_word_in_row = false;
1170 // if we have some data in the paragraph we have ascent/descent
1172 if (width >= maxWidth) {
1174 rows[rows.size() - 1].asc = oasc;
1175 rows[rows.size() - 1].desc = odesc;
1176 // assign and allocate lower row
1178 rows.push_back(row);
1179 rows[rows.size() - 1].asc = wordAscent;
1180 rows[rows.size() - 1].desc = wordDescent;
1181 if (insetWidth < owidth)
1182 insetWidth = owidth;
1184 if (insetWidth < width)
1187 // assign last row data
1188 if (oasc < wordAscent)
1190 if (odesc < wordDescent)
1191 odesc = wordDescent;
1192 rows[rows.size() - 1].asc = oasc;
1193 rows[rows.size() - 1].desc = odesc;
1196 // alocate a dummy row for the endpos
1197 row.pos = par->Last();
1198 rows.push_back(row);
1199 // calculate maxAscent/Descent
1200 maxAscent = rows[0].asc;
1201 maxDescent = rows[0].desc;
1202 for (unsigned int i = 1; i < rows.size() - 1; ++i) {
1203 maxDescent += rows[i].asc + rows[i].desc + interline_space;
1206 if (the_locking_inset) {
1207 computeBaselines(top_baseline);
1210 inset_x = cx - top_x;
1217 void InsetText::computeBaselines(int baseline) const
1219 rows[0].baseline = baseline;
1220 for (unsigned int i = 1; i < rows.size() - 1; i++) {
1221 rows[i].baseline = rows[i - 1].baseline + rows[i - 1].desc +
1222 rows[i].asc + interline_space;