diff options
author | Patrick McDermott <pj@pehjota.net> | 2017-11-01 12:06:57 (EDT) |
---|---|---|
committer | Patrick McDermott <pj@pehjota.net> | 2017-11-01 12:06:57 (EDT) |
commit | da89b824d7d05edf1f2e27a63bbbce2a1d3a333a (patch) | |
tree | ad9c3506aa01acb0e278073733b5813377f21bd5 /src/utils | |
parent | 4f5fc75bd63da2538b3e27f6c63c4776d1425477 (diff) | |
download | marquee-da89b824d7d05edf1f2e27a63bbbce2a1d3a333a.zip marquee-da89b824d7d05edf1f2e27a63bbbce2a1d3a333a.tar.gz marquee-da89b824d7d05edf1f2e27a63bbbce2a1d3a333a.tar.bz2 |
src/html.[ch]: Move under src/utils/
Diffstat (limited to 'src/utils')
-rw-r--r-- | src/utils/html.c | 703 | ||||
-rw-r--r-- | src/utils/html.h | 88 |
2 files changed, 791 insertions, 0 deletions
diff --git a/src/utils/html.c b/src/utils/html.c new file mode 100644 index 0000000..47b2d7a --- /dev/null +++ b/src/utils/html.c @@ -0,0 +1,703 @@ +/* + * HTML document generation + * + * Copyright (C) 2017 Patrick McDermott + * + * This file is part of Marquee. + * + * Marquee 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, either version 3 of the License, or + * (at your option) any later version. + * + * Marquee 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 Marquee. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "html.h" + +#include <stdarg.h> +#include <string.h> + +#include <glib.h> +#include <gtk/gtk.h> + +static const gchar *styles = + /* + * General styles + */ + "* {\n" + "margin: 6px;\n" + "padding: 0;\n" + "background: none;\n" + "border: 0 none;\n" + "}\n" + "html {\n" + "margin: 0;\n" + "}\n" + "body {\n" + "margin: 18px;\n" + "background-color: #AFAFAF;\n" + "font-family: sans-serif;\n" + "}\n" + "h1, h2, h3, h4, h5, h6, p {\n" + "text-align: center;\n" + "}\n" + /* + * Horizontal notebook + */ + "div.notebook-h {\n" + "clear: left;\n" + "position: relative;\n" + "padding: 0;\n" + "}\n" + "div.notebook-h > input {\n" + "display: none;\n" + "}\n" + "div.notebook-h > label {\n" + "display: block;\n" + "background-color: #9F9F9F;\n" + "color: #5F5F5F;\n" + "float: left;\n" + "margin: 6px 3px 0 0;\n" + "border-width: 1px 1px 0 1px;\n" + "border-style: solid;\n" + "border-color: #8F8F8F;\n" + "border-radius: 3px 3px 0 0;\n" + "padding: 6px;\n" + "font-weight: bold;\n" + "position: relative;\n" + "top: 3px;\n" + "}\n" + "div.notebook-h > input:checked + label {\n" + "background-color: #CFCFCF;\n" + "color: #000000;\n" + "padding: 6px 6px 7px 6px;\n" + "border-color: #9F9F9F;\n" + "position: relative;\n" + "top: 0;\n" + "z-index: 1;\n" + "}\n" + "div.notebook-h > div {\n" + "display: none;\n" + "background-color: #CFCFCF;\n" + "clear: left;\n" + "border: 1px solid #9F9F9F;\n" + "border-radius: 0 0 3px 3px;\n" + "position: relative;\n" + "top: -1px;\n" + "margin: 0;\n" + "}\n" + /* + * Vertical notebook + */ + "div.notebook-v {\n" + "position: relative;\n" + /* Why are these weird margin and padding numbers necessary? */ + "margin: 6px 5px 6px 0;\n" + "padding: 6px 0 0 0;\n" + "}\n" + "div.notebook-v > input {\n" + "display: none;\n" + "}\n" + "div.notebook-v > label {\n" + "display: block;\n" + "background-color: #9F9F9F;\n" + "color: #5F5F5F;\n" + "float: left;\n" + "clear: left;\n" + "margin: 0 0 3px 6px;\n" + "border-width: 1px 0 1px 1px;\n" + "border-style: solid;\n" + "border-color: #8F8F8F;\n" + "border-radius: 3px 0 0 3px;\n" + "padding: 6px;\n" + "font-weight: bold;\n" + "position: relative;\n" + "left: 3px;\n" + "}\n" + "div.notebook-v > input:checked + label {\n" + "background-color: #CFCFCF;\n" + "color: #000000;\n" + "padding: 6px 7px 6px 6px;\n" + "border-color: #9F9F9F;\n" + "position: relative;\n" + "left: 0;\n" + "z-index: 1;\n" + "}\n" + "div.notebook-v > div {\n" + "display: none;\n" + "background-color: #CFCFCF;\n" + "border: 1px solid #9F9F9F;\n" + "border-radius: 0 3px 3px 0;\n" + "position: relative;\n" + "left: -1px;\n" + "margin: 0;\n" + "overflow: hidden;\n" + "}\n" + /* + * Form elements + */ + "form {\n" + "margin: 0;\n" + "}\n" + "form input, form select {\n" + "border: 1px solid #9F9F9F;\n" + "border-radius: 3px;\n" + "background-color: #EFEFEF;\n" + "padding: 6px;\n" + "color: #000000;\n" + "transition: all 250ms ease-in-out 0s;\n" + "-moz-transition: all 250ms ease-in-out 0s;\n" + "-wekbit-transition: all 250ms ease-in-out 0s;\n" + "-o-transition: all 250ms ease-in-out 0s;\n" + "}\n" + "div.dialog-buttonbox {\n" + "margin: 0;\n" + "float: right;\n" + "}\n" + "form label {\n" + "display: block;\n" + "}\n" + "form label span {\n" + "display: inline-block;\n" + "width: calc(50% - 6px);\n" + "text-align: right;\n" + "}\n" + "form input[type=submit], form input[type=reset] {\n" + "background-color: #DFDFDF;\n" + "}\n" + "form input:hover, form select:hover,\n" + "form input:focus, form select:focus {\n" + "border: 1px solid #4F8FCF;\n" + "outline: 0;\n" + "}\n" + "form input[type=submit]:hover, form input[type=reset]:hover,\n" + "form input[type=submit]:focus, form input[type=reset]:focus {\n" + "background-color: #EFEFEF;\n" + "}\n" + "iframe {\n" + "width: calc(100% - 12px);\n" + "height: 400px;\n" + "}\n" + ; + +gchar * +mq_html_document(const gchar *title, ...) +{ + gsize len; + va_list ap; + gchar *child; + gchar *document; + gchar *ptr; + + /* Calculate length. */ + len = strlen("<!doctype html>\n<html dir=\""); + len += 3; /* "ltr" or "rtl" */ + len += strlen("\">\n<head>\n<meta charset=\"utf-8\">\n<title>"); + len += strlen(title); + len += strlen("</title>\n<style>\n"); + len += strlen(styles); + len += strlen("</style>\n</head>\n<body>\n"); + va_start(ap, title); + while ((child = va_arg(ap, gchar *))) { + len += strlen(child); + } + va_end(ap); + len += strlen("</body>\n</html>\n"); + ++len; /* NUL byte */ + + /* Build string. */ + document = g_new(gchar, len); + ptr = g_stpcpy(document, "<!doctype html>\n<html dir=\""); + ptr = g_stpcpy(ptr, gtk_widget_get_default_direction() == + GTK_TEXT_DIR_RTL ? "rtl" : "ltr"); + ptr = g_stpcpy(ptr, "\">\n<head>\n<meta charset=\"utf-8\">\n<title>"); + ptr = g_stpcpy(ptr, title); + ptr = g_stpcpy(ptr, "</title>\n<style>\n"); + ptr = g_stpcpy(ptr, styles); + ptr = g_stpcpy(ptr, "</style>\n</head>\n<body>\n"); + va_start(ap, title); + while ((child = va_arg(ap, gchar *))) { + ptr = g_stpcpy(ptr, child); + g_free(child); + } + va_end(ap); + ptr = g_stpcpy(ptr, "</body>\n</html>\n"); /* g_stpcpy() adds NUL. */ + + return document; +} + +#define TEXT_ELEMENT(ELEM) \ + gchar * \ + mq_html_##ELEM(const gchar *text) \ + { \ + return g_strconcat("<" #ELEM ">", text, "</" #ELEM ">\n", \ + NULL); \ + } \ + gchar * \ + mq_html_##ELEM##_free(gchar *text) \ + { \ + gchar *e; \ + e = g_strconcat("<" #ELEM ">", text, "</" #ELEM ">\n", NULL); \ + g_free(text); \ + return e; \ + } +TEXT_ELEMENT(h1) +TEXT_ELEMENT(h2) +TEXT_ELEMENT(h3) +TEXT_ELEMENT(h4) +TEXT_ELEMENT(h5) +TEXT_ELEMENT(h6) +TEXT_ELEMENT(p) +#undef TEXT_ELEMENT + +gchar * +mq_html_list(const gchar *type, GDestroyNotify destroy, ...) +{ + gsize len; + va_list ap; + gchar *child; + gchar *list; + gchar *ptr; + + /* TODO: Doesn't support specification of <ol> list types. */ + + /* Calculate length. */ + len = strlen("<ul>\n"); + va_start(ap, destroy); + while ((child = va_arg(ap, gchar *))) { + len += strlen("<li>\n"); + len += strlen(child); + len += strlen("</li>\n"); + } + va_end(ap); + len += strlen("</ul>\n"); + ++len; /* NUL byte */ + + /* Build string. */ + list = g_new(gchar, len); + if (type && type[0]) { + ptr = g_stpcpy(list, "<ol>\n"); + } else { + ptr = g_stpcpy(list, "<ul>\n"); + } + va_start(ap, destroy); + while ((child = va_arg(ap, gchar *))) { + ptr = g_stpcpy(ptr, "<li>\n"); + ptr = g_stpcpy(ptr, child); + if (destroy) { + destroy(child); + } + ptr = g_stpcpy(ptr, "</li>\n"); + } + va_end(ap); + ptr = g_stpcpy(ptr, "</ul>\n"); /* g_stpcpy() adds the NUL. */ + + return list; +} + +gchar * +mq_html_list_v(const gchar *type, gchar **children) +{ + gsize len; + gsize i; + gchar *list; + gchar *ptr; + + /* TODO: Doesn't support specification of <ol> list types. */ + + /* Calculate length. */ + len = strlen("<ul>\n"); + for (i = 0; children && children[i]; ++i) { + len += strlen("<li>\n"); + len += strlen(children[i]); + len += strlen("</li>\n"); + } + len += strlen("</ul>\n"); + ++len; /* NUL byte */ + + /* Build string. */ + list = g_new(gchar, len); + if (type && type[0]) { + ptr = g_stpcpy(list, "<ol>\n"); + } else { + ptr = g_stpcpy(list, "<ul>\n"); + } + for (i = 0; children && children[i]; ++i) { + ptr = g_stpcpy(ptr, "<li>\n"); + ptr = g_stpcpy(ptr, children[i]); + ptr = g_stpcpy(ptr, "</li>\n"); + } + ptr = g_stpcpy(ptr, "</ul>\n"); /* g_stpcpy() adds the NUL. */ + + return list; +} + +gchar * +mq_html_container(const gchar *element, ...) +{ + gsize len; + va_list ap; + gchar *child; + gchar *container; + gchar *ptr; + + /* Calculate length. */ + len = strlen("<"); + len += strlen(element); + len += strlen(">\n"); + va_start(ap, element); + while ((child = va_arg(ap, gchar *))) { + len += strlen(child); + } + va_end(ap); + len += strlen("</"); + len += strlen(element); + len += strlen(">\n"); + ++len; /* NUL byte */ + + /* Build string. */ + container = g_new(gchar, len); + ptr = g_stpcpy(container, "<"); + ptr = g_stpcpy(ptr, element); + ptr = g_stpcpy(ptr, ">\n"); + va_start(ap, element); + while ((child = va_arg(ap, gchar *))) { + ptr = g_stpcpy(ptr, child); + g_free(child); + } + va_end(ap); + ptr = g_stpcpy(ptr, "</"); + ptr = g_stpcpy(ptr, element); + ptr = g_stpcpy(ptr, ">\n"); /* g_stpcpy() adds the NUL. */ + + return container; +} + +gchar * +mq_html_notebook(gboolean vertical, const gchar *name, guint current_page, ...) +{ + gsize name_len; + gsize len; + va_list ap; + gsize i; + gchar *child; + gchar *tab_label; + gchar *i_str; + gchar *notebook; + gchar *ptr; + + /* Calculate length. */ + name_len = strlen(name); + len = strlen("<div class=\"notebook-") + 1 + strlen("\">\n"); + va_start(ap, current_page); + i = 0; + while ((child = va_arg(ap, gchar *)) && + (tab_label = va_arg(ap, gchar *))) { + i_str = g_strdup_printf("%zu", i); + len += strlen("<input id=\"_tab_"); + len += name_len; + len += strlen("_"); + len += strlen(i_str); + /* len += (gsize) log10(i) + 1; */ + len += strlen("\" type=\"radio\""); + if (i == current_page) { + len += strlen(" checked=\"checked\""); + } + len += strlen(" name=\"_tabs\"></input>\n"); + len += strlen("<label for=\"_tab_"); + len += name_len; + len += strlen("_"); + len += strlen(i_str); + /* len += (gsize) log10(i) + 1; */ + len += strlen("\">"); + len += strlen(tab_label); + len += strlen("</label>\n"); + ++i; + } + va_end(ap); + va_start(ap, current_page); + while ((child = va_arg(ap, gchar *)) && + (tab_label = va_arg(ap, gchar *))) { + i_str = g_strdup_printf("%zu", i); + len += strlen("<div id=\"_tab-page_"); + len += name_len; + len += strlen("_"); + len += strlen(i_str); + len += strlen("\">\n"); + len += strlen(child); + len += strlen("</div>\n<style>\ndiv.notebook-") + 1; + len += strlen(" > input#_tab_"); + len += name_len; + len += strlen("_"); + len += strlen(i_str); + len += strlen(":checked ~ div#_tab-page_"); + len += name_len; + len += strlen("_"); + len += strlen(i_str); + len += strlen(" {\ndisplay: block;\n}\n</style>\n"); + } + va_end(ap); + len += strlen("</div>\n"); + ++len; /* NUL byte */ + + /* Build string. */ + notebook = g_new(gchar, len); + ptr = g_stpcpy(notebook, "<div class=\"notebook-"); + ptr = g_stpcpy(ptr, vertical ? "v" : "h"); + ptr = g_stpcpy(ptr, "\">\n"); + va_start(ap, current_page); + i = 0; + while ((child = va_arg(ap, gchar *)) && + (tab_label = va_arg(ap, gchar *))) { + i_str = g_strdup_printf("%zu", i); + ptr = g_stpcpy(ptr, "<input id=\"_tab_"); + ptr = g_stpcpy(ptr, name); + ptr = g_stpcpy(ptr, "_"); + ptr = g_stpcpy(ptr, i_str); + ptr = g_stpcpy(ptr, "\" type=\"radio\""); + if (i == current_page) { + ptr = g_stpcpy(ptr, " checked=\"checked\""); + } + ptr = g_stpcpy(ptr, " name=\"_tabs\"></input>\n"); + ptr = g_stpcpy(ptr, "<label for=\"_tab_"); + ptr = g_stpcpy(ptr, name); + ptr = g_stpcpy(ptr, "_"); + ptr = g_stpcpy(ptr, i_str); + ptr = g_stpcpy(ptr, "\">"); + ptr = g_stpcpy(ptr, tab_label); + ptr = g_stpcpy(ptr, "</label>\n"); + g_free(i_str); + ++i; + } + va_end(ap); + va_start(ap, current_page); + i = 0; + while ((child = va_arg(ap, gchar *)) && + (tab_label = va_arg(ap, gchar *))) { + i_str = g_strdup_printf("%zu", i); + ptr = g_stpcpy(ptr, "<div id=\"_tab-page_"); + ptr = g_stpcpy(ptr, name); + ptr = g_stpcpy(ptr, "_"); + ptr = g_stpcpy(ptr, i_str); + ptr = g_stpcpy(ptr, "\">\n"); + ptr = g_stpcpy(ptr, child); + g_free(child); + ptr = g_stpcpy(ptr, "</div>\n<style>\ndiv.notebook-"); + ptr = g_stpcpy(ptr, vertical ? "v" : "h"); + ptr = g_stpcpy(ptr, " > input#_tab_"); + ptr = g_stpcpy(ptr, name); + ptr = g_stpcpy(ptr, "_"); + ptr = g_stpcpy(ptr, i_str); + ptr = g_stpcpy(ptr, ":checked ~ div#_tab-page_"); + ptr = g_stpcpy(ptr, name); + ptr = g_stpcpy(ptr, "_"); + ptr = g_stpcpy(ptr, i_str); + ptr = g_stpcpy(ptr, " {\ndisplay: block;\n}\n</style>\n"); + ++i; + } + va_end(ap); + ptr = g_stpcpy(ptr, "</div>\n"); /* g_stpcpy() adds the NUL. */ + + return notebook; +} + +gchar * +mq_html_form(const gchar *submit_label, const gchar *reset_label, ...) +{ + gsize len; + va_list ap; + gchar *child; + gchar *form; + gchar *ptr; + + /* Calculate length. */ + len = strlen("<form>\n"); + va_start(ap, reset_label); + while ((child = va_arg(ap, gchar *))) { + len += strlen(child); + } + va_end(ap); + len += strlen("<div class=\"dialog-buttonbox\">\n") + + strlen("<input type=\"reset\" value=\"") + strlen(reset_label) + + strlen("\">\n<input type=\"submit\" value=\"") + + strlen(submit_label) + strlen("\">\n</div>\n") + + strlen("</form>\n"); + ++len; /* NUL byte */ + + /* Build string. */ + form = g_new(gchar, len); + ptr = g_stpcpy(form, "<form>\n"); + va_start(ap, reset_label); + while ((child = va_arg(ap, gchar *))) { + ptr = g_stpcpy(ptr, child); + g_free(child); + } + va_end(ap); + ptr = g_stpcpy(ptr, "<div class=\"dialog-buttonbox\">\n"); + ptr = g_stpcpy(ptr, "<input type=\"reset\" value=\""); + ptr = g_stpcpy(ptr, reset_label); + ptr = g_stpcpy(ptr, "\">\n<input type=\"submit\" value=\""); + ptr = g_stpcpy(ptr, submit_label); + ptr = g_stpcpy(ptr, "\">\n</div>\n"); + ptr = g_stpcpy(ptr, "</form>\n"); /* g_stpcpy() adds the NUL. */ + + return form; +} + +gchar * +mq_html_input_text(const gchar *name, const gchar *label, const gchar *value) +{ + return g_strdup_printf("<label for=\"%s\">\n<span>%s:</span>\n" + "<input type=\"text\" name=\"%s\" id=\"%s\" value=\"%s\">\n" + "</label>\n", + name, label, name, name, value ? value : ""); +} + +gchar * +mq_html_input_number_i(const gchar *name, const gchar *label, + gint min, gint step, gint max, gint value) +{ + return g_strdup_printf("<label for=\"%s\">\n<span>%s:</span>\n" + "<input type=\"number\" name=\"%s\" id=\"%s\"" + " min=\"%d\" step=\"%d\" max=\"%d\" value=\"%d\">\n" + "</label>\n", + name, label, name, name, min, step, max, value); +} + +gchar * +mq_html_input_number_d(const gchar *name, const gchar *label, + gdouble min, gdouble step, gdouble max, gdouble value) +{ + return g_strdup_printf("<label for=\"%s\">\n<span>%s:</span>\n" + "<input type=\"number\" name=\"%s\" id=\"%s\"" + " min=\"%f\" step=\"%f\" max=\"%f\" value=\"%f\">\n" + "</label>\n", + name, label, name, name, min, step, max, value); +} + +gchar * +mq_html_input_radio(const gchar *name, const gchar *label, gboolean checked) +{ + return g_strdup_printf("<label for=\"%s\">\n<span>%s:</span>\n" + "<input type=\"radio\" name=\"%s\" id=\"%s\"%s>\n</label>\n", + name, label, name, name, checked ? " checked=\"checked\"" : ""); +} + +gchar * +mq_html_input_checkbox(const gchar *name, const gchar *label, gboolean checked) +{ + /* + * Values of "checkbox"-type <input>s that are not checked are not sent + * in queries with form submissions. The "about:preferences" + * query-handling code doesn't handle any preferences that aren't + * submitted in the query, so values need to be submitted for unchecked + * "checkbox"-type <input>s in order for unchecking to have any effect. + * + * This function returns two <input>s: one of type "hidden" with a value + * of "off" and one of type "checkbox". If the "checkbox"-type <input> + * is checked, both <input> values will be submitted in the query, with + * the value of the "checkbox"-type <input> last. Otherwise, only the + * "off" value of the "hidden"-type <input> will be submitted. + * + * The query-parsing code for "about"-scheme resources iterates through + * each "key=value" pair in order, inserting each pair into a + * GHashTable. When keys collide, g_hash_table_insert() replaces the + * previous value with the new value. Thus, the value of the + * "checkbox"-type <input> will override that of the "hidden"-type + * <input> when the former <input> is checked. + */ + + return g_strdup_printf("<label for=\"%s\">\n<span>%s:</span>\n" + "<input type=\"hidden\" name=\"%s\" value=\"off\">\n" + "<input type=\"checkbox\" name=\"%s\" id=\"%s\"%s>\n</label>\n", + name, label, name, name, name, + checked ? " checked=\"checked\"" : ""); +} + +gchar * +mq_html_input_select(const gchar *name, const gchar *label, + const gchar *selected, + GDestroyNotify destroy_value, GDestroyNotify destroy_label, ...) +{ + gsize len; + va_list ap; + gchar *option_value; + gchar *option_label; + gchar *select; + gchar *ptr; + + g_assert(selected && selected[0]); /* Would cause buffer overflow */ + + /* Calculate length. */ + len = strlen("<label for=\""); + len += strlen(name); + len += strlen("\">\n<span>"); + len += strlen(label); + len += strlen(":</span>\n<select name=\""); + len += strlen(name); + len += strlen("\" id=\""); + len += strlen(name); + len += strlen("\">\n"); + va_start(ap, destroy_label); + while ((option_value = va_arg(ap, gchar *)) && (option_label = + va_arg(ap, gchar *))) { + len += strlen("<option value=\""); + len += strlen(option_value); + len += strlen("\""); + len += strlen(">"); + len += strlen(option_label); + len += strlen("</option>\n"); + } + va_end(ap); + len += strlen(" selected=\"selected\""); + len += strlen("</select>\n</label>\n"); + ++len; /* NUL byte */ + + /* Build string. */ + select = g_new(gchar, len); + ptr = g_stpcpy(select, "<label for=\""); + ptr = g_stpcpy(ptr, name); + ptr = g_stpcpy(ptr, "\">\n<span>"); + ptr = g_stpcpy(ptr, label); + ptr = g_stpcpy(ptr, ":</span>\n<select name=\""); + ptr = g_stpcpy(ptr, name); + ptr = g_stpcpy(ptr, "\" id=\""); + ptr = g_stpcpy(ptr, name); + ptr = g_stpcpy(ptr, "\">\n"); + va_start(ap, destroy_label); + while ((option_value = va_arg(ap, gchar *)) && (option_label = + va_arg(ap, gchar *))) { + ptr = g_stpcpy(ptr, "<option value=\""); + ptr = g_stpcpy(ptr, option_value); + ptr = g_stpcpy(ptr, "\""); + if (g_strcmp0(option_value, selected) == 0) { + ptr = g_stpcpy(ptr, " selected=\"selected\""); + } + ptr = g_stpcpy(ptr, ">"); + ptr = g_stpcpy(ptr, option_label); + if (destroy_value) { + destroy_value(option_value); + } + if (destroy_label) { + destroy_label(option_label); + } + ptr = g_stpcpy(ptr, "</option>\n"); + } + va_end(ap); + ptr = g_stpcpy(ptr, "</select>\n</label>\n"); /* g_stpcpy() adds NUL */ + + return select; +} + +gchar * +mq_html_input_iframe(const gchar *src) +{ + return g_strdup_printf("<iframe src=\"%s\"></iframe>", src); +} diff --git a/src/utils/html.h b/src/utils/html.h new file mode 100644 index 0000000..92fe2ea --- /dev/null +++ b/src/utils/html.h @@ -0,0 +1,88 @@ +/* + * HTML document generation + * + * Copyright (C) 2017 Patrick McDermott + * + * This file is part of Marquee. + * + * Marquee 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, either version 3 of the License, or + * (at your option) any later version. + * + * Marquee 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 Marquee. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef MQ_HTML_H +#define MQ_HTML_H + +#include <glib.h> + +gchar * +mq_html_document(const gchar *title, ...) G_GNUC_NULL_TERMINATED; + +#define TEXT_ELEMENT(ELEM) \ + gchar * \ + mq_html_##ELEM(const gchar *text); \ + gchar * \ + mq_html_##ELEM##_free(gchar *text); +TEXT_ELEMENT(h1) +TEXT_ELEMENT(h2) +TEXT_ELEMENT(h3) +TEXT_ELEMENT(h4) +TEXT_ELEMENT(h5) +TEXT_ELEMENT(h6) +TEXT_ELEMENT(p) +#undef TEXT_ELEMENT + +gchar * +mq_html_container(const gchar *element, ...) G_GNUC_NULL_TERMINATED; + +gchar * +mq_html_list(const gchar *type, GDestroyNotify destroy, ...) + G_GNUC_NULL_TERMINATED; + +gchar * +mq_html_list_v(const gchar *type, gchar **children); + +gchar * +mq_html_notebook(gboolean vertical, const gchar *name, guint current_page, ...) + G_GNUC_NULL_TERMINATED; + +gchar * +mq_html_form(const gchar *submit_label, const gchar *reset_label, ...) + G_GNUC_NULL_TERMINATED; + +gchar * +mq_html_input_text(const gchar *name, const gchar *label, const gchar *value); + +gchar * +mq_html_input_number_i(const gchar *name, const gchar *label, + gint min, gint step, gint max, gint value); + +gchar * +mq_html_input_number_d(const gchar *name, const gchar *label, + gdouble min, gdouble step, gdouble max, gdouble value); + +gchar * +mq_html_input_radio(const gchar *name, const gchar *label, gboolean checked); + +gchar * +mq_html_input_checkbox(const gchar *name, const gchar *label, gboolean checked); + +gchar * +mq_html_input_select(const gchar *name, const gchar *label, + const gchar *selected, + GDestroyNotify destroy_value, GDestroyNotify destroy_label, ...) + G_GNUC_NULL_TERMINATED; + +gchar * +mq_html_input_iframe(const gchar *src); + +#endif |