Skip to content

Commit 2db70cd

Browse files
committed
lvtinydom: createXPointer(): better handle <br/> edge cases
Fix text selection when starting/ending selection on a blank line created by <br/><br/> (which would just not work) or at the end of a paragraph ending with <br/> (which would select the full paragraph).
1 parent 614f862 commit 2db70cd

1 file changed

Lines changed: 30 additions & 2 deletions

File tree

crengine/src/lvtinydom.cpp

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9759,10 +9759,16 @@ ldomXPointer ldomDocument::createXPointer( lvPoint pt, int direction, bool stric
97599759
return ldomXPointer(node, 0);
97609760
}
97619761
// It is a word
9762-
if ( find_first ) // return xpointer to logical start of word
9762+
if ( find_first ) { // return xpointer to logical start of word
9763+
if ( node->isElement() ) // (see comment about <br/><br/> below)
9764+
return ldomXPointer(node, 0);
97639765
return ldomXPointer( node, src->t.offset + word->t.start );
9764-
else // return xpointer to logical end of word
9766+
}
9767+
else { // return xpointer to logical end of word
9768+
if ( node->isElement() )
9769+
return ldomXPointer(node, 0);
97659770
return ldomXPointer( node, src->t.offset + word->t.start + word->t.len );
9771+
}
97669772
}
97679773

97689774
// Found line, searching for word (words are in visual order)
@@ -9841,24 +9847,36 @@ ldomXPointer ldomDocument::createXPointer( lvPoint pt, int direction, bool stric
98419847
font->measureText( str.c_str()+word->t.start, word->t.len, width, flg, word->width+50, '?',
98429848
src->lang_cfg, src->letter_spacing + word->added_letter_spacing, false, hints);
98439849

9850+
// In some special cases, node may be an element and not a text node (ie. on a blank
9851+
// line caused by <br/><br/> where our word is a space generated by lvrend): below,
9852+
// we must return node with an offset of 0 (to avoid getting xpointer like p[2]/br[3].1
9853+
// which may fail being resolved back to the br node).
98449854
bool word_is_rtl = word->flags & LTEXT_WORD_DIRECTION_IS_RTL;
98459855
if ( word_is_rtl ) {
98469856
for ( int i=word->t.len-1; i>=0; i-- ) {
98479857
int xx = ( i>0 ) ? (width[i-1] + width[i])/2 : width[i]/2;
98489858
xx = word->width - xx;
98499859
if ( x < word->x + xx ) {
9860+
if ( node->isElement() )
9861+
return ldomXPointer(node, 0);
98509862
return ldomXPointer( node, src->t.offset + word->t.start + i );
98519863
}
98529864
}
9865+
if ( node->isElement() )
9866+
return ldomXPointer(node, 0);
98539867
return ldomXPointer( node, src->t.offset + word->t.start );
98549868
}
98559869
else {
98569870
for ( int i=0; i<word->t.len; i++ ) {
98579871
int xx = ( i>0 ) ? (width[i-1] + width[i])/2 : width[i]/2;
98589872
if ( x < word->x + xx ) {
9873+
if ( node->isElement() )
9874+
return ldomXPointer(node, 0);
98599875
return ldomXPointer( node, src->t.offset + word->t.start + i );
98609876
}
98619877
}
9878+
if ( node->isElement() )
9879+
return ldomXPointer( node, 0 );
98629880
return ldomXPointer( node, src->t.offset + word->t.start + word->t.len );
98639881
}
98649882
}
@@ -10456,6 +10474,16 @@ bool ldomXPointer::getRect(lvRect & rect, bool extended, bool adjusted) const
1045610474
}
1045710475
}
1045810476
}
10477+
if ( frmline->word_count == 0 && l == txtform->GetLineCount() - 1 && frmline->height == 0 ) {
10478+
// Handle a special case: we may end up setting the last added line a height of
10479+
// zero when we realize no word would be added. We don't want to return the full
10480+
// final node.
10481+
rect.left = rc.left;
10482+
rect.top = rc.top + frmline->y;
10483+
rect.right = rect.left + 1; // not the right word: no char width
10484+
rect.bottom = rect.top + frmline->height + 1;
10485+
return true;
10486+
}
1045910487
}
1046010488
// return false;
1046110489
// Not found, which is possible with a final node with only empty

0 commit comments

Comments
 (0)