about summary refs log tree commit diff stats
path: root/html.c
diff options
context:
space:
mode:
Diffstat (limited to 'html.c')
-rw-r--r--html.c303
1 files changed, 303 insertions, 0 deletions
diff --git a/html.c b/html.c
new file mode 100644
index 0000000..1f78adb
--- /dev/null
+++ b/html.c
@@ -0,0 +1,303 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "gemtext.h"
+
+static int
+_case_text(struct gemtext *line, char **out, size_t *outlen)
+{
+	char *app;
+
+	*outlen += gemtext_text_strlen(line);
+	*outlen += 7; /* <p></p> */
+
+	app = realloc(*out, (*outlen+1));
+	if (app == NULL)
+		return -1;
+	*out = app;
+
+	strlcat(*out, "<p>", (*outlen+1));
+	strlcat(*out, gemtext_text_string(line), (*outlen)+1);
+	strlcat(*out, "</p>", (*outlen)+1);
+
+	return 0;
+}
+
+static int
+_case_link(struct gemtext *line, char **out, size_t *outlen)
+{
+	char *app;
+
+	*outlen += gemtext_link_link_strlen(line);
+	*outlen += gemtext_link_label_strlen(line);
+	*outlen += 22; /* <p><a href=""></a></p> */
+
+	app = realloc(*out, (*outlen)+1);
+	if (app == NULL)
+		return -1;
+	*out = app;
+
+	strlcat(*out, "<p><a href=\"", (*outlen)+1);
+	strlcat(*out, gemtext_link_link_string(line), (*outlen)+1);
+	strlcat(*out, "\">", (*outlen)+1);
+	if (gemtext_link_has_label(line))
+		strlcat(*out, gemtext_link_label_string(line), (*outlen)+1);
+	strlcat(*out, "</a></p>", (*outlen)+1);
+
+	return 0;
+}
+
+static int
+_case_pre(struct gemtext *line, char **out, size_t *outlen)
+{
+	char *app;
+
+	*outlen += gemtext_pre_strlen(line);
+	*outlen += 18; /* <p><pre></pre></p> */
+
+	app = realloc(*out, (*outlen)+1);
+	if (app == NULL)
+		return -1;
+	*out = app;
+
+	strlcat(*out, "<p><pre>", (*outlen)+1);
+	strlcat(*out, gemtext_pre_string(line), (*outlen)+1);
+	strlcat(*out, "</pre></p>", (*outlen)+1);
+
+	return 0;
+}
+
+static int
+_case_h1(struct gemtext *line, char **out, size_t *outlen)
+{
+	char *app;
+
+	*outlen += gemtext_h1_strlen(line);
+	*outlen += 9; /* <h1></h1> */
+
+	app = realloc(*out, (*outlen)+1);
+	if (app == NULL)
+		return -1;
+	*out = app;
+
+	strlcat(*out, "<h1>", (*outlen)+1);
+	strlcat(*out, gemtext_h1_string(line), (*outlen)+1);
+	strlcat(*out, "</h1>", (*outlen)+1);
+
+	return 0;
+}
+
+static int
+_case_h2(struct gemtext *line, char **out, size_t *outlen)
+{
+	char *app;
+
+	*outlen += gemtext_h2_strlen(line);
+	*outlen += 9; /* <h2></h2> */
+
+	app = realloc(*out, (*outlen)+1);
+	if (app == NULL)
+		return -1;
+	*out = app;
+
+	strlcat(*out, "<h2>", (*outlen)+1);
+	strlcat(*out, gemtext_h2_string(line), (*outlen)+1);
+	strlcat(*out, "</h2>", (*outlen)+1);
+
+	return 0;
+}
+
+static int
+_case_h3(struct gemtext *line, char **out, size_t *outlen)
+{
+	char *app;
+
+	*outlen += gemtext_h3_strlen(line);
+	*outlen += 9; /* <h3></h3> */
+
+	app = realloc(*out, (*outlen)+1);
+	if (app == NULL)
+		return -1;
+	*out = app;
+
+	strlcat(*out, "<h3>", (*outlen)+1);
+	strlcat(*out, gemtext_h3_string(line), (*outlen)+1);
+	strlcat(*out, "</h3>", (*outlen)+1);
+
+	return 0;
+}
+
+static int
+_case_ul(struct gemtext *line, char **out, size_t *outlen)
+{
+	char *app;
+
+	*outlen += gemtext_ul_strlen(line);
+	*outlen += 9; /* <li></li> */
+
+	app = realloc(*out, (*outlen)+1);
+	if (app == NULL)
+		return -1;
+	*out = app;
+
+	strlcat(*out, "<li>", (*outlen)+1);
+	strlcat(*out, gemtext_ul_string(line), (*outlen)+1);
+	strlcat(*out, "</li>", (*outlen)+1);
+
+	return 0;
+}
+
+static int
+_case_qt(struct gemtext *line, char **out, size_t *outlen)
+{
+	char *app;
+
+	*outlen += gemtext_qt_strlen(line);
+	*outlen += 25; /* <blockquote></blockquote> */
+
+	app = realloc(*out, (*outlen)+1);
+	if (app == NULL)
+		return -1;
+	*out = app;
+
+	strlcat(*out, "<blockquote>", (*outlen)+1);
+	strlcat(*out, gemtext_qt_string(line), (*outlen)+1);
+	strlcat(*out, "</blockquote>", (*outlen)+1);
+
+	return 0;
+}
+
+int
+gemtext_list_encode_to_html(struct gemtext **list, char **out, size_t *outlen)
+{
+	char *app;
+	int i;
+	int ulindic;
+
+	*out = NULL;
+	*outlen = 0;
+	ulindic = 0;
+
+	*out = malloc(1);
+	if (*out == NULL)
+		return -1;
+	*out[0] = '\0'; /* for strlcat() */
+
+	for (i = 0; list[i] != NULL; i++) {
+		if (gemtext_type(list[i]) != GEMTEXT_UL && ulindic) {
+			*outlen += 5; /* </ul> */
+			app = realloc(*out, (*outlen)+1);
+			if (app == NULL) {
+				free(*out);
+				return -1;
+			}
+			*out = app;
+			strlcat(*out, "</ul>", (*outlen)+1);
+			ulindic = 0;
+		}
+		switch (gemtext_type(list[i])) {
+		case GEMTEXT_TEXT:
+			if (_case_text(list[i], out, outlen) == -1) {
+				free(*out);
+				return -1;
+			}
+			break;
+		case GEMTEXT_LINK:
+			if (_case_link(list[i], out, outlen) == -1) {
+				free(*out);
+				return -1;
+			}
+			break;
+		case GEMTEXT_PRE:
+			if (_case_pre(list[i], out, outlen) == -1) {
+				free(*out);
+				return -1;
+			}
+			break;
+		case GEMTEXT_H1:
+			if (_case_h1(list[i], out, outlen) == -1) {
+				free(*out);
+				return -1;
+			}
+			break;
+		case GEMTEXT_H2:
+			if (_case_h2(list[i], out, outlen) == -1) {
+				free(*out);
+				return -1;
+			}
+			break;
+		case GEMTEXT_H3:
+			if (_case_h3(list[i], out, outlen) == -1) {
+				free(*out);
+				return -1;
+			}
+			break;
+		case GEMTEXT_UL:
+			if (!ulindic) {
+				*outlen += 4; /* <ul> */
+				app = realloc(*out, (*outlen)+1);
+				if (app == NULL) {
+					free(*out);
+					return -1;
+				}
+				*out = app;
+				strlcat(*out, "<ul>", (*outlen)+1);
+				ulindic = 1;
+			}
+			if (_case_ul(list[i], out, outlen) == -1) {
+				free(*out);
+				return -1;
+			}
+			break;
+		case GEMTEXT_QT:
+			if (_case_qt(list[i], out, outlen) == -1) {
+				free(*out);
+				return -1;
+			}
+			break;
+		}
+	}
+
+	return 0;
+}
+
+int
+gemtext_list_encode_to_html_fd(struct gemtext **list, int fd)
+{
+	char *out;
+	size_t len;
+
+	if (gemtext_list_encode_to_html(list, &out, &len) == -1)
+		return -1;
+	if (write(fd, out, len) == -1) {
+		free(out);
+		return -1;
+	}
+	free(out);
+
+	return 0;
+}
+
+int
+gemtext_list_encode_to_html_file(struct gemtext **list, const char *file)
+{
+	int fd;
+
+	fd = open(file, O_WRONLY|O_TRUNC|O_CREAT);
+	if (fd == -1)
+		return -1;
+	/* file does not have to be owned by user, so errors are expected */
+	fchmod(fd, 0644);
+	if (gemtext_list_encode_to_html_fd(list, fd) == -1) {
+		close(fd);
+		return -1;
+	}
+	close(fd);
+
+	return 0;
+}