Gitweb links:

...log 
http://git.netsurf-browser.org/netsurf.git/shortlog/04900e82e65f8669675538a66a01b56a3e473cb2
...commit 
http://git.netsurf-browser.org/netsurf.git/commit/04900e82e65f8669675538a66a01b56a3e473cb2
...tree 
http://git.netsurf-browser.org/netsurf.git/tree/04900e82e65f8669675538a66a01b56a3e473cb2

The branch, vince/fltk has been created
        at  04900e82e65f8669675538a66a01b56a3e473cb2 (commit)

- Log -----------------------------------------------------------------
commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=04900e82e65f8669675538a66a01b56a3e473cb2
commit 04900e82e65f8669675538a66a01b56a3e473cb2
Author: Vincent Sanders <vi...@kyllikki.org>
Commit: Vincent Sanders <vi...@kyllikki.org>

    Initial minimal FLTK toolkit implementation

diff --git a/frontends/Makefile.hts b/frontends/Makefile.hts
index b5af240..a78e34c 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 0000000..1cfb278
--- /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 0000000..ad70fb0
--- /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 0000000..460a957
--- /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 0000000..bc41822
--- /dev/null
+++ b/frontends/fltk/bitmap.cpp
@@ -0,0 +1,193 @@
+/*
+ * Copyright 2021 Vincent Sanders <vi...@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 0000000..e0f01a6
--- /dev/null
+++ b/frontends/fltk/bitmap.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2021 Vincent Sanders <vi...@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 0000000..39c15a6
--- /dev/null
+++ b/frontends/fltk/fetch.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2021 Vincent Sanders <vi...@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 0000000..6f9913e
--- /dev/null
+++ b/frontends/fltk/fetch.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2021 Vincent Sanders <vi...@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 0000000..4504430
--- /dev/null
+++ b/frontends/fltk/layout.cpp
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2021 Vincent Sanders <vi...@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 0000000..5e19cc0
--- /dev/null
+++ b/frontends/fltk/layout.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2021 Vincent Sanders <vi...@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 0000000..935bd2a
--- /dev/null
+++ b/frontends/fltk/main.cpp
@@ -0,0 +1,256 @@
+/*
+ * Copyright 2021 Vincent Sanders <vi...@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();
+               if (schedtm > 0) {
+                       NSLOG(netsurf, INFO, "scheduling for %d", schedtm);
+               }
+               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 0000000..b86affd
--- /dev/null
+++ b/frontends/fltk/misc.cpp
@@ -0,0 +1,237 @@
+/*
+ * Copyright 2021 Vincent Sanders <vi...@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 0000000..e088043
--- /dev/null
+++ b/frontends/fltk/misc.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2021 Vincent Sanders <vi...@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 0000000..65268f1
--- /dev/null
+++ b/frontends/fltk/plotters.cpp
@@ -0,0 +1,300 @@
+/*
+ * Copyright 2021 Vincent Sanders <vi...@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 0000000..f0c8df9
--- /dev/null
+++ b/frontends/fltk/plotters.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2021 Vincent Sanders <vi...@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 0000000..0d12aaa
--- /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 0000000..fa3ae6c
--- /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 0000000..f73ecd4
--- /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 0000000..0c3b430
--- /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 0000000..543f31d
--- /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 0000000..5583a98
--- /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 0000000..d0ab72a
--- /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 0000000..1e752cb
--- /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 0000000..78925eb
--- /dev/null
+++ b/frontends/fltk/resources.cpp
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2021 Vincent Sanders <vi...@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 0000000..849179b
--- /dev/null
+++ b/frontends/fltk/resources.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 Vincent Sanders <vi...@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 0000000..19aa265
--- /dev/null
+++ b/frontends/fltk/window.cpp
@@ -0,0 +1,344 @@
+/*
+ * Copyright 2021 Vincent Sanders <vi...@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 0000000..c339418
--- /dev/null
+++ b/frontends/fltk/window.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2021 Vincent Sanders <vi...@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


-----------------------------------------------------------------------


-- 
NetSurf Browser
_______________________________________________
netsurf-commits mailing list -- netsurf-commits@netsurf-browser.org
To unsubscribe send an email to netsurf-commits-le...@netsurf-browser.org

Reply via email to