Skip to content

Commit

Permalink
interpret html tags inside <pre> (bnc #724119),
Browse files Browse the repository at this point in the history
also solves problem with license text (bnc #737752)

svn path=/branches/SuSE-Code-11-SP2-Branch/ncurses/; revision=67590
  • Loading branch information
gabi2 committed Mar 8, 2012
1 parent 6ab501e commit d220034
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 44 deletions.
153 changes: 113 additions & 40 deletions src/NCRichText.cc
Expand Up @@ -160,7 +160,7 @@ NCRichText::NCRichText( YWidget * parent, const string & ntext,
, NCPadWidget( parent )
, text( ntext )
, plainText( plainTextMode )
, textwidth( 0 )
, textwidth( 0 )
, cl( 0 )
, cc( 0 )
, cindent( 0 )
Expand Down Expand Up @@ -322,36 +322,23 @@ void NCRichText::DrawPlainPad()
}
}


void NCRichText::PadPlainTXT( const wchar_t * osch, const unsigned olen )
void NCRichText::PadPreTXT( const wchar_t * osch, const unsigned olen )
{
wstring wtxt( osch, olen );

// resolve the entities even in PRE (#71718)
wtxt = filterEntities( wtxt );

NCstring nctxt( wtxt );
NCtext ftext( nctxt );

if ( ftext.Columns() > textwidth )
textwidth = ftext.Columns();

AdjustPad( wsze( cl + ftext.Lines(), textwidth ) );

// insert the text
const wchar_t * sch = wtxt.data();

while ( *sch )
{
if ( *sch != L'\r' ) // skip carriage return
{
myPad()->addwstr( sch, 1 ); // add one wide chararacter
cc += wcwidth( *sch );
myPad()->addwstr( sch, 1 ); // add one wide chararacter

if ( *sch == L'\n' )
{
PadNL(); // add a new line
}
}
++sch;
}
}
Expand Down Expand Up @@ -398,21 +385,92 @@ inline void SkipWord( const wchar_t *& wch )
while ( *wch && WDtoken.find( *wch ) == wstring::npos );
}

static wstring PREtoken( L"<\n\v\r\f" ); // line manipulations + TokenStart '<'


inline void SkipPreTXT( const wchar_t *& wch )
{
do
{
++wch;
}
while ( *wch && PREtoken.find( *wch ) == wstring::npos );
}


void NCRichText::AdjustPrePad( const wchar_t *osch )
{
const wchar_t * wch = osch;
wstring wstr( wch, 6 );

size_t llen = 0; // longest line
size_t tmp_len = 0; // width of current line

list<NCstring>::const_iterator line; // iterator for list <NCstring> mtext
std::wstring::const_iterator wstr_it; // iterator for wstring

do
{
++wch;
++wch;
wstr.assign( wch, 6 );
}
while ( *wch && wstr != L"</pre>" );
}

wstring wtxt( osch, wch - osch );

// resolve the entities to get correct length for calculation of longest line
wtxt = filterEntities( wtxt );

wstring to_repl = L"<br>";
size_t pos;

// replace <br> by \n to get appropriate lines in NCtext
for ( ; (pos = wtxt.find( to_repl )) != wstring::npos ; )
wtxt.replace( pos, to_repl.length(), L"\n" );
// handle DOS text
for ( ; (pos = wtxt.find( L"\r" )) != wstring::npos ; )
wtxt.replace( pos, 1, L"" );
for ( ; (pos = wtxt.find( L"\f" )) != wstring::npos ; )
wtxt.replace( pos, 1, L"\n" );

yuiDebug() << "Input: " << wtxt << " olen: " << wch - osch << endl;

NCstring nctxt( wtxt );
NCtext ftext( nctxt );

// iterate through NCtext
for ( line = ftext.Text().begin(); line != ftext.Text().end(); ++line )
{
tmp_len = 0;

for ( wstr_it = ( *line ).str().begin(); wstr_it != ( *line ).str().end() ; ++wstr_it )
{
// skip html tags
if ( *wstr_it == '<' )
{
wstr_it = find(wstr_it, (*line).str().end(), L'>');
}
else if ( *wstr_it == '\t' )
{
tmp_len += myPad()->tabsize();
}
else
{
tmp_len += wcwidth( *wstr_it );
}
}

if ( tmp_len > llen )
llen = tmp_len;
}

if ( llen > textwidth )
{
textwidth = llen;
AdjustPad( wsze( cl + ftext.Lines(), llen ) ); // adjust pad to longest line
}

}

void NCRichText::DrawHTMLPad()
{
Expand Down Expand Up @@ -441,36 +499,43 @@ void NCRichText::DrawHTMLPad()
case L'\n':
case L'\v':
case L'\r':
case L'\f':
if ( ! preTag )
{
SkipWS( wch );
PadWS();
}
else
{
if ( *wch != L'\r' ) // skip carriage return
switch ( *wch )
{
myPad()->addwstr( wch, 1 ); // add the wide chararacter
cc += wcwidth( *wch );
if ( *wch == '\n' )
PadNL();
case L' ': // add white space
case L'\t':
myPad()->addwstr( wch, 1 );
break;

case L'\n':
case L'\f':
PadNL(); // add new line
break;

default:
yuiDebug() << "Ignoring " << *wch << endl;
}
++wch;
}

break;

case L'<':
if ( !preTag )
{
swch = wch;
SkipToken( wch );
swch = wch;
SkipToken( wch );

if ( PadTOKEN( swch, wch ) )
break; // strip token
else
wch = swch; // reset and fall through

if ( PadTOKEN( swch, wch ) )
break; // strip token
else
wch = swch; // reset and fall through
}
default:
swch = wch;

Expand All @@ -482,9 +547,7 @@ void NCRichText::DrawHTMLPad()
else
{
SkipPreTXT( wch );
PadPlainTXT( swch, wch - swch );
preTag = false;
PadNL(); // add new line after pre is closed
PadPreTXT( swch, wch - swch );
}

break;
Expand All @@ -493,6 +556,7 @@ void NCRichText::DrawHTMLPad()

PadBOL();
AdjustPad( wsze( cl, textwidth ) );

yuiDebug() << "Anchors: " << anchors.size() << endl;

for ( unsigned i = 0; i < anchors.size(); ++i )
Expand Down Expand Up @@ -575,7 +639,8 @@ inline void NCRichText::PadTXT( const wchar_t * osch, const unsigned olen )

/**
* Get the number of columns needed to print a 'wstring'. Only printable characters
* are taken into account because others would return -1 (e.g. '\n').
* are taken into account because otherwise 'wcwidth' would return -1 (e.g. for '\n').
* Tabs are calculated with tabsize().
* Attention: only use textWidth() to calculate space, not for iterating through a text
* or to get the length of a text (real text length includes new lines).
*/
Expand All @@ -588,7 +653,13 @@ size_t NCRichText::textWidth( wstring wstr )
{
// check whether char is printable
if ( iswprint( *wstr_it ) )
{
len += wcwidth( *wstr_it );
}
else if ( *wstr_it == '\t' )
{
len += myPad()->tabsize();
}
}

return len;
Expand Down Expand Up @@ -819,7 +890,7 @@ bool NCRichText::PadTOKEN( const wchar_t * sch, const wchar_t *& ech )
else if ( value == L"li" ) token = T_LI;
else if ( value == L"ol" ) { token = T_LEVEL; leveltag = 1; }
else if ( value == L"qt" ) token = T_IGNORE;
else if ( value == L"tt" ) token = T_TT;
else if ( value == L"tt" ) token = T_IGNORE;
else if ( value == L"ul" ) { token = T_LEVEL; leveltag = 0; }

break;
Expand Down Expand Up @@ -959,11 +1030,13 @@ bool NCRichText::PadTOKEN( const wchar_t * sch, const wchar_t *& ech )

if ( !endtag )
{
preTag = true; // display plain text
preTag = true; // display text preserving newlines and spaces
AdjustPrePad( ech );
}
else
{
preTag = false;
PadNL(); // add new line (text may continue after </pre>)
}

break;
Expand Down
7 changes: 3 additions & 4 deletions src/NCRichText.h
@@ -1,4 +1,3 @@

/*---------------------------------------------------------------------\
| |
| __ __ ____ _____ ____ |
Expand Down Expand Up @@ -69,8 +68,7 @@ class NCRichText : public YRichText, public NCPadWidget
unsigned cindent;
bool atbol;

bool preTag; // default is false; set true
// if <pre> tag is found
bool preTag; // <pre> tag

unsigned Tattr;

Expand Down Expand Up @@ -190,7 +188,8 @@ class NCRichText : public YRichText, public NCPadWidget
void PadBOL();
void PadWS( const bool tab = false );
void PadTXT( const wchar_t * sch, const unsigned len );
void PadPlainTXT( const wchar_t * sch, const unsigned len );
void PadPreTXT( const wchar_t * sch, const unsigned len );
void AdjustPrePad( const wchar_t * sch );
bool PadTOKEN( const wchar_t * sch, const wchar_t *& ech );

protected:
Expand Down

0 comments on commit d220034

Please sign in to comment.