From 1e2857dc28a1bb32e485dd407bb6cbc392a50624 Mon Sep 17 00:00:00 2001
From: Erich Hoover <ehoover@mines.edu>
Date: Fri, 8 Jun 2012 15:13:30 -0600
Subject: hhctrl.ocx: Add HTML to Unicode parsing capability.

---
 dlls/hhctrl.ocx/Makefile.in  |    1 +
 dlls/hhctrl.ocx/htmlparser.c |  219 ++++++++++++++++++++++++++++++++++++++++++
 dlls/hhctrl.ocx/htmlparser.h |   24 +++++
 3 files changed, 244 insertions(+), 0 deletions(-)
 create mode 100644 dlls/hhctrl.ocx/htmlparser.c
 create mode 100644 dlls/hhctrl.ocx/htmlparser.h

diff --git a/dlls/hhctrl.ocx/Makefile.in b/dlls/hhctrl.ocx/Makefile.in
index 05b3e35..6066316 100644
--- a/dlls/hhctrl.ocx/Makefile.in
+++ b/dlls/hhctrl.ocx/Makefile.in
@@ -6,6 +6,7 @@ C_SRCS = \
 	content.c \
 	help.c \
 	hhctrl.c \
+	htmlparser.c \
 	index.c \
 	search.c \
 	stream.c \
diff --git a/dlls/hhctrl.ocx/htmlparser.c b/dlls/hhctrl.ocx/htmlparser.c
new file mode 100644
index 0000000..eb4bf8c
--- /dev/null
+++ b/dlls/hhctrl.ocx/htmlparser.c
@@ -0,0 +1,219 @@
+/*
+ * Copyright 2012 Erich Hoover
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "hhctrl.h"
+#include <mshtml.h>
+#include <shlwapi.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(htmlhelp);
+
+struct html_encoded_symbol {
+    const char *html_code;
+    char        ascii_symbol;
+};
+
+struct html_encoded_symbol html_encoded_symbols[] =
+{
+    /* Special HTML symbols */
+    {"quot",   '"'},
+    {"amp",    '&'},
+    {"lt",     '<'},
+    {"gt",     '>'},
+    {"nbsp",   ' '},
+    /* Currency symbols */
+    {"cent",   0xA2},
+    {"pound",  0xA3},
+    {"curren", 0xA4},
+    {"yen",    0xA5},
+    /* Formatting characters */
+    {"iexcl",  0xA1},
+    {"brvbar", 0xA6},
+    {"sect",   0xA7},
+    {"uml",    0xA8},
+    {"copy",   0xA9},
+    {"ordf",   0xAA},
+    {"laquo",  0xAB},
+    {"shy",    0xAD},
+    {"reg",    0xAE},
+    {"macr",   0xAF},
+    {"deg",    0xB0},
+    {"sup2",   0xB2},
+    {"sup3",   0xB3},
+    {"acute",  0xB4},
+    {"para",   0xB6},
+    {"cedil",  0xB8},
+    {"sup1",   0xB9},
+    {"ordm",   0xBA},
+    {"raquo",  0xBB},
+    {"iquest", 0xBF},
+    /* Math characters */
+    {"not",    0xAC},
+    {"plusmn", 0xB1},
+    {"micro",  0xB5},
+    {"middot", 0xB7},
+    {"frac14", 0xBC},
+    {"frac12", 0xBD},
+    {"frac34", 0xBE},
+    {"times",  0xD7},
+    {"divide", 0xF7},
+    /* Capital latin characters */
+    {"Agrave", 0xC0},
+    {"Aacute", 0xC1},
+    {"Acirc",  0xC2},
+    {"Atilde", 0xC3},
+    {"Auml",   0xC4},
+    {"Aring",  0xC5},
+    {"AElig",  0xC6},
+    {"Ccedil", 0xC7},
+    {"Egrave", 0xC8},
+    {"Eacute", 0xC9},
+    {"Ecirc",  0xCA},
+    {"Euml",   0xCB},
+    {"Igrave", 0xCC},
+    {"Iacute", 0xCD},
+    {"Icirc",  0xCE},
+    {"Iuml",   0xCF},
+    {"ETH",    0xD0},
+    {"Ntilde", 0xD1},
+    {"Ograve", 0xD2},
+    {"Oacute", 0xD3},
+    {"Ocirc",  0xD4},
+    {"Otilde", 0xD5},
+    {"Ouml",   0xD6},
+    {"Oslash", 0xD8},
+    {"Ugrave", 0xD9},
+    {"Uacute", 0xDA},
+    {"Ucirc",  0xDB},
+    {"Uuml",   0xDC},
+    {"Yacute", 0xDD},
+    {"THORN",  0xDE},
+    /* Lower case latin characters */
+    {"szlig",  0xDF},
+    {"agrave", 0xE0},
+    {"aacute", 0xE1},
+    {"acirc",  0xE2},
+    {"atilde", 0xE3},
+    {"auml",   0xE4},
+    {"aring",  0xE5},
+    {"aelig",  0xE6},
+    {"ccedil", 0xE7},
+    {"egrave", 0xE8},
+    {"eacute", 0xE9},
+    {"ecirc",  0xEA},
+    {"euml",   0xEB},
+    {"igrave", 0xEC},
+    {"iacute", 0xED},
+    {"icirc",  0xEE},
+    {"iuml",   0xEF},
+    {"eth",    0xF0},
+    {"ntilde", 0xF1},
+    {"ograve", 0xF2},
+    {"oacute", 0xF3},
+    {"ocirc",  0xF4},
+    {"otilde", 0xF5},
+    {"ouml",   0xF6},
+    {"oslash", 0xF8},
+    {"ugrave", 0xF9},
+    {"uacute", 0xFA},
+    {"ucirc",  0xFB},
+    {"uuml",   0xFC},
+    {"yacute", 0xFD},
+    {"thorn",  0xFE},
+    {"yuml",   0xFF}
+};
+
+/*
+ * Parse an HTML fragment into a unicode string.
+ */
+BOOL decode_html(const char *html_fragment, int html_fragment_len, LPWSTR *unicode_text)
+{
+    const char *h = html_fragment;
+    char *amp, *sem, *spc, symbol;
+    int i, len, wlen;
+    WCHAR *w;
+
+    /* Allocate sufficient space for the unicode representation */
+    wlen = MultiByteToWideChar(CP_ACP, 0, html_fragment, html_fragment_len, NULL, 0);
+    *unicode_text = heap_alloc(wlen*sizeof(WCHAR));
+    w = *unicode_text;
+
+    while(1)
+    {
+        symbol = 0;
+        amp = strchr(h, '&');
+        if(!amp) break;
+        len = amp-h;
+        amp++; /* skip ampersand */
+        sem = strchr(amp, ';');
+        if(!sem) break;
+        spc = strchr(amp, ' ');
+        if(spc && spc < sem)
+            break; /* cannot have a space between the ampersand and the semicolon */
+        /* Convert the characters prior to the HTML encoded character */
+        wlen = MultiByteToWideChar(CP_ACP, 0, h, len, NULL, 0);
+        MultiByteToWideChar(CP_ACP, 0, h, len, w, wlen);
+        w += wlen;
+        /* If the symbol is not an HTML ASCII number then search the symbol table */
+        len = sem-amp;
+        if(amp[0] != '#')
+        {
+            for(i=0;i<sizeof(html_encoded_symbols)/sizeof(html_encoded_symbols[0]);i++)
+            {
+                const char *encoded_symbol = html_encoded_symbols[i].html_code;
+
+                if(strncmp(encoded_symbol, amp, len) == 0)
+                {
+                    symbol = html_encoded_symbols[i].ascii_symbol;
+                    break;
+                }
+            }
+        }
+        else
+        {
+            int tmp;
+
+            sscanf(amp, "%d", &tmp);
+            symbol = tmp;
+        }
+        /* Insert the new symbol */
+        if(symbol)
+        {
+            wlen = MultiByteToWideChar(CP_ACP, 0, &symbol, 1, NULL, 0);
+            MultiByteToWideChar(CP_ACP, 0, &symbol, 1, w, wlen);
+            w += wlen;
+        }
+        else
+            FIXME("Failed to translate HTML encoded character '&%.*s;'.\n", len, amp);
+        h = sem+1;
+    }
+    /* Convert any remaining characters */
+    if(h != NULL)
+    {
+        len = html_fragment_len-(h-html_fragment);
+        wlen = MultiByteToWideChar(CP_ACP, 0, h, len, NULL, 0);
+        MultiByteToWideChar(CP_ACP, 0, h, len, w, wlen);
+        w += wlen;
+    }
+    w[0] = 0; /* NULL-terminate the string */
+    return TRUE;
+} 
+
diff --git a/dlls/hhctrl.ocx/htmlparser.h b/dlls/hhctrl.ocx/htmlparser.h
new file mode 100644
index 0000000..8aa9855
--- /dev/null
+++ b/dlls/hhctrl.ocx/htmlparser.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2012 Erich Hoover
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef HTMLPARSER_H
+#define HTMLPARSER_H
+
+BOOL decode_html(const char *html_fragment, int html_fragment_len, LPWSTR *unicode_text);
+
+#endif
-- 
1.7.5.4

