From 867e640cb836f4a54141541536222c6304a7d2ed Mon Sep 17 00:00:00 2001 From: Manolo Gouy Date: Thu, 19 May 2016 16:50:09 +0000 Subject: [PATCH] Fix handing of html entities in copied text by Fl_Help_View widget. git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3-porting@11747 ea41ed52-d2ee-0310-a9c1-e6b18d33e121 --- FL/Fl_Help_View.H | 2 +- src/Fl_Help_View.cxx | 46 ++++++++++++++++++++++++++++---------------- 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/FL/Fl_Help_View.H b/FL/Fl_Help_View.H index 30c63587e..ebef81d65 100644 --- a/FL/Fl_Help_View.H +++ b/FL/Fl_Help_View.H @@ -275,7 +275,7 @@ public: int handle(int); private: - 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 extend_selection(); void end_selection(int c=0); diff --git a/src/Fl_Help_View.cxx b/src/Fl_Help_View.cxx index 9ef1cbaf8..223064bfb 100644 --- a/src/Fl_Help_View.cxx +++ b/src/Fl_Help_View.cxx @@ -225,11 +225,9 @@ Fl_Color Fl_Help_View::hv_selection_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! */ -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_first) { Fl_Color c = fl_color(); @@ -255,7 +253,7 @@ void Fl_Help_View::hv_draw(const char *t, int x, int y) selection_push_last = l; } else { selection_drag_first = f; - selection_drag_last = l; + selection_drag_last = l + entity_extra_length; } } } @@ -722,7 +720,9 @@ Fl_Help_View::draw() underline = 0; 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;) { if ((*ptr == '<' || isspace((*ptr)&255)) && buf.size() > 0) @@ -744,8 +744,9 @@ Fl_Help_View::draw() 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(); + entity_extra_length = 0; if (underline) { xtra_ww = isspace((*ptr)&255)?(int)fl_width(' '):0; fl_xyline(xx + x() - leftline_, yy + y() + 1, @@ -1116,7 +1117,7 @@ Fl_Help_View::draw() if (!pre) current_pos = (int) (ptr-value_); needspace = 1; } - else if (*ptr == '&') + else if (*ptr == '&') // process html entity { ptr ++; @@ -1125,8 +1126,12 @@ Fl_Help_View::draw() if (qch < 0) buf.add('&'); else { + int utf8l = buf.size(); buf.add(qch); + utf8l = buf.size() - utf8l; // length of added UTF-8 text + const char *oldptr = ptr; ptr = strchr(ptr, ';') + 1; + entity_extra_length += ptr - (oldptr-1) - utf8l; // extra length between html entity and UTF-8 } if ((fsize + 2) > hh) @@ -3025,15 +3030,15 @@ void Fl_Help_View::end_selection(int clipboard) { if (!selected || current_view!=this) 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 - // *FIXME* Should be UTF-8 (not ASCII), including HTML Entities &x; etc. - char p = 0, pre = 0;; + int p = 0; + char pre = 0; int len = (int) strlen(value_); char *txt = (char*)malloc(len+1), *d = txt; const char *s = value_, *cmd, *src; for (;;) { - char c = *s++; + int c = *s++; if (c==0) break; if (c=='<') { // begin of some html command. Skip until we find a '>' cmd = s; @@ -3080,26 +3085,33 @@ void Fl_Help_View::end_selection(int clipboard) } 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); - if (xx>=0) { - c = (char)xx; // *FIXME* *UTF-8* + if (xx >= 0) { + c = xx; for (;;) { char cc = *s++; if (!cc || cc==';') break; } } } - int n = (int) (s-value_); + int n = (int) (s2-value_); if (n>selection_first && n<=selection_last) { if (!pre && isspace(c&255)) c = ' '; - if (p!=' '||c!=' ') - *d++ = c; + if (p!=' ' || c!=' ') { + if (s2 != s) { // c was an HTML entity + d += fl_utf8encode(c, d); + } + else *d++ = c; + } p = c; } + if (n>selection_last) break; // stop parsing html after end of selection } *d = 0; Fl::copy(txt, (int) strlen(txt), clipboard); +//printf("copy [%s]\n", txt); free(txt); }