summaryrefslogtreecommitdiff
path: root/content/handlers/html
diff options
context:
space:
mode:
Diffstat (limited to 'content/handlers/html')
-rw-r--r--content/handlers/html/Makefile1
-rw-r--r--content/handlers/html/box_construct.c286
-rw-r--r--content/handlers/html/list_counter_style.c312
-rw-r--r--content/handlers/html/list_counter_style.h45
4 files changed, 366 insertions, 278 deletions
diff --git a/content/handlers/html/Makefile b/content/handlers/html/Makefile
index 8bb329b76..968c96feb 100644
--- a/content/handlers/html/Makefile
+++ b/content/handlers/html/Makefile
@@ -16,6 +16,7 @@ S_HTML := box_construct.c \
imagemap.c \
interaction.c \
layout.c \
+ list_counter_style.c \
object.c \
redraw.c \
redraw_border.c \
diff --git a/content/handlers/html/box_construct.c b/content/handlers/html/box_construct.c
index cf0d91607..9204090fe 100644
--- a/content/handlers/html/box_construct.c
+++ b/content/handlers/html/box_construct.c
@@ -47,6 +47,7 @@
#include "html/box_special.h"
#include "html/box_normalise.h"
#include "html/form_internal.h"
+#include "html/list_counter_style.h"
/**
* Context for box tree construction
@@ -396,284 +397,13 @@ static unsigned int compute_list_marker_index(struct box *last)
return last->list_marker->rows + 1;
}
-
-/**
- * Roman numeral conversion
- *
- * \return The number of characters that are nesesary for full output
- */
-static int
-ntoromannumeral(char *buf, const size_t maxlen, int value, const char *C)
-{
- const int S[] = { 0, 2, 4, 2, 4, 2, 4 };
- const int D[] = { 1000, 500, 100, 50, 10, 5, 1 };
- const size_t L = sizeof(D) / sizeof(int) - 1;
- size_t k = 0; /* index into output buffer */
- unsigned int i = 0; /* index into maps */
- int r, r2;
-
- while (value > 0) {
- if (D[i] <= value) {
- r = value / D[i];
- value = value - (r * D[i]);
- if (i < L) {
- /* lookahead */
- r2 = value / D[i+1];
- }
- if (i < L && r2 >= S[i+1]) {
- /* will violate repeat boundary on next pass */
- value = value - (r2 * D[i+1]);
- if (k < maxlen) buf[k++] = C[i+1];
- if (k < maxlen) buf[k++] = C[i-1];
- } else if (S[i] && r >= S[i]) {
- /* violated repeat boundary on this pass */
- if (k < maxlen) buf[k++] = C[i];
- if (k < maxlen) buf[k++] = C[i-1];
- } else {
- while (r-- > 0 && k < maxlen) {
- buf[k++] = C[i];
- }
- }
- }
- i++;
- }
- if (k < maxlen) {
- buf[k] = '\0';
- }
- return k;
-}
-
-
-/**
- * lower case roman numeral
- */
-static int ntolcromannumeral(char *buf, const size_t maxlen, int value)
-{
- const char C[] = { 'm', 'd', 'c', 'l', 'x', 'v', 'i' };
- return ntoromannumeral(buf, maxlen, value, C);
-}
-
-/**
- * upper case roman numeral
- */
-static int ntoucromannumeral(char *buf, const size_t maxlen, int value)
-{
- const char C[] = { 'M', 'D', 'C', 'L', 'X', 'V', 'I' };
- return ntoromannumeral(buf, maxlen, value, C);
-}
-
-
-/**
- * generate alphabet symbol values for latin and greek labelling
- *
- * fills array with alphabet values suitable for the input value
- *
- * \param ares Buffer to recive the converted values
- * \param alen the length of \a ares buffer
- * \param value The value to convert
- * \param slen The number of symbols in the alphabet
- * \return The length a complete conversion which may be larger than \a alen
- */
-static size_t
-calc_alphabet_values(uint8_t *ares,
- const size_t alen,
- int value,
- unsigned char slen)
-{
- size_t idx = 0;
- uint8_t *first;
- uint8_t *last;
-
- /* generate alphabet values in ascending order */
- while (value > 0) {
- --value;
- if (idx < alen) ares[idx] = value % slen;
- idx++;
- value = value / slen;
- }
-
- /* put the values in decending order */
- first = ares;
- if (idx < alen) {
- last = first + (idx - 1);
- } else {
- last = first + (alen - 1);
- }
- while (first < last) {
- *first ^= *last;
- *last ^= *first;
- *first ^= *last;
- first++;
- last--;
- }
-
- return idx;
-}
-
-/**
- * maps alphabet values to output values with a symbol table
- *
- * Takes a list of alphabet values and for each one outputs the
- * compete symbol (in utf8) to an output buffer.
- *
- * \param buf The oputput buffer
- * \param buflen the length of \a buf
- * \param aval array of alphabet values
- * \param alen The number of values in \a alen
- * \param symtab The symbol table
- * \param symtablen The number of symbols in \a symtab
- * \return The number of bytes needed in the output buffer whichmay be
- * larger than \a buflen but the buffer will not be overrun
- */
-static int
-map_aval_to_symbols(char *buf, const size_t buflen,
- const uint8_t *aval, const size_t alen,
- const char symtab[][4], const size_t symtablen)
-{
- size_t oidx;
- size_t aidx;
- int sidx;
-
- oidx = 0;
- for (aidx=0; aidx < alen; aidx++) {
- sidx=0;
- while ((sidx < 4) &&
- (symtab[aval[aidx]][sidx] != 0)) {
- if (oidx < buflen) {
- buf[oidx] = symtab[aval[aidx]][sidx];
- }
- oidx++;
- sidx++;
- }
- }
- return oidx;
-}
-
-static int ntolcalpha(char *buf, const size_t buflen, int value)
-{
- size_t alen;
- uint8_t aval[20];
- const char symtab[][4] = {
- "a", "b", "c", "d", "e", "f", "g", "h", "i", "j",
- "k", "l", "m", "n", "o", "p", "q", "r", "s", "t",
- "u", "v", "w", "x", "y", "z"
- };
- const size_t symtablen = sizeof(symtab) / 4;
-
- alen = calc_alphabet_values(aval, sizeof(aval), value, symtablen);
- if (alen >= sizeof(aval)) {
- *buf = '?';
- return 1;
- }
-
- return map_aval_to_symbols(buf, buflen, aval, alen, symtab, symtablen);
-}
-
-static int ntoucalpha(char *buf, const size_t buflen, int value)
-{
- size_t alen;
- uint8_t aval[20];
- const char symtab[][4] = {
- "A", "B", "C", "D", "E", "F", "G", "H", "I", "J",
- "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
- "U", "V", "W", "X", "Y", "Z"
- };
- const size_t symtablen = sizeof(symtab) / 4;
-
- alen = calc_alphabet_values(aval, sizeof(aval), value, symtablen);
- if (alen >= sizeof(aval)) {
- *buf = '?';
- return 1;
- }
-
- return map_aval_to_symbols(buf, buflen, aval, alen, symtab, symtablen);
-}
-
-static int ntolcgreek(char *buf, const size_t buflen, int value)
-{
- size_t alen;
- uint8_t aval[20];
- const char symtab[][4] = {
- "α", "β", "γ", "δ", "ε", "ζ", "η", "θ", "ι", "κ",
- "λ", "μ", "ν", "ξ", "ο", "π", "ρ", "σ", "τ", "υ",
- "φ", "χ", "ψ", "ω"
- };
- const size_t symtablen = sizeof(symtab) / 4;
-
- alen = calc_alphabet_values(aval, sizeof(aval), value, symtablen);
- if (alen >= sizeof(aval)) {
- *buf = '?';
- return 1;
- }
-
- return map_aval_to_symbols(buf, buflen, aval, alen, symtab, symtablen);
-}
-
/**
- * format value into a list marker with a style
+ * maximum length of a list marker
*
- * The value is a one based index into the list. This means for
- * numeric printing the value must be incremented by one.
+ * enough for 9,999,999,999,999,999,999 in decimal
+ * or six characters for 3byte utf8
*/
-static size_t
-format_list_marker_value(char *text,
- size_t text_len,
- enum css_list_style_type_e list_style_type,
- unsigned int value)
-{
- int res = -1;
-
- switch (list_style_type) {
- case CSS_LIST_STYLE_TYPE_DECIMAL_LEADING_ZERO:
- res = snprintf(text, text_len, "%02u", value);
- break;
-
- case CSS_LIST_STYLE_TYPE_LOWER_ROMAN:
- res = ntolcromannumeral(text, text_len, value);
- break;
-
- case CSS_LIST_STYLE_TYPE_UPPER_ROMAN:
- res = ntoucromannumeral(text, text_len, value);
- break;
-
- case CSS_LIST_STYLE_TYPE_LOWER_ALPHA:
- case CSS_LIST_STYLE_TYPE_LOWER_LATIN:
- res = ntolcalpha(text, text_len, value);
- break;
-
- case CSS_LIST_STYLE_TYPE_UPPER_ALPHA:
- case CSS_LIST_STYLE_TYPE_UPPER_LATIN:
- res = ntoucalpha(text, text_len, value);
- break;
-
- case CSS_LIST_STYLE_TYPE_LOWER_GREEK:
- res = ntolcgreek(text, text_len, value);
- break;
-
- case CSS_LIST_STYLE_TYPE_ARMENIAN:
- case CSS_LIST_STYLE_TYPE_GEORGIAN:
- case CSS_LIST_STYLE_TYPE_DECIMAL:
- default:
- res = snprintf(text, text_len, "%u", value);
- break;
- }
-
- /* deal with error */
- if (res < 0) {
- text[0] = 0;
- return 0;
- }
-
- /* deal with overflow */
- if ((size_t)res >= (text_len-2)) {
- res = text_len-2;
- }
- text[res++] = '.';
- text[res++] = 0;
-
- return res;
-}
-
+#define LIST_MARKER_SIZE 20
/**
* Construct a list marker box
@@ -731,12 +461,12 @@ box_construct_marker(struct box *box,
default:
marker->rows = compute_list_marker_index(parent->last);
- marker->text = talloc_array(ctx->bctx, char, 20);
+ marker->text = talloc_array(ctx->bctx, char, LIST_MARKER_SIZE);
if (marker->text == NULL)
return false;
- marker->length = format_list_marker_value(marker->text,
- 20,
+ marker->length = list_counter_style_value(marker->text,
+ LIST_MARKER_SIZE,
list_style_type,
marker->rows);
break;
diff --git a/content/handlers/html/list_counter_style.c b/content/handlers/html/list_counter_style.c
new file mode 100644
index 000000000..a5ce3ae64
--- /dev/null
+++ b/content/handlers/html/list_counter_style.c
@@ -0,0 +1,312 @@
+/*
+ * Copyright 2021 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * Implementation of css list counter styling
+ */
+
+#include <stddef.h>
+#include <stdio.h>
+
+#include "css/select.h"
+
+#include "html/list_counter_style.h"
+
+
+/**
+ * maps alphabet values to output values with a symbol table
+ *
+ * Takes a list of alphabet values and for each one outputs the
+ * compete symbol (in utf8) to an output buffer.
+ *
+ * \param buf The oputput buffer
+ * \param buflen the length of \a buf
+ * \param aval array of alphabet values
+ * \param alen The number of values in \a alen
+ * \param symtab The symbol table
+ * \param symtablen The number of symbols in \a symtab
+ * \return The number of bytes needed in the output buffer whichmay be
+ * larger than \a buflen but the buffer will not be overrun
+ */
+static int
+map_aval_to_symbols(char *buf, const size_t buflen,
+ const uint8_t *aval, const size_t alen,
+ const char symtab[][4], const size_t symtablen)
+{
+ size_t oidx;
+ size_t aidx;
+ int sidx;
+
+ oidx = 0;
+ for (aidx=0; aidx < alen; aidx++) {
+ sidx=0;
+ while ((sidx < 4) &&
+ (symtab[aval[aidx]][sidx] != 0)) {
+ if (oidx < buflen) {
+ buf[oidx] = symtab[aval[aidx]][sidx];
+ }
+ oidx++;
+ sidx++;
+ }
+ }
+ return oidx;
+}
+
+
+/**
+ * generate alphabet symbol values for latin and greek labelling
+ *
+ * fills array with alphabet values suitable for the input value
+ *
+ * \param ares Buffer to recive the converted values
+ * \param alen the length of \a ares buffer
+ * \param value The value to convert
+ * \param slen The number of symbols in the alphabet
+ * \return The length a complete conversion which may be larger than \a alen
+ */
+static size_t
+calc_alphabet_values(uint8_t *ares,
+ const size_t alen,
+ int value,
+ unsigned char slen)
+{
+ size_t idx = 0;
+ uint8_t *first;
+ uint8_t *last;
+
+ /* generate alphabet values in ascending order */
+ while (value > 0) {
+ --value;
+ if (idx < alen) ares[idx] = value % slen;
+ idx++;
+ value = value / slen;
+ }
+
+ /* put the values in decending order */
+ first = ares;
+ if (idx < alen) {
+ last = first + (idx - 1);
+ } else {
+ last = first + (alen - 1);
+ }
+ while (first < last) {
+ *first ^= *last;
+ *last ^= *first;
+ *first ^= *last;
+ first++;
+ last--;
+ }
+
+ return idx;
+}
+
+
+/**
+ * Roman numeral conversion
+ *
+ * \return The number of characters that are nesesary for full output
+ */
+static int
+ntoromannumeral(char *buf, const size_t maxlen, int value, const char *C)
+{
+ const int S[] = { 0, 2, 4, 2, 4, 2, 4 };
+ const int D[] = { 1000, 500, 100, 50, 10, 5, 1 };
+ const size_t L = sizeof(D) / sizeof(int) - 1;
+ size_t k = 0; /* index into output buffer */
+ unsigned int i = 0; /* index into maps */
+ int r, r2;
+
+ while (value > 0) {
+ if (D[i] <= value) {
+ r = value / D[i];
+ value = value - (r * D[i]);
+ if (i < L) {
+ /* lookahead */
+ r2 = value / D[i+1];
+ }
+ if (i < L && r2 >= S[i+1]) {
+ /* will violate repeat boundary on next pass */
+ value = value - (r2 * D[i+1]);
+ if (k < maxlen) buf[k++] = C[i+1];
+ if (k < maxlen) buf[k++] = C[i-1];
+ } else if (S[i] && r >= S[i]) {
+ /* violated repeat boundary on this pass */
+ if (k < maxlen) buf[k++] = C[i];
+ if (k < maxlen) buf[k++] = C[i-1];
+ } else {
+ while (r-- > 0 && k < maxlen) {
+ buf[k++] = C[i];
+ }
+ }
+ }
+ i++;
+ }
+ if (k < maxlen) {
+ buf[k] = '\0';
+ }
+ return k;
+}
+
+
+/**
+ * lower case roman numeral
+ */
+static int ntolcromannumeral(char *buf, const size_t maxlen, int value)
+{
+ const char C[] = { 'm', 'd', 'c', 'l', 'x', 'v', 'i' };
+ return ntoromannumeral(buf, maxlen, value, C);
+}
+
+/**
+ * upper case roman numeral
+ */
+static int ntoucromannumeral(char *buf, const size_t maxlen, int value)
+{
+ const char C[] = { 'M', 'D', 'C', 'L', 'X', 'V', 'I' };
+ return ntoromannumeral(buf, maxlen, value, C);
+}
+
+
+
+
+static int ntolcalpha(char *buf, const size_t buflen, int value)
+{
+ size_t alen;
+ uint8_t aval[20];
+ const char symtab[][4] = {
+ "a", "b", "c", "d", "e", "f", "g", "h", "i", "j",
+ "k", "l", "m", "n", "o", "p", "q", "r", "s", "t",
+ "u", "v", "w", "x", "y", "z"
+ };
+ const size_t symtablen = sizeof(symtab) / 4;
+
+ alen = calc_alphabet_values(aval, sizeof(aval), value, symtablen);
+ if (alen >= sizeof(aval)) {
+ *buf = '?';
+ return 1;
+ }
+
+ return map_aval_to_symbols(buf, buflen, aval, alen, symtab, symtablen);
+}
+
+static int ntoucalpha(char *buf, const size_t buflen, int value)
+{
+ size_t alen;
+ uint8_t aval[20];
+ const char symtab[][4] = {
+ "A", "B", "C", "D", "E", "F", "G", "H", "I", "J",
+ "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
+ "U", "V", "W", "X", "Y", "Z"
+ };
+ const size_t symtablen = sizeof(symtab) / 4;
+
+ alen = calc_alphabet_values(aval, sizeof(aval), value, symtablen);
+ if (alen >= sizeof(aval)) {
+ *buf = '?';
+ return 1;
+ }
+
+ return map_aval_to_symbols(buf, buflen, aval, alen, symtab, symtablen);
+}
+
+static int ntolcgreek(char *buf, const size_t buflen, int value)
+{
+ size_t alen;
+ uint8_t aval[20];
+ const char symtab[][4] = {
+ "α", "β", "γ", "δ", "ε", "ζ", "η", "θ", "ι", "κ",
+ "λ", "μ", "ν", "ξ", "ο", "π", "ρ", "σ", "τ", "υ",
+ "φ", "χ", "ψ", "ω"
+ };
+ const size_t symtablen = sizeof(symtab) / 4;
+
+ alen = calc_alphabet_values(aval, sizeof(aval), value, symtablen);
+ if (alen >= sizeof(aval)) {
+ *buf = '?';
+ return 1;
+ }
+
+ return map_aval_to_symbols(buf, buflen, aval, alen, symtab, symtablen);
+}
+
+
+/**
+ * format value into a list marker with a style
+ *
+ * The value is a one based index into the list. This means for
+ * numeric printing the value must be incremented by one.
+ */
+size_t
+list_counter_style_value(char *text,
+ size_t text_len,
+ enum css_list_style_type_e list_style_type,
+ unsigned int value)
+{
+ int res = -1;
+
+ switch (list_style_type) {
+ case CSS_LIST_STYLE_TYPE_DECIMAL_LEADING_ZERO:
+ res = snprintf(text, text_len, "%02u", value);
+ break;
+
+ case CSS_LIST_STYLE_TYPE_LOWER_ROMAN:
+ res = ntolcromannumeral(text, text_len, value);
+ break;
+
+ case CSS_LIST_STYLE_TYPE_UPPER_ROMAN:
+ res = ntoucromannumeral(text, text_len, value);
+ break;
+
+ case CSS_LIST_STYLE_TYPE_LOWER_ALPHA:
+ case CSS_LIST_STYLE_TYPE_LOWER_LATIN:
+ res = ntolcalpha(text, text_len, value);
+ break;
+
+ case CSS_LIST_STYLE_TYPE_UPPER_ALPHA:
+ case CSS_LIST_STYLE_TYPE_UPPER_LATIN:
+ res = ntoucalpha(text, text_len, value);
+ break;
+
+ case CSS_LIST_STYLE_TYPE_LOWER_GREEK:
+ res = ntolcgreek(text, text_len, value);
+ break;
+
+ case CSS_LIST_STYLE_TYPE_ARMENIAN:
+ case CSS_LIST_STYLE_TYPE_GEORGIAN:
+ case CSS_LIST_STYLE_TYPE_DECIMAL:
+ default:
+ res = snprintf(text, text_len, "%u", value);
+ break;
+ }
+
+ /* deal with error */
+ if (res < 0) {
+ text[0] = 0;
+ return 0;
+ }
+
+ /* deal with overflow */
+ if ((size_t)res >= (text_len-2)) {
+ res = text_len-2;
+ }
+ text[res++] = '.';
+ text[res++] = 0;
+
+ return res;
+}
diff --git a/content/handlers/html/list_counter_style.h b/content/handlers/html/list_counter_style.h
new file mode 100644
index 000000000..6446b933d
--- /dev/null
+++ b/content/handlers/html/list_counter_style.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2021 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * List counter style handling
+ *
+ * These functions provide font related services. They all work on
+ * UTF-8 strings with lengths given.
+ */
+
+#ifndef NETSURF_HTML_LIST_COUNTER_STYLE_H
+#define NETSURF_HTML_LIST_COUNTER_STYLE_H
+
+/**
+ * format value into a list marker with a style
+ *
+ * \param text The buffer to recive the output
+ * \param text_len The length available in \a text
+ * \param list_style_type The css list style type
+ * \param value The value to style
+ * \return The size of data placed in \a text
+ */
+size_t
+list_counter_style_value(char *text,
+ size_t text_len,
+ enum css_list_style_type_e list_style_type,
+ unsigned int value);
+
+#endif