summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Sanders <vince@kyllikki.org>2021-02-26 13:33:08 +0000
committerVincent Sanders <vince@kyllikki.org>2021-03-23 22:12:21 +0000
commit28ecbf82ed3024f51be4c87928fd91bacfc15cbc (patch)
tree8c6fbd3a4c8ae1d94c700958a4883cb3d7293d0c
parent847d5680613cb578ba4a548960480363a3230174 (diff)
downloadnetsurf-28ecbf82ed3024f51be4c87928fd91bacfc15cbc.tar.gz
netsurf-28ecbf82ed3024f51be4c87928fd91bacfc15cbc.tar.bz2
Initial minimal FLTK toolkit implementation
-rw-r--r--frontends/Makefile.hts2
-rw-r--r--frontends/fltk/Makefile35
-rw-r--r--frontends/fltk/Makefile.defaults28
-rw-r--r--frontends/fltk/Makefile.tools8
-rw-r--r--frontends/fltk/bitmap.cpp193
-rw-r--r--frontends/fltk/bitmap.h27
-rw-r--r--frontends/fltk/fetch.cpp114
-rw-r--r--frontends/fltk/fetch.h27
-rw-r--r--frontends/fltk/layout.cpp141
-rw-r--r--frontends/fltk/layout.h27
-rw-r--r--frontends/fltk/main.cpp253
-rw-r--r--frontends/fltk/misc.cpp237
-rw-r--r--frontends/fltk/misc.h34
-rw-r--r--frontends/fltk/plotters.cpp300
-rw-r--r--frontends/fltk/plotters.h32
l---------frontends/fltk/res/adblock.css1
l---------frontends/fltk/res/default.css1
l---------frontends/fltk/res/en/credits.html1
l---------frontends/fltk/res/en/licence.html1
l---------frontends/fltk/res/en/welcome.html1
l---------frontends/fltk/res/internal.css1
l---------frontends/fltk/res/netsurf.png1
l---------frontends/fltk/res/quirks.css1
-rw-r--r--frontends/fltk/resources.cpp157
-rw-r--r--frontends/fltk/resources.h42
-rw-r--r--frontends/fltk/window.cpp344
-rw-r--r--frontends/fltk/window.h27
27 files changed, 2035 insertions, 1 deletions
diff --git a/frontends/Makefile.hts b/frontends/Makefile.hts
index b5af240f1..a78e34cea 100644
--- a/frontends/Makefile.hts
+++ b/frontends/Makefile.hts
@@ -114,7 +114,7 @@ else
endif
# valid values for the TARGET
-VLDTARGET := amiga atari beos framebuffer gtk monkey riscos windows
+VLDTARGET := amiga atari beos fltk framebuffer gtk monkey riscos windows
# Check for valid TARGET
ifeq ($(filter $(VLDTARGET),$(TARGET)),)
diff --git a/frontends/fltk/Makefile b/frontends/fltk/Makefile
new file mode 100644
index 000000000..1cfb278f8
--- /dev/null
+++ b/frontends/fltk/Makefile
@@ -0,0 +1,35 @@
+#
+# Makefile for NetSurf ftlk target
+#
+# This file is part of NetSurf
+#
+# ----------------------------------------------------------------------------
+# FLTK flag setup (using pkg-config)
+# ----------------------------------------------------------------------------
+
+CXXFLAGS += -DFLTK_RESPATH=\"$(NETSURF_FLTK_RES_PATH)\"
+
+# fltk does not ship a pkg-config file, instead it has its own program
+
+FLTKCONFIG = fltk-config
+CXXFLAGS += $(shell $(FLTKCONFIG) --cxxflags)
+LDFLAGS += -lstdc++ $(shell $(FLTKCONFIG) --ldstaticflags)
+
+# ---------------------------------------------------------------------------
+# Target setup
+# ---------------------------------------------------------------------------
+
+# The binary target.
+EXETARGET := nsfltk
+
+# ----------------------------------------------------------------------------
+# Source file setup
+# ----------------------------------------------------------------------------
+
+# S_FRONTEND are sources purely for the FLTK frontend
+S_FRONTEND := main.cpp misc.cpp window.cpp fetch.cpp bitmap.cpp layout.cpp plotters.cpp resources.cpp
+
+# This is the final source build list
+# Note this is deliberately *not* expanded here as common and image
+# are not yet available
+SOURCES = $(S_COMMON) $(S_IMAGE) $(S_BROWSER) $(S_RESOURCE) $(S_FRONTEND)
diff --git a/frontends/fltk/Makefile.defaults b/frontends/fltk/Makefile.defaults
new file mode 100644
index 000000000..ad70fb0e5
--- /dev/null
+++ b/frontends/fltk/Makefile.defaults
@@ -0,0 +1,28 @@
+# ----------------------------------------------------------------------------
+# FLTK-specific options
+# ----------------------------------------------------------------------------
+
+# Where to search for NetSurf's resources after looking in ~/.netsurf and
+# $NETSURFRES. It must have a trailing /
+NETSURF_FLTK_RES_PATH := $(PREFIX)/share/netsurf/:./frontends/fltk/res/
+
+# Where to install the netsurf binary
+NETSURF_FLTK_BIN := $(PREFIX)/bin/
+
+# Enable NetSurf's use of librsvg in conjunction with Cairo to display SVGs
+# Valid options: YES, NO, AUTO
+NETSURF_USE_RSVG := NO
+
+# Enable NetSurf's use of libsvgtiny for displaying SVGs
+# Valid options: YES, NO, AUTO
+NETSURF_USE_NSSVG := NO
+
+# Enable NetSurf's use of librosprite for displaying RISC OS Sprites
+# Valid options: YES, NO, AUTO
+NETSURF_USE_ROSPRITE := NO
+
+# Enable building the source object cache filesystem based backing store.
+NETSURF_FS_BACKING_STORE := NO
+
+# Optimisation levels
+CFLAGS += -O2
diff --git a/frontends/fltk/Makefile.tools b/frontends/fltk/Makefile.tools
new file mode 100644
index 000000000..460a957c9
--- /dev/null
+++ b/frontends/fltk/Makefile.tools
@@ -0,0 +1,8 @@
+# -*- mode: makefile-gmake -*-
+##
+## tool setup for the fltk target
+##
+
+# use native package config
+PKG_CONFIG := pkg-config
+
diff --git a/frontends/fltk/bitmap.cpp b/frontends/fltk/bitmap.cpp
new file mode 100644
index 000000000..bc41822f9
--- /dev/null
+++ b/frontends/fltk/bitmap.cpp
@@ -0,0 +1,193 @@
+/*
+ * 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 netsurf bitmap for fltk.
+ */
+
+#include <stddef.h>
+
+extern "C" {
+
+#include "utils/errors.h"
+#include "netsurf/bitmap.h"
+
+}
+
+#include "fltk/bitmap.h"
+
+/**
+ * Create a new bitmap.
+ *
+ * \param width width of image in pixels
+ * \param height width of image in pixels
+ * \param state The state to create the bitmap in.
+ * \return A bitmap structure or NULL on error.
+ */
+static void *nsfltk_bitmap_create(int width, int height, unsigned int state)
+{
+ return NULL;
+}
+
+/**
+ * Destroy a bitmap.
+ *
+ * \param bitmap The bitmap to destroy.
+ */
+static void nsfltk_bitmap_destroy(void *bitmap)
+{
+}
+
+/**
+ * Set the opacity of a bitmap.
+ *
+ * \param bitmap The bitmap to set opacity on.
+ * \param opaque The bitmap opacity to set.
+ */
+static void nsfltk_bitmap_set_opaque(void *bitmap, bool opaque)
+{
+}
+
+/**
+ * Get the opacity of a bitmap.
+ *
+ * \param bitmap The bitmap to examine.
+ * \return The bitmap opacity.
+ */
+static bool nsfltk_bitmap_get_opaque(void *bitmap)
+{
+ return false;
+}
+
+/**
+ * Test if a bitmap is opaque.
+ *
+ * \param bitmap The bitmap to examine.
+ * \return The bitmap opacity.
+ */
+static bool nsfltk_bitmap_test_opaque(void *bitmap)
+{
+ return false;
+}
+
+/**
+ * Get the image buffer from a bitmap
+ *
+ * \param bitmap The bitmap to get the buffer from.
+ * \return The image buffer or NULL if there is none.
+ */
+static unsigned char *nsfltk_bitmap_get_buffer(void *bitmap)
+{
+ return NULL;
+}
+
+/**
+ * Get the number of bytes per row of the image
+ *
+ * \param bitmap The bitmap
+ * \return The number of bytes for a row of the bitmap.
+ */
+static size_t nsfltk_bitmap_get_rowstride(void *bitmap)
+{
+ return 0;
+}
+
+/**
+ * Get the bitmap width
+ *
+ * \param bitmap The bitmap
+ * \return The bitmap width in pixels.
+ */
+static int nsfltk_bitmap_get_width(void *bitmap)
+{
+ return 0;
+}
+
+/**
+ * Get the bitmap height
+ *
+ * \param bitmap The bitmap
+ * \return The bitmap height in pixels.
+ */
+static int nsfltk_bitmap_get_height(void *bitmap)
+{
+ return 0;
+}
+
+/**
+ * Get the *bytes* per pixel.
+ *
+ * \param bitmap The bitmap
+ */
+static size_t nsfltk_bitmap_get_bpp(void *bitmap)
+{
+ return 4;
+}
+
+/**
+ * Save a bitmap to disc.
+ *
+ * \param bitmap The bitmap to save
+ * \param path The path to save the bitmap to.
+ * \param flags Flags affecting the save.
+ */
+static bool nsfltk_bitmap_save(void *bitmap, const char *path, unsigned flags)
+{
+ return false;
+}
+
+/**
+ * Marks a bitmap as modified.
+ *
+ * \param bitmap The bitmap set as modified.
+ */
+static void nsfltk_bitmap_modified(void *bitmap)
+{
+}
+
+/**
+ * Render content into a bitmap.
+ *
+ * \param bitmap The bitmap to render into.
+ * \param content The content to render.
+ */
+static nserror
+nsfltk_bitmap_render(struct bitmap *bitmap, struct hlcache_handle *content)
+{
+ return NSERROR_OK;
+}
+
+
+static struct gui_bitmap_table bitmap_table = {
+ .create = nsfltk_bitmap_create,
+ .destroy = nsfltk_bitmap_destroy,
+ .set_opaque = nsfltk_bitmap_set_opaque,
+ .get_opaque = nsfltk_bitmap_get_opaque,
+ .test_opaque = nsfltk_bitmap_test_opaque,
+ .get_buffer = nsfltk_bitmap_get_buffer,
+ .get_rowstride = nsfltk_bitmap_get_rowstride,
+ .get_width = nsfltk_bitmap_get_width,
+ .get_height = nsfltk_bitmap_get_height,
+ .get_bpp = nsfltk_bitmap_get_bpp,
+ .save = nsfltk_bitmap_save,
+ .modified = nsfltk_bitmap_modified,
+ .render = nsfltk_bitmap_render,
+};
+
+struct gui_bitmap_table *nsfltk_bitmap_table = &bitmap_table;
diff --git a/frontends/fltk/bitmap.h b/frontends/fltk/bitmap.h
new file mode 100644
index 000000000..e0f01a6f6
--- /dev/null
+++ b/frontends/fltk/bitmap.h
@@ -0,0 +1,27 @@
+/*
+ * 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/>.
+ */
+
+#ifndef NETSURF_FLTK_BITMAP_H
+#define NETSURF_FLTK_BITMAP_H 1
+
+/**
+ * fltk bitmap operations table
+ */
+extern struct gui_bitmap_table *nsfltk_bitmap_table;
+
+#endif
diff --git a/frontends/fltk/fetch.cpp b/frontends/fltk/fetch.cpp
new file mode 100644
index 000000000..39c15a617
--- /dev/null
+++ b/frontends/fltk/fetch.cpp
@@ -0,0 +1,114 @@
+/*
+ * 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 netsurf fetch for fltk.
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <limits.h>
+
+extern "C" {
+
+#include "utils/errors.h"
+#include "utils/log.h"
+#include "utils/filepath.h"
+#include "utils/file.h"
+#include "netsurf/fetch.h"
+
+}
+
+#include "fltk/fetch.h"
+#include "fltk/resources.h"
+
+/**
+ * Determine the MIME type of a local file.
+ *
+ * @note used in file fetcher
+ *
+ * \param unix_path Unix style path to file on disk
+ * \return Pointer to MIME type string (should not be freed) -
+ * invalidated on next call to fetch_filetype.
+ */
+static const char *nsfltk_fetch_filetype(const char *unix_path)
+{
+ int l;
+ char * res = (char*)"text/html";
+ l = strlen(unix_path);
+ NSLOG(netsurf, INFO, "unix path: %s", unix_path);
+
+
+ if (2 < l && strcasecmp(unix_path + l - 3, "f79") == 0)
+ res = (char*)"text/css";
+ else if (2 < l && strcasecmp(unix_path + l - 3, "css") == 0)
+ res = (char*)"text/css";
+ else if (2 < l && strcasecmp(unix_path + l - 3, "jpg") == 0)
+ res = (char*)"image/jpeg";
+ else if (3 < l && strcasecmp(unix_path + l - 4, "jpeg") == 0)
+ res = (char*)"image/jpeg";
+ else if (2 < l && strcasecmp(unix_path + l - 3, "gif") == 0)
+ res = (char*)"image/gif";
+ else if (2 < l && strcasecmp(unix_path + l - 3, "png") == 0)
+ res = (char*)"image/png";
+ else if (2 < l && strcasecmp(unix_path + l - 3, "jng") == 0)
+ res = (char*)"image/jng";
+ else if (2 < l && strcasecmp(unix_path + l - 3, "svg") == 0)
+ res = (char*)"image/svg";
+ else if (2 < l && strcasecmp(unix_path + l - 3, "txt") == 0)
+ res = (char*)"text/plain";
+
+ NSLOG(netsurf, INFO, "mime type: %s", res);
+ return res;
+}
+
+/**
+ * Translate resource path to full url.
+ *
+ * @note Only used in resource protocol fetcher
+ *
+ * Transforms a resource protocol path into a full URL. The returned URL
+ * is used as the target for a redirect. The caller takes ownership of
+ * the returned nsurl including unrefing it when finished with it.
+ *
+ * \param path The path of the resource to locate.
+ * \return A netsurf url object containing the full URL of the resource path
+ * or NULL if a suitable resource URL can not be generated.
+ */
+static nsurl *nsfltk_get_resource_url(const char *path)
+{
+ char buf[PATH_MAX];
+ nsurl *url = NULL;
+
+ netsurf_path_to_nsurl(filepath_sfind(respaths, buf, path), &url);
+
+ return url;
+}
+
+static struct gui_fetch_table fetch_table = {
+ .filetype = nsfltk_fetch_filetype,
+
+ .get_resource_url = nsfltk_get_resource_url,
+ .get_resource_data = NULL,
+ .release_resource_data = NULL,
+ .mimetype = NULL,
+};
+
+struct gui_fetch_table *nsfltk_fetch_table = &fetch_table;
diff --git a/frontends/fltk/fetch.h b/frontends/fltk/fetch.h
new file mode 100644
index 000000000..6f9913ed8
--- /dev/null
+++ b/frontends/fltk/fetch.h
@@ -0,0 +1,27 @@
+/*
+ * 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/>.
+ */
+
+#ifndef NETSURF_FLTK_FETCH_H
+#define NETSURF_FLTK_FETCH_H 1
+
+/**
+ * fltk fetch operations table
+ */
+extern struct gui_fetch_table *nsfltk_fetch_table;
+
+#endif
diff --git a/frontends/fltk/layout.cpp b/frontends/fltk/layout.cpp
new file mode 100644
index 000000000..45044307d
--- /dev/null
+++ b/frontends/fltk/layout.cpp
@@ -0,0 +1,141 @@
+/*
+ * 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 netsurf layout operations for fltk.
+ */
+
+#include <stddef.h>
+
+extern "C" {
+
+#include "utils/errors.h"
+#include "utils/utf8.h"
+#include "netsurf/layout.h"
+#include "netsurf/plot_style.h"
+
+}
+
+#include "fltk/layout.h"
+
+/**
+ * Measure the width of a string.
+ *
+ * \param[in] fstyle plot style for this text
+ * \param[in] string UTF-8 string to measure
+ * \param[in] length length of string, in bytes
+ * \param[out] width updated to width of string[0..length)
+ * \return NSERROR_OK and width updated or appropriate error
+ * code on faliure
+ */
+static nserror
+nsfltk_layout_width(const struct plot_font_style *fstyle,
+ const char *string,
+ size_t length,
+ int *width)
+{
+ *width = (fstyle->size * utf8_bounded_length(string, length)) / PLOT_STYLE_SCALE;
+ return NSERROR_OK;
+}
+
+
+/**
+ * Find the position in a string where an x coordinate falls.
+ *
+ * \param[in] fstyle style for this text
+ * \param[in] string UTF-8 string to measure
+ * \param[in] length length of string, in bytes
+ * \param[in] x coordinate to search for
+ * \param[out] char_offset updated to offset in string of actual_x, [0..length]
+ * \param[out] actual_x updated to x coordinate of character closest to x
+ * \return NSERROR_OK and char_offset and actual_x updated or appropriate error code on faliure
+ */
+static nserror
+nsfltk_layout_position(const struct plot_font_style *fstyle,
+ const char *string,
+ size_t length,
+ int x,
+ size_t *char_offset,
+ int *actual_x)
+{
+ *char_offset = x / (fstyle->size / PLOT_STYLE_SCALE);
+ if (*char_offset > length)
+ *char_offset = length;
+ *actual_x = *char_offset * (fstyle->size / PLOT_STYLE_SCALE);
+ return NSERROR_OK;
+}
+
+
+/**
+ * Find where to split a string to make it fit a width.
+ *
+ * \param[in] fstyle style for this text
+ * \param[in] string UTF-8 string to measure
+ * \param[in] length length of string, in bytes
+ * \param[in] x width available
+ * \param[out] char_offset updated to offset in string of actual_x, [1..length]
+ * \param[out] actual_x updated to x coordinate of character closest to x
+ * \return NSERROR_OK or appropriate error code on faliure
+ *
+ * On exit, char_offset indicates first character after split point.
+ *
+ * \note char_offset of 0 must never be returned.
+ *
+ * Returns:
+ * char_offset giving split point closest to x, where actual_x <= x
+ * else
+ * char_offset giving split point closest to x, where actual_x > x
+ *
+ * Returning char_offset == length means no split possible
+ */
+static nserror
+nsfltk_layout_split(const struct plot_font_style *fstyle,
+ const char *string,
+ size_t length,
+ int x,
+ size_t *char_offset,
+ int *actual_x)
+{
+ int c_off = *char_offset = x / (fstyle->size / PLOT_STYLE_SCALE);
+ if (*char_offset > length) {
+ *char_offset = length;
+ } else {
+ while (*char_offset > 0) {
+ if (string[*char_offset] == ' ')
+ break;
+ (*char_offset)--;
+ }
+ if (*char_offset == 0) {
+ *char_offset = c_off;
+ while (*char_offset < length && string[*char_offset] != ' ') {
+ (*char_offset)++;
+ }
+ }
+ }
+ *actual_x = *char_offset * (fstyle->size / PLOT_STYLE_SCALE);
+ return NSERROR_OK;
+}
+
+static struct gui_layout_table layout_table = {
+ .width = nsfltk_layout_width,
+ .position = nsfltk_layout_position,
+ .split = nsfltk_layout_split,
+};
+
+struct gui_layout_table *nsfltk_layout_table = &layout_table;
diff --git a/frontends/fltk/layout.h b/frontends/fltk/layout.h
new file mode 100644
index 000000000..5e19cc0cb
--- /dev/null
+++ b/frontends/fltk/layout.h
@@ -0,0 +1,27 @@
+/*
+ * 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/>.
+ */
+
+#ifndef NETSURF_FLTK_LAYOUT_H
+#define NETSURF_FLTK_LAYOUT_H 1
+
+/**
+ * fltk layout operations table
+ */
+extern struct gui_layout_table *nsfltk_layout_table;
+
+#endif
diff --git a/frontends/fltk/main.cpp b/frontends/fltk/main.cpp
new file mode 100644
index 000000000..ab0e1bca5
--- /dev/null
+++ b/frontends/fltk/main.cpp
@@ -0,0 +1,253 @@
+/*
+ * 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/>.
+ */
+
+#include <assert.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <FL/Fl.H>
+
+extern "C" {
+
+#include "utils/utils.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/nsoption.h"
+#include "utils/nsurl.h"
+
+#include "netsurf/netsurf.h"
+#include "netsurf/content.h"
+#include "netsurf/browser_window.h"
+
+}
+
+#include "fltk/misc.h"
+#include "fltk/window.h"
+#include "fltk/fetch.h"
+#include "fltk/bitmap.h"
+#include "fltk/layout.h"
+#include "fltk/resources.h"
+
+bool nsfltk_done = false;
+
+/**
+ * Set option defaults for fltk frontend
+ *
+ * @param defaults The option table to update.
+ * @return error status.
+ */
+static nserror set_option_defaults(struct nsoption_s *defaults)
+{
+ return NSERROR_OK;
+}
+
+
+/**
+ * Ensures output logging stream is correctly configured
+ */
+static bool nslog_stream_configure(FILE *fptr)
+{
+ /* set log stream to be non-buffering */
+ setbuf(fptr, NULL);
+
+ return true;
+}
+
+
+/**
+ * fltk frontend specific initialisation
+ */
+static nserror nsfltk_init(int *pargc, char** argv)
+{
+ nserror res;
+
+ /* Prep the resource search paths */
+ res = nsfltk_init_resource_path("${HOME}/.netsurf/:${NETSURFRES}:" FLTK_RESPATH);
+ if (res != NSERROR_OK) {
+ fprintf(stderr, "Resources failed to initialise (%s)\n",
+ messages_get_errorcode(res));
+ return res;
+ }
+
+ /* Initialise logging. Not fatal if it fails but not much we
+ * can do about it either.
+ */
+ nslog_init(nslog_stream_configure, pargc, argv);
+
+ /* override loaded options with those from commandline */
+ nsoption_commandline(pargc, argv, nsoptions);
+
+ /* Initialise user options */
+ res = nsoption_init(set_option_defaults, &nsoptions, &nsoptions_default);
+ if (res != NSERROR_OK) {
+ fprintf(stderr, "Options failed to initialise (%s)\n",
+ messages_get_errorcode(res));
+ return res;
+ }
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * Start fltk browser.
+ *
+ * performs fltk specific startup including opening initial window if necessary
+ *
+ * \param argc The number of arguments on the command line
+ * \param argv A string vector of command line arguments.
+ */
+static nserror nsfltk_start(int argc, char** argv)
+{
+ char *addr = NULL;
+ nsurl *url;
+ nserror res;
+
+ /* If there is a url specified on the command line use it */
+ if (argc > 1) {
+ struct stat fs;
+ if (stat(argv[1], &fs) == 0) {
+ size_t addrlen;
+ char *rp = realpath(argv[1], NULL);
+ assert(rp != NULL);
+
+ /* calculate file url length including terminator */
+ addrlen = SLEN("file://") + strlen(rp) + 1;
+ addr = (char *)malloc(addrlen);
+ assert(addr != NULL);
+ snprintf(addr, addrlen, "file://%s", rp);
+ free(rp);
+ } else {
+ addr = strdup(argv[1]);
+ }
+ }
+ if (addr != NULL) {
+ /* managed to set up based on local launch */
+ } else if (nsoption_charp(homepage_url) != NULL) {
+ addr = strdup(nsoption_charp(homepage_url));
+ } else {
+ addr = strdup(NETSURF_HOMEPAGE);
+ }
+
+ /* create an initial browser window */
+ res = nsurl_create(addr, &url);
+ if (res == NSERROR_OK) {
+ res = browser_window_create(BW_CREATE_HISTORY,
+ url,
+ NULL,
+ NULL,
+ NULL);
+ nsurl_unref(url);
+ }
+
+ free(addr);
+
+ return res;
+}
+
+/**
+ * Run the fltk event loop.
+ *
+ */
+static void nsfltk_run(void)
+{
+ int schedtm;
+ do {
+ /* run scheduled callbacks and get the next event delta in ms */
+ schedtm = nsfltk_schedule_run();
+ Fl::wait(((double)schedtm/1000));
+ } while(nsfltk_done != true);
+}
+
+static nserror nsfltk_finalise(void)
+{
+ /* common finalisation */
+ netsurf_exit();
+
+ /* finalise options */
+ nsoption_finalise(nsoptions, nsoptions_default);
+
+ /* finalise logging */
+ nslog_finalise();
+
+ return NSERROR_OK;
+}
+
+/**
+ * Main entry point from OS.
+ */
+int main(int argc, char** argv)
+{
+ nserror res;
+ struct netsurf_table nsfltk_table = {
+ .misc = nsfltk_misc_table,
+ .window = nsfltk_window_table,
+ .download = NULL, /* no download functionality */
+ .clipboard = NULL, /* no clipboard functionality */
+ .fetch = nsfltk_fetch_table,
+ .file = NULL, /* use the posix default file operations */
+ .utf8 = NULL, /* use default utf-8 processing */
+ .search = NULL, /* use the default text search */
+ .search_web = NULL, /* use default web search */
+ .llcache = NULL, /* use default low level cache storage */
+ .bitmap = nsfltk_bitmap_table,
+ .layout = nsfltk_layout_table,
+ };
+
+ /* register operation tables */
+ res = netsurf_register(&nsfltk_table);
+ if (res != NSERROR_OK) {
+ fprintf(stderr,
+ "NetSurf operation table failed registration (%s)\n",
+ messages_get_errorcode(res));
+ return 1;
+ }
+
+ /* fltk specific initialisation */
+ res = nsfltk_init(&argc, argv);
+ if (res != NSERROR_OK) {
+ fprintf(stderr, "NetSurf fltk initialisation failed (%s)\n",
+ messages_get_errorcode(res));
+ return 2;
+ }
+
+ /* netsurf initialisation */
+ res = netsurf_init(NULL);
+ if (res != NSERROR_OK) {
+ fprintf(stderr, "NetSurf core failed to initialise (%s)\n",
+ messages_get_errorcode(res));
+ return 3;
+ }
+
+ /* fltk specific startup */
+ res = nsfltk_start(argc, argv);
+ if (res != NSERROR_OK) {
+ fprintf(stderr, "NetSurf fltk startup failed (%s)\n",
+ messages_get_errorcode(res));
+ nsfltk_finalise();
+ return 4;
+ }
+
+ /* startup suceeded so main run loop */
+ nsfltk_run();
+
+ /* finalise everything */
+ nsfltk_finalise();
+
+ return 0;
+
+}
diff --git a/frontends/fltk/misc.cpp b/frontends/fltk/misc.cpp
new file mode 100644
index 000000000..b86affdf1
--- /dev/null
+++ b/frontends/fltk/misc.cpp
@@ -0,0 +1,237 @@
+/*
+ * 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 netsurf miscelaneous operations for fltk.
+ */
+
+#include <stddef.h>
+#include <time.h>
+#include <stdlib.h>
+
+extern "C" {
+
+#include "utils/errors.h"
+#include "utils/sys_time.h"
+#include "utils/log.h"
+#include "netsurf/misc.h"
+
+}
+
+#include "fltk/misc.h"
+
+/* linked list of scheduled callbacks */
+static struct nscallback *schedule_list = NULL;
+
+/**
+ * scheduled callback.
+ */
+struct nscallback
+{
+ struct nscallback *next;
+ struct timeval tv;
+ void (*callback)(void *p);
+ void *p;
+};
+
+/* exported function documented in fltk/misc.h */
+int nsfltk_schedule_run(void)
+{
+ struct timeval tv;
+ struct timeval nexttime;
+ struct timeval rettime;
+ struct nscallback *cur_nscb;
+ struct nscallback *prev_nscb;
+ struct nscallback *unlnk_nscb;
+
+ if (schedule_list == NULL)
+ return -1;
+
+ /* reset enumeration to the start of the list */
+ cur_nscb = schedule_list;
+ prev_nscb = NULL;
+ nexttime = cur_nscb->tv;
+
+ gettimeofday(&tv, NULL);
+
+ while (cur_nscb != NULL) {
+ if (timercmp(&tv, &cur_nscb->tv, >)) {
+ /* scheduled time */
+
+ /* remove callback */
+ unlnk_nscb = cur_nscb;
+
+ if (prev_nscb == NULL) {
+ schedule_list = unlnk_nscb->next;
+ } else {
+ prev_nscb->next = unlnk_nscb->next;
+ }
+
+ unlnk_nscb->callback(unlnk_nscb->p);
+
+ free(unlnk_nscb);
+
+ /* need to deal with callback modifying the list. */
+ if (schedule_list == NULL)
+ return -1; /* no more callbacks scheduled */
+
+ /* reset enumeration to the start of the list */
+ cur_nscb = schedule_list;
+ prev_nscb = NULL;
+ nexttime = cur_nscb->tv;
+ } else {
+ /* if the time to the event is sooner than the
+ * currently recorded soonest event record it
+ */
+ if (timercmp(&nexttime, &cur_nscb->tv, >)) {
+ nexttime = cur_nscb->tv;
+ }
+ /* move to next element */
+ prev_nscb = cur_nscb;
+ cur_nscb = prev_nscb->next;
+ }
+ }
+
+ /* make rettime relative to now */
+ timersub(&nexttime, &tv, &rettime);
+
+ NSLOG(schedule, DEBUG, "returning time to next event as %ldms",
+ (long)((rettime.tv_sec * 1000) + (rettime.tv_usec / 1000)));
+
+ /* return next event time in milliseconds (24days max wait) */
+ return (rettime.tv_sec * 1000) + (rettime.tv_usec / 1000);
+}
+
+/**
+ * Unschedule a callback.
+ *
+ * \param callback callback function
+ * \param p user parameter, passed to callback function
+ * \return NSERROR_OK if callback found and removed else NSERROR_NOT_FOUND
+ *
+ * All scheduled callbacks matching both callback and p are removed.
+ */
+static nserror schedule_remove(void (*callback)(void *p), void *p)
+{
+ struct nscallback *cur_nscb;
+ struct nscallback *prev_nscb;
+ struct nscallback *unlnk_nscb;
+ bool removed = false;
+
+ /* check there is something on the list to remove */
+ if (schedule_list == NULL) {
+ return NSERROR_NOT_FOUND;
+ }
+
+ NSLOG(schedule, DEBUG, "removing %p, %p", callback, p);
+
+ cur_nscb = schedule_list;
+ prev_nscb = NULL;
+
+ while (cur_nscb != NULL) {
+ if ((cur_nscb->callback == callback) &&
+ (cur_nscb->p == p)) {
+ /* item to remove */
+
+ NSLOG(schedule, DEBUG, "callback entry %p removing %p(%p)",
+ cur_nscb, cur_nscb->callback, cur_nscb->p);
+
+ /* remove callback */
+ unlnk_nscb = cur_nscb;
+ cur_nscb = unlnk_nscb->next;
+
+ if (prev_nscb == NULL) {
+ schedule_list = cur_nscb;
+ } else {
+ prev_nscb->next = cur_nscb;
+ }
+ free (unlnk_nscb);
+ removed = true;
+ } else {
+ /* move to next element */
+ prev_nscb = cur_nscb;
+ cur_nscb = prev_nscb->next;
+ }
+ }
+
+ if (removed == false) {
+ return NSERROR_NOT_FOUND;
+ }
+ return NSERROR_OK;
+}
+
+
+/**
+ * Schedule a callback.
+ *
+ * \param tival interval before the callback should be made in ms or
+ * negative value to remove any existing callback.
+ * \param callback callback function
+ * \param p user parameter passed to callback function
+ * \return NSERROR_OK on sucess or appropriate error on faliure
+ *
+ * The callback function will be called as soon as possible
+ * after the timeout has elapsed.
+ *
+ * Additional calls with the same callback and user parameter will
+ * reset the callback time to the newly specified value.
+ *
+ */
+static nserror nsfltk_schedule(int tival, void (*callback)(void *p), void *p)
+{
+ struct nscallback *nscb;
+ struct timeval tv;
+ nserror ret;
+
+ /* ensure uniqueness of the callback and context */
+ ret = schedule_remove(callback, p);
+ if (tival < 0) {
+ return ret;
+ }
+
+ NSLOG(schedule, DEBUG, "Adding %p(%p) in %d", callback, p, tival);
+
+ tv.tv_sec = tival / 1000; /* miliseconds to seconds */
+ tv.tv_usec = (tival % 1000) * 1000; /* remainder to microseconds */
+
+ nscb = (struct nscallback*)calloc(1, sizeof(struct nscallback));
+
+ gettimeofday(&nscb->tv, NULL);
+ timeradd(&nscb->tv, &tv, &nscb->tv);
+
+ nscb->callback = callback;
+ nscb->p = p;
+
+ /* add to list front */
+ nscb->next = schedule_list;
+ schedule_list = nscb;
+
+ return NSERROR_OK;
+}
+
+static struct gui_misc_table misc_table = {
+ .schedule = nsfltk_schedule,
+ .quit = NULL,
+ .launch_url = NULL,
+ .login = NULL,
+ .pdf_password = NULL,
+ .present_cookies = NULL,
+};
+
+struct gui_misc_table *nsfltk_misc_table = &misc_table;
diff --git a/frontends/fltk/misc.h b/frontends/fltk/misc.h
new file mode 100644
index 000000000..e088043d1
--- /dev/null
+++ b/frontends/fltk/misc.h
@@ -0,0 +1,34 @@
+/*
+ * 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/>.
+ */
+
+#ifndef NETSURF_FLTK_MISC_H
+#define NETSURF_FLTK_MISC_H 1
+
+/**
+ * fltk miscellaneous (scheduling) operations table
+ */
+extern struct gui_misc_table *nsfltk_misc_table;
+
+/**
+ * run and pending scheduling callbacks
+ *
+ * \return number of miliseconds before next scheduled event
+ */
+int nsfltk_schedule_run(void);
+
+#endif
diff --git a/frontends/fltk/plotters.cpp b/frontends/fltk/plotters.cpp
new file mode 100644
index 000000000..65268f1b7
--- /dev/null
+++ b/frontends/fltk/plotters.cpp
@@ -0,0 +1,300 @@
+/*
+ * 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 plotters for fltk.
+ */
+
+#include <stddef.h>
+#include <FL/Fl.H>
+#include <FL/fl_draw.H>
+
+extern "C" {
+
+#include "utils/errors.h"
+#include "netsurf/types.h"
+#include "netsurf/mouse.h"
+#include "netsurf/window.h"
+#include "netsurf/plotters.h"
+
+}
+
+#include "fltk/window.h"
+#include "fltk/plotters.h"
+
+
+static inline void nsfltk_set_colour(colour c)
+{
+ fl_color(fl_rgb_color((c & 0xff),
+ ((c & 0xff00) >> 8),
+ ((c & 0xff0000) >> 16)));
+}
+
+
+/**
+ * \brief Sets a clip rectangle for subsequent plot operations.
+ *
+ * \param ctx The current redraw context.
+ * \param clip The rectangle to limit all subsequent plot
+ * operations within.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+nsfltk_plot_clip(const struct redraw_context *ctx, const struct rect *clip)
+{
+ return NSERROR_OK;
+}
+
+
+/**
+ * Plots an arc
+ *
+ * plot an arc segment around (x,y), anticlockwise from angle1
+ * to angle2. Angles are measured anticlockwise from
+ * horizontal, in degrees.
+ *
+ * \param ctx The current redraw context.
+ * \param style Style controlling the arc plot.
+ * \param x The x coordinate of the arc.
+ * \param y The y coordinate of the arc.
+ * \param radius The radius of the arc.
+ * \param angle1 The start angle of the arc.
+ * \param angle2 The finish angle of the arc.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+nsfltk_plot_arc(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ int x, int y, int radius, int angle1, int angle2)
+{
+ return NSERROR_OK;
+}
+
+
+/**
+ * Plots a circle
+ *
+ * Plot a circle centered on (x,y), which is optionally filled.
+ *
+ * \param ctx The current redraw context.
+ * \param style Style controlling the circle plot.
+ * \param x x coordinate of circle centre.
+ * \param y y coordinate of circle centre.
+ * \param radius circle radius.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+nsfltk_plot_disc(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ int x, int y, int radius)
+{
+ return NSERROR_OK;
+}
+
+
+/**
+ * Plots a line
+ *
+ * plot a line from (x0,y0) to (x1,y1). Coordinates are at
+ * centre of line width/thickness.
+ *
+ * \param ctx The current redraw context.
+ * \param style Style controlling the line plot.
+ * \param line A rectangle defining the line to be drawn
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+nsfltk_plot_line(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ const struct rect *line)
+{
+ if (style->stroke_type != PLOT_OP_TYPE_NONE) {
+ nsfltk_set_colour(style->stroke_colour);
+ fl_line(line->x0, line->y0, line->x1, line->y1);
+ }
+ return NSERROR_OK;
+}
+
+
+/**
+ * Plots a rectangle.
+ *
+ * The rectangle can be filled an outline or both controlled
+ * by the plot style The line can be solid, dotted or
+ * dashed. Top left corner at (x0,y0) and rectangle has given
+ * width and height.
+ *
+ * \param ctx The current redraw context.
+ * \param style Style controlling the rectangle plot.
+ * \param rect A rectangle defining the line to be drawn
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+nsfltk_plot_rectangle(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ const struct rect *rect)
+{
+ if (style->fill_type != PLOT_OP_TYPE_NONE) {
+ nsfltk_set_colour(style->fill_colour);
+ fl_rectf(rect->x0,
+ rect->y0,
+ rect->x1 - rect->x0,
+ rect->y1 - rect->y0);
+ }
+
+ if (style->stroke_type != PLOT_OP_TYPE_NONE) {
+ nsfltk_set_colour(style->stroke_colour);
+ fl_rect(rect->x0,
+ rect->y0,
+ rect->x1 - rect->x0,
+ rect->y1 - rect->y0);
+ }
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * Plot a polygon
+ *
+ * Plots a filled polygon with straight lines between
+ * points. The lines around the edge of the ploygon are not
+ * plotted. The polygon is filled with the non-zero winding
+ * rule.
+ *
+ * \param ctx The current redraw context.
+ * \param style Style controlling the polygon plot.
+ * \param p verticies of polygon
+ * \param n number of verticies.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+nsfltk_plot_polygon(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ const int *p,
+ unsigned int n)
+{
+ return NSERROR_OK;
+}
+
+
+/**
+ * Plots a path.
+ *
+ * Path plot consisting of cubic Bezier curves. Line and fill colour is
+ * controlled by the plot style.
+ *
+ * \param ctx The current redraw context.
+ * \param pstyle Style controlling the path plot.
+ * \param p elements of path
+ * \param n nunber of elements on path
+ * \param transform A transform to apply to the path.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+nsfltk_plot_path(const struct redraw_context *ctx,
+ const plot_style_t *pstyle,
+ const float *p,
+ unsigned int n,
+ const float transform[6])
+{
+ return NSERROR_OK;
+}
+
+
+/**
+ * Plot a bitmap
+ *
+ * Tiled plot of a bitmap image. (x,y) gives the top left
+ * coordinate of an explicitly placed tile. From this tile the
+ * image can repeat in all four directions -- up, down, left
+ * and right -- to the extents given by the current clip
+ * rectangle.
+ *
+ * The bitmap_flags say whether to tile in the x and y
+ * directions. If not tiling in x or y directions, the single
+ * image is plotted. The width and height give the dimensions
+ * the image is to be scaled to.
+ *
+ * \param ctx The current redraw context.
+ * \param bitmap The bitmap to plot
+ * \param x The x coordinate to plot the bitmap
+ * \param y The y coordiante to plot the bitmap
+ * \param width The width of area to plot the bitmap into
+ * \param height The height of area to plot the bitmap into
+ * \param bg the background colour to alpha blend into
+ * \param flags the flags controlling the type of plot operation
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+nsfltk_plot_bitmap(const struct redraw_context *ctx,
+ struct bitmap *bitmap,
+ int x, int y,
+ int width,
+ int height,
+ colour bg,
+ bitmap_flags_t flags)
+{
+ return NSERROR_OK;
+}
+
+
+/**
+ * Text plotting.
+ *
+ * \param ctx The current redraw context.
+ * \param fstyle plot style for this text
+ * \param x x coordinate
+ * \param y y coordinate
+ * \param text UTF-8 string to plot
+ * \param length length of string, in bytes
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+nsfltk_plot_text(const struct redraw_context *ctx,
+ const struct plot_font_style *fstyle,
+ int x,
+ int y,
+ const char *text,
+ size_t length)
+{
+ nsfltk_set_colour(fstyle->foreground);
+ fl_draw(text,length,x,y);
+ return NSERROR_OK;
+}
+
+
+/**
+ * FLTK plotter table
+ */
+const struct plotter_table nsfltk_plotters = {
+ .clip = nsfltk_plot_clip,
+ .arc = nsfltk_plot_arc,
+ .disc = nsfltk_plot_disc,
+ .line = nsfltk_plot_line,
+ .rectangle = nsfltk_plot_rectangle,
+ .polygon = nsfltk_plot_polygon,
+ .path = nsfltk_plot_path,
+ .bitmap = nsfltk_plot_bitmap,
+ .text = nsfltk_plot_text,
+ .group_start = NULL,
+ .group_end = NULL,
+ .flush = NULL,
+ .option_knockout = true
+};
diff --git a/frontends/fltk/plotters.h b/frontends/fltk/plotters.h
new file mode 100644
index 000000000..f0c8df91c
--- /dev/null
+++ b/frontends/fltk/plotters.h
@@ -0,0 +1,32 @@
+/*
+ * 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
+ * Target independent plotting FLGTK+ interface.
+ */
+
+#ifndef NETSURF_FLTK_PLOTTERS_H
+#define NETSURF_FLTK_PLOTTERS_H 1
+
+struct plotter_table;
+
+extern const struct plotter_table nsfltk_plotters;
+
+#endif /* NETSURF_FLTK_PLOTTERS_H */
+
diff --git a/frontends/fltk/res/adblock.css b/frontends/fltk/res/adblock.css
new file mode 120000
index 000000000..0d12aaa7c
--- /dev/null
+++ b/frontends/fltk/res/adblock.css
@@ -0,0 +1 @@
+../../../resources/adblock.css \ No newline at end of file
diff --git a/frontends/fltk/res/default.css b/frontends/fltk/res/default.css
new file mode 120000
index 000000000..fa3ae6c26
--- /dev/null
+++ b/frontends/fltk/res/default.css
@@ -0,0 +1 @@
+../../../resources/default.css \ No newline at end of file
diff --git a/frontends/fltk/res/en/credits.html b/frontends/fltk/res/en/credits.html
new file mode 120000
index 000000000..f73ecd4aa
--- /dev/null
+++ b/frontends/fltk/res/en/credits.html
@@ -0,0 +1 @@
+../../../../resources/en/credits.html \ No newline at end of file
diff --git a/frontends/fltk/res/en/licence.html b/frontends/fltk/res/en/licence.html
new file mode 120000
index 000000000..0c3b430b7
--- /dev/null
+++ b/frontends/fltk/res/en/licence.html
@@ -0,0 +1 @@
+../../../../resources/en/licence.html \ No newline at end of file
diff --git a/frontends/fltk/res/en/welcome.html b/frontends/fltk/res/en/welcome.html
new file mode 120000
index 000000000..543f31ddd
--- /dev/null
+++ b/frontends/fltk/res/en/welcome.html
@@ -0,0 +1 @@
+../../../../resources/en/welcome.html \ No newline at end of file
diff --git a/frontends/fltk/res/internal.css b/frontends/fltk/res/internal.css
new file mode 120000
index 000000000..5583a9811
--- /dev/null
+++ b/frontends/fltk/res/internal.css
@@ -0,0 +1 @@
+../../../resources/internal.css \ No newline at end of file
diff --git a/frontends/fltk/res/netsurf.png b/frontends/fltk/res/netsurf.png
new file mode 120000
index 000000000..d0ab72a5e
--- /dev/null
+++ b/frontends/fltk/res/netsurf.png
@@ -0,0 +1 @@
+../../../resources/netsurf.png \ No newline at end of file
diff --git a/frontends/fltk/res/quirks.css b/frontends/fltk/res/quirks.css
new file mode 120000
index 000000000..1e752cb9e
--- /dev/null
+++ b/frontends/fltk/res/quirks.css
@@ -0,0 +1 @@
+../../../resources/quirks.css \ No newline at end of file
diff --git a/frontends/fltk/resources.cpp b/frontends/fltk/resources.cpp
new file mode 100644
index 000000000..78925eb8c
--- /dev/null
+++ b/frontends/fltk/resources.cpp
@@ -0,0 +1,157 @@
+/*
+ * 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/>.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+extern "C" {
+
+#include "utils/errors.h"
+#include "utils/filepath.h"
+
+}
+
+#include "fltk/resources.h"
+
+/** resource search path vector */
+char **respaths;
+
+/** maximum number of languages in language vector */
+#define LANGV_SIZE 32
+/** maximum length of all strings in language vector */
+#define LANGS_SIZE 4096
+
+/**
+ * obtain language from environment
+ *
+ * start with GNU extension LANGUAGE environment variable and then try
+ * POSIX variables LC_ALL, LC_MESSAGES and LANG
+ *
+ */
+static const char *get_language(void)
+{
+ const char *lang;
+
+ lang = getenv("LANGUAGE");
+ if ((lang != NULL) && (lang[0] != '\0')) {
+ return lang;
+ }
+
+ lang = getenv("LC_ALL");
+ if ((lang != NULL) && (lang[0] != '\0')) {
+ return lang;
+ }
+
+ lang = getenv("LC_MESSAGES");
+ if ((lang != NULL) && (lang[0] != '\0')) {
+ return lang;
+ }
+
+ lang = getenv("LANG");
+ if ((lang != NULL) && (lang[0] != '\0')) {
+ return lang;
+ }
+
+ return NULL;
+}
+
+
+/** provide a string vector of languages in preference order
+ *
+ * environment variables are processed to aquire a colon separated
+ * list of languages which are converted into a string vector. The
+ * vector will always have the C language as its last entry.
+ *
+ * This implementation creates an internal static representation of
+ * the vector when first called and returns that for all subsequent
+ * calls. i.e. changing the environment does not change the returned
+ * vector on repeated calls.
+ *
+ * If the environment variables have more than LANGV_SIZE languages or
+ * LANGS_SIZE bytes of data the results list will be curtailed.
+ */
+static const char * const *get_languagev(void)
+{
+ static const char *langv[LANGV_SIZE];
+ int langidx = 0; /* index of next entry in vector */
+ static char langs[LANGS_SIZE];
+ char *curp; /* next language parameter in langs string */
+ const char *lange; /* language from environment variable */
+ int lang_len;
+ char *cln; /* colon in lange */
+
+ /* return cached vector */
+ if (langv[0] != NULL) {
+ return &langv[0];
+ }
+
+ curp = &langs[0];
+
+ lange = get_language();
+
+ if (lange != NULL) {
+ lang_len = strlen(lange) + 1;
+ if (lang_len < (LANGS_SIZE - 2)) {
+ memcpy(curp, lange, lang_len);
+ while ((curp[0] != 0) &&
+ (langidx < (LANGV_SIZE - 2))) {
+ /* avoid using strchrnul as it is not portable */
+ cln = strchr(curp, ':');
+ if (cln == NULL) {
+ langv[langidx++] = curp;
+ curp += lang_len;
+ break;
+ } else {
+ if ((cln - curp) > 1) {
+ /* only place non empty entries in vector */
+ langv[langidx++] = curp;
+ }
+ *cln++ = 0; /* null terminate */
+ lang_len -= (cln - curp);
+ curp = cln;
+ }
+ }
+ }
+ }
+
+ /* ensure C language is present */
+ langv[langidx++] = curp;
+ *curp++ = 'C';
+ *curp++ = 0;
+ langv[langidx] = NULL;
+
+ return &langv[0];
+}
+
+
+/* exported interface documented in fltk/resources.h */
+nserror nsfltk_init_resource_path(const char *resource_path)
+{
+ const char * const *langv;
+ char **pathv; /* resource path string vector */
+
+ pathv = filepath_path_to_strvec(resource_path);
+
+ langv = get_languagev();
+
+ respaths = filepath_generate(pathv, langv);
+
+ filepath_free_strvec(pathv);
+
+ return NSERROR_OK;
+}
diff --git a/frontends/fltk/resources.h b/frontends/fltk/resources.h
new file mode 100644
index 000000000..849179b2a
--- /dev/null
+++ b/frontends/fltk/resources.h
@@ -0,0 +1,42 @@
+/*
+ * 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/>.
+ */
+
+#ifndef NETSURF_FLTK_RESOURCES_H
+#define NETSURF_FLTK_RESOURCES_H 1
+
+/**
+ * resource search path vector
+ */
+extern char **respaths;
+
+/**
+ * Create an array of valid paths to search for resources.
+ *
+ * The idea is that all the complex path computation to find resources
+ * is performed here, once, rather than every time a resource is
+ * searched for.
+ *
+ * \param resource_path A shell style colon separated path list
+
+ * \return NSERROR_OK on success and the respaths set to a string
+ * vector of valid paths where resources can be found or appropriate
+ * error code on faliure.
+ */
+nserror nsfltk_init_resource_path(const char *resource_path);
+
+#endif
diff --git a/frontends/fltk/window.cpp b/frontends/fltk/window.cpp
new file mode 100644
index 000000000..19aa26556
--- /dev/null
+++ b/frontends/fltk/window.cpp
@@ -0,0 +1,344 @@
+/*
+ * 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 netsurf window (widget) for fltk.
+ */
+
+#include <stddef.h>
+#include <FL/Fl.H>
+#include <FL/Fl_Double_Window.H>
+#include <FL/fl_draw.H>
+
+extern "C" {
+
+#include "utils/errors.h"
+#include "netsurf/types.h"
+#include "netsurf/mouse.h"
+#include "netsurf/window.h"
+#include "netsurf/plotters.h"
+#include "netsurf/content.h"
+#include "netsurf/browser_window.h"
+#include "netsurf/mouse.h"
+
+}
+
+#include "fltk/window.h"
+#include "fltk/plotters.h"
+
+extern bool nsfltk_done;
+
+class NS_Widget : public Fl_Widget
+{
+private:
+ struct browser_window *mbw;
+
+protected:
+ void draw();
+ int handle(int event);
+
+public:
+ NS_Widget(int X,int Y,int W,int H, struct browser_window *bw)
+ : Fl_Widget(X,Y,W,H), mbw(bw) {}
+};
+
+
+class NS_Window : public Fl_Double_Window
+{
+private:
+ struct browser_window *mbw;
+ NS_Widget *mnswidget;
+
+ void close_callback(Fl_Widget *w);
+ static void static_close_callback(Fl_Widget *w, void *f) { ((NS_Window *)f)->close_callback(w); }
+
+public:
+ NS_Window(int W, int H, struct browser_window *bw)
+ : Fl_Double_Window(W,H), mbw(bw) {
+ this->callback(static_close_callback, (void *)this);
+ mnswidget = new NS_Widget(0, 0, W, H, bw);
+ this->end();
+ }
+ ~NS_Window() { nsfltk_done=true; }
+
+ NS_Widget *get_nswidget() { return mnswidget; }
+};
+
+struct gui_window {
+ struct browser_window *bw;
+ NS_Window *window;
+};
+
+/**
+ * method to handle events on the netsurf browsing widget
+ */
+int NS_Widget::handle(int event)
+{
+ int state = BROWSER_MOUSE_HOVER;
+ int button;
+
+ switch (event) {
+ case FL_PUSH:
+ button = Fl::event_button();
+ if (button == FL_LEFT_MOUSE) {
+ state |= BROWSER_MOUSE_PRESS_1;
+ }
+ browser_window_mouse_click(mbw,
+ (browser_mouse_state)state,
+ Fl::event_x() - x(),
+ Fl::event_y() - y());
+ return 1;
+
+ case FL_RELEASE:
+ button = Fl::event_button();
+ if (button == FL_LEFT_MOUSE) {
+ state |= BROWSER_MOUSE_CLICK_1;
+
+ }
+ browser_window_mouse_click(mbw,
+ (browser_mouse_state)state,
+ Fl::event_x() - x(),
+ Fl::event_y() - y());
+
+ return 1;
+ default:
+ return Fl_Widget::handle(event);
+ }
+}
+
+
+/**
+ * method to redraw the netsurf browsing widget
+ */
+void NS_Widget::draw()
+{
+ struct rect clip;
+ fl_clip_box(x(), y(), w(), h(), clip.x0, clip.y0, clip.x1, clip.y1);
+ /* clip box generates width/height so convert to absolute */
+ clip.x1 += clip.x0;
+ clip.y1 += clip.y0;
+ struct redraw_context ctx = {
+ .interactive = true,
+ .background_images = true,
+ .plot = &nsfltk_plotters,
+ .priv = NULL,
+ };
+
+ browser_window_redraw(mbw, x(), y(), &clip, &ctx);
+
+}
+
+/**
+ * callback when fltk window is closed
+ */
+void NS_Window::close_callback(Fl_Widget *w)
+{
+ browser_window_destroy(mbw);
+}
+
+/**
+ * Create and open a gui window for a browsing context.
+ *
+ * The implementing front end must create a context suitable
+ * for it to display a window referred to as the "gui window".
+ *
+ * The frontend will be expected to request the core redraw
+ * areas of the gui window which have become invalidated
+ * either from toolkit expose events or as a result of a
+ * invalidate() call.
+ *
+ * Most core operations used by the frontend concerning browser
+ * windows require passing the browser window context therefor
+ * the gui window must include a reference to the browser
+ * window passed here.
+ *
+ * If GW_CREATE_CLONE flag is set existing is non-NULL.
+ *
+ * \param bw The core browsing context associated with the gui window
+ * \param existing An existing gui_window, may be NULL.
+ * \param flags flags to control the gui window creation.
+ * \return gui window, or NULL on error.
+ */
+static struct gui_window *
+nsfltk_window_create(struct browser_window *bw,
+ struct gui_window *existing,
+ gui_window_create_flags flags)
+{
+ struct gui_window *gw;
+ gw = (struct gui_window *)calloc(1, sizeof(struct gui_window));
+
+ gw->window = new NS_Window(800,600, bw);
+
+ gw->window->show();
+
+ return gw;
+}
+
+/**
+ * Destroy previously created gui window
+ *
+ * \param gw The gui window to destroy.
+ */
+static void nsfltk_window_destroy(struct gui_window *gw)
+{
+ Fl::delete_widget(gw->window);
+ free(gw);
+}
+
+
+/**
+ * Invalidate an area of a window.
+ *
+ * The specified area of the window should now be considered
+ * out of date. If the area is NULL the entire window must be
+ * invalidated. It is expected that the windowing system will
+ * then subsequently cause redraw/expose operations as
+ * necessary.
+ *
+ * \note the frontend should not attempt to actually start the
+ * redraw operations as a result of this callback because the
+ * core redraw functions may already be threaded.
+ *
+ * \param gw The gui window to invalidate.
+ * \param rect area to redraw or NULL for the entire window area
+ * \return NSERROR_OK on success or appropriate error code
+ */
+static nserror
+nsfltk_window_invalidate(struct gui_window *gw, const struct rect *rect)
+{
+ NS_Widget *nswidget;
+ nswidget = gw->window->get_nswidget();
+
+ if (rect == NULL) {
+ nswidget->damage(FL_DAMAGE_ALL);
+ } else {
+ nswidget->damage(FL_DAMAGE_ALL,
+ rect->x0,
+ rect->y0,
+ rect->x1 - rect->x0,
+ rect->y1 - rect->y0);
+ }
+ return NSERROR_OK;
+}
+
+
+/**
+ * Get the scroll position of a browser window.
+ *
+ * \param gw The gui window to obtain the scroll position from.
+ * \param sx receives x ordinate of point at top-left of window
+ * \param sy receives y ordinate of point at top-left of window
+ * \return true iff successful
+ */
+static bool nsfltk_window_get_scroll(struct gui_window *gw, int *sx, int *sy)
+{
+ return false;
+}
+
+
+/**
+ * Set the scroll position of a browser window.
+ *
+ * scrolls the viewport to ensure the specified rectangle of
+ * the content is shown.
+ * If the rectangle is of zero size i.e. x0 == x1 and y0 == y1
+ * the contents will be scrolled so the specified point in the
+ * content is at the top of the viewport.
+ * If the size of the rectangle is non zero the frontend may
+ * add padding or centre the defined area or it may simply
+ * align as in the zero size rectangle
+ *
+ * \param gw The gui window to scroll.
+ * \param rect The rectangle to ensure is shown.
+ * \return NSERROR_OK on success or appropriate error code.
+ */
+static nserror
+nsfltk_window_set_scroll(struct gui_window *gw, const struct rect *rect)
+{
+ return NSERROR_OK;
+}
+
+
+/**
+ * Find the current dimensions of a browser window's content area.
+ *
+ * This is used to determine the actual available drawing size
+ * in pixels. This allows contents that can be dynamically
+ * reformatted, such as HTML, to better use the available
+ * space.
+ *
+ * \param gw The gui window to measure content area of.
+ * \param width receives width of window
+ * \param height receives height of window
+ * \return NSERROR_OK on success and width and height updated
+ * else error code.
+ */
+static nserror
+nsfltk_window_get_dimensions(struct gui_window *gw, int *width, int *height)
+{
+ NS_Widget *nswidget;
+ nswidget = gw->window->get_nswidget();
+
+ *width = nswidget->w();
+ *height = nswidget->h();
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * Miscellaneous event occurred for a window
+ *
+ * This is used to inform the frontend of window events which
+ * require no additional parameters.
+ *
+ * \param gw The gui window the event occurred for
+ * \param event Which event has occurred.
+ * \return NSERROR_OK if the event was processed else error code.
+ */
+static nserror
+nsfltk_window_event(struct gui_window *gw, enum gui_window_event event)
+{
+ return NSERROR_OK;
+}
+
+static struct gui_window_table window_table = {
+ .create = nsfltk_window_create,
+ .destroy = nsfltk_window_destroy,
+ .invalidate = nsfltk_window_invalidate,
+ .get_scroll = nsfltk_window_get_scroll,
+ .set_scroll = nsfltk_window_set_scroll,
+ .get_dimensions = nsfltk_window_get_dimensions,
+ .event = nsfltk_window_event,
+ .set_title = NULL,
+ .set_url = NULL,
+ .set_icon = NULL,
+ .set_status = NULL,
+ .set_pointer = NULL,
+ .place_caret = NULL,
+ .drag_start = NULL,
+ .save_link = NULL,
+ .create_form_select_menu = NULL,
+ .file_gadget_open = NULL,
+ .drag_save_object = NULL,
+ .drag_save_selection = NULL,
+ .console_log = NULL,
+};
+
+struct gui_window_table *nsfltk_window_table = &window_table;
diff --git a/frontends/fltk/window.h b/frontends/fltk/window.h
new file mode 100644
index 000000000..c33941822
--- /dev/null
+++ b/frontends/fltk/window.h
@@ -0,0 +1,27 @@
+/*
+ * 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/>.
+ */
+
+#ifndef NETSURF_FLTK_WINDOW_H
+#define NETSURF_FLTK_WINDOW_H 1
+
+/**
+ * fltk window (browser widget) operations table
+ */
+extern struct gui_window_table *nsfltk_window_table;
+
+#endif