On Tue, 28 Mar 2000, Robert Sievers wrote:
> Ok, I took a look at this new patch, and there is still a major problem.
> Turn on underline, and start typing. Once you wrap to the next line, the
> underline on the previous line of text disappears, never to be seen or
> heard from again.
>
> I am really nervous about checking in a patch which introduces a bug of
> relatively the same magnitude as the one it is trying to fix. Martin, can
> you take another stab at this patch?
>
Arg! Sorry about that. I should have though to try that test. I thought
that sequence of runs would always be terminated at a line break. It does
not do this so that clever formating tricks can be performed. This third
patch fixes the behaviour noticed by you by looking for the last run on a
line as well.
Give it a whirl and let me know of any new problems you find.
Cheers
Martin
PS. Any chance of looking at the "Insert Symbol" patch? I've received no
feedback for 4 weeks.
diff -Naur abi/CREDITS.TXT abi-new/CREDITS.TXT
--- abi/CREDITS.TXT Thu Mar 30 02:26:12 2000
+++ abi-new/CREDITS.TXT Thu Mar 30 01:38:06 2000
@@ -51,7 +51,7 @@
Andy Richardson <[EMAIL PROTECTED]> PostScript image handling
Duncan Rose <[EMAIL PROTECTED]>
Pierre Sarrazin <[EMAIL PROTECTED]>
-Martin Sevior <[EMAIL PROTECTED]> Symbol dialog, Overline
+Martin Sevior <[EMAIL PROTECTED]> Symbol dialog, Overline
Dan Schreiber <[EMAIL PROTECTED]>
<[EMAIL PROTECTED]> OpenBSD
Alexey Sinutin <[EMAIL PROTECTED]> Insert Date/Time dialog
diff -Naur abi/src/text/fmt/xp/fp_Run.cpp abi-new/src/text/fmt/xp/fp_Run.cpp
--- abi/src/text/fmt/xp/fp_Run.cpp Thu Mar 30 02:26:17 2000
+++ abi-new/src/text/fmt/xp/fp_Run.cpp Thu Mar 30 01:38:06 2000
@@ -271,6 +271,8 @@
return pSpanAP;
}
+
+
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
diff -Naur abi/src/text/fmt/xp/fp_Run.h abi-new/src/text/fmt/xp/fp_Run.h
--- abi/src/text/fmt/xp/fp_Run.h Thu Mar 30 02:26:17 2000
+++ abi-new/src/text/fmt/xp/fp_Run.h Thu Mar 30 01:38:06 2000
@@ -150,7 +150,20 @@
virtual UT_Bool doesContainNonBlankData(void) const { return
UT_TRUE; } // Things like text whould return false if it is all spaces.
virtual UT_Bool isSuperscript(void) const { return UT_FALSE; }
virtual UT_Bool isSubscript(void) const { return UT_FALSE; }
-
+ virtual UT_Bool isUnderline(void) const { return
+UT_FALSE; };
+ virtual UT_Bool isOverline(void) const { return
+UT_FALSE; };
+ virtual UT_Bool isStrikethrough(void) const { return
+UT_FALSE; };
+ virtual void setLinethickness(UT_sint32
+max_linethickness) { return; };
+ virtual UT_sint32 getLinethickness(void) {return 0; } ;
+ virtual void setUnderlineXoff(UT_sint32 xoff) {
+return; };
+ virtual UT_sint32 getUnderlineXoff(void) { return 0; } ;
+ virtual void setOverlineXoff(UT_sint32 xoff){
+return ;};
+ virtual UT_sint32 getOverlineXoff(void) {return 0; };
+ virtual void setMaxUnderline(UT_sint32 xoff){
+return; };
+ virtual UT_sint32 getMaxUnderline(void) {return 0; };
+ virtual void setMinOverline(UT_sint32 xoff)
+{return; };
+ virtual UT_sint32 getMinOverline(void) { return 0; };
+
#ifdef FMT_TEST
virtual void __dump(FILE * fp) const;
#endif
@@ -369,3 +382,9 @@
};
#endif /* FP_RUN_H */
+
+
+
+
+
+
diff -Naur abi/src/text/fmt/xp/fp_TextRun.cpp abi-new/src/text/fmt/xp/fp_TextRun.cpp
--- abi/src/text/fmt/xp/fp_TextRun.cpp Thu Mar 30 02:26:17 2000
+++ abi-new/src/text/fmt/xp/fp_TextRun.cpp Thu Mar 30 02:18:28 2000
@@ -951,37 +951,170 @@
Upon entry to this function, yoff is the TOP of the run,
NOT the baseline.
*/
-
- /*
- TODO I *think* this line width should be proportional
- to the size of the font.
- */
+
+ /*
+ Here is the code to work out the position and thickness of under
+ and overlines for a run of text. This is neccessary because an
+underline or overline could shift position depending on the text size -
+particularly for subscripts and superscripts. We can't work out where to put
+the lines until the end of the lined span. This info is saved in the fp_TextRun
+class. If a underline or overline is pending (because the next run continues
+ the underline or overline), mark the next run as dirty to make sure it is
+drawn.
+ */
+
+ if( (m_fDecorations & (TEXT_DECOR_UNDERLINE | TEXT_DECOR_OVERLINE |
+ TEXT_DECOR_LINETHROUGH)) == 0) return;
UT_sint32 old_LineWidth = m_iLineWidth;
- m_iLineWidth = 1 + (UT_MAX(10,getAscent()) - 10)/8;
+ UT_sint32 cur_linewidth = 1+ (UT_MAX(10,m_iAscent)-10)/8;
+ UT_sint32 iDrop = 0;
+ fp_Run* P_Run = getPrev();
+ fp_Run* N_Run = getNext();
+ UT_Bool b_Underline = isUnderline();
+ UT_Bool b_Overline = isOverline();
+ UT_Bool b_Strikethrough = isStrikethrough();
+ const UT_UCSChar* pSpan;
+ UT_uint32 lenSpan;
+ UT_Bool b_Firstrun = (P_Run == NULL) || (m_pLine->getFirstRun()== this);
+ UT_Bool b_Lastrun = (N_Run == NULL) || (m_pLine->getLastRun()== this);
+ /*
+ If the previous run is NULL or if this is the first run of a line,
+we are on the first run of the line so set the linethickness, start of the line span
+and the overline and underline positions from the current measurements.
+ */
+ if(P_Run == NULL || b_Firstrun )
+ {
+ setLinethickness(cur_linewidth);
+ if(b_Underline)
+ {
+ iDrop = yoff + m_iAscent + m_iDescent/3;
+ setUnderlineXoff( xoff);
+ setMaxUnderline(iDrop);
+ }
+ if(b_Overline)
+ {
+ iDrop = yoff + 1 + (UT_MAX(10,m_iAscent) - 10)/8;
+ setOverlineXoff( xoff);
+ setMinOverline(iDrop);
+ }
+ }
+ /*
+ Otherwise look to see if the previous run had an underline or
+overline. If it does, merge the information with the present information. Take
+the Maximum of the underline offsets and the minimum of the overline offsets.
+Always take the maximum of the linewidths. If there is no previous underline
+or overline set the underline and overline locations with the current data.
+ */
+ else
+ {
+ if (!P_Run->isUnderline() && !P_Run->isOverline() &&
+ !P_Run->isStrikethrough())
+ {
+ setLinethickness(cur_linewidth);
+ }
+ else
+ {
+
+setLinethickness(UT_MAX(P_Run->getLinethickness(),cur_linewidth));
+ }
+ if (b_Underline)
+ {
+ iDrop = yoff + m_iAscent + m_iDescent/3;
+ if(!P_Run->isUnderline())
+ {
+ setUnderlineXoff( xoff);
+ setMaxUnderline(iDrop);
+ }
+ else
+ {
+ setUnderlineXoff( P_Run->getUnderlineXoff());
+ setMaxUnderline(UT_MAX( P_Run->getMaxUnderline(), iDrop));
+ }
+ }
+ if (b_Overline)
+ {
+ iDrop = yoff + 1 + (UT_MAX(10,m_iAscent) - 10)/8;
+ if(!P_Run->isOverline())
+ {
+ setOverlineXoff( xoff);
+ setMinOverline(iDrop);
+ }
+ else
+ {
+ setOverlineXoff( P_Run->getOverlineXoff());
+ setMinOverline(UT_MIN( P_Run->getMinOverline(), iDrop));
+ }
+ }
+ }
+ m_iLineWidth = getLinethickness();
m_pG->setLineWidth(m_iLineWidth);
-
- if (m_fDecorations & TEXT_DECOR_UNDERLINE)
+ /*
+ If the next run returns NULL or if we are on the last run
+ we've reached the of the line of text so the overlines and underlines must
+be drawn.
+ */
+ if(N_Run == NULL || b_Lastrun)
{
- UT_sint32 iDrop = (m_pLine->getDescent() / 3);
- m_pG->drawLine(xoff, yoff + iDrop + m_iAscent, xoff+getWidth(), yoff +
iDrop + m_iAscent);
+ if ( b_Underline)
+ {
+ iDrop = UT_MAX( getMaxUnderline(), iDrop);
+ UT_sint32 totx = getUnderlineXoff();
+ m_pG->drawLine(totx, iDrop, xoff+getWidth(), iDrop);
+ }
+ if ( b_Overline)
+ {
+ iDrop = UT_MIN( getMinOverline(), iDrop);
+ UT_sint32 totx = getOverlineXoff();
+ m_pG->drawLine(totx, iDrop, xoff+getWidth(), iDrop);
+ }
}
- if (m_fDecorations & TEXT_DECOR_OVERLINE)
+ /*
+ Otherwise look to see if the next run has an underline or overline
+if not, draw the line, if does mark the next run as dirty to make sure it
+is drawn later.
+ */
+ else
{
- UT_sint32 y2 = yoff + (UT_MAX(10,getAscent()) - 10)/8;
- m_pG->drawLine(xoff, y2, xoff+getWidth(), y2);
+ if ( b_Underline )
+ {
+ if(!N_Run->isUnderline())
+ {
+ iDrop = UT_MAX( getMaxUnderline(), iDrop);
+ UT_sint32 totx = getUnderlineXoff();
+ m_pG->drawLine(totx, iDrop, xoff+getWidth(), iDrop);
+ }
+ else
+ {
+ N_Run->markAsDirty();
+ }
+ }
+ if ( b_Overline )
+ {
+ if(!N_Run->isOverline())
+ {
+ iDrop = UT_MIN( getMinOverline(), iDrop);
+ UT_sint32 totx = getOverlineXoff();
+ m_pG->drawLine(totx, iDrop, xoff+getWidth(), iDrop);
+ }
+ else
+ {
+ N_Run->markAsDirty();
+ }
+ }
}
-
- if (m_fDecorations & TEXT_DECOR_LINETHROUGH)
+ /*
+ We always want strikethrough to go right through the middle of the
+text so we can keep the original code.
+ */
+ if ( b_Strikethrough)
{
- UT_sint32 y2 = yoff + getAscent() * 2 / 3;
- m_pG->drawLine(xoff, y2, xoff+getWidth(), y2);
+ iDrop = yoff + getAscent() * 2 / 3;
+ m_pG->drawLine(xoff, iDrop, xoff+getWidth(), iDrop);
}
-
+ /*
+ Restore the previous line width.
+ */
m_iLineWidth = old_LineWidth;
m_pG->setLineWidth(m_iLineWidth);
-
-
}
void fp_TextRun::_drawSquiggle(UT_sint32 top, UT_sint32 left, UT_sint32 right)
@@ -1034,7 +1167,7 @@
// I think this is safe, although it begs the question, why did we get
called if iLen is zero? TODO
return;
}
-
+
UT_sint32 xoff = 0, yoff = 0;
UT_sint32 iAscent = m_pLine->getAscent();
UT_sint32 iDescent = m_pLine->getDescent();
@@ -1211,6 +1344,71 @@
UT_Bool fp_TextRun::isSubscript(void) const
{
return (m_fPosition == TEXT_POSITION_SUBSCRIPT);
+}
+
+UT_Bool fp_TextRun::isUnderline(void) const
+{
+ return ((m_fDecorations & TEXT_DECOR_UNDERLINE) != 0);
+}
+
+UT_Bool fp_TextRun::isOverline(void) const
+{
+ return ((m_fDecorations & TEXT_DECOR_OVERLINE) != 0);
+}
+
+UT_Bool fp_TextRun::isStrikethrough(void) const
+{
+ return ((m_fDecorations & TEXT_DECOR_LINETHROUGH) != 0);
+}
+
+void fp_TextRun::setLinethickness(UT_sint32 max_linethickness)
+{
+ m_iLinethickness = max_linethickness;
+}
+
+void fp_TextRun::setUnderlineXoff(UT_sint32 xoff)
+{
+ m_iUnderlineXoff = xoff;
+}
+
+UT_sint32 fp_TextRun::getUnderlineXoff(void)
+{
+ return m_iUnderlineXoff;
+}
+
+void fp_TextRun::setOverlineXoff(UT_sint32 xoff)
+{
+ m_iOverlineXoff = xoff;
+}
+
+UT_sint32 fp_TextRun::getOverlineXoff(void)
+{
+ return m_iOverlineXoff;
+}
+
+void fp_TextRun::setMaxUnderline(UT_sint32 maxh)
+{
+ m_imaxUnderline = maxh;
+}
+
+UT_sint32 fp_TextRun::getMaxUnderline(void)
+{
+ return m_imaxUnderline;
+}
+
+void fp_TextRun::setMinOverline(UT_sint32 minh)
+{
+ m_iminOverline = minh;
+}
+
+UT_sint32 fp_TextRun::getMinOverline(void)
+{
+ return m_iminOverline;
+}
+
+UT_sint32 fp_TextRun::getLinethickness( void)
+{
+ return m_iLinethickness;
}
UT_sint32 fp_TextRun::findTrailingSpaceDistance(void) const
diff -Naur abi/src/text/fmt/xp/fp_TextRun.h abi-new/src/text/fmt/xp/fp_TextRun.h
--- abi/src/text/fmt/xp/fp_TextRun.h Thu Mar 30 02:26:17 2000
+++ abi-new/src/text/fmt/xp/fp_TextRun.h Thu Mar 30 01:38:06 2000
@@ -76,6 +76,19 @@
virtual UT_Bool doesContainNonBlankData(void) const;
virtual UT_Bool isSuperscript(void) const;
virtual UT_Bool isSubscript(void) const;
+ virtual UT_Bool isUnderline(void) const;
+ virtual UT_Bool isOverline(void) const;
+ virtual UT_Bool isStrikethrough(void) const;
+ virtual void setLinethickness(UT_sint32
+max_linethickness);
+ virtual UT_sint32 getLinethickness(void);
+ virtual void setUnderlineXoff(UT_sint32 xoff);
+ virtual UT_sint32 getUnderlineXoff(void);
+ virtual void setOverlineXoff(UT_sint32 xoff);
+ virtual UT_sint32 getOverlineXoff(void);
+ virtual void setMaxUnderline(UT_sint32 xoff);
+ virtual UT_sint32 getMaxUnderline(void);
+ virtual void setMinOverline(UT_sint32 xoff);
+ virtual UT_sint32 getMinOverline(void);
UT_uint32 countTrailingSpaces(void) const;
#ifdef FMT_TEST
@@ -145,7 +158,21 @@
JUSTIFICATION_NOT_USED = -1
};
UT_sint32 m_iSpaceWidthBeforeJustification;
+ UT_sint32 m_iLinethickness;
+ UT_sint32 m_iUnderlineXoff;
+ UT_sint32 m_imaxUnderline;
+ UT_sint32 m_iminOverline;
+ UT_sint32 m_iOverlineXoff;
};
#endif /* FP_TEXTRUN_H */
+
+
+
+
+
+
+
+
+
diff -Naur abi/src/text/fmt/xp/fv_View.cpp abi-new/src/text/fmt/xp/fv_View.cpp
--- abi/src/text/fmt/xp/fv_View.cpp Thu Mar 30 02:26:17 2000
+++ abi-new/src/text/fmt/xp/fv_View.cpp Thu Mar 30 01:38:06 2000
@@ -3327,9 +3327,10 @@
}
UT_Bool bDone = UT_FALSE;
+ UT_Bool bIsDirty = UT_FALSE;
fp_Run* pCurRun = pRun1;
- while (!bDone)
+ while (!bDone || bIsDirty)
{
if (pCurRun == pRun2)
{
@@ -3361,6 +3362,14 @@
{
pCurRun = pNextBlock->getFirstRun();
}
+ }
+ if( !pCurRun)
+ {
+ bIsDirty = UT_FALSE;
+ }
+ else
+ {
+ bIsDirty = pCurRun->isDirty();
}
}
}