Gitweb links:

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

The branch, vince/qt6 has been created
        at  bb606f6b5957690662f46143bd047cd756e53db6 (commit)

- Log -----------------------------------------------------------------
commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=bb606f6b5957690662f46143bd047cd756e53db6
commit bb606f6b5957690662f46143bd047cd756e53db6
Author: Vincent Sanders <[email protected]>
Commit: Vincent Sanders <[email protected]>

    Initial working QT frontend

diff --git a/docs/env.sh b/docs/env.sh
index 4cb056e..1bff76a 100644
--- a/docs/env.sh
+++ b/docs/env.sh
@@ -35,6 +35,8 @@ else
     NS_GTK_DEB="libgtk2.0-dev librsvg2-dev"
 fi
 
+NS_QT_DEB="qt6-base-dev-tools qt6-base-dev"
+
 # apt get commandline to install necessary dev packages
 ns-apt-get-install()
 {
diff --git a/frontends/Makefile.hts b/frontends/Makefile.hts
index b5af240..5713e82 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 framebuffer gtk monkey qt riscos windows
 
 # Check for valid TARGET
 ifeq ($(filter $(VLDTARGET),$(TARGET)),)
diff --git a/frontends/qt/Makefile b/frontends/qt/Makefile
new file mode 100644
index 0000000..f3afee1
--- /dev/null
+++ b/frontends/qt/Makefile
@@ -0,0 +1,52 @@
+#
+# Makefile for NetSurf ftlk target
+#
+# This file is part of NetSurf
+#
+# ----------------------------------------------------------------------------
+# QT flag setup (using pkg-config)
+# ----------------------------------------------------------------------------
+
+CXXFLAGS += -DQT_RESPATH=\"$(NETSURF_QT_RES_PATH)\" -g
+
+$(eval $(call pkg_config_find_and_add,Qt6Widgets,Qt6Widgets))
+$(eval $(call pkg_config_find_and_add,Qt6Core,Qt6Core))
+$(eval $(call pkg_config_find_and_add,Qt6Gui,Qt6Gui))
+
+LDFLAGS += -lm -lstdc++
+
+# Generate cpp from h via Qt's Meta Object Compiler
+%.moc.cpp: %.h
+       $(MOC) $(IFLAGS) $< -o $@
+
+# ---------------------------------------------------------------------------
+# Target setup
+# ---------------------------------------------------------------------------
+
+# The binary target.
+EXETARGET := nsqt
+
+# The filter and target for split messages
+MESSAGES_FILTER=qt
+MESSAGES_TARGET=$(FRONTEND_RESOURCES_DIR)
+
+# ----------------------------------------------------------------------------
+# Builtin resource handling
+# ----------------------------------------------------------------------------
+
+# builtin resource sources
+S_RESOURCE :=
+
+# ----------------------------------------------------------------------------
+# Source file setup
+# ----------------------------------------------------------------------------
+
+# S_FRONTEND are sources purely for the QT frontend
+S_FRONTEND := main.cpp misc.cpp window.cpp fetch.cpp bitmap.cpp layout.cpp \
+       plotters.cpp resources.cpp \
+       window.cls.moc.cpp widget.cls.moc.cpp urlbar.cls.moc.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/qt/Makefile.defaults b/frontends/qt/Makefile.defaults
new file mode 100644
index 0000000..b471744
--- /dev/null
+++ b/frontends/qt/Makefile.defaults
@@ -0,0 +1,28 @@
+# ----------------------------------------------------------------------------
+# QT-specific options
+# ----------------------------------------------------------------------------
+
+# Where to search for NetSurf's resources after looking in ~/.netsurf and
+# $NETSURFRES.  It must have a trailing /
+NETSURF_QT_RES_PATH := $(PREFIX)/share/netsurf/:./frontends/qt/res/
+
+# Where to install the netsurf binary
+NETSURF_QT_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/qt/Makefile.tools b/frontends/qt/Makefile.tools
new file mode 100644
index 0000000..26fab44
--- /dev/null
+++ b/frontends/qt/Makefile.tools
@@ -0,0 +1,10 @@
+# -*- mode: makefile-gmake -*-
+##
+## tool setup for the fltk target
+##
+
+# use native package config
+PKG_CONFIG := pkg-config
+
+# Meta object compiler
+MOC := /usr/lib/qt6/libexec/moc
diff --git a/frontends/qt/bitmap.cpp b/frontends/qt/bitmap.cpp
new file mode 100644
index 0000000..72c6ede
--- /dev/null
+++ b/frontends/qt/bitmap.cpp
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2021 Vincent Sanders <[email protected]>
+ *
+ * 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 qt.
+ */
+
+#include <stddef.h>
+
+extern "C" {
+
+#include "utils/errors.h"
+#include "netsurf/bitmap.h"
+
+}
+
+#include "qt/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 *nsqt_bitmap_create(int width, int height, enum gui_bitmap_flags 
flags)
+{
+       return NULL;
+}
+
+/**
+ * Destroy a bitmap.
+ *
+ * \param bitmap The bitmap to destroy.
+ */
+static void nsqt_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 nsqt_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 nsqt_bitmap_get_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 *nsqt_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 nsqt_bitmap_get_rowstride(void *bitmap)
+{
+       return 0;
+}
+
+/**
+ * Get the bitmap width
+ *
+ * \param bitmap The bitmap
+ * \return The bitmap width in pixels.
+ */
+static int nsqt_bitmap_get_width(void *bitmap)
+{
+       return 0;
+}
+
+/**
+ * Get the bitmap height
+ *
+ * \param bitmap The bitmap
+ * \return The bitmap height in pixels.
+ */
+static int nsqt_bitmap_get_height(void *bitmap)
+{
+       return 0;
+}
+
+
+
+/**
+ * Marks a bitmap as modified.
+ *
+ * \param bitmap The bitmap set as modified.
+ */
+static void nsqt_bitmap_modified(void *bitmap)
+{
+}
+
+/**
+ * Render content into a bitmap.
+ *
+ * \param bitmap The bitmap to render into.
+ * \param content The content to render.
+ */
+static nserror
+nsqt_bitmap_render(struct bitmap *bitmap, struct hlcache_handle *content)
+{
+       return NSERROR_OK;
+}
+
+
+static struct gui_bitmap_table bitmap_table = {
+       .create = nsqt_bitmap_create,
+       .destroy = nsqt_bitmap_destroy,
+       .set_opaque = nsqt_bitmap_set_opaque,
+       .get_opaque = nsqt_bitmap_get_opaque,
+       .get_buffer = nsqt_bitmap_get_buffer,
+       .get_rowstride = nsqt_bitmap_get_rowstride,
+       .get_width = nsqt_bitmap_get_width,
+       .get_height = nsqt_bitmap_get_height,
+       .modified = nsqt_bitmap_modified,
+       .render = nsqt_bitmap_render,
+};
+
+struct gui_bitmap_table *nsqt_bitmap_table = &bitmap_table;
diff --git a/frontends/qt/bitmap.h b/frontends/qt/bitmap.h
new file mode 100644
index 0000000..ac90a57
--- /dev/null
+++ b/frontends/qt/bitmap.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2023 Vincent Sanders <[email protected]>
+ *
+ * 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_QT_BITMAP_H
+#define NETSURF_QT_BITMAP_H 1
+
+/**
+ * qt bitmap operations table
+ */
+extern struct gui_bitmap_table *nsqt_bitmap_table;
+
+#endif
diff --git a/frontends/qt/fetch.cpp b/frontends/qt/fetch.cpp
new file mode 100644
index 0000000..98567c5
--- /dev/null
+++ b/frontends/qt/fetch.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2021 Vincent Sanders <[email protected]>
+ *
+ * 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 qt.
+ */
+
+#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 "qt/fetch.h"
+#include "qt/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 *nsqt_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 *nsqt_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 = nsqt_fetch_filetype,
+
+       .get_resource_url = nsqt_get_resource_url,
+       .get_resource_data = NULL,
+       .release_resource_data = NULL,
+       .mimetype = NULL,
+};
+
+struct gui_fetch_table *nsqt_fetch_table = &fetch_table;
diff --git a/frontends/qt/fetch.h b/frontends/qt/fetch.h
new file mode 100644
index 0000000..5cd0607
--- /dev/null
+++ b/frontends/qt/fetch.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2021 Vincent Sanders <[email protected]>
+ *
+ * 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_QT_FETCH_H
+#define NETSURF_QT_FETCH_H 1
+
+/**
+ * qt fetch operations table
+ */
+extern struct gui_fetch_table *nsqt_fetch_table;
+
+#endif
diff --git a/frontends/qt/layout.cpp b/frontends/qt/layout.cpp
new file mode 100644
index 0000000..3aab3ca
--- /dev/null
+++ b/frontends/qt/layout.cpp
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2023 Vincent Sanders <[email protected]>
+ *
+ * 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 qt.
+ */
+
+#include <stddef.h>
+
+extern "C" {
+
+#include "utils/errors.h"
+#include "utils/utf8.h"
+#include "netsurf/layout.h"
+#include "netsurf/plot_style.h"
+
+}
+
+#include "qt/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
+nsqt_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
+nsqt_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
+nsqt_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 = nsqt_layout_width,
+       .position = nsqt_layout_position,
+       .split = nsqt_layout_split,
+};
+
+struct gui_layout_table *nsqt_layout_table = &layout_table;
diff --git a/frontends/qt/layout.h b/frontends/qt/layout.h
new file mode 100644
index 0000000..62173d6
--- /dev/null
+++ b/frontends/qt/layout.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2021 Vincent Sanders <[email protected]>
+ *
+ * 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_QT_LAYOUT_H
+#define NETSURF_QT_LAYOUT_H 1
+
+/**
+ * qt layout operations table
+ */
+extern struct gui_layout_table *nsqt_layout_table;
+
+#endif
diff --git a/frontends/qt/main.cpp b/frontends/qt/main.cpp
new file mode 100644
index 0000000..a1c89c3
--- /dev/null
+++ b/frontends/qt/main.cpp
@@ -0,0 +1,263 @@
+/*
+ * Copyright 2023 Vincent Sanders <[email protected]>
+ *
+ * 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 <QApplication>
+
+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 "qt/misc.h"
+#include "qt/window.h"
+#include "qt/fetch.h"
+#include "qt/bitmap.h"
+#include "qt/layout.h"
+#include "qt/resources.h"
+
+bool nsqt_done = false;
+
+/**
+ * Set option defaults for qt 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;
+}
+
+
+/**
+ * qt frontend specific initialisation
+ */
+static nserror nsqt_init(int *pargc, char** argv,QApplication **papp)
+{
+       nserror res;
+       QApplication *app;
+
+       /* qt application */
+       app = new QApplication(*pargc, argv);
+       if (app == NULL) {
+               return NSERROR_NOMEM;
+       }
+       *papp = app;
+
+       /* Prep the resource search paths */
+       res = nsqt_init_resource_path("${HOME}/.netsurf/:${NETSURFRES}:" 
QT_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 qt browser.
+ *
+ * performs qt 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 nsqt_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 qt event loop.
+ *
+ */
+static void nsqt_run(QApplication *app)
+{
+       int schedtm;
+       do {
+               /* run scheduled callbacks and get the next event delta in ms */
+               schedtm = nsqt_schedule_run();
+               app->processEvents(QEventLoop::AllEvents, schedtm);
+       } while(nsqt_done != true);
+}
+
+static nserror nsqt_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;
+       QApplication *app;
+       struct netsurf_table nsqt_table = {
+               .misc = nsqt_misc_table,
+               .window = nsqt_window_table,
+               .download = NULL, /* no download functionality */
+               .clipboard = NULL, /* no clipboard functionality */
+               .fetch = nsqt_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 = nsqt_bitmap_table,
+               .layout = nsqt_layout_table,
+       };
+
+       /* register operation tables */
+       res = netsurf_register(&nsqt_table);
+       if (res != NSERROR_OK) {
+               fprintf(stderr,
+                       "NetSurf operation table failed registration (%s)\n",
+                       messages_get_errorcode(res));
+               return 1;
+       }
+
+       /* qt specific initialisation */
+       res = nsqt_init(&argc, argv, &app);
+       if (res != NSERROR_OK) {
+               fprintf(stderr, "NetSurf qt 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;
+       }
+
+       /* qt specific startup */
+       res = nsqt_start(argc, argv);
+       if (res != NSERROR_OK) {
+               fprintf(stderr, "NetSurf qt startup failed (%s)\n",
+                       messages_get_errorcode(res));
+               nsqt_finalise();
+               return 4;
+       }
+
+       /* startup suceeded so main run loop */
+       nsqt_run(app);
+
+       /* finalise everything */
+       nsqt_finalise();
+
+       return 0;
+
+}
diff --git a/frontends/qt/misc.cpp b/frontends/qt/misc.cpp
new file mode 100644
index 0000000..d11f997
--- /dev/null
+++ b/frontends/qt/misc.cpp
@@ -0,0 +1,237 @@
+/*
+ * Copyright 2021 Vincent Sanders <[email protected]>
+ *
+ * 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 qt.
+ */
+
+#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 "qt/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 qt/misc.h */
+int nsqt_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 nsqt_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 = nsqt_schedule,
+       .quit = NULL,
+       .launch_url = NULL,
+       .login = NULL,
+       .pdf_password = NULL,
+       .present_cookies = NULL,
+};
+
+struct gui_misc_table *nsqt_misc_table = &misc_table;
diff --git a/frontends/qt/misc.h b/frontends/qt/misc.h
new file mode 100644
index 0000000..9500858
--- /dev/null
+++ b/frontends/qt/misc.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2023 Vincent Sanders <[email protected]>
+ *
+ * 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_QT_MISC_H
+#define NETSURF_QT_MISC_H 1
+
+/**
+ * qt miscellaneous (scheduling) operations table
+ */
+extern struct gui_misc_table *nsqt_misc_table;
+
+/**
+ * run and pending scheduling callbacks
+ *
+ * \return number of miliseconds before next scheduled event
+ */
+int nsqt_schedule_run(void);
+
+#endif
diff --git a/frontends/qt/plotters.cpp b/frontends/qt/plotters.cpp
new file mode 100644
index 0000000..6986e84
--- /dev/null
+++ b/frontends/qt/plotters.cpp
@@ -0,0 +1,330 @@
+/*
+ * Copyright 2021 Vincent Sanders <[email protected]>
+ *
+ * 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 qt.
+ */
+
+#include <stddef.h>
+#include <QPainter>
+
+extern "C" {
+
+#include "utils/log.h"
+#include "utils/errors.h"
+#include "netsurf/types.h"
+#include "netsurf/mouse.h"
+#include "netsurf/window.h"
+#include "netsurf/plotters.h"
+
+}
+
+#include "qt/window.h"
+#include "qt/plotters.h"
+
+
+/**
+ * setup qt painter styles according to netsurf plot style
+ */
+static nserror nsqt_set_style(QPainter* painter, const plot_style_t *style)
+{
+       QColor fillcolour(style->fill_colour & 0xFF,
+                         (style->fill_colour & 0xFF00) >>8,
+                         (style->fill_colour & 0xFF0000) >>16);
+       /*NSLOG(netsurf, WARNING,"fill_colour %x -> %d,%d,%d",
+             style->fill_colour,
+             style->fill_colour & 0xFF,
+             (style->fill_colour & 0xFF00) >>8,
+             (style->fill_colour & 0xFF0000) >>16);*/
+       Qt::BrushStyle brushstyle = Qt::NoBrush;
+       if (style->fill_type != PLOT_OP_TYPE_NONE) {
+               brushstyle = Qt::SolidPattern;
+       }       
+       QBrush brush(fillcolour, brushstyle);
+       painter->setBrush(brush);
+
+       QColor strokecolour(style->stroke_colour & 0xFF,
+                           (style->stroke_colour & 0xFF00) >>8,
+                           (style->stroke_colour & 0xFF0000) >>16);
+       QPen pen(strokecolour);
+       Qt::PenStyle penstyle = Qt::NoPen;
+       if (style->stroke_type != PLOT_OP_TYPE_NONE) {
+               penstyle = Qt::SolidLine;
+       }
+       pen.setStyle(penstyle);
+       
+       painter->setPen(pen);
+
+       return NSERROR_OK;
+}
+
+
+/**
+ * \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
+nsqt_plot_clip(const struct redraw_context *ctx, const struct rect *clip)
+{
+       QPainter* painter = (QPainter*)ctx->priv;
+
+       painter->setClipRect(clip->x0,clip->y0,clip->x1-clip->x0, 
clip->y1-clip->y0);
+       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
+nsqt_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
+nsqt_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
+nsqt_plot_line(const struct redraw_context *ctx,
+                const plot_style_t *style,
+                const struct rect *line)
+{
+       QPainter* painter = (QPainter*)ctx->priv;
+       nsqt_set_style(painter,style);
+
+       painter->drawLine(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
+nsqt_plot_rectangle(const struct redraw_context *ctx,
+                     const plot_style_t *style,
+                     const struct rect *rect)
+{
+       QPainter* painter = (QPainter*)ctx->priv;
+       nsqt_set_style(painter,style);
+//     NSLOG(netsurf, WARNING,"rect %d,%d %d,%d",            rect->x0,       
rect->y0,       rect->x1 - rect->x0,            rect->y1 - rect->y0);
+       painter->drawRect(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
+nsqt_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
+nsqt_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
+nsqt_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
+nsqt_plot_text(const struct redraw_context *ctx,
+                const struct plot_font_style *fstyle,
+                int x,
+                int y,
+                const char *text,
+                size_t length)
+{
+       QPainter* painter = (QPainter*)ctx->priv;
+       QColor strokecolour(fstyle->foreground & 0xFF,
+                           (fstyle->foreground & 0xFF00) >>8,
+                           (fstyle->foreground & 0xFF0000) >>16);
+       QPen pen(strokecolour);
+       painter->setPen(pen);
+       
+       painter->drawText(x,y, QString::fromUtf8(text,length));
+
+       return NSERROR_OK;
+}
+
+
+/**
+ * QT plotter table
+ */
+const struct plotter_table nsqt_plotters = {
+       .clip = nsqt_plot_clip,
+       .arc = nsqt_plot_arc,
+       .disc = nsqt_plot_disc,
+       .line = nsqt_plot_line,
+       .rectangle = nsqt_plot_rectangle,
+       .polygon = nsqt_plot_polygon,
+       .path = nsqt_plot_path,
+       .bitmap = nsqt_plot_bitmap,
+       .text = nsqt_plot_text,
+       .group_start = NULL,
+       .group_end = NULL,
+       .flush = NULL,
+       .option_knockout = true
+};
diff --git a/frontends/qt/plotters.h b/frontends/qt/plotters.h
new file mode 100644
index 0000000..506342c
--- /dev/null
+++ b/frontends/qt/plotters.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2023 Vincent Sanders <[email protected]>
+ *
+ * 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 QT interface.
+ */
+
+#ifndef NETSURF_QT_PLOTTERS_H
+#define NETSURF_QT_PLOTTERS_H 1
+
+struct plotter_table;
+
+extern const struct plotter_table nsqt_plotters;
+
+#endif /* NETSURF_QT_PLOTTERS_H */
+
diff --git a/frontends/qt/res/adblock.css b/frontends/qt/res/adblock.css
new file mode 120000
index 0000000..0d12aaa
--- /dev/null
+++ b/frontends/qt/res/adblock.css
@@ -0,0 +1 @@
+../../../resources/adblock.css
\ No newline at end of file
diff --git a/frontends/qt/res/default.css b/frontends/qt/res/default.css
new file mode 120000
index 0000000..fa3ae6c
--- /dev/null
+++ b/frontends/qt/res/default.css
@@ -0,0 +1 @@
+../../../resources/default.css
\ No newline at end of file
diff --git a/frontends/qt/res/en/credits.html b/frontends/qt/res/en/credits.html
new file mode 120000
index 0000000..f73ecd4
--- /dev/null
+++ b/frontends/qt/res/en/credits.html
@@ -0,0 +1 @@
+../../../../resources/en/credits.html
\ No newline at end of file
diff --git a/frontends/qt/res/en/licence.html b/frontends/qt/res/en/licence.html
new file mode 120000
index 0000000..0c3b430
--- /dev/null
+++ b/frontends/qt/res/en/licence.html
@@ -0,0 +1 @@
+../../../../resources/en/licence.html
\ No newline at end of file
diff --git a/frontends/qt/res/en/welcome.html b/frontends/qt/res/en/welcome.html
new file mode 120000
index 0000000..543f31d
--- /dev/null
+++ b/frontends/qt/res/en/welcome.html
@@ -0,0 +1 @@
+../../../../resources/en/welcome.html
\ No newline at end of file
diff --git a/frontends/qt/res/internal.css b/frontends/qt/res/internal.css
new file mode 120000
index 0000000..5583a98
--- /dev/null
+++ b/frontends/qt/res/internal.css
@@ -0,0 +1 @@
+../../../resources/internal.css
\ No newline at end of file
diff --git a/frontends/qt/res/netsurf.png b/frontends/qt/res/netsurf.png
new file mode 120000
index 0000000..d0ab72a
--- /dev/null
+++ b/frontends/qt/res/netsurf.png
@@ -0,0 +1 @@
+../../../resources/netsurf.png
\ No newline at end of file
diff --git a/frontends/qt/res/quirks.css b/frontends/qt/res/quirks.css
new file mode 120000
index 0000000..1e752cb
--- /dev/null
+++ b/frontends/qt/res/quirks.css
@@ -0,0 +1 @@
+../../../resources/quirks.css
\ No newline at end of file
diff --git a/frontends/qt/resources.cpp b/frontends/qt/resources.cpp
new file mode 100644
index 0000000..40ca84f
--- /dev/null
+++ b/frontends/qt/resources.cpp
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2021 Vincent Sanders <[email protected]>
+ *
+ * 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 "qt/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 qt/resources.h */
+nserror nsqt_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/qt/resources.h b/frontends/qt/resources.h
new file mode 100644
index 0000000..f47a7e5
--- /dev/null
+++ b/frontends/qt/resources.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 Vincent Sanders <[email protected]>
+ *
+ * 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_QT_RESOURCES_H
+#define NETSURF_QT_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 nsqt_init_resource_path(const char *resource_path);
+
+#endif
diff --git a/frontends/qt/urlbar.cls.h b/frontends/qt/urlbar.cls.h
new file mode 100644
index 0000000..3e4ceb0
--- /dev/null
+++ b/frontends/qt/urlbar.cls.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2023 Vincent Sanders <[email protected]>
+ *
+ * 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
+ * Ineterface of netsurf window for qt.
+ */
+
+#include <QToolBar>
+extern "C" {
+#include "netsurf/types.h"
+#include "netsurf/content_type.h"
+#include "netsurf/browser_window.h"
+}
+
+class NS_URLBar :public QToolBar
+{
+       Q_OBJECT
+private:
+       struct browser_window *m_bw;
+
+public:
+       NS_URLBar(QWidget* parent, struct browser_window *bw);
+
+};
diff --git a/frontends/qt/widget.cls.h b/frontends/qt/widget.cls.h
new file mode 100644
index 0000000..d709afd
--- /dev/null
+++ b/frontends/qt/widget.cls.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2023 Vincent Sanders <[email protected]>
+ *
+ * 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 widget for qt.
+ */
+
+#include <QWidget>
+extern "C" {
+#include "netsurf/types.h"
+#include "netsurf/content_type.h"
+#include "netsurf/browser_window.h"
+}
+
+class NS_Widget : public QWidget
+{
+       Q_OBJECT
+private:
+       struct browser_window *m_bw;
+       int m_xoffset;
+       int m_yoffset;
+
+protected:
+       void paintEvent(QPaintEvent *event);
+       void resizeEvent(QResizeEvent *event);
+       int handle(int event);
+
+public:
+       NS_Widget(QWidget *parent, struct browser_window *bw)
+               : QWidget(parent, Qt::Widget), m_bw(bw), m_xoffset(0), 
m_yoffset(0) {}
+
+       bool get_scroll(int *sx, int *sy);
+       nserror get_dimensions(int *width, int *height);
+
+       nserror invalidate(const struct rect *rect);
+/*
+  void vscroll_callback(Fl_Scrollbar *w);
+       void hscroll_callback(Fl_Scrollbar *w);
+*/
+};
diff --git a/frontends/qt/window.cls.h b/frontends/qt/window.cls.h
new file mode 100644
index 0000000..f59e61e
--- /dev/null
+++ b/frontends/qt/window.cls.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2023 Vincent Sanders <[email protected]>
+ *
+ * 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
+ * Window class for QT frontend.
+ */
+
+#include <QWidget>
+
+extern "C" {
+#include "utils/errors.h"
+#include "netsurf/mouse.h"
+#include "netsurf/window.h"
+}
+
+#include "qt/widget.cls.h"
+
+/**
+ * Class for netsurf window
+ */
+class NS_Window : public QWidget
+{
+       Q_OBJECT
+private:
+       struct browser_window *m_bw;
+
+       //NS_URLBar *m_nsurlbar;
+       NS_Widget *m_nswidget;
+       //Fl_Scrollbar *m_vscrollbar;
+       //Fl_Scrollbar *m_hscrollbar;
+       //Fl_Output *m_status;
+
+       nserror set_scroll(const struct rect *rect);
+       void set_status(const char *text);
+       void set_title(const char *title);
+       nserror set_extent(int w, int h);
+
+       //void close_callback(Fl_Widget *w);
+
+       /* static wrapper for qt callbacks */
+       //static void static_close_callback(Fl_Widget *w, void *f);
+       //static void static_hscroll_callback(Fl_Widget *w, void *f);
+       //static void static_vscroll_callback(Fl_Widget *w, void *f);
+protected:
+       void closeEvent(QCloseEvent *event);
+public:
+       NS_Window(QWidget* parent, struct browser_window *bw);
+       ~NS_Window();
+
+       /* static wrappers to be able to call instance methods */
+       static nserror static_set_scroll(struct gui_window *gw, const struct 
rect *rect);
+       static void static_set_status(struct gui_window *gw, const char *text);
+       static void static_set_title(struct gui_window *gw, const char *title);
+
+       static bool static_get_scroll(struct gui_window *gw, int *sx, int *sy);
+       static nserror static_set_url(struct gui_window *gw, struct nsurl *url);
+
+       static nserror static_event(struct gui_window *gw, enum 
gui_window_event event);
+       static nserror static_invalidate(struct gui_window *gw, const struct 
rect *rect);
+       static nserror static_get_dimensions(struct gui_window *gw, int *width, 
int *height);
+       static struct gui_window *static_create(struct browser_window *bw, 
struct gui_window *existing, gui_window_create_flags flags);
+       static void static_destroy(struct gui_window *gw);
+};
diff --git a/frontends/qt/window.cpp b/frontends/qt/window.cpp
new file mode 100644
index 0000000..7c577ca
--- /dev/null
+++ b/frontends/qt/window.cpp
@@ -0,0 +1,676 @@
+/*
+ * Copyright 2023 Vincent Sanders <[email protected]>
+ *
+ * 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 qt.
+ */
+
+#include <stddef.h>
+#include <QWidget>
+#include <QPaintEvent>
+#include <QPainter>
+#include <QGridLayout>
+#include <QHBoxLayout>
+#include <QPushButton>
+#include <QScrollBar>
+#include <QToolBar>
+
+extern "C" {
+
+#include "utils/errors.h"
+#include "utils/log.h"
+#include "utils/nsoption.h"
+#include "utils/nsurl.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 "desktop/browser_history.h"
+
+}
+
+#include "qt/window.cls.h"
+#include "qt/urlbar.cls.h"
+
+#include "qt/window.h"
+#include "qt/plotters.h"
+
+extern bool nsqt_done;
+
+struct gui_window {
+       class NS_Window *window;
+};
+
+
+#if 0
+/**
+ * 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(m_bw,
+                                          (browser_mouse_state)state,
+                                          Fl::event_x() - x() + m_xoffset,
+                                          Fl::event_y() - y() + m_yoffset);
+               return 1;
+
+       case FL_RELEASE:
+               button = Fl::event_button();
+               if (button == FL_LEFT_MOUSE) {
+                       state |= BROWSER_MOUSE_CLICK_1;
+
+               }
+               browser_window_mouse_click(m_bw,
+                                          (browser_mouse_state)state,
+                                          Fl::event_x() - x() + m_xoffset,
+                                          Fl::event_y() - y() + m_yoffset);
+
+               return 1;
+       default:
+               return Fl_Widget::handle(event);
+               
+       }
+               
+}
+#endif
+
+/**
+ * widget has been resized
+ */
+void NS_Widget::resizeEvent(QResizeEvent *event)
+{
+       browser_window_schedule_reformat(m_bw);
+}
+
+/**
+ * redraw the netsurf browsing widget
+ */
+void NS_Widget::paintEvent(QPaintEvent *event)
+{
+       struct rect clip;
+       QPainter *painter;
+       struct redraw_context ctx = {
+               .interactive = true,
+               .background_images = true,
+               .plot = &nsqt_plotters,
+               .priv = NULL,
+       };
+
+       /* netsurf render clip region coordinates */
+       clip.x0 = event->rect().left();
+       clip.y0 = event->rect().top();
+       clip.x1 = clip.x0 + event->rect().width();
+       clip.y1 = clip.y0 + event->rect().height();
+
+       painter = new QPainter(this);
+       ctx.priv = painter;
+
+       //NSLOG(netsurf, WARNING, "redrawing");
+       browser_window_redraw(m_bw,
+                             - m_xoffset,
+                             - m_yoffset,
+                             &clip,
+                             &ctx);
+
+       delete painter;
+
+}
+
+#if 0
+/**
+ * vertical scrollbar position has been changed
+ */
+void NS_Widget::vscroll_callback(Fl_Scrollbar *sb)
+{
+       m_yoffset = sb->value();
+       //damage(FL_DAMAGE_SCROLL);
+}
+
+
+/**
+ * horizontal scrollbar position has been changed
+ */
+void NS_Widget::hscroll_callback(Fl_Scrollbar *sb)
+{
+       m_xoffset = sb->value();
+       //damage(FL_DAMAGE_SCROLL);
+}
+#endif
+/**
+ * get the current scroll offsets
+ */
+bool NS_Widget::get_scroll(int *sx, int *sy)
+{
+       *sx = m_xoffset;
+       *sy = m_yoffset;
+
+       return true;
+}
+
+
+/**
+ * get the viewable dimensions of browsing context
+ */
+nserror NS_Widget::get_dimensions(int *width, int *height)
+{
+       *width = size().width();
+       *height = size().height();
+
+       return NSERROR_OK;
+}
+
+
+/**
+ * mark an area of the browsing context as invalid
+ */
+nserror NS_Widget::invalidate(const struct rect *rect)
+{
+       
+       if (rect == NULL) {
+               update();
+       } else {
+               update(rect->x0,
+                      rect->y0,
+                      rect->x1 - rect->x0,
+                      rect->y1 - rect->y0);
+                      }
+       return NSERROR_OK;
+
+}
+#include <QLineEdit>
+
+NS_URLBar::NS_URLBar(QWidget* parent, struct browser_window *bw)
+       : QToolBar(parent), m_bw(bw)
+{
+       addAction(QIcon(":/icons/back.png"), "Back");
+       addAction(QIcon(":/icons/forward.png"), "Forward");
+       QLineEdit *input=new QLineEdit();
+       addWidget(input);
+}
+
+#if 0
+/**
+ * widget representing url bar
+ */
+class NS_URLBar : public Fl_Pack
+{
+private:
+       struct browser_window *m_bw;
+       Fl_Button *m_back_button;
+       Fl_Button *m_forward_button;
+       Fl_Input *m_input;
+
+       void back_callback(Fl_Button *button);
+       void forward_callback(Fl_Button *button);
+public:
+       NS_URLBar(int X,int Y,int W,int H, struct browser_window *bw);
+       nserror set_url(struct nsurl *url);
+
+       /* static wrapper for qt callbacks */
+       static void static_back_callback(Fl_Widget *w, void *f);
+       static void static_forward_callback(Fl_Widget *w, void *f);
+
+};
+
+NS_URLBar::NS_URLBar(int X,int Y,int W,int H, struct browser_window *bw)
+       : Fl_Pack(X,Y,W,H), m_bw(bw)
+{
+       type(Fl_Pack::HORIZONTAL);
+       spacing(4);
+
+       m_back_button = new Fl_Button(0,0,H,H, "B");
+       m_back_button->callback(static_back_callback, (void *)this);
+
+       m_forward_button = new Fl_Button(0,0,H,H, "F");
+       m_forward_button->callback(static_forward_callback, (void *)this);
+
+       m_input = new Fl_Input(0,0,W,H);
+
+       end();
+
+       resizable(m_input);
+}
+
+nserror NS_URLBar::set_url(struct nsurl *url)
+{
+       size_t idn_url_l;
+       char *idn_url_s = NULL;
+       if (nsurl_get_utf8(url, &idn_url_s, &idn_url_l) == NSERROR_OK) {
+               m_input->value(idn_url_s, idn_url_l-1);
+               free(idn_url_s);
+       } else {
+               m_input->value(nsurl_access(url));
+       }
+       return NSERROR_OK;
+}
+
+void NS_URLBar::back_callback(Fl_Button *button)
+{
+       browser_window_history_back(m_bw, false);
+}
+
+void NS_URLBar::forward_callback(Fl_Button *button)
+{
+       browser_window_history_forward(m_bw, false);
+}
+
+
+void NS_URLBar::static_back_callback(Fl_Widget *w, void *f)
+{
+       ((NS_URLBar *)f)->back_callback((Fl_Button *)w);
+}
+
+void NS_URLBar::static_forward_callback(Fl_Widget *w, void *f)
+{
+       ((NS_URLBar *)f)->forward_callback((Fl_Button *)w);
+}
+
+#endif
+
+
+/**
+ * netsurf window class constructor
+ */
+NS_Window::NS_Window(QWidget *parent, struct browser_window *bw)
+       : QWidget(parent), m_bw(bw)
+{
+       //int scrlsize = Fl::scrollbar_size();
+       //int splitx = (nsoption_int(toolbar_status_size) * W) / 10000;
+       //int urlbarh = scrlsize * 2;
+
+       //callback(static_close_callback, (void *)this);
+
+       // url bar
+       //m_nsurlbar = new NS_URLBar(0, 0, W, urlbarh, bw);
+       NS_URLBar *urlbar= new NS_URLBar(nullptr, m_bw);
+
+       QScrollBar *vscrollbar= new QScrollBar(Qt::Vertical);
+       
+       
+       // browser drawing canvas widget
+       m_nswidget = new NS_Widget(this,  bw);
+       QGridLayout *layout = new QGridLayout(this);
+       layout->setContentsMargins(0,0,0,0);
+       layout->addWidget(urlbar, 0, 0, 1, 2);
+       layout->addWidget(m_nswidget,1,0);
+       layout->addWidget(vscrollbar, 1,1);
+       layout->setRowStretch(1,1);
+       
+       #if 0
+       // vertical scrollbar
+       m_vscrollbar = new Fl_Scrollbar(m_nswidget->w(),
+                                       m_nsurlbar->h(),
+                                      scrlsize,
+                                       m_nswidget->h());
+       m_vscrollbar->callback(static_vscroll_callback, (void *)m_nswidget);
+       m_vscrollbar->value(0, m_nswidget->h(), 0, m_nswidget->h());
+
+       // horizontal scrollbar
+       m_hscrollbar = new Fl_Scrollbar(splitx,
+                                      m_nswidget->y() + m_nswidget->h(),
+                                      m_nswidget->w() - splitx,
+                                      scrlsize);
+       m_hscrollbar->type(FL_HORIZONTAL);
+       m_hscrollbar->callback(static_hscroll_callback, (void *)m_nswidget);
+       m_hscrollbar->value(0, m_nswidget->w(), 0, m_nswidget->w());
+
+       // status text
+       m_status = new Fl_Output(0, m_hscrollbar->y(), splitx, scrlsize);
+       end();
+
+       resizable(m_nswidget);
+       #endif
+}
+
+NS_Window::~NS_Window() {
+       nsqt_done=true;
+}
+
+void NS_Window::closeEvent(QCloseEvent *event)
+{
+       browser_window_destroy(m_bw);
+}
+
+#if 0
+/**
+ * qt window has been closed
+ */
+void NS_Window::close_callback(Fl_Widget *w)
+{
+       browser_window_destroy(m_bw);
+}
+#endif
+
+/**
+ * set the status text
+ */
+void NS_Window::set_status(const char *text)
+{
+       //m_status->value(text);
+}
+
+
+/**
+ * set the window title text
+ */
+void NS_Window::set_title(const char *text)
+{
+       //label(text);
+}
+
+
+/**
+ * set the current position of the scroll bars
+ */
+nserror NS_Window::set_scroll(const struct rect *rect)
+{
+       //m_vscrollbar->value(rect->y0);
+       //m_hscrollbar->value(rect->x0);
+
+       //m_nswidget->vscroll_callback(m_vscrollbar);
+       //m_nswidget->hscroll_callback(m_hscrollbar);
+
+       return NSERROR_OK;
+}
+
+
+/**
+ * Set the extent of the underlying canvas
+ */
+nserror NS_Window::set_extent(int ew, int eh)
+{
+       //m_hscrollbar->value(0, w(), 0, ew);
+       //m_vscrollbar->value(0, h(), 0, eh);
+
+       return NSERROR_OK;
+}
+
+
+/* static methods */
+#if 0
+/**
+ * static window close qt callback which calls the instance
+ */
+void NS_Window::static_close_callback(Fl_Widget *w, void *f)
+{
+       ((NS_Window *)f)->close_callback(w);
+}
+
+/**
+ * static vertical scrollbar qt callback which calls the instance
+ */
+void NS_Window::static_vscroll_callback(Fl_Widget *w, void *f)
+{
+       ((NS_Widget *)f)->vscroll_callback((Fl_Scrollbar *)w);
+}
+
+/**
+ * static horizontal scrollbar qt callback which calls the instance
+ */
+void NS_Window::static_hscroll_callback(Fl_Widget *w, void *f)
+{
+       ((NS_Widget *)f)->hscroll_callback((Fl_Scrollbar *)w);
+}
+#endif
+
+/**
+ * Set the status bar message of a browser window.
+ *
+ * \param g gui_window to update
+ * \param text new status text
+ */
+void NS_Window::static_set_status(struct gui_window *gw, const char *text)
+{
+       ((NS_Window *)gw->window)->set_status(text);
+}
+
+
+/**
+ * Set the title of a window.
+ *
+ * \param gw The gui window to set title of.
+ * \param title new window title
+ */
+void NS_Window::static_set_title(struct gui_window *gw, const char *title)
+{
+       ((NS_Window *)gw->window)->set_title(title);
+}
+
+
+/**
+ * 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
+ */
+bool NS_Window::static_get_scroll(struct gui_window *gw, int *sx, int *sy)
+{
+       return gw->window->m_nswidget->get_scroll(sx, sy);
+}
+
+
+/**
+ * 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.
+ */
+nserror
+NS_Window::static_set_scroll(struct gui_window *gw, const struct rect *rect)
+{
+       return gw->window->set_scroll(rect);
+}
+
+
+/**
+ * Set the navigation url.
+ *
+ * \param gw window to update.
+ * \param url The url to use as icon.
+ */
+nserror NS_Window::static_set_url(struct gui_window *gw, struct nsurl *url)
+{
+       //return gw->window->m_nsurlbar->set_url(url);
+       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.
+ */
+nserror
+NS_Window::static_event(struct gui_window *gw, enum gui_window_event event)
+{
+       nserror res;
+
+       switch (event) {
+       case GW_EVENT_UPDATE_EXTENT:
+       {
+               int w, h;
+
+               res = browser_window_get_extents(gw->window->m_bw, true, &w, 
&h);
+               if (res == NSERROR_OK) {
+                       res = (gw->window)->set_extent(w, h);
+               }
+               break;
+       }
+       default:
+               res = NSERROR_OK;
+               break;
+       }
+       return res;
+}
+
+
+/**
+ * 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
+ */
+nserror
+NS_Window::static_invalidate(struct gui_window *gw, const struct rect *rect)
+{
+       return gw->window->m_nswidget->invalidate(rect);
+}
+
+
+/**
+ * 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.
+ */
+nserror
+NS_Window::static_get_dimensions(struct gui_window *gw, int *width, int 
*height)
+{
+       return gw->window->m_nswidget->get_dimensions(width, height);
+}
+
+
+/**
+ * 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.
+ */
+struct gui_window *
+NS_Window::static_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));
+
+       if (gw != NULL) {
+               gw->window = new NS_Window(nullptr, bw);
+
+               gw->window->show();
+       }
+
+       return gw;
+}
+
+/**
+ * Destroy previously created gui window
+ *
+ * \param gw The gui window to destroy.
+ */
+void NS_Window::static_destroy(struct gui_window *gw)
+{
+       delete gw->window;
+       free(gw);
+}
+
+
+/**
+ * window operations table for qt frontend
+ */
+static struct gui_window_table window_table = {
+       .create = NS_Window::static_create,
+       .destroy = NS_Window::static_destroy,
+       .invalidate = NS_Window::static_invalidate,
+       .get_scroll = NS_Window::static_get_scroll,
+       .set_scroll = NS_Window::static_set_scroll,
+       .get_dimensions = NS_Window::static_get_dimensions,
+       .event = NS_Window::static_event,
+       .set_title = NS_Window::static_set_title,
+       .set_url = NS_Window::static_set_url,
+       .set_icon = NULL,
+       .set_status = NS_Window::static_set_status,
+       .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 *nsqt_window_table = &window_table;
diff --git a/frontends/qt/window.h b/frontends/qt/window.h
new file mode 100644
index 0000000..17e4c5b
--- /dev/null
+++ b/frontends/qt/window.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2021 Vincent Sanders <[email protected]>
+ *
+ * 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_QT_WINDOW_H
+#define NETSURF_QT_WINDOW_H 1
+
+/**
+ * qt window (browser widget) operations table
+ */
+extern struct gui_window_table *nsqt_window_table;
+
+#endif


commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=1f5e7ce3c81314129e090cc07d71ed19538dcdc5
commit 1f5e7ce3c81314129e090cc07d71ed19538dcdc5
Author: Vincent Sanders <[email protected]>
Commit: Vincent Sanders <[email protected]>

    fix spelling errors in documentation

diff --git a/docs/implementing-new-frontend.md 
b/docs/implementing-new-frontend.md
index 4bda47a..24adfbb 100644
--- a/docs/implementing-new-frontend.md
+++ b/docs/implementing-new-frontend.md
@@ -54,14 +54,14 @@ cookie, bookmark, history windows which require only 
minimal frontend
 support with the [core window API](docs/core-window-interface.md).
 
 A frontend developer is free to implement any and all of this generic
-functionality thelselves in a manner more integrated into a toolkit.
+functionality themselves in a manner more integrated into a toolkit.
 
 # Implementation
 
 A frontend is generally named for the toolkit it is implementing (i.e
 gtk for the GTK+ toolkit). It is advisable to be as specific as
 possible e.g. the frontend for the windows operating system should
-have been named win32 allowing for an impementation using a differnt
+have been named win32 allowing for an implementation using a different
 toolkit (e.g mfc)
 
 All the files needed for the frontend are contained in a single
@@ -80,7 +80,7 @@ included from the core Makefile):
  - `Makefile.defaults` - allows setting frontend specific makefile variables 
and overriding of the default core build variables.
  - `Makefile.tools` - allows setting up frontend specific build tooling (as a 
minimum a tool for the package configuration in PKG_CONFIG)
  
-Source code modules can be named as the devloper desires within the
+Source code modules can be named as the developer desires within the
 frontend directory and should be added to the SOURCES variable as
 desired.
  
@@ -94,16 +94,16 @@ The usual shape for the `main()` function is a six step 
process:
  2. The toolkit specific initialisation is performed (which may involve 
calling NetSurf provided utility functions for support operations like logging, 
message translations etc.)
  3. Initialise the NetSurf core. After this point all browser functionality is 
available and registered operations can be called.
  4. Perform toolkiit setup, usually opening the initial browsing window 
(perhaps according to user preferences)
- 5. Run the toolkits main loop while ensuring the Netsurf scheduled operations 
are also run at teh apropriate time.
+ 5. Run the toolkits main loop while ensuring the NetSurf scheduled operations 
are also run at the appropriate time.
  6. Finalisation on completion.
 
 ## NetSurf operations tables
 
-The frontend will generally call netsurf interfaces to get a desired
+The frontend will generally call NetSurf interfaces to get a desired
 behaviour e.g. `browser_window_create()` to create a new browsing
 context (the `browser_window_` prefix is historical and does not
 necessarily create a window e.g. on gtk it is more likely to open a
-tab in an existing window). To achive the desired operation some
+tab in an existing window). To achieve the desired operation some
 operations need to be performed by the frontend under control of
 NetSurf, these operations are listed in tables.
 
@@ -113,22 +113,22 @@ tables (and the tables themselves) must remain valid until
 `netsurf_exit()` is called.
 
 There are (currently) twelve sets of operation tables held in separate
-structures. Only five of these are mandantory (misc, window, fetch,
+structures. Only five of these are mandatory (misc, window, fetch,
 bitmap and layout).
 
-In this context mandantory means the tables must be non NULL and do
-not have a suitable default. Each of the mandantory sets contain
+In this context mandatory means the tables must be non NULL and do
+not have a suitable default. Each of the mandatory sets contain
 function pointers to implement operations.
 
 ### misc operation table
 
-The only mandantory operation in this table is schedule.
+The only mandatory operation in this table is schedule.
 
 When schedule is called the frontend must arrange for the passed
 callback to be called with the context parameter after a number of
-miliseconds.
+milliseconds.
 
-This callback is typicaly driven through the toolkits event loop and
+This callback is typically driven through the toolkits event loop and
 it is important such callbacks are not attempted from an operation.
 
 ### window operation table
@@ -143,27 +143,27 @@ generally assumed to contain at least a reference to the 
underlying
 `browser_window` which is provided in the initial create operation to
 allow subsequent use of various core functionality.
 
-The mandantory window operations are:
+The mandatory window operations are:
  - create - create a new browsing context widget in the frontend toolkit
- - destroy - destoy a previously created `gui_window`
+ - destroy - destroy a previously created `gui_window`
  - invalidate - mark an area of the browsing context viewport as requiring 
redraw (note no redraw should be attempted from here)
  - get_scroll - get the scroll offsets from the toolkit drawing widget
  - set_scroll - set the scroll offsets on the toolkit drawing widget
  - get_dimensions - get the dimensions of the toolkit drawing widget
- - event - deal with various window events from netsurf which have no 
additional parameters
+ - event - deal with various window events from NetSurf which have no 
additional parameters
 
 
 ### fetch operation table
 
 The fetch operations allow the built in scheme fetchers (file, about, 
resource) to obtain additional information necessary to complete their 
operation.
 
-The two mandantory operations are:
+The two mandatory operations are:
  - `filetype` - allows the file scheme to obtain a mime type from a file path 
e.g. `a.file.name.png` would result in `image/png`
  - `get_resource_url` - maps resource scheme paths to URL e.g. 
`resource:default.css` to `file:///usr/share/netsurf/default.css`
 
 ### bitmap operation table
 
-The bitmap table and all of its operations are mandantory only because
+The bitmap table and all of its operations are mandatory only because
 the empty defaults have not been included as it is assumed a browser
 will want to display images.
 
@@ -173,7 +173,7 @@ until full implementations are made.
 ### layout operation table
 
 The layout table is used to layout text. All operations are given
-strings to manipulate encoded in UTF-8. There are three mandantory
+strings to manipulate encoded in UTF-8. There are three mandatory
 operations:
  - `width` - Calculate the width of a string.
  - `position` - Find the position in a string where an x coordinate falls.
@@ -184,7 +184,7 @@ operations:
 Rather than attempt to describe every aspect of an implementation we
 will rather work from an actual minimal example for the FLTK toolkit.
 
-This is availble as a single commit (`git show 
28ecbf82ed3024f51be4c87928fd91bacfc15cbc`) in the NetSurf source repository. 
Alternatively it can be [viewed in a web 
browser](https://git.netsurf-browser.org/netsurf.git/commit/?h=vince/fltk&id=28ecbf82ed3024f51be4c87928fd91bacfc15cbc).
+This is available as a single commit (`git show 
28ecbf82ed3024f51be4c87928fd91bacfc15cbc`) in the NetSurf source repository. 
Alternatively it can be [viewed in a web 
browser](https://git.netsurf-browser.org/netsurf.git/commit/?h=vince/fltk&id=28ecbf82ed3024f51be4c87928fd91bacfc15cbc).
 
 This represents the absolute minimum implementation to get a browser
 window on screen (and be able to click visible links). It is
@@ -201,13 +201,13 @@ As previously described the three GNU Make files are 
added:
 
 
[Makefile](https://git.netsurf-browser.org/netsurf.git/diff/frontends/fltk/Makefile?h=vince/fltk&id=28ecbf82ed3024f51be4c87928fd91bacfc15cbc)
 this shows how the flags are extended to add the fltk headers and
-library. Additionaly the list of sources are built here, as teh
+library. Additionally the list of sources are built here, as the
 comment suggests it is important the SOURCES variable is not expanded
-here so the S_FRONTEND variable is used to allow expansion at teh
+here so the S_FRONTEND variable is used to allow expansion at the
 correct time in the build process.
 
 
[Makefile.defaults](https://git.netsurf-browser.org/netsurf.git/diff/frontends/fltk/Makefile.defaults?h=vince/fltk&id=28ecbf82ed3024f51be4c87928fd91bacfc15cbc)
 
-has the default setting to control the build parameters and file locations. 
These can be overriden by the `Makefile.config` at compile time.
+has the default setting to control the build parameters and file locations. 
These can be overridden by the `Makefile.config` at compile time.
 
 
[Makefile.tools](https://git.netsurf-browser.org/netsurf.git/diff/frontends/fltk/Makefile.tools?h=vince/fltk&id=28ecbf82ed3024f51be4c87928fd91bacfc15cbc)
 allows the configuration of additional tools necessary to build for the target 
as a minimum pkg-config is usually required to find libraries.
@@ -224,21 +224,21 @@ The `netsurf_table` structure is initialised and passed to
 `netsurf_register()`. It should be noted that the approach taken here
 and in most frontends is to have a source module for each operation
 table. The header for each module exposes just the pointer to the
-indivial operation set, this allows for all the operation functions to
+individual operation set, this allows for all the operation functions to
 be static to their module and hence helps reduce global symbol usage.
 
 ### Frontend specific initialisation
 
 Her it is implemented in `nsfltk_init()` this function performs all
 the operations specific to the frontend which must be initialised
-before netsurf itself. In some toolkits this would require calling the
+before NetSurf itself. In some toolkits this would require calling the
 toolkit initialisation (e.g. `gtk_init()`).
 
-It is nessesary to initialise netsurf logging and user options at this
+It is necessary to initialise NetSurf logging and user options at this
 point. A more fully featured implementation would also initialise the
 message translation system here.
 
-### Netsurf initialisation
+### NetSurf initialisation
 
 This is simply the call to `netsurf_init()` from this point the
 browser is fully operational and operations can and will be called.
@@ -256,7 +256,7 @@ example here is a good start.
 
 ### Toolkit run loop
 
-The function `nsfltk_run()` runs the toolkit event loop. In this case it is 
using the generic scheduleing in the 
[misc.cpp](https://git.netsurf-browser.org/netsurf.git/diff/frontends/fltk/misc.cpp?h=vince/fltk&id=28ecbf82ed3024f51be4c87928fd91bacfc15cbc)
 module to ensure callbacks get made at the apropriate time.
+The function `nsfltk_run()` runs the toolkit event loop. In this case it is 
using the generic scheduling in the 
[misc.cpp](https://git.netsurf-browser.org/netsurf.git/diff/frontends/fltk/misc.cpp?h=vince/fltk&id=28ecbf82ed3024f51be4c87928fd91bacfc15cbc)
 module to ensure callbacks get made at the appropriate time.
 
 There is a `nsfltk_done` boolean global checked here so when all the
 browser windows are closed the program will exit.
@@ -265,7 +265,7 @@ A more fully featured port might use the toolkits 
scheduling rather
 than open coding a solution with a linked list as is done
 here.
 
-A futher optimisation would be to obtain the set of file descriptors
+A further optimisation would be to obtain the set of file descriptors
 being used (with `fetch_fdset()`) for active fetches allowing for
 activity based fetch progress instead of the fallback polling method.
 
@@ -276,7 +276,7 @@ up any resource usage. After the call to `netsurf_exit()` 
no more
 operation calls will be made and all caches used by the core will be
 flushed.
 
-If user option chnages are to be made persistant `nsoption_finalise()`
+If user option changes are to be made persistent `nsoption_finalise()`
 should be called.
 
 The finalisation of logging will ensure that any output buffers are
@@ -293,7 +293,7 @@ references it in the gui_window structure which it returns 
to the
 caller. Technically we could simply return the `NS_Window` object as
 the gui_window pointer but this implementation is avoiding the cast.
 
-Secondly `Fl_Double_Window` is subclassed as `NS_Widget`. The sublass
+Secondly `Fl_Double_Window` is subclassed as `NS_Widget`. The subclass
 allows the close callback to be accessed so the global `nsfltk_done`
 boolean can be set during the destructor method.
 
@@ -303,11 +303,11 @@ more extensive implementation would add other window 
furniture here
 
 The implementation subclasses `Fl_Widget` implementing the draw
 method to render the browsing context and the handle method to handle
-mouse events to allow teh user to click.
+mouse events to allow the user to click.
 
 The `NS_Widget::handle()` method simply translates the mouse press
-event from widget coordinates to netsurf canvas cooridinates and maps
-teh mouse button state. The core is informed of these events using
+event from widget coordinates to NetSurf canvas coordinates and maps
+the mouse button state. The core is informed of these events using
 `browser_window_mouse_click()`
 
 The `NS_Widget::draw` method similarly translates the fltk toolkits
@@ -317,7 +317,7 @@ the plotting context to render the browsing context within 
the area
 specified. One thing to note here is the translation between the
 coordinates of the render area and the internal page canvas given as
 the second and third parameters to the draw call. When scrolling is
-required this is achived by altering these offsets.
+required this is achieved by altering these offsets.
 
 
 ### `nsfltk_window_invalidate()`
@@ -343,7 +343,7 @@ colour and performs the appropriate fltk draw function 
(`fl_line`,
 # Worked Example next steps
 
 The previous section outlined the absolute minimum
-implementation. Here we can exmaine some next steps taken to extend
+implementation. Here we can examine some next steps taken to extend
 the frontend.
 
 ## Improving the user interface
@@ -397,17 +397,17 @@ perceived functionality.
 
 The [core window interface](docs/core-window-interface.md) allows a
 frontend to use inbuilt rendering for several interfaces gaining a
-great deal of functionality for very litte code. This one interface
+great deal of functionality for very little code. This one interface
 set gives a cookie viewer,a local and global history viewer and a
 hotlist(bookmarks) viewer.
 
 # Conclusion
 
-Hopefully this breif overview and worked example should give the
-prospectinve frontend developer enough information to understand how
+Hopefully this brief overview and worked example should give the
+prospective frontend developer enough information to understand how
 to get started implementing a new frontend toolkit for NetSurf.
 
-As can be seen there is actualy very little novel code necessary to
+As can be seen there is actually very little novel code necessary to
 get started though I should mention that the move from "minimal" to
 "full" implementation is a large undertaking and it would be wise to
 talk with the NetSurf developers if undertaking such work.


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


-- 
NetSurf Browser
_______________________________________________
netsurf-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to