Proper handling of html entities (&name;) in text selections of Fl_Help_View widget.
This commit reproduces the same changes in the fltk-1.3-porting branch. git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@11761 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
parent
6b288980cb
commit
d850775282
@ -283,7 +283,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void hv_draw(const char *t, int x, int y);
|
void hv_draw(const char *t, int x, int y, int entity_extra_length = 0);
|
||||||
char begin_selection();
|
char begin_selection();
|
||||||
char extend_selection();
|
char extend_selection();
|
||||||
void end_selection(int c=0);
|
void end_selection(int c=0);
|
||||||
|
|||||||
@ -234,11 +234,9 @@ Fl_Color Fl_Help_View::hv_selection_color;
|
|||||||
Fl_Color Fl_Help_View::hv_selection_text_color;
|
Fl_Color Fl_Help_View::hv_selection_text_color;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Limitation: if a word contains &code; notations, we will calculate a wrong length.
|
|
||||||
*
|
|
||||||
* This function must be optimized for speed!
|
* This function must be optimized for speed!
|
||||||
*/
|
*/
|
||||||
void Fl_Help_View::hv_draw(const char *t, int x, int y)
|
void Fl_Help_View::hv_draw(const char *t, int x, int y, int entity_extra_length)
|
||||||
{
|
{
|
||||||
if (selected && current_view==this && current_pos<selection_last && current_pos>=selection_first) {
|
if (selected && current_view==this && current_pos<selection_last && current_pos>=selection_first) {
|
||||||
Fl_Color c = fl_color();
|
Fl_Color c = fl_color();
|
||||||
@ -264,7 +262,7 @@ void Fl_Help_View::hv_draw(const char *t, int x, int y)
|
|||||||
selection_push_last = l;
|
selection_push_last = l;
|
||||||
} else {
|
} else {
|
||||||
selection_drag_first = f;
|
selection_drag_first = f;
|
||||||
selection_drag_last = l;
|
selection_drag_last = l + entity_extra_length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -731,7 +729,9 @@ Fl_Help_View::draw()
|
|||||||
underline = 0;
|
underline = 0;
|
||||||
|
|
||||||
initfont(font, fsize, fcolor);
|
initfont(font, fsize, fcolor);
|
||||||
|
// byte length difference between html entity (encoded by &...;) and
|
||||||
|
// UTF-8 encoding of same character
|
||||||
|
int entity_extra_length = 0;
|
||||||
for (ptr = block->start, buf.clear(); ptr < block->end;)
|
for (ptr = block->start, buf.clear(); ptr < block->end;)
|
||||||
{
|
{
|
||||||
if ((*ptr == '<' || isspace((*ptr)&255)) && buf.size() > 0)
|
if ((*ptr == '<' || isspace((*ptr)&255)) && buf.size() > 0)
|
||||||
@ -753,8 +753,9 @@ Fl_Help_View::draw()
|
|||||||
hh = 0;
|
hh = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
hv_draw(buf.c_str(), xx + x() - leftline_, yy + y());
|
hv_draw(buf.c_str(), xx + x() - leftline_, yy + y(), entity_extra_length);
|
||||||
buf.clear();
|
buf.clear();
|
||||||
|
entity_extra_length = 0;
|
||||||
if (underline) {
|
if (underline) {
|
||||||
xtra_ww = isspace((*ptr)&255)?(int)fl_width(' '):0;
|
xtra_ww = isspace((*ptr)&255)?(int)fl_width(' '):0;
|
||||||
fl_xyline(xx + x() - leftline_, yy + y() + 1,
|
fl_xyline(xx + x() - leftline_, yy + y() + 1,
|
||||||
@ -1125,7 +1126,7 @@ Fl_Help_View::draw()
|
|||||||
if (!pre) current_pos = (int) (ptr-value_);
|
if (!pre) current_pos = (int) (ptr-value_);
|
||||||
needspace = 1;
|
needspace = 1;
|
||||||
}
|
}
|
||||||
else if (*ptr == '&')
|
else if (*ptr == '&')// process html entity
|
||||||
{
|
{
|
||||||
ptr ++;
|
ptr ++;
|
||||||
|
|
||||||
@ -1134,8 +1135,12 @@ Fl_Help_View::draw()
|
|||||||
if (qch < 0)
|
if (qch < 0)
|
||||||
buf.add('&');
|
buf.add('&');
|
||||||
else {
|
else {
|
||||||
|
int utf8l = buf.size();
|
||||||
buf.add(qch);
|
buf.add(qch);
|
||||||
|
utf8l = buf.size() - utf8l; // length of added UTF-8 text
|
||||||
|
const char *oldptr = ptr;
|
||||||
ptr = strchr(ptr, ';') + 1;
|
ptr = strchr(ptr, ';') + 1;
|
||||||
|
entity_extra_length += ptr - (oldptr-1) - utf8l; // extra length between html entity and UTF-8
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((fsize + 2) > hh)
|
if ((fsize + 2) > hh)
|
||||||
@ -3034,20 +3039,20 @@ void Fl_Help_View::end_selection(int clipboard)
|
|||||||
{
|
{
|
||||||
if (!selected || current_view!=this)
|
if (!selected || current_view!=this)
|
||||||
return;
|
return;
|
||||||
// convert the select part of our html text into some kind of somewhat readable ASCII
|
// convert the select part of our html text into some kind of somewhat readable UTF-8
|
||||||
// and store it in the selection buffer
|
// and store it in the selection buffer
|
||||||
// *FIXME* Should be UTF-8 (not ASCII), including HTML Entities &x; etc.
|
int p = 0;
|
||||||
char p = 0, pre = 0;;
|
char pre = 0;;
|
||||||
int len = (int) strlen(value_);
|
int len = (int) strlen(value_);
|
||||||
char *txt = (char*)malloc(len+1), *d = txt;
|
char *txt = (char*)malloc(len+1), *d = txt;
|
||||||
const char *s = value_, *cmd, *src;
|
const char *s = value_, *cmd, *src;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
char c = *s++;
|
int c = (*s++) & 0xff;
|
||||||
if (c==0) break;
|
if (c==0) break;
|
||||||
if (c=='<') { // begin of some html command. Skip until we find a '>'
|
if (c=='<') { // begin of some html command. Skip until we find a '>'
|
||||||
cmd = s;
|
cmd = s;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
c = *s++;
|
c = (*s++) & 0xff;
|
||||||
if (c==0 || c=='>') break;
|
if (c==0 || c=='>') break;
|
||||||
}
|
}
|
||||||
if (c==0) break;
|
if (c==0) break;
|
||||||
@ -3084,28 +3089,34 @@ void Fl_Help_View::end_selection(int clipboard)
|
|||||||
while (*src) {
|
while (*src) {
|
||||||
*d++ = *src++;
|
*d++ = *src++;
|
||||||
}
|
}
|
||||||
c = src[-1];
|
c = src[-1] & 0xff;
|
||||||
p = isspace(c&255) ? ' ' : c;
|
p = isspace(c&255) ? ' ' : c;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (c=='&') { // special characters (HTML entities) // *FIXME* *UTF-8*
|
const char *s2 = s;
|
||||||
|
if (c=='&') { // special characters (HTML entities)
|
||||||
int xx = quote_char(s);
|
int xx = quote_char(s);
|
||||||
if (xx>=0) {
|
if (xx >= 0) {
|
||||||
c = (char)xx; // *FIXME* *UTF-8*
|
c = xx;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
char cc = *s++;
|
char cc = *s++;
|
||||||
if (!cc || cc==';') break;
|
if (!cc || cc==';') break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int n = (int) (s-value_);
|
int n = (int) (s2-value_);
|
||||||
if (n>selection_first && n<=selection_last) {
|
if (n>selection_first && n<=selection_last) {
|
||||||
if (!pre && isspace(c&255)) c = ' ';
|
if (!pre && isspace(c)) c = ' ';
|
||||||
if (p!=' '||c!=' ')
|
if (p!=' ' || c!=' ') {
|
||||||
*d++ = c;
|
if (s2 != s) { // c was an HTML entity
|
||||||
|
d += fl_utf8encode(c, d);
|
||||||
|
}
|
||||||
|
else *d++ = c;
|
||||||
|
}
|
||||||
p = c;
|
p = c;
|
||||||
}
|
}
|
||||||
|
if (n>selection_last) break; // stop parsing html after end of selection
|
||||||
}
|
}
|
||||||
*d = 0;
|
*d = 0;
|
||||||
Fl::copy(txt, (int) strlen(txt), clipboard);
|
Fl::copy(txt, (int) strlen(txt), clipboard);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user