summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlbrecht Schlosser <albrechts.fltk@online.de>2016-05-17 16:33:50 +0000
committerAlbrecht Schlosser <albrechts.fltk@online.de>2016-05-17 16:33:50 +0000
commitccf3681097763b8246d314d73cfee6dffdddaf86 (patch)
tree6aa9cea61c3eb740b84d0ad47c30e25f104c4337
parent495d15cf7a0a30aa4400f6e089709c498fa977c5 (diff)
Fix Fl_Help_View buffer overflow (STR #3275).
This version works much better than the previous one: - fixed buffer overflow ("stack corruption") - fixed potential long text truncation - fixed tab formatting at line start or any offset divisible by 8 - better handling of HTML entities (aka quoted characters) - code simplifications, e.g. HV_Edit_Buffer::cmp() + width() Todo: - improve and standardize handling of HTML entities - more tests Missing features and known bugs: - strike out text (not implemented) - table and horizontal line formatting issues (STR #3227) git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3-porting@11746 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
-rw-r--r--FL/Fl_Help_View.H2
-rw-r--r--src/Fl_Help_View.cxx887
2 files changed, 541 insertions, 348 deletions
diff --git a/FL/Fl_Help_View.H b/FL/Fl_Help_View.H
index abc5bc739..30c63587e 100644
--- a/FL/Fl_Help_View.H
+++ b/FL/Fl_Help_View.H
@@ -187,7 +187,7 @@ struct Fl_Help_Target {
- macr micro middot
- nbsp not Ntilde ntilde
- Oacute oacute Ocirc ocirc Ograve ograve ordf ordm Oslash oslash Otilde otilde Ouml ouml
- - para premil plusmn pound
+ - para permil plusmn pound
- quot
- raquo reg
- sect shy sup1 sup2 sup3 szlig
diff --git a/src/Fl_Help_View.cxx b/src/Fl_Help_View.cxx
index 1a57db88d..9ef1cbaf8 100644
--- a/src/Fl_Help_View.cxx
+++ b/src/Fl_Help_View.cxx
@@ -6,6 +6,9 @@
// Copyright 1997-2010 by Easy Software Products.
// Image support by Matthias Melcher, Copyright 2000-2009.
//
+// Buffer management (HV_Edit_Buffer) and more by AlbrechtS and others.
+// Copyright 2011-2016 by Bill Spitzak and others.
+//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
// file is missing or damaged, see the license at:
@@ -232,7 +235,7 @@ void Fl_Help_View::hv_draw(const char *t, int x, int y)
Fl_Color c = fl_color();
fl_color(hv_selection_color);
int w = (int)fl_width(t);
- if (current_pos+(int)strlen(t)<selection_last)
+ if (current_pos+(int)strlen(t)<selection_last)
w += (int)fl_width(' ');
fl_rectf(x, y+fl_descent()-fl_height(), w, fl_height());
fl_color(hv_selection_text_color);
@@ -259,6 +262,221 @@ void Fl_Help_View::hv_draw(const char *t, int x, int y)
}
}
+#define DEBUG_EDIT_BUFFER 0
+
+#if (DEBUG_EDIT_BUFFER > 1)
+#define DEBUG_FUNCTION(L,F) \
+ printf("\n========\n [%d] --- %s\n========\n", L, F); \
+ fflush(stdout);
+#else
+#define DEBUG_FUNCTION(L,F)
+#endif
+
+
+/* ** Intentionally not Doxygen docs.
+ HelpView Edit Buffer management class.
+ <b>Internal use only.</b>
+
+ This class is for internal use in this file. Its sole purpose is to
+ allow buffer management to avoid buffer overflows in stack variables
+ used to edit strings for formatting and drawing (STR #3275).
+
+ This class will likely be superseded by an Fl_String or Fl_Buffer class
+ in a later FLTK release (1.4.x).
+
+ Note: The buffer allocation and extension size (chunk size) must be
+ a power of 2, but this is deliberately never checked, because this
+ class is only used here with default values. Using extension sizes
+ that are not a power of 2 may result in unpredictable behavior.
+*/
+
+class HV_Edit_Buffer {
+
+ int size_; // actually used text size w/o nul
+ int allocated_; // allocated buffer size
+ int extend_; // extend size (must be a power of 2)
+
+ char *buf_; // internal buffer
+
+public:
+
+ HV_Edit_Buffer (int alloc = 1024, int ext = 1024); // c'tor
+ ~HV_Edit_Buffer (); // d'tor
+
+ char *c_str() { return buf_; }
+ void clear();
+ int size() { return size_; }
+ void check(int size);
+ const char *add(const char *text, int size = -1);
+ void add(char c);
+ void add(int ucs);
+
+ int cmp(const char * str) { return !strcasecmp(buf_, str); }
+ int width() { return (int)fl_width(buf_); }
+
+ char & operator[] (int idx) { return buf_[idx]; }
+ char const operator[] (int idx) const { return buf_[idx]; }
+
+#if (DEBUG_EDIT_BUFFER)
+ void print(const char *text = "");
+#endif
+};
+
+/*
+ Edit buffer constructor.
+*/
+HV_Edit_Buffer::HV_Edit_Buffer(
+ int alloc,
+ int ext)
+{
+ alloc = (alloc + ext-1) & (~(ext-1)); // round to chunk size
+
+ size_ = 0;
+ allocated_ = alloc;
+ extend_ = ext;
+ buf_ = (char *)malloc(alloc);
+}
+
+/*
+ Clears the edit buffer, but doesn't free the buffer.
+*/
+void HV_Edit_Buffer::clear()
+{
+
+ // DEBUG_FUNCTION(__LINE__,__FUNCTION__);
+
+ size_ = 0;
+ buf_[0] = '\0';
+}
+
+/*
+ Adds text to the buffer.
+
+ \param[in] text text to be added
+ \param[in] size text size, default: -1 => strlen(text)
+ \returns new input text pointer, i.e. points beyond inserted text
+*/
+const char *HV_Edit_Buffer::add(const char *text, int size) {
+
+ if (size < 0) size = (int)strlen(text);
+ if (!size) return text;
+
+ check(size);
+
+#if (DEBUG_EDIT_BUFFER > 1)
+ printf("HV_Edit_Buffer::add(text,%d), allocated=%d, size=%d\n",
+ size, allocated_, size_+size);
+ fflush(stdout);
+#endif
+
+ memcpy(buf_+size_, text, size);
+ size_ += size;
+ buf_[size_] = '\0';
+
+ return (text + size);
+
+} // add(const char *text, int size)
+
+/*
+ Adds one byte (character) to the buffer.
+
+ \note It is possible to add partial UTF-8 sequences.
+
+ \param[in] c byte (char) to be added
+*/
+void HV_Edit_Buffer::add(char c) {
+
+ check(1);
+
+#if (DEBUG_EDIT_BUFFER > 1)
+ printf("HV_Edit_Buffer::add(char = '%c'), allocated=%d, size=%d\n",
+ c, allocated_, size_+1);
+ fflush(stdout);
+#endif
+
+ buf_[size_++] = c;
+ buf_[size_] = '\0';
+
+} // add(char c)
+
+/*
+ Adds one Unicode character (int) to the buffer.
+
+ The Unicode character \p ucs is converted to UTF-8 and appended to
+ the buffer.
+
+ \param[in] ucs Unicode character (code point) to be added
+*/
+void HV_Edit_Buffer::add(int ucs) {
+
+ int len;
+ char cbuf[6];
+
+ len = fl_utf8encode((unsigned int)ucs, cbuf);
+ if (len < 1) len = 1;
+ add(cbuf,len);
+
+} // add(int ucs)
+
+/*
+ Checks needed buffer size and reallocates the buffer if necessary.
+
+ Tests if the given string \p size can be added to the string buffer.
+ An additional nul byte is also considered in the calculation.
+
+ \p size must be >= 0.
+
+ If the requested \p size doesn't fit in the allocated buffer size,
+ the buffer is extended.
+
+ \param[in] size requested text size to be added (w/o trailing nul)
+*/
+void HV_Edit_Buffer::check(int size) {
+
+ if (size_ + size + 1 <= allocated_) return;
+
+ int new_size = (allocated_ + size + extend_) & (~(extend_-1)); // round to chunk size
+
+ buf_ = (char *)realloc(buf_, new_size);
+
+#if (DEBUG_EDIT_BUFFER)
+ printf("HV_Edit_Buffer::check(%d), allocated: %d ->%d\n",
+ size, allocated_, new_size);
+ fflush(stdout);
+#endif
+
+ allocated_ = new_size;
+
+} // HV_Edit_Buffer::check()
+
+
+/*
+ The destructor frees the edit buffer.
+*/
+HV_Edit_Buffer::~HV_Edit_Buffer() {
+
+ if (buf_) {
+#if (DEBUG_EDIT_BUFFER)
+ printf("~HV_Edit_Buffer(): size = %d, allocated = %d\n",
+ size_, allocated_);
+ fflush(stdout);
+#endif
+ free(buf_);
+ }
+} // ~HV_Edit_Buffer()
+
+
+/*
+ Prints the edit buffer (Debug only).
+*/
+#if (DEBUG_EDIT_BUFFER)
+void HV_Edit_Buffer::print(const char *text) {
+ printf("HV_Edit_Buffer::print(%s), allocated=%d, size=%d\n",
+ text, allocated_, size_);
+ printf(" \"%s\"\n", buf_ && size_ ? buf_ : "");
+ fflush(stdout);
+} // print()
+#endif
/** Adds a text block to the list. */
Fl_Help_Block * // O - Pointer to new block
@@ -272,8 +490,8 @@ Fl_Help_View::add_block(const char *s, // I - Pointer to start of block text
Fl_Help_Block *temp; // New block
-// printf("add_block(s = %p, xx = %d, yy = %d, ww = %d, hh = %d, border = %d)\n",
-// s, xx, yy, ww, hh, border);
+ // printf("add_block(s = %p, xx = %d, yy = %d, ww = %d, hh = %d, border = %d)\n",
+ // s, xx, yy, ww, hh, border);
if (nblocks_ >= ablocks_)
{
@@ -423,14 +641,13 @@ Fl_Help_View::draw()
const Fl_Help_Block *block; // Pointer to current block
const char *ptr, // Pointer to text in block
*attrs; // Pointer to start of element attributes
- char *s, // Pointer into buffer
- buf[1024], // Text buffer
- attr[1024]; // Attribute buffer
+ HV_Edit_Buffer buf; // Text buffer
+ char attr[1024]; // Attribute buffer
int xx, yy, ww, hh; // Current positions and sizes
int line; // Current line
Fl_Font font;
Fl_Fontsize fsize; // Current font and size
- Fl_Color fcolor; // current font color
+ Fl_Color fcolor; // current font color
int head, pre, // Flags for text
needspace; // Do we need whitespace?
Fl_Boxtype b = box() ? box() : FL_DOWN_BOX;
@@ -438,6 +655,8 @@ Fl_Help_View::draw()
int underline, // Underline text?
xtra_ww; // Extra width for underlined space between words
+ DEBUG_FUNCTION(__LINE__,__FUNCTION__);
+
// Draw the scrollbar(s) and box first...
ww = w();
hh = h();
@@ -504,16 +723,14 @@ Fl_Help_View::draw()
initfont(font, fsize, fcolor);
- for (ptr = block->start, s = buf; ptr < block->end;)
+ for (ptr = block->start, buf.clear(); ptr < block->end;)
{
- if ((*ptr == '<' || isspace((*ptr)&255)) && s > buf)
+ if ((*ptr == '<' || isspace((*ptr)&255)) && buf.size() > 0)
{
if (!head && !pre)
{
// Check width...
- *s = '\0';
- s = buf;
- ww = (int)fl_width(buf);
+ ww = buf.width();
if (needspace && xx > block->x)
xx += (int)fl_width(' ');
@@ -527,7 +744,8 @@ Fl_Help_View::draw()
hh = 0;
}
- hv_draw(buf, xx + x() - leftline_, yy + y());
+ hv_draw(buf.c_str(), xx + x() - leftline_, yy + y());
+ buf.clear();
if (underline) {
xtra_ww = isspace((*ptr)&255)?(int)fl_width(' '):0;
fl_xyline(xx + x() - leftline_, yy + y() + 1,
@@ -547,17 +765,13 @@ Fl_Help_View::draw()
{
if (*ptr == '\n')
{
- *s = '\0';
- s = buf;
-
- hv_draw(buf, xx + x() - leftline_, yy + y());
+ hv_draw(buf.c_str(), xx + x() - leftline_, yy + y());
if (underline) fl_xyline(xx + x() - leftline_, yy + y() + 1,
- xx + x() - leftline_ +
- (int)fl_width(buf));
-
- current_pos = (int) (ptr-value_);
+ xx + x() - leftline_ + buf.width());
+ buf.clear();
+ current_pos = (int) (ptr-value_);
if (line < 31)
- line ++;
+ line ++;
xx = block->line[line];
yy += hh;
hh = fsize + 2;
@@ -565,25 +779,24 @@ Fl_Help_View::draw()
else if (*ptr == '\t')
{
// Do tabs every 8 columns...
- while (((s - buf) & 7))
- *s++ = ' ';
+ buf.add(' '); // add at least one space
+ while (buf.size() & 7)
+ buf.add(' ');
+ }
+ else {
+ buf.add(' ');
}
- else
- *s++ = ' ';
-
if ((fsize + 2) > hh)
hh = fsize + 2;
ptr ++;
}
- if (s > buf)
+ if (buf.size() > 0)
{
- *s = '\0';
- s = buf;
-
- hv_draw(buf, xx + x() - leftline_, yy + y());
- ww = (int)fl_width(buf);
+ hv_draw(buf.c_str(), xx + x() - leftline_, yy + y());
+ ww = buf.width();
+ buf.clear();
if (underline) fl_xyline(xx + x() - leftline_, yy + y() + 1,
xx + x() - leftline_ + ww);
xx += ww;
@@ -594,7 +807,7 @@ Fl_Help_View::draw()
}
else
{
- s = buf;
+ buf.clear();
while (isspace((*ptr)&255))
ptr ++;
@@ -620,13 +833,7 @@ Fl_Help_View::draw()
}
while (*ptr && *ptr != '>' && !isspace((*ptr)&255))
- if (s < (buf + sizeof(buf) - 1))
- *s++ = *ptr++;
- else
- ptr ++;
-
- *s = '\0';
- s = buf;
+ buf.add(*ptr++);
attrs = ptr;
while (*ptr && *ptr != '>')
@@ -637,9 +844,9 @@ Fl_Help_View::draw()
// end of command reached, set the supposed start of printed eord here
current_pos = (int) (ptr-value_);
- if (strcasecmp(buf, "HEAD") == 0)
+ if (buf.cmp("HEAD"))
head = 1;
- else if (strcasecmp(buf, "BR") == 0)
+ else if (buf.cmp("BR"))
{
if (line < 31)
line ++;
@@ -647,7 +854,7 @@ Fl_Help_View::draw()
yy += hh;
hh = 0;
}
- else if (strcasecmp(buf, "HR") == 0)
+ else if (buf.cmp("HR"))
{
fl_line(block->x + x(), yy + y(), block->w + x(),
yy + y());
@@ -658,64 +865,61 @@ Fl_Help_View::draw()
yy += 2 * hh;
hh = 0;
}
- else if (strcasecmp(buf, "CENTER") == 0 ||
- strcasecmp(buf, "P") == 0 ||
- strcasecmp(buf, "H1") == 0 ||
- strcasecmp(buf, "H2") == 0 ||
- strcasecmp(buf, "H3") == 0 ||
- strcasecmp(buf, "H4") == 0 ||
- strcasecmp(buf, "H5") == 0 ||
- strcasecmp(buf, "H6") == 0 ||
- strcasecmp(buf, "UL") == 0 ||
- strcasecmp(buf, "OL") == 0 ||
- strcasecmp(buf, "DL") == 0 ||
- strcasecmp(buf, "LI") == 0 ||
- strcasecmp(buf, "DD") == 0 ||
- strcasecmp(buf, "DT") == 0 ||
- strcasecmp(buf, "PRE") == 0)
+ else if (buf.cmp("CENTER") ||
+ buf.cmp("P") ||
+ buf.cmp("H1") ||
+ buf.cmp("H2") ||
+ buf.cmp("H3") ||
+ buf.cmp("H4") ||
+ buf.cmp("H5") ||
+ buf.cmp("H6") ||
+ buf.cmp("UL") ||
+ buf.cmp("OL") ||
+ buf.cmp("DL") ||
+ buf.cmp("LI") ||
+ buf.cmp("DD") ||
+ buf.cmp("DT") ||
+ buf.cmp("PRE"))
{
if (tolower(buf[0]) == 'h')
{
font = FL_HELVETICA_BOLD;
fsize = textsize_ + '7' - buf[1];
}
- else if (strcasecmp(buf, "DT") == 0)
+ else if (buf.cmp("DT"))
{
font = textfont_ | FL_ITALIC;
fsize = textsize_;
}
- else if (strcasecmp(buf, "PRE") == 0)
+ else if (buf.cmp("PRE"))
{
font = FL_COURIER;
fsize = textsize_;
pre = 1;
}
- if (strcasecmp(buf, "LI") == 0)
+ if (buf.cmp("LI"))
{
-// fl_font(FL_SYMBOL, fsize); // The default SYMBOL font on my XP box is not Unicode...
- char buf[8];
- wchar_t b[] = {0x2022, 0x0};
-// buf[fl_unicode2utf(b, 1, buf)] = 0;
- unsigned dstlen = fl_utf8fromwc(buf, 8, b, 1);
- buf[dstlen] = 0;
- hv_draw(buf, xx - fsize + x() - leftline_, yy + y());
+ // draw bullet (&bull;) Unicode: U+2022, UTF-8 (hex): e2 80 a2
+ unsigned char bullet[4] = { 0xe2, 0x80, 0xa2, 0x00 };
+ hv_draw((char *)bullet, xx - fsize + x() - leftline_, yy + y());
}
pushfont(font, fsize);
+ buf.clear();
}
- else if (strcasecmp(buf, "A") == 0 &&
+ else if (buf.cmp("A") &&
get_attr(attrs, "HREF", attr, sizeof(attr)) != NULL)
{
fl_color(linkcolor_);
underline = 1;
}
- else if (strcasecmp(buf, "/A") == 0)
+ else if (buf.cmp("/A"))
{
fl_color(textcolor_);
underline = 0;
}
- else if (strcasecmp(buf, "FONT") == 0)
+ else if (buf.cmp("FONT"))
{
if (get_attr(attrs, "COLOR", attr, sizeof(attr)) != NULL) {
textcolor_ = get_color(attr, textcolor_);
@@ -743,19 +947,19 @@ Fl_Help_View::draw()
pushfont(font, fsize);
}
- else if (strcasecmp(buf, "/FONT") == 0)
+ else if (buf.cmp("/FONT"))
{
popfont(font, fsize, textcolor_);
}
- else if (strcasecmp(buf, "U") == 0)
+ else if (buf.cmp("U"))
underline = 1;
- else if (strcasecmp(buf, "/U") == 0)
+ else if (buf.cmp("/U"))
underline = 0;
- else if (strcasecmp(buf, "B") == 0 ||
- strcasecmp(buf, "STRONG") == 0)
+ else if (buf.cmp("B") ||
+ buf.cmp("STRONG"))
pushfont(font |= FL_BOLD, fsize);
- else if (strcasecmp(buf, "TD") == 0 ||
- strcasecmp(buf, "TH") == 0)
+ else if (buf.cmp("TD") ||
+ buf.cmp("TH"))
{
int tx, ty, tw, th;
@@ -794,39 +998,39 @@ Fl_Help_View::draw()
if (block->border)
fl_rect(tx, ty, tw, th);
}
- else if (strcasecmp(buf, "I") == 0 ||
- strcasecmp(buf, "EM") == 0)
+ else if (buf.cmp("I") ||
+ buf.cmp("EM"))
pushfont(font |= FL_ITALIC, fsize);
- else if (strcasecmp(buf, "CODE") == 0 ||
- strcasecmp(buf, "TT") == 0)
+ else if (buf.cmp("CODE") ||
+ buf.cmp("TT"))
pushfont(font = FL_COURIER, fsize);
- else if (strcasecmp(buf, "KBD") == 0)
+ else if (buf.cmp("KBD"))
pushfont(font = FL_COURIER_BOLD, fsize);
- else if (strcasecmp(buf, "VAR") == 0)
+ else if (buf.cmp("VAR"))
pushfont(font = FL_COURIER_ITALIC, fsize);
- else if (strcasecmp(buf, "/HEAD") == 0)
+ else if (buf.cmp("/HEAD"))
head = 0;
- else if (strcasecmp(buf, "/H1") == 0 ||
- strcasecmp(buf, "/H2") == 0 ||
- strcasecmp(buf, "/H3") == 0 ||
- strcasecmp(buf, "/H4") == 0 ||
- strcasecmp(buf, "/H5") == 0 ||
- strcasecmp(buf, "/H6") == 0 ||
- strcasecmp(buf, "/B") == 0 ||
- strcasecmp(buf, "/STRONG") == 0 ||
- strcasecmp(buf, "/I") == 0 ||
- strcasecmp(buf, "/EM") == 0 ||
- strcasecmp(buf, "/CODE") == 0 ||
- strcasecmp(buf, "/TT") == 0 ||
- strcasecmp(buf, "/KBD") == 0 ||
- strcasecmp(buf, "/VAR") == 0)
+ else if (buf.cmp("/H1") ||
+ buf.cmp("/H2") ||
+ buf.cmp("/H3") ||
+ buf.cmp("/H4") ||
+ buf.cmp("/H5") ||
+ buf.cmp("/H6") ||
+ buf.cmp("/B") ||
+ buf.cmp("/STRONG") ||
+ buf.cmp("/I") ||
+ buf.cmp("/EM") ||
+ buf.cmp("/CODE") ||
+ buf.cmp("/TT") ||
+ buf.cmp("/KBD") ||
+ buf.cmp("/VAR"))
popfont(font, fsize, fcolor);
- else if (strcasecmp(buf, "/PRE") == 0)
+ else if (buf.cmp("/PRE"))
{
popfont(font, fsize, fcolor);
pre = 0;
}
- else if (strcasecmp(buf, "IMG") == 0)
+ else if (buf.cmp("IMG"))
{
Fl_Shared_Image *img = 0;
int width, height;
@@ -876,13 +1080,12 @@ Fl_Help_View::draw()
needspace = 0;
}
+ buf.clear();
}
else if (*ptr == '\n' && pre)
{
- *s = '\0';
- s = buf;
-
- hv_draw(buf, xx + x() - leftline_, yy + y());
+ hv_draw(buf.c_str(), xx + x() - leftline_, yy + y());
+ buf.clear();
if (line < 31)
line ++;
@@ -899,12 +1102,13 @@ Fl_Help_View::draw()
if (pre)
{
if (*ptr == ' ')
- *s++ = ' ';
+ buf.add(' ');
else
{
// Do tabs every 8 columns...
- while (((s - buf) & 7))
- *s++ = ' ';
+ buf.add(' '); // at least one space
+ while (buf.size() & 7)
+ buf.add(' ');
}
}
@@ -919,12 +1123,9 @@ Fl_Help_View::draw()
int qch = quote_char(ptr);
if (qch < 0)
- *s++ = '&';
+ buf.add('&');
else {
- int l;
- l = fl_utf8encode((unsigned int) qch, s);
- if (l < 1) l = 1;
- s += l;
+ buf.add(qch);
ptr = strchr(ptr, ';') + 1;
}
@@ -933,18 +1134,16 @@ Fl_Help_View::draw()
}
else
{
- *s++ = *ptr++;
+ buf.add(*ptr++);
if ((fsize + 2) > hh)
hh = fsize + 2;
}
}
- *s = '\0';
-
- if (s > buf && !pre && !head)
+ if (buf.size() > 0 && !pre && !head)
{
- ww = (int)fl_width(buf);
+ ww = buf.width();
if (needspace && xx > block->x)
xx += (int)fl_width(' ');
@@ -959,9 +1158,9 @@ Fl_Help_View::draw()
}
}
- if (s > buf && !head)
+ if (buf.size() > 0 && !head)
{
- hv_draw(buf, xx + x() - leftline_, yy + y());
+ hv_draw(buf.c_str(), xx + x() - leftline_, yy + y());
if (underline) fl_xyline(xx + x() - leftline_, yy + y() + 1,
xx + x() - leftline_ + ww);
current_pos = (int) (ptr-value_);
@@ -969,7 +1168,7 @@ Fl_Help_View::draw()
}
fl_pop_clip();
-}
+} // draw()
@@ -989,6 +1188,8 @@ Fl_Help_View::find(const char *s, // I - String to find
*sp; // Search string pointer
+ DEBUG_FUNCTION(__LINE__,__FUNCTION__);
+
// Range check input and value...
if (!s || !value_) return -1;
@@ -1010,10 +1211,18 @@ Fl_Help_View::find(const char *s, // I - String to find
continue;
} else if (*bp == '&') {
// decode HTML entity...
- if ((c = quote_char(bp + 1)) < 0) c = '&';
+ if ((c = quote_char(bp + 1)) < 0) c = '&'; // *FIXME* UTF-8, see below
else bp = strchr(bp + 1, ';') + 1;
} else c = *bp;
+ // *FIXME* *UTF-8* (A.S. 02/14/2016)
+ // At this point c may be an arbitrary Unicode Code Point corresponding
+ // to a quoted character (see above), i.e. it _can_ be a multi byte
+ // UTF-8 sequence and must be compared with the corresponding
+ // multi byte string in (*sp)...
+ // For instance: "&euro;" == 0x20ac -> 0xe2 0x82 0xac (UTF-8: 3 bytes).
+ // Hint: use fl_utf8encode() [see below]
+
if (tolower(*sp) == tolower(c)) sp ++;
else {
// No match, so reset to start of search...
@@ -1046,9 +1255,8 @@ void Fl_Help_View::format() {
const char *ptr, // Pointer into block
*start, // Pointer to start of element
*attrs; // Pointer to start of element attributes
- char *s, // Pointer into buffer
- buf[1024], // Text buffer
- attr[1024], // Attribute buffer
+ HV_Edit_Buffer buf; // Text buffer
+ char attr[1024], // Attribute buffer
wattr[1024], // Width attribute buffer
hattr[1024], // Height attribute buffer
linkdest[1024]; // Link destination
@@ -1074,6 +1282,7 @@ void Fl_Help_View::format() {
// Box to draw...
fl_margins margins; // Left margin stack...
+ DEBUG_FUNCTION(__LINE__,__FUNCTION__);
// Reset document width...
int scrollsize = scrollbar_size_ ? scrollbar_size_ : Fl::scrollbar_size();
@@ -1121,14 +1330,13 @@ void Fl_Help_View::format() {
table_offset = 0;
// Html text character loop
- for (ptr = value_, s = buf; *ptr;)
+ for (ptr = value_, buf.clear(); *ptr;)
{
// End of word?
- if ((*ptr == '<' || isspace((*ptr)&255)) && s > buf)
+ if ((*ptr == '<' || isspace((*ptr)&255)) && buf.size() > 0)
{
// Get width of word parsed so far...
- *s = '\0';
- ww = (int)fl_width(buf);
+ ww = buf.width();
if (!head && !pre)
{
@@ -1210,7 +1418,7 @@ void Fl_Help_View::format() {
ptr ++;
}
- s = buf;
+ buf.clear();
}
if (*ptr == '<')
@@ -1233,15 +1441,7 @@ void Fl_Help_View::format() {
}
while (*ptr && *ptr != '>' && !isspace((*ptr)&255))
- if (s < (buf + sizeof(buf) - 1))
- *s++ = *ptr++;
- else
- ptr ++;
-
- *s = '\0';
- s = buf;
-
-// puts(buf);
+ buf.add(*ptr++);
attrs = ptr;
while (*ptr && *ptr != '>')
@@ -1250,21 +1450,22 @@ void Fl_Help_View::format() {
if (*ptr == '>')
ptr ++;
- if (strcasecmp(buf, "HEAD") == 0)
+ if (buf.cmp("HEAD"))
head = 1;
- else if (strcasecmp(buf, "/HEAD") == 0)
+ else if (buf.cmp("/HEAD"))
head = 0;
- else if (strcasecmp(buf, "TITLE") == 0)
+ else if (buf.cmp("TITLE"))
{
// Copy the title in the document...
- for (s = title_;
- *ptr != '<' && *ptr && s < (title_ + sizeof(title_) - 1);
- *s++ = *ptr++) {/*empty*/}
+ char *st;
+ for (st = title_;
+ *ptr != '<' && *ptr && st < (title_ + sizeof(title_) - 1);
+ *st++ = *ptr++) {/*empty*/}
- *s = '\0';
- s = buf;
+ *st = '\0';
+ buf.clear();
}
- else if (strcasecmp(buf, "A") == 0)
+ else if (buf.cmp("A"))
{
if (get_attr(attrs, "NAME", attr, sizeof(attr)) != NULL)
add_target(attr, yy - fsize - 2);
@@ -1272,9 +1473,9 @@ void Fl_Help_View::format() {
if (get_attr(attrs, "HREF", attr, sizeof(attr)) != NULL)
strlcpy(linkdest, attr, sizeof(linkdest));
}
- else if (strcasecmp(buf, "/A") == 0)
+ else if (buf.cmp("/A"))
linkdest[0] = '\0';
- else if (strcasecmp(buf, "BODY") == 0)
+ else if (buf.cmp("BODY"))
{
bgcolor_ = get_color(get_attr(attrs, "BGCOLOR", attr, sizeof(attr)),
color());
@@ -1283,7 +1484,7 @@ void Fl_Help_View::format() {
linkcolor_ = get_color(get_attr(attrs, "LINK", attr, sizeof(attr)),
fl_contrast(FL_BLUE, color()));
}
- else if (strcasecmp(buf, "BR") == 0)
+ else if (buf.cmp("BR"))
{
line = do_align(block, line, xx, newalign, links);
xx = block->x;
@@ -1291,38 +1492,38 @@ void Fl_Help_View::format() {
yy += hh;
hh = 0;
}
- else if (strcasecmp(buf, "CENTER") == 0 ||
- strcasecmp(buf, "P") == 0 ||
- strcasecmp(buf, "H1") == 0 ||
- strcasecmp(buf, "H2") == 0 ||
- strcasecmp(buf, "H3") == 0 ||
- strcasecmp(buf, "H4") == 0 ||
- strcasecmp(buf, "H5") == 0 ||
- strcasecmp(buf, "H6") == 0 ||
- strcasecmp(buf, "UL") == 0 ||
- strcasecmp(buf, "OL") == 0 ||
- strcasecmp(buf, "DL") == 0 ||
- strcasecmp(buf, "LI") == 0 ||
- strcasecmp(buf, "DD") == 0 ||
- strcasecmp(buf, "DT") == 0 ||
- strcasecmp(buf, "HR") == 0 ||
- strcasecmp(buf, "PRE") == 0 ||
- strcasecmp(buf, "TABLE") == 0)
+ else if (buf.cmp("CENTER") ||
+ buf.cmp("P") ||
+ buf.cmp("H1") ||
+ buf.cmp("H2") ||
+ buf.cmp("H3") ||
+ buf.cmp("H4") ||
+ buf.cmp("H5") ||
+ buf.cmp("H6") ||
+ buf.cmp("UL") ||
+ buf.cmp("OL") ||
+ buf.cmp("DL") ||
+ buf.cmp("LI") ||
+ buf.cmp("DD") ||
+ buf.cmp("DT") ||
+ buf.cmp("HR") ||
+ buf.cmp("PRE") ||
+ buf.cmp("TABLE"))
{
block->end = start;
line = do_align(block, line, xx, newalign, links);
- newalign = strcasecmp(buf, "CENTER") ? LEFT : CENTER;
+ newalign = buf.cmp("CENTER") ? CENTER : LEFT;
xx = block->x;
block->h += hh;
- if (strcasecmp(buf, "UL") == 0 ||
- strcasecmp(buf, "OL") == 0 ||
- strcasecmp(buf, "DL") == 0)
+ if (buf.cmp("UL") ||
+ buf.cmp("OL") ||
+ buf.cmp("DL"))
{
block->h += fsize + 2;
xx = margins.push(4 * fsize);
}
- else if (strcasecmp(buf, "TABLE") == 0)
+ else if (buf.cmp("TABLE"))
{
if (get_attr(attrs, "BORDER", attr, sizeof(attr)))
border = (uchar)atoi(attr);
@@ -1368,12 +1569,12 @@ void Fl_Help_View::format() {
font = FL_HELVETICA_BOLD;
fsize = textsize_ + '7' - buf[1];
}
- else if (strcasecmp(buf, "DT") == 0)
+ else if (buf.cmp("DT"))
{
font = textfont_ | FL_ITALIC;
fsize = textsize_;
}
- else if (strcasecmp(buf, "PRE") == 0)
+ else if (buf.cmp("PRE"))
{
font = FL_COURIER;
fsize = textsize_;
@@ -1391,11 +1592,11 @@ void Fl_Help_View::format() {
hh = 0;
if ((tolower(buf[0]) == 'h' && isdigit(buf[1])) ||
- strcasecmp(buf, "DD") == 0 ||
- strcasecmp(buf, "DT") == 0 ||
- strcasecmp(buf, "P") == 0)
+ buf.cmp("DD") ||
+ buf.cmp("DT") ||
+ buf.cmp("P"))
yy += fsize + 2;
- else if (strcasecmp(buf, "HR") == 0)
+ else if (buf.cmp("HR"))
{
hh += 2 * fsize;
yy += fsize;
@@ -1409,47 +1610,47 @@ void Fl_Help_View::format() {
needspace = 0;
line = 0;
- if (strcasecmp(buf, "CENTER") == 0)
+ if (buf.cmp("CENTER"))
newalign = talign = CENTER;
else
newalign = get_align(attrs, talign);
}
- else if (strcasecmp(buf, "/CENTER") == 0 ||
- strcasecmp(buf, "/P") == 0 ||
- strcasecmp(buf, "/H1") == 0 ||
- strcasecmp(buf, "/H2") == 0 ||
- strcasecmp(buf, "/H3") == 0 ||
- strcasecmp(buf, "/H4") == 0 ||
- strcasecmp(buf, "/H5") == 0 ||
- strcasecmp(buf, "/H6") == 0 ||
- strcasecmp(buf, "/PRE") == 0 ||
- strcasecmp(buf, "/UL") == 0 ||
- strcasecmp(buf, "/OL") == 0 ||
- strcasecmp(buf, "/DL") == 0 ||
- strcasecmp(buf, "/TABLE") == 0)
+ else if (buf.cmp("/CENTER") ||
+ buf.cmp("/P") ||
+ buf.cmp("/H1") ||
+ buf.cmp("/H2") ||
+ buf.cmp("/H3") ||
+ buf.cmp("/H4") ||
+ buf.cmp("/H5") ||
+ buf.cmp("/H6") ||
+ buf.cmp("/PRE") ||
+ buf.cmp("/UL") ||
+ buf.cmp("/OL") ||
+ buf.cmp("/DL") ||
+ buf.cmp("/TABLE"))
{
line = do_align(block, line, xx, newalign, links);
xx = block->x;
block->end = ptr;
- if (strcasecmp(buf, "/UL") == 0 ||
- strcasecmp(buf, "/OL") == 0 ||
- strcasecmp(buf, "/DL") == 0)
+ if (buf.cmp("/UL") ||
+ buf.cmp("/OL") ||
+ buf.cmp("/DL"))
{
xx = margins.pop();
block->h += fsize + 2;
}
- else if (strcasecmp(buf, "/TABLE") == 0)
+ else if (buf.cmp("/TABLE"))
{
block->h += fsize + 2;
xx = margins.current();
}
- else if (strcasecmp(buf, "/PRE") == 0)
+ else if (buf.cmp("/PRE"))
{
pre = 0;
hh = 0;
}
- else if (strcasecmp(buf, "/CENTER") == 0)
+ else if (buf.cmp("/CENTER"))
talign = LEFT;
popfont(font, fsize, fcolor);
@@ -1476,7 +1677,7 @@ void Fl_Help_View::format() {
line = 0;
newalign = talign;
}
- else if (strcasecmp(buf, "TR") == 0)
+ else if (buf.cmp("TR"))
{
block->end = start;
line = do_align(block, line, xx, newalign, links);
@@ -1515,7 +1716,7 @@ void Fl_Help_View::format() {
rc = get_color(get_attr(attrs, "BGCOLOR", attr, sizeof(attr)), tc);
}
- else if (strcasecmp(buf, "/TR") == 0 && row)
+ else if (buf.cmp("/TR") && row)
{
line = do_align(block, line, xx, newalign, links);
block->end = start;
@@ -1546,8 +1747,8 @@ void Fl_Help_View::format() {
row = 0;
line = 0;
}
- else if ((strcasecmp(buf, "TD") == 0 ||
- strcasecmp(buf, "TH") == 0) && row)
+ else if ((buf.cmp("TD") ||
+ buf.cmp("TH")) && row)
{
int colspan; // COLSPAN attribute
@@ -1556,7 +1757,7 @@ void Fl_Help_View::format() {
block->end = start;
block->h += hh;
- if (strcasecmp(buf, "TH") == 0)
+ if (buf.cmp("TH"))
font = textfont_ | FL_BOLD;
else
font = textfont_;
@@ -1600,15 +1801,15 @@ void Fl_Help_View::format() {
block->bgcolor = get_color(get_attr(attrs, "BGCOLOR", attr,
sizeof(attr)), rc);
}
- else if ((strcasecmp(buf, "/TD") == 0 ||
- strcasecmp(buf, "/TH") == 0) && row)
+ else if ((buf.cmp("/TD") ||
+ buf.cmp("/TH")) && row)
{
line = do_align(block, line, xx, newalign, links);
popfont(font, fsize, fcolor);
xx = margins.pop();
talign = LEFT;
}
- else if (strcasecmp(buf, "FONT") == 0)
+ else if (buf.cmp("FONT"))
{
if (get_attr(attrs, "FACE", attr, sizeof(attr)) != NULL) {
if (!strncasecmp(attr, "helvetica", 9) ||
@@ -1632,39 +1833,39 @@ void Fl_Help_View::format() {
pushfont(font, fsize);
}
- else if (strcasecmp(buf, "/FONT") == 0)
+ else if (buf.cmp("/FONT"))
popfont(font, fsize, fcolor);
- else if (strcasecmp(buf, "B") == 0 ||
- strcasecmp(buf, "STRONG") == 0)
+ else if (buf.cmp("B") ||
+ buf.cmp("STRONG"))
pushfont(font |= FL_BOLD, fsize);
- else if (strcasecmp(buf, "I") == 0 ||
- strcasecmp(buf, "EM") == 0)
+ else if (buf.cmp("I") ||
+ buf.cmp("EM"))
pushfont(font |= FL_ITALIC, fsize);
- else if (strcasecmp(buf, "CODE") == 0 ||
- strcasecmp(buf, "TT") == 0)
+ else if (buf.cmp("CODE") ||
+ buf.cmp("TT"))
pushfont(font = FL_COURIER, fsize);
- else if (strcasecmp(buf, "KBD") == 0)
+ else if (buf.cmp("KBD"))
pushfont(font = FL_COURIER_BOLD, fsize);
- else if (strcasecmp(buf, "VAR") == 0)
+ else if (buf.cmp("VAR"))
pushfont(font = FL_COURIER_ITALIC, fsize);
- else if (strcasecmp(buf, "/B") == 0 ||
- strcasecmp(buf, "/STRONG") == 0 ||
- strcasecmp(buf, "/I") == 0 ||
- strcasecmp(buf, "/EM") == 0 ||
- strcasecmp(buf, "/CODE") == 0 ||
- strcasecmp(buf, "/TT") == 0 ||
- strcasecmp(buf, "/KBD") == 0 ||
- strcasecmp(buf, "/VAR") == 0)
+ else if (buf.cmp("/B") ||
+ buf.cmp("/STRONG") ||
+ buf.cmp("/I") ||
+ buf.cmp("/EM") ||
+ buf.cmp("/CODE") ||
+ buf.cmp("/TT") ||
+ buf.cmp("/KBD") ||
+ buf.cmp("/VAR"))
popfont(font, fsize, fcolor);
- else if (strcasecmp(buf, "IMG") == 0)
+ else if (buf.cmp("IMG"))
{
Fl_Shared_Image *img = 0;
int width;
int height;
- get_attr(attrs, "WIDTH", wattr, sizeof(wattr));
- get_attr(attrs, "HEIGHT", hattr, sizeof(hattr));
+ get_attr(attrs, "WIDTH", wattr, sizeof(wattr));
+ get_attr(attrs, "HEIGHT", hattr, sizeof(hattr));
width = get_length(wattr);
height = get_length(hattr);
@@ -1703,6 +1904,7 @@ void Fl_Help_View::format() {
needspace = 0;
}
+ buf.clear();
}
else if (*ptr == '\n' && pre)
{
@@ -1730,7 +1932,7 @@ void Fl_Help_View::format() {
}
ptr ++;
}
- else if (*ptr == '&' && s < (buf + sizeof(buf) - 1))
+ else if (*ptr == '&')
{
// Handle html '&' codes, eg. "&amp;"
ptr ++;
@@ -1738,12 +1940,9 @@ void Fl_Help_View::format() {
int qch = quote_char(ptr);
if (qch < 0)
- *s++ = '&';
+ buf.add('&');
else {
- int l;
- l = fl_utf8encode((unsigned int) qch, s);
- if (l < 1) l = 1;
- s += l;
+ buf.add(qch);
ptr = strchr(ptr, ';') + 1;
}
@@ -1752,20 +1951,16 @@ void Fl_Help_View::format() {
}
else
{
- if (s < (buf + sizeof(buf) - 1))
- *s++ = *ptr++;
- else
- ptr ++;
+ buf.add(*ptr++);
if ((fsize + 2) > hh)
hh = fsize + 2;
}
}
- if (s > buf && !head)
+ if (buf.size() > 0 && !head)
{
- *s = '\0';
- ww = (int)fl_width(buf);
+ ww = buf.width();
// printf("line = %d, xx = %d, ww = %d, block->x = %d, block->w = %d\n",
// line, xx, ww, block->x, block->w);
@@ -1870,9 +2065,8 @@ Fl_Help_View::format_table(int *table_width, // O - Total table width
incell, // In a table cell?
pre, // <PRE> text?
needspace; // Need whitespace?
- char *s, // Pointer into buffer
- buf[1024], // Text buffer
- attr[1024], // Other attribute
+ HV_Edit_Buffer buf; // Text buffer
+ char attr[1024], // Other attribute
wattr[1024], // WIDTH attribute
hattr[1024]; // HEIGHT attribute
const char *ptr, // Pointer into table
@@ -1883,6 +2077,8 @@ Fl_Help_View::format_table(int *table_width, // O - Total table width
Fl_Fontsize fsize; // Current font and size
Fl_Color fcolor; // Currrent font color
+ DEBUG_FUNCTION(__LINE__,__FUNCTION__);
+
// Clear widths...
*table_width = 0;
for (column = 0; column < MAX_COLUMNS; column ++)
@@ -1899,20 +2095,19 @@ Fl_Help_View::format_table(int *table_width, // O - Total table width
fstack_.top(font, fsize, fcolor);
// Scan the table...
- for (ptr = table, column = -1, width = 0, s = buf, incell = 0; *ptr;)
+ for (ptr = table, column = -1, width = 0, incell = 0; *ptr;)
{
- if ((*ptr == '<' || isspace((*ptr)&255)) && s > buf && incell)
+ if ((*ptr == '<' || isspace((*ptr)&255)) && buf.size() > 0 && incell)
{
// Check width...
if (needspace)
{
- *s++ = ' ';
+ buf.add(' ');
needspace = 0;
}
- *s = '\0';
- temp_width = (int)fl_width(buf);
- s = buf;
+ temp_width = buf.width();
+ buf.clear();
if (temp_width > minwidths[column])
minwidths[column] = temp_width;
@@ -1927,14 +2122,8 @@ Fl_Help_View::format_table(int *table_width, // O - Total table width
{
start = ptr;
- for (s = buf, ptr ++; *ptr && *ptr != '>' && !isspace((*ptr)&255);)
- if (s < (buf + sizeof(buf) - 1))
- *s++ = *ptr++;
- else
- ptr ++;
-
- *s = '\0';
- s = buf;
+ for (buf.clear(), ptr ++; *ptr && *ptr != '>' && !isspace((*ptr)&255);)
+ buf.add(*ptr++);
attrs = ptr;
while (*ptr && *ptr != '>')
@@ -1943,29 +2132,29 @@ Fl_Help_View::format_table(int *table_width, // O - Total table width
if (*ptr == '>')
ptr ++;
- if (strcasecmp(buf, "BR") == 0 ||
- strcasecmp(buf, "HR") == 0)
+ if (buf.cmp("BR") ||
+ buf.cmp("HR"))
{
width = 0;
needspace = 0;
}
- else if (strcasecmp(buf, "TABLE") == 0 && start > table)
+ else if (buf.cmp("TABLE") && start > table)
break;
- else if (strcasecmp(buf, "CENTER") == 0 ||
- strcasecmp(buf, "P") == 0 ||
- strcasecmp(buf, "H1") == 0 ||
- strcasecmp(buf, "H2") == 0 ||
- strcasecmp(buf, "H3") == 0 ||
- strcasecmp(buf, "H4") == 0 ||
- strcasecmp(buf, "H5") == 0 ||
- strcasecmp(buf, "H6") == 0 ||
- strcasecmp(buf, "UL") == 0 ||
- strcasecmp(buf, "OL") == 0 ||
- strcasecmp(buf, "DL") == 0 ||
- strcasecmp(buf, "LI") == 0 ||
- strcasecmp(buf, "DD") == 0 ||
- strcasecmp(buf, "DT") == 0 ||
- strcasecmp(buf, "PRE") == 0)
+ else if (buf.cmp("CENTER") ||
+ buf.cmp("P") ||
+ buf.cmp("H1") ||
+ buf.cmp("H2") ||
+ buf.cmp("H3") ||
+ buf.cmp("H4") ||
+ buf.cmp("H5") ||
+ buf.cmp("H6") ||
+ buf.cmp("UL") ||
+ buf.cmp("OL") ||
+ buf.cmp("DL") ||
+ buf.cmp("LI") ||
+ buf.cmp("DD") ||
+ buf.cmp("DT") ||
+ buf.cmp("PRE"))
{
width = 0;
needspace = 0;
@@ -1975,18 +2164,18 @@ Fl_Help_View::format_table(int *table_width, // O - Total table width
font = FL_HELVETICA_BOLD;
fsize = textsize_ + '7' - buf[1];
}
- else if (strcasecmp(buf, "DT") == 0)
+ else if (buf.cmp("DT"))
{
font = textfont_ | FL_ITALIC;
fsize = textsize_;
}
- else if (strcasecmp(buf, "PRE") == 0)
+ else if (buf.cmp("PRE"))
{
font = FL_COURIER;
fsize = textsize_;
pre = 1;
}
- else if (strcasecmp(buf, "LI") == 0)
+ else if (buf.cmp("LI"))
{
width += 4 * fsize;
font = textfont_;
@@ -2000,29 +2189,29 @@ Fl_Help_View::format_table(int *table_width, // O - Total table width
pushfont(font, fsize);
}
- else if (strcasecmp(buf, "/CENTER") == 0 ||
- strcasecmp(buf, "/P") == 0 ||
- strcasecmp(buf, "/H1") == 0 ||
- strcasecmp(buf, "/H2") == 0 ||
- strcasecmp(buf, "/H3") == 0 ||
- strcasecmp(buf, "/H4") == 0 ||
- strcasecmp(buf, "/H5") == 0 ||
- strcasecmp(buf, "/H6") == 0 ||
- strcasecmp(buf, "/PRE") == 0 ||
- strcasecmp(buf, "/UL") == 0 ||
- strcasecmp(buf, "/OL") == 0 ||
- strcasecmp(buf, "/DL") == 0)
+ else if (buf.cmp("/CENTER") ||
+ buf.cmp("/P") ||
+ buf.cmp("/H1") ||
+ buf.cmp("/H2") ||
+ buf.cmp("/H3") ||
+ buf.cmp("/H4") ||
+ buf.cmp("/H5") ||
+ buf.cmp("/H6") ||
+ buf.cmp("/PRE") ||
+ buf.cmp("/UL") ||
+ buf.cmp("/OL") ||
+ buf.cmp("/DL"))
{
width = 0;
needspace = 0;
popfont(font, fsize, fcolor);
}
- else if (strcasecmp(buf, "TR") == 0 || strcasecmp(buf, "/TR") == 0 ||
- strcasecmp(buf, "/TABLE") == 0)
+ else if (buf.cmp("TR") || buf.cmp("/TR") ||
+ buf.cmp("/TABLE"))
{
// printf("%s column = %d, colspan = %d, num_columns = %d\n",
-// buf, column, colspan, num_columns);
+// buf.c_str(), column, colspan, num_columns);
if (column >= 0)
{
@@ -2039,7 +2228,7 @@ Fl_Help_View::format_table(int *table_width, // O - Total table width
}
}
- if (strcasecmp(buf, "/TABLE") == 0)
+ if (buf.cmp("/TABLE"))
break;
needspace = 0;
@@ -2048,8 +2237,8 @@ Fl_Help_View::format_table(int *table_width, // O - Total table width
max_width = 0;
incell = 0;
}
- else if (strcasecmp(buf, "TD") == 0 ||
- strcasecmp(buf, "TH") == 0)
+ else if (buf.cmp("TD") ||
+ buf.cmp("TH"))
{
// printf("BEFORE column = %d, colspan = %d, num_columns = %d\n",
// column, colspan, num_columns);
@@ -2086,7 +2275,7 @@ Fl_Help_View::format_table(int *table_width, // O - Total table width
width = 0;
incell = 1;
- if (strcasecmp(buf, "TH") == 0)
+ if (buf.cmp("TH"))
font = textfont_ | FL_BOLD;
else
font = textfont_;
@@ -2102,35 +2291,35 @@ Fl_Help_View::format_table(int *table_width, // O - Total table width
// printf("max_width = %d\n", max_width);
}
- else if (strcasecmp(buf, "/TD") == 0 ||
- strcasecmp(buf, "/TH") == 0)
+ else if (buf.cmp("/TD") ||
+ buf.cmp("/TH"))
{
incell = 0;
popfont(font, fsize, fcolor);
}
- else if (strcasecmp(buf, "B") == 0 ||
- strcasecmp(buf, "STRONG") == 0)
+ else if (buf.cmp("B") ||
+ buf.cmp("STRONG"))
pushfont(font |= FL_BOLD, fsize);
- else if (strcasecmp(buf, "I") == 0 ||
- strcasecmp(buf, "EM") == 0)
+ else if (buf.cmp("I") ||
+ buf.cmp("EM"))
pushfont(font |= FL_ITALIC, fsize);
- else if (strcasecmp(buf, "CODE") == 0 ||
- strcasecmp(buf, "TT") == 0)
+ else if (buf.cmp("CODE") ||
+ buf.cmp("TT"))
pushfont(font = FL_COURIER, fsize);
- else if (strcasecmp(buf, "KBD") == 0)
+ else if (buf.cmp("KBD"))
pushfont(font = FL_COURIER_BOLD, fsize);
- else if (strcasecmp(buf, "VAR") == 0)
+ else if (buf.cmp("VAR"))
pushfont(font = FL_COURIER_ITALIC, fsize);
- else if (strcasecmp(buf, "/B") == 0 ||
- strcasecmp(buf, "/STRONG") == 0 ||
- strcasecmp(buf, "/I") == 0 ||
- strcasecmp(buf, "/EM") == 0 ||
- strcasecmp(buf, "/CODE") == 0 ||
- strcasecmp(buf, "/TT") == 0 ||
- strcasecmp(buf, "/KBD") == 0 ||
- strcasecmp(buf, "/VAR") == 0)
+ else if (buf.cmp("/B") ||
+ buf.cmp("/STRONG") ||
+ buf.cmp("/I") ||
+ buf.cmp("/EM") ||
+ buf.cmp("/CODE") ||
+ buf.cmp("/TT") ||
+ buf.cmp("/KBD") ||
+ buf.cmp("/VAR"))
popfont(font, fsize, fcolor);
- else if (strcasecmp(buf, "IMG") == 0 && incell)
+ else if (buf.cmp("IMG") && incell)
{
Fl_Shared_Image *img = 0;
int iwidth, iheight;
@@ -2159,6 +2348,7 @@ Fl_Help_View::format_table(int *table_width, // O - Total table width
needspace = 0;
}
+ buf.clear();
}
else if (*ptr == '\n' && pre)
{
@@ -2172,29 +2362,22 @@ Fl_Help_View::format_table(int *table_width, // O - Total table width
ptr ++;
}
- else if (*ptr == '&' && s < (buf + sizeof(buf) - 1))
+ else if (*ptr == '&' )
{
ptr ++;
int qch = quote_char(ptr);
if (qch < 0)
- *s++ = '&';
+ buf.add('&');
else {
-// int l;
-// l = fl_utf8encode((unsigned int) qch, s);
-// if (l < 1) l = 1;
-// s += l;
- *s++ = qch;
+ buf.add(qch);
ptr = strchr(ptr, ';') + 1;
}
}
else
{
- if (s < (buf + sizeof(buf) - 1))
- *s++ = *ptr++;
- else
- ptr ++;
+ buf.add(*ptr++);
}
}
@@ -2296,12 +2479,13 @@ Fl_Help_View::free_data() {
if (value_) {
const char *ptr, // Pointer into block
*attrs; // Pointer to start of element attributes
- char *s, // Pointer into buffer
- buf[1024], // Text buffer
- attr[1024], // Attribute buffer
+ HV_Edit_Buffer buf; // Text buffer
+ char attr[1024], // Attribute buffer
wattr[1024], // Width attribute buffer
hattr[1024]; // Height attribute buffer
+ DEBUG_FUNCTION(__LINE__,__FUNCTION__);
+
for (ptr = value_; *ptr;)
{
if (*ptr == '<')
@@ -2321,15 +2505,10 @@ Fl_Help_View::free_data() {
break;
}
- s = buf;
+ buf.clear();
while (*ptr && *ptr != '>' && !isspace((*ptr)&255))
- if (s < (buf + sizeof(buf) - 1))
- *s++ = *ptr++;
- else
- ptr ++;
-
- *s = '\0';
+ buf.add(*ptr++);
attrs = ptr;
while (*ptr && *ptr != '>')
@@ -2338,7 +2517,7 @@ Fl_Help_View::free_data() {
if (*ptr == '>')
ptr ++;
- if (strcasecmp(buf, "IMG") == 0)
+ if (buf.cmp("IMG"))
{
Fl_Shared_Image *img;
int width;
@@ -2390,7 +2569,7 @@ Fl_Help_View::free_data() {
ntargets_ = 0;
targets_ = 0;
}
-}
+} // free_data()
/** Gets an alignment attribute. */
int // O - Alignment
@@ -2842,12 +3021,13 @@ static unsigned int command(const char *cmd)
#define CMD(a, b, c, d) ((a<<24)|(b<<16)|(c<<8)|d)
-void Fl_Help_View::end_selection(int clipboard)
+void Fl_Help_View::end_selection(int clipboard)
{
- if (!selected || current_view!=this)
+ if (!selected || current_view!=this)
return;
// convert the select part of our html text into some kind of somewhat readable ASCII
// 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 len = (int) strlen(value_);
char *txt = (char*)malloc(len+1), *d = txt;
@@ -2863,7 +3043,8 @@ void Fl_Help_View::end_selection(int clipboard)
}
if (c==0) break;
// do something with this command... .
- // the replacement string must not be longer that the command itself plus '<' and '>'
+ // The replacement string must not be longer than the command
+ // itself plus '<' and '>'
src = 0;
switch (command(cmd)) {
case CMD('p','r','e', 0 ): pre = 1; break;
@@ -2899,10 +3080,10 @@ void Fl_Help_View::end_selection(int clipboard)
}
continue;
}
- if (c=='&') { // special characters
+ if (c=='&') { // special characters (HTML entities) // *FIXME* *UTF-8*
int xx = quote_char(s);
if (xx>=0) {
- c = (char)xx;
+ c = (char)xx; // *FIXME* *UTF-8*
for (;;) {
char cc = *s++;
if (!cc || cc==';') break;
@@ -3007,7 +3188,7 @@ Fl_Help_View::handle(int event) // I - Event to handle
return (Fl_Group::handle(event));
}
-/**
+/**
The constructor creates the Fl_Help_View widget at the specified
position and size.
*/
@@ -3346,14 +3527,26 @@ Fl_Help_View::value(const char *val) // I - Text to view
/* Returns the Unicode Code Point associated with a quoted character
(aka "HTML Entity").
+ Possible encoding formats:
+ - &name; named entity
+ - &#nn..; numeric (decimal) Unicode Code Point
+ - &#xnn..; numeric (hexadecimal) Unicode Code Point
+ - &#Xnn..; numeric (hexadecimal) Unicode Code Point
+ 'nn..' = decimal or hexadecimal number, resp.
+
+ Contents of the table names[] below:
+
All printable ASCII (32-126) and ISO-8859-1 (160-255) characters
are encoded with the same value in Unicode. Special characters
- outside the range [0-255] are encoded with their Unicode value
+ outside the range [0-255] are encoded with their Unicode Code Point
as hexadecimal constants. Example:
- Euro sign: (Unicode) U+20ac = (hex) 0x20ac
Note: Converted to correct Unicode values and tested (compared with
the display of Firefox). AlbrechtS, 14 Feb. 2016.
+
+ Note to devs: if you add or remove items to/from this list, please
+ update the documentation in FL/Fl_Help_View.H.
*/
static int // O - Code or -1 on error
quote_char(const char *p) { // I - Quoted string