summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAshish Gupta <ashmew2@gmail.com>2017-04-05 19:39:01 (GMT)
committer Ashish Gupta <ashmew2@gmail.com>2017-09-12 17:55:02 (GMT)
commit4eec01ed36e64d085935f136d2b950f89d34c6f6 (patch)
treeefab3ef439b35fafe94b13716f4ea2871a381c8e
parent0a6e8fc0b072da21c7ec9c8d602b7ffad6bd4100 (diff)
downloadnetsurf-4eec01ed36e64d085935f136d2b950f89d34c6f6.tar.gz
netsurf-4eec01ed36e64d085935f136d2b950f89d34c6f6.tar.bz2
Add kolibrios/ dir : Step 1 towards porting this to Kolibri OS
-rw-r--r--frontends/kolibrios/#main.c#331
-rw-r--r--frontends/kolibrios/.svn/entries1
-rw-r--r--frontends/kolibrios/.svn/format1
-rw-r--r--frontends/kolibrios/.svn/wc.dbbin0 -> 35840 bytes
-rw-r--r--frontends/kolibrios/Makefile156
-rw-r--r--frontends/kolibrios/Makefile.defaults41
-rw-r--r--frontends/kolibrios/bitmap_table.h96
-rw-r--r--frontends/kolibrios/browser_table.h57
-rw-r--r--frontends/kolibrios/clipboard_table.h20
-rw-r--r--frontends/kolibrios/convert_image.c315
-rw-r--r--frontends/kolibrios/download_table.h34
-rw-r--r--frontends/kolibrios/fb/Makefile184
-rw-r--r--frontends/kolibrios/fb/Makefile.defaults51
-rw-r--r--frontends/kolibrios/fb/bitmap.c352
-rw-r--r--frontends/kolibrios/fb/bitmap.h26
-rw-r--r--frontends/kolibrios/fb/clipboard.c105
-rw-r--r--frontends/kolibrios/fb/clipboard.h24
-rw-r--r--frontends/kolibrios/fb/convert_font.c1215
-rw-r--r--frontends/kolibrios/fb/convert_image.c304
-rw-r--r--frontends/kolibrios/fb/fb_search.c74
-rw-r--r--frontends/kolibrios/fb/fbtk.h618
-rw-r--r--frontends/kolibrios/fb/fbtk/bitmap.c136
-rw-r--r--frontends/kolibrios/fb/fbtk/event.c349
-rw-r--r--frontends/kolibrios/fb/fbtk/fbtk.c830
-rw-r--r--frontends/kolibrios/fb/fbtk/fill.c81
-rw-r--r--frontends/kolibrios/fb/fbtk/osk.c199
-rw-r--r--frontends/kolibrios/fb/fbtk/scroll.c589
-rw-r--r--frontends/kolibrios/fb/fbtk/text.c654
-rw-r--r--frontends/kolibrios/fb/fbtk/user.c63
-rw-r--r--frontends/kolibrios/fb/fbtk/widget.h259
-rw-r--r--frontends/kolibrios/fb/fbtk/window.c91
-rw-r--r--frontends/kolibrios/fb/fetch.c100
-rw-r--r--frontends/kolibrios/fb/fetch.h25
-rw-r--r--frontends/kolibrios/fb/findfile.c56
-rw-r--r--frontends/kolibrios/fb/findfile.h32
-rw-r--r--frontends/kolibrios/fb/font.h68
-rw-r--r--frontends/kolibrios/fb/font_freetype.c566
-rw-r--r--frontends/kolibrios/fb/font_freetype.h30
-rw-r--r--frontends/kolibrios/fb/font_internal.c492
-rw-r--r--frontends/kolibrios/fb/font_internal.h49
-rw-r--r--frontends/kolibrios/fb/framebuffer.c651
-rw-r--r--frontends/kolibrios/fb/framebuffer.h40
-rw-r--r--frontends/kolibrios/fb/gui.c2226
-rw-r--r--frontends/kolibrios/fb/gui.h84
-rw-r--r--frontends/kolibrios/fb/image_data.h60
-rw-r--r--frontends/kolibrios/fb/localhistory.c144
-rw-r--r--frontends/kolibrios/fb/options.h70
-rw-r--r--frontends/kolibrios/fb/schedule.c254
-rw-r--r--frontends/kolibrios/fb/schedule.h45
-rw-r--r--frontends/kolibrios/gui_fetch_table.h42
-rw-r--r--frontends/kolibrios/gui_file_table.h37
-rw-r--r--frontends/kolibrios/gui_llcache_table.h49
-rw-r--r--frontends/kolibrios/gui_search_table.h38
-rw-r--r--frontends/kolibrios/gui_search_web_table.h11
-rw-r--r--frontends/kolibrios/gui_utf8_table.h18
-rw-r--r--frontends/kolibrios/kolibri_boxlib.h18
-rw-r--r--frontends/kolibrios/kolibri_button.h46
-rw-r--r--frontends/kolibrios/kolibri_checkbox.h43
-rw-r--r--frontends/kolibrios/kolibri_colors.h28
-rw-r--r--frontends/kolibrios/kolibri_debug.c28
-rw-r--r--frontends/kolibrios/kolibri_debug.h11
-rw-r--r--frontends/kolibrios/kolibri_debug.obin0 -> 717056 bytes
-rw-r--r--frontends/kolibrios/kolibri_editbox.h90
-rw-r--r--frontends/kolibrios/kolibri_filebrowser.h4
-rw-r--r--frontends/kolibrios/kolibri_filesystem.c45
-rw-r--r--frontends/kolibrios/kolibri_filesystem.h22
-rw-r--r--frontends/kolibrios/kolibri_gui.h130
-rw-r--r--frontends/kolibrios/kolibri_gui_elements.h126
-rw-r--r--frontends/kolibrios/kolibri_http.c36
-rw-r--r--frontends/kolibrios/kolibri_http.h81
-rw-r--r--frontends/kolibrios/kolibri_iconv.c12
-rw-r--r--frontends/kolibrios/kolibri_misc.c27
-rw-r--r--frontends/kolibrios/kolibri_misc.obin0 -> 505 bytes
-rw-r--r--frontends/kolibrios/kolibri_regex.c24
-rw-r--r--frontends/kolibrios/kos32sys.h557
-rw-r--r--frontends/kolibrios/loadboxlib.asm135
-rw-r--r--frontends/kolibrios/loadboxlib.objbin0 -> 1075 bytes
-rw-r--r--frontends/kolibrios/loadhttp.asm64
-rw-r--r--frontends/kolibrios/loadhttp.objbin0 -> 1254 bytes
-rw-r--r--frontends/kolibrios/main.c314
-rw-r--r--frontends/kolibrios/options.h70
l---------frontends/kolibrios/res/Messages1
l---------frontends/kolibrios/res/adblock.css1
l---------frontends/kolibrios/res/credits.html1
l---------frontends/kolibrios/res/default.css1
l---------frontends/kolibrios/res/favicon.png1
-rw-r--r--frontends/kolibrios/res/fonts/glyph_data9508
-rw-r--r--frontends/kolibrios/res/icons/back.pngbin0 -> 741 bytes
-rw-r--r--frontends/kolibrios/res/icons/back_g.pngbin0 -> 701 bytes
-rw-r--r--frontends/kolibrios/res/icons/forward.pngbin0 -> 672 bytes
-rw-r--r--frontends/kolibrios/res/icons/forward_g.pngbin0 -> 702 bytes
-rw-r--r--frontends/kolibrios/res/icons/history.pngbin0 -> 884 bytes
-rw-r--r--frontends/kolibrios/res/icons/history_g.pngbin0 -> 798 bytes
-rw-r--r--frontends/kolibrios/res/icons/home.pngbin0 -> 818 bytes
-rw-r--r--frontends/kolibrios/res/icons/home_g.pngbin0 -> 798 bytes
-rw-r--r--frontends/kolibrios/res/icons/osk.pngbin0 -> 262 bytes
-rw-r--r--frontends/kolibrios/res/icons/reload.pngbin0 -> 1075 bytes
-rw-r--r--frontends/kolibrios/res/icons/reload_g.pngbin0 -> 1109 bytes
-rw-r--r--frontends/kolibrios/res/icons/scrolld.pngbin0 -> 294 bytes
-rw-r--r--frontends/kolibrios/res/icons/scrolll.pngbin0 -> 307 bytes
-rw-r--r--frontends/kolibrios/res/icons/scrollr.pngbin0 -> 286 bytes
-rw-r--r--frontends/kolibrios/res/icons/scrollu.pngbin0 -> 280 bytes
-rw-r--r--frontends/kolibrios/res/icons/stop.pngbin0 -> 1023 bytes
-rw-r--r--frontends/kolibrios/res/icons/stop_g.pngbin0 -> 1050 bytes
l---------frontends/kolibrios/res/internal.css1
l---------frontends/kolibrios/res/licence.html1
l---------frontends/kolibrios/res/maps.html1
l---------frontends/kolibrios/res/netsurf.png1
-rw-r--r--frontends/kolibrios/res/pointers/caret.pngbin0 -> 146 bytes
-rw-r--r--frontends/kolibrios/res/pointers/cross.pngbin0 -> 144 bytes
-rw-r--r--frontends/kolibrios/res/pointers/default.pngbin0 -> 179 bytes
-rw-r--r--frontends/kolibrios/res/pointers/help.pngbin0 -> 209 bytes
-rw-r--r--frontends/kolibrios/res/pointers/left-right.pngbin0 -> 163 bytes
-rw-r--r--frontends/kolibrios/res/pointers/lu-rd.pngbin0 -> 170 bytes
-rw-r--r--frontends/kolibrios/res/pointers/menu.pngbin0 -> 220 bytes
-rw-r--r--frontends/kolibrios/res/pointers/move.pngbin0 -> 183 bytes
-rw-r--r--frontends/kolibrios/res/pointers/no_drop.pngbin0 -> 224 bytes
-rw-r--r--frontends/kolibrios/res/pointers/not_allowed.pngbin0 -> 197 bytes
-rw-r--r--frontends/kolibrios/res/pointers/point.pngbin0 -> 181 bytes
-rw-r--r--frontends/kolibrios/res/pointers/progress.pngbin0 -> 213 bytes
-rw-r--r--frontends/kolibrios/res/pointers/ru-ld.pngbin0 -> 171 bytes
-rw-r--r--frontends/kolibrios/res/pointers/up-down.pngbin0 -> 167 bytes
-rw-r--r--frontends/kolibrios/res/pointers/wait.pngbin0 -> 211 bytes
l---------frontends/kolibrios/res/quirks.css1
l---------frontends/kolibrios/res/throbber1
l---------frontends/kolibrios/res/welcome.html1
-rw-r--r--frontends/kolibrios/window_table.h126
127 files changed, 24000 insertions, 0 deletions
diff --git a/frontends/kolibrios/#main.c# b/frontends/kolibrios/#main.c#
new file mode 100644
index 0000000..b65f2c4
--- a/dev/null
+++ b/frontends/kolibrios/#main.c#
@@ -0,0 +1,331 @@
+#include <stdbool.h>
+#include <sys/types.h>
+
+#include "kolibrios/kolibri_debug.h"
+#include "kolibrios/kolibri_gui.h"
+
+#include "utils/errors.h"
+
+#include "utils/messages.h"
+#include "utils/filepath.h"
+#include "utils/nsoption.h"
+#include "utils/nsurl.h"
+
+#include "desktop/gui_table.h" /* netsurf_table struct */
+#include "desktop/gui_misc.h" /* gui_browser_table struct */
+#include "desktop/gui_window.h" /* gui_window_table struct */
+#include "desktop/netsurf.h" /* for netsurf_register */
+#include "image/bitmap.h" /* for gui_bitmap_table struct */
+#include "desktop/gui_clipboard.h" /* gui_clipboard_table struct */
+#include "desktop/gui_download.h" /* gui_download_table struct */
+#include "desktop/gui_fetch.h" /* gui_fetch_table struct */
+#include "desktop/browser.h"
+
+#include "utils/file.h" /* gui_file_table struct */
+#include "desktop/gui_utf8.h" /* gui_utf8_table struct */
+#include "desktop/gui_search.h" /* gui_search_table struct */
+#include "desktop/searchweb.h" /* gui_search_web_table struct */
+#include "content/backing_store.h" /* gui_llcache_table struct */
+
+/* #include "kolibrios/browser_table.h" */
+/* #include "kolibrios/window_table.h" */
+/* #include "kolibrios/download_table.h" */
+/* #include "kolibrios/clipboard_table.h" */
+/* #include "kolibrios/gui_fetch_table.h" */
+/* #include "kolibrios/bitmap_table.h" */
+/* #include "kolibrios/gui_file_table.h" */
+/* #include "kolibrios/gui_llcache_table.h" */
+/* #include "kolibrios/gui_search_table.h" */
+/* #include "kolibrios/gui_search_web_table.h" */
+/* #include "kolibrios/gui_utf8_table.h" */
+
+#include "kolibrios/kolibri_http.h"
+#include <libnsfb.h>
+#include <libnsfb_plot.h>
+#include <libnsfb_event.h>
+#include <libnsfb_surface.h>
+
+#include "utils/utils.h"
+#include "utils/nsoption.h"
+#include "utils/filepath.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "desktop/browser.h"
+#include "desktop/textinput.h"
+#include "desktop/browser_history.h"
+#include "desktop/plotters.h"
+#include "desktop/gui_window.h"
+#include "desktop/gui_misc.h"
+#include "desktop/netsurf.h"
+
+#include "framebuffer/gui.h"
+#include "framebuffer/fbtk.h"
+#include "framebuffer/framebuffer.h"
+#include "framebuffer/schedule.h"
+#include "framebuffer/findfile.h"
+#include "framebuffer/image_data.h"
+#include "framebuffer/font.h"
+#include "framebuffer/clipboard.h"
+#include "framebuffer/fetch.h"
+#include "framebuffer/bitmap.h"
+
+/**************************************************
+Make life easier with these path specifiers here.
+***************************************************/
+/* #define KOLIBRI_FONTFILE "/usbhd0/1/kolibrios/res/sans.ttf" */
+/* #define KOLIBRI_RESPATH "/usbhd0/1/kolibrios/res/" */
+/* #define FILE_KOLIBRI_RESPATH "file:///usbhd0/1/kolibrios/res/" */
+/************************************************/
+
+char **respaths; /** resource search path vector */
+
+extern struct gui_browser_table framebuffer_browser_table;
+extern struct gui_window_table framebuffer_window_table ;
+extern struct gui_clipboard_table *framebuffer_clipboard_table ;
+extern struct gui_fetch_table *framebuffer_fetch_table ;
+extern struct gui_utf8_table *framebuffer_utf8_table ;
+extern struct gui_bitmap_table *framebuffer_bitmap_table ;
+
+extern const char *fename;
+extern int febpp;
+extern int fewidth;
+extern int feheight;
+extern const char *feurl;
+extern bool nslog_stream_configure(FILE *fptr);
+extern struct fbtk_bitmap pointer_image;
+extern fbtk_widget_t *fbtk;
+
+static void die(const char *error)
+{
+ debug_board_write_str(error);
+ debug_board_write_str('\n');
+ exit(1);
+}
+
+/* Inspired from monkey, but without the GTK bloat */
+static char **nskolibri_init_resource(const char *resource_path)
+{
+ char **langv = {"de", "en_US", "en", "C"};
+ char **pathv; /* resource path string vector */
+ char **respath; /* resource paths vector */
+
+ pathv = filepath_path_to_strvec(resource_path);
+ respath = filepath_generate(pathv, langv);
+ filepath_free_strvec(pathv);
+
+ return respath;
+}
+
+static nserror set_defaults(struct nsoption_s *defaults)
+{
+ /* Set defaults for absent option strings */
+ nsoption_setnull_charp(cookie_file, *respaths);
+ nsoption_setnull_charp(cookie_jar, *respaths);
+ //TODO: This creates an nsoptions error in macro expansion...
+
+ return NSERROR_OK;
+}
+
+/**
+ * Main entry point from Kolibri OS.
+ */
+extern struct http_msg;
+
+int
+main(int argc, char** argv)
+{
+ struct browser_window *bw;
+ char *options;
+ char *messages;
+ nsurl *url;
+ nserror ret;
+ nsfb_t *nsfb;
+
+ struct netsurf_table framebuffer_table = {
+ .browser = &framebuffer_browser_table,
+ .window = &framebuffer_window_table,
+ .clipboard = framebuffer_clipboard_table,
+ .fetch = framebuffer_fetch_table,
+ .utf8 = framebuffer_utf8_table,
+ .bitmap = framebuffer_bitmap_table,
+ };
+
+
+
+ /* Initialize HTTP Library */
+ ret = kolibri_http_init();
+ if (ret == 0)
+ debug_board_write_str("Netsurf: KolibriOS HTTP Library Initialized.\n");
+ else {
+ debug_board_write_str("Netsurf: HTTP Library initialization failed..\n");
+ return ret;
+ }
+
+ /* Initialize BoxLib Library for GUI textboxes, etc */
+ ret = kolibri_gui_init();
+ if (ret == 0)
+ debug_board_write_str("Netsurf: KolibriOS BOXLIB Library Initialized.\n");
+ else {
+ debug_board_write_str("Netsurf: BOXLIB Library initialization failed..\n");
+ return ret;
+ }
+
+ /* End of KolibriOS specific libraries initialization phase */
+ debug_board_write_str("Netsurf: Trying to register nskolibri_table.\n");
+
+ ret = netsurf_register(&framebuffer_table);
+ if (ret != NSERROR_OK) {
+ die("NetSurf operation table failed registration");
+ }
+
+ /* Drop the last slash if caller provided it. */
+
+ char current_dir[100];
+ int i = 0;
+
+ for(i = strlen(argv[0]); i>=0; i--)
+ {
+ if(argv[0][i]=='/') {
+ strncpy(current_dir, argv[0], i+1);
+ i++;
+ current_dir[i++] = 'r';
+ current_dir[i++] = 'e';
+ current_dir[i++] = 's';
+ current_dir[i++] = '\0';
+ break;
+ }
+ }
+
+
+ respaths = (char **) malloc(sizeof(char **));
+ *respaths = malloc(i);
+ strcpy(*respaths, current_dir);
+
+ debug_board_write_str("\nCWD: ");
+ debug_board_write_str(*respaths);
+ debug_board_write_str("\n");
+
+ /* __asm__ __volatile__("int3"); */
+
+ /* initialise logging. Not fatal if it fails but not much we
+ * can do about it either.
+ */
+ nslog_init(nslog_stream_configure, &argc, argv);
+
+ /* user options setup */
+ ret = nsoption_init(set_defaults, &nsoptions, &nsoptions_default);
+ if (ret != NSERROR_OK) {
+ die("Options failed to initialise");
+ }
+ options = filepath_find(respaths, "Choices");
+ nsoption_read(options, nsoptions);
+ free(options);
+ nsoption_commandline(&argc, argv, nsoptions);
+
+ /* message init */
+ messages = filepath_find(respaths, "Messages");
+ ret = messages_add_from_file(messages);
+ free(messages);
+ if (ret != NSERROR_OK) {
+ debug_board_write_str("Message translations failed to load\n");
+ }
+
+ /* common initialisation */
+ ret = netsurf_init(NULL);
+ if (ret != NSERROR_OK) {
+ die("NetSurf failed to initialise");
+ }
+
+ /* Override, since we have no support for non-core SELECT menu */
+ nsoption_set_bool(core_select_menu, true);
+ /* Do we really need to parse command line in KolibriOS?
+ Most users will use the GUI to trigger NS .
+ TODO: Look at this later.
+ */
+
+ /* if (process_cmdline(argc,argv) != true) */
+ /* die("unable to process command line.\n"); */
+
+ /* Move the initialization stuff from process_cmdline() to here */
+ /* fename = "sdl"; */
+
+ extern nsfb_surface_rtns_t kolibri_rtns;
+ _nsfb_register_surface(NSFB_SURFACE_KOLIBRI, &kolibri_rtns, "kolibri");
+
+ extern nsfb_surface_rtns_t ram_rtns;
+ _nsfb_register_surface(NSFB_SURFACE_RAM, &ram_rtns, "ram");
+
+ /* fewidth = nsoption_int(window_width); */
+ /* if (fewidth <= 0) { */
+ /* fewidth = 800; */
+ /* } */
+
+ /* feheight = nsoption_int(window_height); */
+ /* if (feheight <= 0) { */
+ /* feheight = 600; */
+ /* } */
+
+ fename = "kolibri";
+ febpp = 32;
+ fewidth = 800;
+ feheight = 600;
+
+ // feurl = "board.kolibrios.org/ucp.php?i=pm&mode=compose";
+ feurl = "ashmew2.me";
+ /* feurl = "kolibrios.org"; */
+ /* feurl = "file://usbhd0/1/kolibrios/res/welcome.html"; */
+ nsfb = framebuffer_initialise(fename, fewidth, feheight, febpp);
+ if (nsfb == NULL)
+ die("Unable to initialise framebuffer");
+
+ framebuffer_set_cursor(&pointer_image);
+
+ if (fb_font_init() == false)
+ die("Unable to initialise the font system");
+
+ fbtk = fbtk_init(nsfb);
+
+ fbtk_enable_oskb(fbtk);
+
+ urldb_load_cookies(nsoption_charp(cookie_file));
+
+ /* create an initial browser window */
+
+ debug_board_write_str("calling browser_window_create\n");
+
+ ret = nsurl_create(feurl, &url);
+ if (ret == NSERROR_OK) {
+ ret = browser_window_create(BW_CREATE_HISTORY,
+ url,
+ NULL,
+ NULL,
+ &bw);
+ nsurl_unref(url);
+ }
+
+ if (ret != NSERROR_OK) {
+ warn_user(messages_get_errorcode(ret), 0);
+ } else {
+ debug_board_write_str("calling framebuffer run\n");
+
+ framebuffer_run();
+
+ debug_board_write_str("framebuffer run returned. \n");
+
+ debug_board_write_str("Killing browser window.\n");
+ browser_window_destroy(bw);
+ }
+
+ debug_board_write_str("Calling netsurf_exit()\n");
+ netsurf_exit();
+
+ if (fb_font_finalise() == false)
+ LOG("Font finalisation failed.");
+
+ /* finalise options */
+ nsoption_finalise(nsoptions, nsoptions_default);
+
+ free(*respaths);
+ free(respaths);
+ return 0;
+}
diff --git a/frontends/kolibrios/.svn/entries b/frontends/kolibrios/.svn/entries
new file mode 100644
index 0000000..48082f7
--- a/dev/null
+++ b/frontends/kolibrios/.svn/entries
@@ -0,0 +1 @@
+12
diff --git a/frontends/kolibrios/.svn/format b/frontends/kolibrios/.svn/format
new file mode 100644
index 0000000..48082f7
--- a/dev/null
+++ b/frontends/kolibrios/.svn/format
@@ -0,0 +1 @@
+12
diff --git a/frontends/kolibrios/.svn/wc.db b/frontends/kolibrios/.svn/wc.db
new file mode 100644
index 0000000..e9efbf1
--- a/dev/null
+++ b/frontends/kolibrios/.svn/wc.db
Binary files differ
diff --git a/frontends/kolibrios/Makefile b/frontends/kolibrios/Makefile
new file mode 100644
index 0000000..ad86c43
--- a/dev/null
+++ b/frontends/kolibrios/Makefile
@@ -0,0 +1,156 @@
+CWARNFLAGS += -Wno-error -Wno-redundant-decls -Wno-char-subscripts -Wno-undef
+CDMACROS := -D_BSD_SOURCE -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200809L -D_NETBSD_SOURCE
+KOL_LIBC_INCLUDES := -I$(HOME)/kolibrios/contrib/sdk/sources/newlib/libc/include/
+KOL_OTHER_INCLUDES := -I$(HOME)/kolibrios/contrib/sdk/sources/libpng/ -I$(HOME)/kolibrios/contrib/sdk/sources/zlib -I$(HOME)/kolibrios/contrib/sdk/sources/freetype/include -I$(HOME)/kolibrios/contrib/sdk/sources/freetype/include -I$(HOME)/dev-netsurf/workspace/netsurf/libiconv/libiconv-1.14 -I$(HOME)/dev-netsurf/workspace/netsurf/libjpeg
+
+CFLAGS += -fno-ident -fomit-frame-pointer $(KOL_LIBC_INCLUDES) $(KOL_OTHER_INCLUDES) -std=c99 -g
+
+CFLAGS += '-DNETSURF_KOLIBRI_FONTPATH="$(NETSURF_KOLIBRI_FONTPATH)"'
+CFLAGS += '-DNETSURF_KOLIBRI_FONT_SANS_SERIF="$(NETSURF_KOLIBRI_FONT_SANS_SERIF)"'
+CFLAGS += '-DKOLIBRIOS_RESPATH="$(NETSURF_KOLIBRIOS_RESOURCES)"'
+CFLAGS += '-DKOLIBRI_USE_FREETYPE'
+
+##########################################################################
+# Only for FB compat with kolibri. Get rid soon.
+CFLAGS += '-DNETSURF_FB_RESPATH="$(NETSURF_FB_RESPATH)"'
+# compile time font locations
+CFLAGS += '-DNETSURF_FB_FONTPATH="$(NETSURF_FB_FONTPATH)"'
+CFLAGS += '-DNETSURF_FB_FONT_SANS_SERIF="$(NETSURF_KOLIBRI_FONT_SANS_SERIF)"'
+CFLAGS += '-DNETSURF_FB_FONT_SANS_SERIF_BOLD="$(NETSURF_KOLIBRI_FONT_SANS_SERIF)"'
+CFLAGS += '-DNETSURF_FB_FONT_SANS_SERIF_ITALIC="$(NETSURF_KOLIBRI_FONT_SANS_SERIF)"'
+CFLAGS += '-DNETSURF_FB_FONT_SANS_SERIF_ITALIC_BOLD="$(NETSURF_KOLIBRI_FONT_SANS_SERIF)"'
+CFLAGS += '-DNETSURF_FB_FONT_SERIF="$(NETSURF_KOLIBRI_FONT_SANS_SERIF)"'
+CFLAGS += '-DNETSURF_FB_FONT_SERIF_BOLD="$(NETSURF_KOLIBRI_FONT_SANS_SERIF)"'
+CFLAGS += '-DNETSURF_FB_FONT_MONOSPACE="$(NETSURF_KOLIBRI_FONT_SANS_SERIF)"'
+CFLAGS += '-DNETSURF_FB_FONT_MONOSPACE_BOLD="$(NETSURF_KOLIBRI_FONT_SANS_SERIF)"'
+CFLAGS += '-DNETSURF_FB_FONT_CURSIVE="$(NETSURF_KOLIBRI_FONT_SANS_SERIF)"'
+CFLAGS += '-DNETSURF_FB_FONT_FANTASY="$(NETSURF_KOLIBRI_FONT_SANS_SERIF)"'
+
+
+#########################################################################
+
+KOLIBRI_IMAGE_left_arrow := icons/back.png
+KOLIBRI_IMAGE_right_arrow := icons/forward.png
+KOLIBRI_IMAGE_reload := icons/reload.png
+KOLIBRI_IMAGE_stop_image := icons/stop.png
+KOLIBRI_IMAGE_history_image := icons/history.png
+
+KOLIBRI_IMAGE_left_arrow_g := icons/back_g.png
+KOLIBRI_IMAGE_right_arrow_g := icons/forward_g.png
+KOLIBRI_IMAGE_reload_g := icons/reload_g.png
+KOLIBRI_IMAGE_stop_image_g := icons/stop_g.png
+KOLIBRI_IMAGE_history_image_g := icons/history_g.png
+
+KOLIBRI_IMAGE_scrolll := icons/scrolll.png
+KOLIBRI_IMAGE_scrollr := icons/scrollr.png
+KOLIBRI_IMAGE_scrollu := icons/scrollu.png
+KOLIBRI_IMAGE_scrolld := icons/scrolld.png
+
+KOLIBRI_IMAGE_osk_image := icons/osk.png
+
+KOLIBRI_IMAGE_pointer_image := pointers/default.png
+KOLIBRI_IMAGE_hand_image := pointers/point.png
+KOLIBRI_IMAGE_caret_image := pointers/caret.png
+KOLIBRI_IMAGE_menu_image := pointers/menu.png
+KOLIBRI_IMAGE_progress_image := pointers/progress.png
+KOLIBRI_IMAGE_move_image := pointers/move.png
+
+KOLIBRI_IMAGE_throbber0 := throbber/throbber0.png
+KOLIBRI_IMAGE_throbber1 := throbber/throbber1.png
+KOLIBRI_IMAGE_throbber2 := throbber/throbber2.png
+KOLIBRI_IMAGE_throbber3 := throbber/throbber3.png
+KOLIBRI_IMAGE_throbber4 := throbber/throbber4.png
+KOLIBRI_IMAGE_throbber5 := throbber/throbber5.png
+KOLIBRI_IMAGE_throbber6 := throbber/throbber6.png
+KOLIBRI_IMAGE_throbber7 := throbber/throbber7.png
+KOLIBRI_IMAGE_throbber8 := throbber/throbber8.png
+
+# Host tool to convert image bitmaps to source code.
+#
+# convert_image depends on fb_bitmap.h so that if we change that
+# header, we get new images built.
+
+HOST_LDFLAGS += -lpng
+$(TOOLROOT)/convert_image: $(TOOLROOT)/created $(FRONTEND_SOURCE_DIR)/fb/convert_image.c
+ $(VQ)echo " HOST CC: $@"
+ $(Q)$(HOST_CC) $(HOST_CFLAGS) -o $@ $(FRONTEND_SOURCE_DIR)/fb/convert_image.c $(HOST_LDFLAGS)
+
+# 1: input file
+# 2: output file
+# 3: bitmap name
+
+define convert_image
+
+S_IMAGES += $(2)
+
+$(2): $(1) $(TOOLROOT)/convert_image
+ $(Q)$(TOOLROOT)/convert_image $(1) $(2) $(3)
+endef
+
+S_IMAGES :=
+
+$(eval $(foreach V,$(filter KOLIBRI_IMAGE_%,$(.VARIABLES)),$(call convert_image,$($(V)),$(OBJROOT)/image-$(patsubst KOLIBRI_IMAGE_%,%,$(V)).c,$(patsubst KOLIBRI_IMAGE_%,%,$(V)))))
+$(warning eval $(foreach V,$(filter KOLIBRI_IMAGE_%,$(.VARIABLES)),$(call convert_image,$($(V)),$(OBJROOT)/image-$(patsubst KOLIBRI_IMAGE_%,%,$(V)).c,$(patsubst KOLIBRI_IMAGE_%,%,$(V)))))
+$(error fuck this)
+
+# Internal fonts to generate
+KOLIBRI_FONT_internal_ns-sans := framebuffer/res/fonts/glyph_data
+
+# Internal font conversion
+$(TOOLROOT)/convert_font: $(TOOLROOT)/created framebuffer/convert_font.c
+ $(VQ)echo " HOST CC: $@"
+ $(Q)$(HOST_CC) -o $@ framebuffer/convert_font.c
+
+# 1: input file
+# 2: output source code file
+# 3: output header file
+# 4: font name
+define convert_font
+
+S_FONTS += $(2)
+
+$(2): $(1) $(TOOLROOT)/convert_font
+ $(VQ)echo " FONT: $(1) ($(4))"
+ $(Q)$(TOOLROOT)/convert_font -H $(3) $(1) $(2)
+
+endef
+
+S_FONTS :=
+
+$(eval $(foreach V,$(filter KOLIBRI_FONT_$(NETSURF_KOLIBRI_FONTLIB)_%,$(.VARIABLES)),$(call convert_font,$($(V)),$(OBJROOT)/font-$(patsubst KOLIBRI_FONT_$(NETSURF_KOLIBRI_FONTLIB)_%,%,$(V)).c,$(OBJROOT)/font-$(patsubst KOLIBRI_FONT_$(NETSURF_KOLIBRI_FONTLIB)_%,%,$(V)).h,$(patsubst KOLIBRI_FONT_$(NETSURF_KOLIBRI_FONTLIB)_%,%,$(V)))))
+
+
+LDFLAGS := -static -Tapp-static.lds -L /home/bob/kolibrios/contrib/sdk/lib/ -lfreetype -lz /home/bob/dev-netsurf/workspace/netsurf/inst/lib/libcss.a /home/bob/dev-netsurf/workspace/netsurf/inst/lib/libdom.a /home/bob/dev-netsurf/workspace/netsurf/inst/lib/libhubbub.a /home/bob/dev-netsurf/workspace/netsurf/inst/lib/libnsbmp.a /home/bob/dev-netsurf/workspace/netsurf/inst/lib/libnsfb.a /home/bob/dev-netsurf/workspace/netsurf/inst/lib/libnsgif.a /home/bob/dev-netsurf/workspace/netsurf/inst/lib/libnsutils.a /home/bob/dev-netsurf/workspace/netsurf/inst/lib/libparserutils.a /home/bob/dev-netsurf/workspace/netsurf/inst/lib/libutf8proc.a /home/bob/dev-netsurf/workspace/netsurf/inst/lib/libwapcaplet.a /home/bob/dev-netsurf/workspace/netsurf/inst/lib/libnsgif.a /home/autobuild/tools/win32/lib/libiconv.a -ldll -lc -lgcc -lc -ldll
+
+# non optional pkg-configed libs
+#$(eval $(call pkg_config_find_and_add,libcurl,Curl ))
+#$(eval $(call pkg_config_find_and_add,openssl,OpenSSL))
+#$(eval $(call pkg_config_find_and_add,glib-2.0,GLib2))
+
+# optional pkg-config configured libraries
+# $(eval $(call pkg_config_find_and_add_enabled,NSSVG,libsvgtiny,SVG))
+# $(eval $(call pkg_config_find_and_add_enabled,ROSPRITE,librosprite,Sprite))
+# $(eval $(call pkg_config_find_and_add_enabled,BMP,libnsbmp,BMP))
+# $(eval $(call pkg_config_find_and_add_enabled,GIF,libnsgif,GIF))
+# $(eval $(call pkg_config_find_and_add_enabled,JPEG,libnsjpeg,JPEG))
+# $(eval $(call pkg_config_find_and_add_enabled,PNG,libpng,PNG ))
+# $(eval $(call pkg_config_find_and_add_enabled,MOZJS,mozjs185,JavaScript))
+# $(eval $(call pkg_config_find_and_add_enabled,JS,mozilla-js,JavaScript))
+
+#S_KOLIBRIOS := main.c kolibri_misc.c kolibri_debug.c kolibri_filesystem.c kolibri_regex.c kolibri_http.c
+S_KOLIBRIOS :=
+S_FRAMEBUFFER := gui.c framebuffer.c schedule.c bitmap.c fetch.c findfile.c localhistory.c clipboard.c
+S_FRAMEBUFFER_FBTK := fbtk.c event.c fill.c bitmap.c user.c window.c text.c scroll.c osk.c
+S_FRAMEBUFFER += font_$(NETSURF_KOLIBRI_FONTLIB).c
+
+S_FRAMEBUFFER := $(addprefix fb/,$(S_FRAMEBUFFER)) $(addprefix fb/fbtk/,$(S_FRAMEBUFFER_FBTK))
+S_KOLIBRIOS += $(S_FRAMEBUFFER)
+S_FRONTEND := $(S_KOLIBRIOS)
+
+SOURCES = $(S_COMMON) $(S_IMAGE) $(S_BROWSER) $(S_FRONTEND) $(S_IMAGES) $(S_FONTS)
+
+EXETARGET := nskolibrios
+
+install-kolibri:
+
+
diff --git a/frontends/kolibrios/Makefile.defaults b/frontends/kolibrios/Makefile.defaults
new file mode 100644
index 0000000..e5e5111
--- a/dev/null
+++ b/frontends/kolibrios/Makefile.defaults
@@ -0,0 +1,41 @@
+# ----------------------------------------------------------------------------
+# kolibrios-target-specific options
+# ----------------------------------------------------------------------------
+
+# Optimisation levels
+# CFLAGS += -O2
+
+# Framebuffer default surface provider.
+# Valid values are: x, sdl, linux, vnc, able, kolibri
+NETSURF_KOLIBRI_FRONTEND := kolibri
+
+# Use libharu to enable PDF export and GTK printing support.
+# Valid options: YES, NO
+NETSURF_USE_HARU_PDF := 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
+
+# Library to use for font plotting
+# Valid options: internal, freetype
+NETSURF_KOLIBRI_FONTLIB := freetype
+
+# Default freetype font files
+NETSURF_KOLIBRI_FONT_SANS_SERIF := sans.ttf
+
+# Default binary install path
+NETSURF_FRAMEBUFFER_BIN := $(PREFIX)/bin/
+
+# Default resource install path
+NETSURF_FRAMEBUFFER_RESOURCES := $(PREFIX)/share/netsurf/
+
+# Res path when running on KolibriOS
+NETSURF_KOLIBRI_RESPATH := /usbhd0/1/framebuffer/res/
+
+#Where are the fonts in Kolibri?
+#NETSURF_KOLIBRI_FONTPATH := /usr/share/fonts/truetype/ttf-dejavu:/usr/share/fonts/truetype/msttcorefonts
diff --git a/frontends/kolibrios/bitmap_table.h b/frontends/kolibrios/bitmap_table.h
new file mode 100644
index 0000000..e11274c
--- a/dev/null
+++ b/frontends/kolibrios/bitmap_table.h
@@ -0,0 +1,96 @@
+/* ------------------------------ */
+/* Part about GUI BITMAP TABLE. Will contain all functions required as well. */
+/* ------------------------------ */
+
+void *kolibri_create_bitmap(int width, int height, unsigned int state)
+{
+
+}
+
+
+void kolibri_destroy_bitmap(void *bitmap)
+{
+
+}
+
+
+void kolibri_set_bitmap_opaque(void *bitmap, bool opaque)
+{
+
+}
+
+
+void kolibri_get_bitmap_opaque(void *bitmap)
+{
+
+}
+
+
+bool kolibri_test_bitmap_opaque(void *bitmap)
+{
+
+}
+
+
+unsigned char *kolibri_get_imgbuffer_from_bitmap(void *bitmap)
+{
+
+}
+
+
+size_t kolibri_get_numbytes_row_image(void *bitmap)
+{
+
+}
+
+
+int kolibri_get_width_bitmap(void *bitmap)
+{
+
+}
+
+
+int kolibri_get_height_bitmap(void *bitmap)
+{
+
+}
+
+
+size_t kolibri_get_bpp(void *bitmap)
+{
+
+}
+
+
+bool kolibri_save_to_disk_bitmap(void *bitmap, const char *path, unsigned flags)
+{
+
+}
+
+
+void kolibri_mark_modified(void *bitmap)
+{
+
+}
+
+
+nserror kolibri_render_content_bitmap(struct bitmap *bitmap, struct hlcache_handle *content)
+{
+
+}
+
+struct gui_bitmap_table kolibri_bitmap_table = {
+ .create = kolibri_create_bitmap,
+ .destroy = kolibri_destroy_bitmap,
+ .set_opaque = kolibri_set_bitmap_opaque,
+ .get_opaque = kolibri_get_bitmap_opaque,
+ .test_opaque = kolibri_test_bitmap_opaque,
+ .get_buffer = kolibri_get_imgbuffer_from_bitmap,
+ .get_rowstride = kolibri_get_numbytes_row_image,
+ .get_width = kolibri_get_width_bitmap,
+ .get_height = kolibri_get_height_bitmap,
+ .get_bpp = kolibri_get_bpp,
+ .save = kolibri_save_to_disk_bitmap,
+ .modified = kolibri_mark_modified,
+ .render = kolibri_render_content_bitmap,
+ };
diff --git a/frontends/kolibrios/browser_table.h b/frontends/kolibrios/browser_table.h
new file mode 100644
index 0000000..2ee1182
--- a/dev/null
+++ b/frontends/kolibrios/browser_table.h
@@ -0,0 +1,57 @@
+/* ------------------------------ */
+/* Part about Browser table. Will contain all functions required as well. */
+/* ------------------------------ */
+nserror kolibri_schedule_cb(int t, void (*callback)(void *p), void *p);
+void kolibri_browser_quit(void);
+
+struct kolibri_callback {
+ void (*cb)(void *p);
+ void *arg;
+ struct kolibri_callback *next_cb;
+} head_dummy;
+
+struct kolibri_callback *kcb_head = &head_dummy;
+struct kolibri_callback *kcb_tail = &head_dummy;
+
+static struct gui_browser_table kolibri_browser_table = {
+ .schedule = kolibri_schedule_cb,
+ .quit = kolibri_browser_quit,
+ };
+
+nserror kolibri_schedule_cb(int t, void (*callback)(void *p), void *p)
+{
+ /* debug_board_write_str("kolibri_schedule_cb called!\n"); */
+ struct kolibri_callback *new_cb = malloc(sizeof(struct kolibri_callback));
+ new_cb->arg = p;
+ new_cb->cb = callback;
+ new_cb->next_cb = NULL;
+
+ kcb_tail -> next_cb = new_cb;
+ kcb_tail = new_cb;
+
+ return NSERROR_OK;
+}
+
+bool kolibri_schedule_run(void)
+{
+ if(kcb_head != kcb_tail)
+ return false;
+
+ struct kolibri_callback *runner = kcb_head -> next_cb;
+
+ while(runner != NULL)
+ {
+ runner->cb(runner->arg);
+ runner = runner -> next_cb;
+ }
+
+ return true;
+ /* TODO: Free the whole list of callbacks */
+}
+
+void kolibri_browser_quit(void)
+{
+ debug_board_write_str("Netsurf is shutting down Normally..GoodBye.");
+ /* TODO: Do the actual killing of process with mcall -1 */
+ /* Maybe set Kolibri_quit = 1 here */
+}
diff --git a/frontends/kolibrios/clipboard_table.h b/frontends/kolibrios/clipboard_table.h
new file mode 100644
index 0000000..93f3704
--- a/dev/null
+++ b/frontends/kolibrios/clipboard_table.h
@@ -0,0 +1,20 @@
+/* ------------------------------ */
+/* Part about GUI CLIPBOARD table. Will contain all functions required as well. */
+/* ------------------------------ */
+
+void kolibri_get_clipboard_contents(char **buffer, size_t *length)
+{
+
+}
+
+
+void kolibri_set_clipboard_contents(const char *buffer, size_t length, nsclipboard_styles styles[], int n_styles)
+{
+
+}
+
+static struct gui_clipboard_table kolibri_clipboard_table = {
+ .get = kolibri_get_clipboard_contents,
+ .set = kolibri_set_clipboard_contents,
+ };
+
diff --git a/frontends/kolibrios/convert_image.c b/frontends/kolibrios/convert_image.c
new file mode 100644
index 0000000..838a907
--- a/dev/null
+++ b/frontends/kolibrios/convert_image.c
@@ -0,0 +1,315 @@
+/*
+ * Copyright 2009 Daniel Silverstone <dsilvers@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdbool.h>
+#include <errno.h>
+#include <stdio.h>
+#include <png.h>
+#include <stdlib.h>
+
+#if PNG_LIBPNG_VER < 10209
+#define png_set_expand_gray_1_2_4_to_8(png) png_set_gray_1_2_4_to_8(png)
+#endif
+
+static png_structp png;
+static png_infop info;
+static int interlace;
+static size_t rowbytes;
+static int raw_width, raw_height;
+static int rowstride;
+static unsigned char *bitmap_data;
+static bool is_cursor = true;
+static int raw_hot_x, raw_hot_y;
+
+#define WIDTH (is_cursor?raw_width-1:raw_width)
+#define HEIGHT (is_cursor?raw_height-1:raw_height)
+
+#define HOT_X (is_cursor?raw_hot_x-1:0)
+#define HOT_Y (is_cursor?raw_hot_y-1:0)
+
+#define REAL(v) (is_cursor?v+1:v)
+
+#define PPIX_AT(x,y) ((bitmap_data + (rowstride * y)) + (x * 4))
+
+#define R_OFF 2
+#define G_OFF 1
+#define B_OFF 0
+#define A_OFF 3
+
+#define R_AT(x,y) *(PPIX_AT(x,y) + R_OFF)
+#define G_AT(x,y) *(PPIX_AT(x,y) + G_OFF)
+#define B_AT(x,y) *(PPIX_AT(x,y) + B_OFF)
+#define A_AT(x,y) *(PPIX_AT(x,y) + A_OFF)
+
+static void info_callback(png_structp png, png_infop info);
+static void row_callback(png_structp png, png_bytep new_row,
+ png_uint_32 row_num, int pass);
+static void end_callback(png_structp png, png_infop info);
+
+
+
+static void
+usage(void)
+{
+ fprintf(stderr, "usage: fb_convert_image input.png output.inc varname\n");
+}
+
+static void info_callback(png_structp png, png_infop info);
+static void row_callback(png_structp png, png_bytep new_row,
+ png_uint_32 row_num, int pass);
+static void end_callback(png_structp png, png_infop info);
+
+
+static void
+detect_hotspot(void)
+{
+ int i;
+ int greenpixels = 0;
+
+ for (i = 0; i < raw_width; ++i) {
+ if (A_AT(i, 0) == 255) {
+ if (G_AT(i, 0) == 255) {
+ greenpixels++;
+ raw_hot_x = i;
+ }
+ if ((B_AT(i, 0) != 0) || (R_AT(i, 0) != 0)) {
+ is_cursor = false;
+ return;
+ }
+ } else if (A_AT(i, 0) != 0) {
+ is_cursor = false;
+ return;
+ }
+ }
+ if (greenpixels != 1) {
+ is_cursor = false;
+ return;
+ }
+
+ for (i = 0; i < raw_height; ++i) {
+ if (A_AT(0, i) == 255) {
+ if (G_AT(0, i) == 255) {
+ greenpixels++;
+ raw_hot_y = i;
+ }
+ if ((B_AT(0, i) != 0) || (R_AT(0, i) != 0)) {
+ is_cursor = false;
+ return;
+ }
+ } else if (A_AT(0, i) != 0) {
+ is_cursor = false;
+ return;
+ }
+ }
+ if (greenpixels != 2) {
+ is_cursor = false;
+ return;
+ }
+ printf(" Pointer detected. Adjusted hotspot at %d, %d (0-based)\n",
+ raw_hot_x - 1, raw_hot_y - 1);
+}
+
+int
+main(int argc, char **argv)
+{
+ FILE *f;
+ unsigned char buffer[1024];
+ int br;
+ int x, y, c;
+
+ if (argc != 4) {
+ usage();
+ return 1;
+ }
+
+ printf(" CONVERT: %s (%s)\n", argv[1], argv[3]);
+
+ png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
+ info = png_create_info_struct(png);
+
+ png_set_progressive_read_fn(png, NULL, info_callback, row_callback, end_callback);
+
+ f = fopen(argv[1], "rb");
+ if (f == NULL) {
+ printf(" Unable to open %s\n", argv[1]);
+ return 1;
+ }
+
+ do {
+ br = fread(buffer, 1, 1024, f);
+ if (br > 0) {
+ png_process_data(png, info, buffer, br);
+ }
+ } while (br > 0);
+
+ if (br < 0) {
+ printf("Error reading input: %s\n", strerror(errno));
+ fclose(f);
+ return 1;
+ }
+
+ fclose(f);
+
+ detect_hotspot();
+
+ f = fopen(argv[2], "w");
+ if (f == NULL) {
+ printf(" Unable to open %s\n", argv[2]);
+ return 2;
+ }
+
+ fprintf(f, "/* This file is auto-generated from %s\n", argv[1]);
+ fprintf(f, " *\n * Do not edit this file directly.\n */\n\n");
+ fprintf(f, "#include <sys/types.h>\n\n");
+ fprintf(f, "#include <stdint.h>\n\n");
+ fprintf(f, "#include <stdbool.h>\n\n");
+ fprintf(f, "#include <libnsfb.h>\n\n");
+ fprintf(f, "#include \"desktop/plot_style.h\"\n");
+ fprintf(f, "#include \"framebuffer/gui.h\"\n");
+ fprintf(f, "#include \"framebuffer/fbtk.h\"\n\n");
+
+ fprintf(f, "static uint8_t %s_pixdata[] = {\n", argv[3]);
+ for (y = 0; y < HEIGHT; ++y) {
+ unsigned char *rowptr = bitmap_data + (rowstride * y);
+ if (is_cursor) {
+ /* If it's a cursor, skip one row and one column */
+ rowptr += rowstride + 4;
+ }
+ fprintf(f, "\t");
+ for (x = 0; x < WIDTH; ++x) {
+ for (c = 0; c < 4; ++c) {
+ unsigned char b = *rowptr++;
+ fprintf(f, "0x%02x, ", b);
+ }
+ }
+ fprintf(f, "\n");
+ }
+ fprintf(f, "};\n\n");
+
+ fprintf(f, "struct fbtk_bitmap %s = {\n", argv[3]);
+ fprintf(f, "\t.width\t\t= %d,\n", WIDTH);
+ fprintf(f, "\t.height\t\t= %d,\n", HEIGHT);
+ fprintf(f, "\t.hot_x\t\t= %d,\n", HOT_X);
+ fprintf(f, "\t.hot_y\t\t= %d,\n", HOT_Y);
+ fprintf(f, "\t.pixdata\t= %s_pixdata,\n", argv[3]);
+
+ fprintf(f, "};\n\n");
+ fclose(f);
+
+ return 0;
+}
+
+static void
+info_callback(png_structp png, png_infop info)
+{
+ int bit_depth, color_type, interlace, intent;
+ double gamma;
+ unsigned long width, height;
+
+ /* Read the PNG details */
+ png_get_IHDR(png, info, &width, &height, &bit_depth,
+ &color_type, &interlace, 0, 0);
+
+ /* Set up our transformations */
+ if (color_type == PNG_COLOR_TYPE_PALETTE)
+ png_set_palette_to_rgb(png);
+ if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
+ png_set_expand_gray_1_2_4_to_8(png);
+ if (png_get_valid(png, info, PNG_INFO_tRNS))
+ png_set_tRNS_to_alpha(png);
+ if (bit_depth == 16)
+ png_set_strip_16(png);
+ if (color_type == PNG_COLOR_TYPE_GRAY ||
+ color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+ png_set_gray_to_rgb(png);
+ if (!(color_type & PNG_COLOR_MASK_ALPHA))
+ png_set_filler(png, 0xff, PNG_FILLER_AFTER);
+ /* gamma correction - we use 2.2 as our screen gamma
+ * this appears to be correct (at least in respect to !Browse)
+ * see http://www.w3.org/Graphics/PNG/all_seven.html for a test case
+ */
+ if (png_get_sRGB(png, info, &intent))
+ png_set_gamma(png, 2.2, 0.45455);
+ else {
+ if (png_get_gAMA(png, info, &gamma))
+ png_set_gamma(png, 2.2, gamma);
+ else
+ png_set_gamma(png, 2.2, 0.45455);
+ }
+
+
+ png_read_update_info(png, info);
+
+ rowbytes = png_get_rowbytes(png, info);
+ interlace = (interlace == PNG_INTERLACE_ADAM7);
+ raw_width = width;
+ raw_height = height;
+
+ rowstride = raw_width * 4;
+ bitmap_data = malloc(rowstride * raw_height);
+}
+
+static unsigned int interlace_start[8] = {0, 16, 0, 8, 0, 4, 0};
+static unsigned int interlace_step[8] = {28, 28, 12, 12, 4, 4, 0};
+static unsigned int interlace_row_start[8] = {0, 0, 4, 0, 2, 0, 1};
+static unsigned int interlace_row_step[8] = {8, 8, 8, 4, 4, 2, 2};
+
+static void
+row_callback(png_structp png, png_bytep new_row,
+ png_uint_32 row_num, int pass)
+{
+ unsigned long i, j;
+ unsigned int start, step;
+ unsigned char *row = bitmap_data + (rowstride * row_num);
+
+ if (new_row == 0)
+ return;
+
+ if (interlace) {
+ start = interlace_start[pass];
+ step = interlace_step[pass];
+ row_num = interlace_row_start[pass] +
+ interlace_row_step[pass] * row_num;
+
+ /* Copy the data to our current row taking interlacing
+ * into consideration */
+ row = bitmap_data + (rowstride * row_num);
+ for (j = 0, i = start; i < rowbytes; i += step) {
+ row[i++] = new_row[j++];
+ row[i++] = new_row[j++];
+ row[i++] = new_row[j++];
+ row[i++] = new_row[j++];
+ }
+ } else {
+ memcpy(row, new_row, rowbytes);
+ }
+}
+
+static void
+end_callback(png_structp png, png_infop info)
+{
+}
+
+
+
+/*
+ * Local Variables:
+ * c-basic-offset:8
+ * End:
+ */
+
diff --git a/frontends/kolibrios/download_table.h b/frontends/kolibrios/download_table.h
new file mode 100644
index 0000000..58fcb54
--- a/dev/null
+++ b/frontends/kolibrios/download_table.h
@@ -0,0 +1,34 @@
+/* ------------------------------ */
+/* Part about GUI DOWNLOAD table. Will contain all functions required as well. */
+/* ------------------------------ */
+
+struct gui_download_window *kolibri_create_download_window(struct download_context *ctx, struct gui_window *parent)
+{
+
+}
+
+
+nserror kolibri_download_data(struct gui_download_window *dw, const char *data, unsigned int size)
+{
+
+}
+
+
+void kolibri_download_error(struct gui_download_window *dw, const char *error_msg)
+{
+
+}
+
+
+void kolibri_download_done(struct gui_download_window *dw)
+{
+
+}
+
+
+static struct gui_download_table kolibri_download_table = {
+ .create = kolibri_create_download_window,
+ .data = kolibri_download_data,
+ .error = kolibri_download_error,
+ .done = kolibri_download_done
+};
diff --git a/frontends/kolibrios/fb/Makefile b/frontends/kolibrios/fb/Makefile
new file mode 100644
index 0000000..6d2acb0
--- a/dev/null
+++ b/frontends/kolibrios/fb/Makefile
@@ -0,0 +1,184 @@
+# ----------------------------------------------------------------------------
+# Framebuffer target setup
+# ----------------------------------------------------------------------------
+
+CFLAGS += -Dnsframebuffer
+
+#resource path
+CFLAGS += '-DNETSURF_FB_RESPATH="$(NETSURF_FB_RESPATH)"'
+
+# compile time font locations
+CFLAGS += '-DNETSURF_FB_FONTPATH="$(NETSURF_FB_FONTPATH)"'
+CFLAGS += '-DNETSURF_FB_FONT_SANS_SERIF="$(NETSURF_FB_FONT_SANS_SERIF)"'
+CFLAGS += '-DNETSURF_FB_FONT_SANS_SERIF_BOLD="$(NETSURF_FB_FONT_SANS_SERIF_BOLD)"'
+CFLAGS += '-DNETSURF_FB_FONT_SANS_SERIF_ITALIC="$(NETSURF_FB_FONT_SANS_SERIF_ITALIC)"'
+CFLAGS += '-DNETSURF_FB_FONT_SANS_SERIF_ITALIC_BOLD="$(NETSURF_FB_FONT_SANS_SERIF_ITALIC_BOLD)"'
+CFLAGS += '-DNETSURF_FB_FONT_SERIF="$(NETSURF_FB_FONT_SERIF)"'
+CFLAGS += '-DNETSURF_FB_FONT_SERIF_BOLD="$(NETSURF_FB_FONT_SERIF_BOLD)"'
+CFLAGS += '-DNETSURF_FB_FONT_MONOSPACE="$(NETSURF_FB_FONT_MONOSPACE)"'
+CFLAGS += '-DNETSURF_FB_FONT_MONOSPACE_BOLD="$(NETSURF_FB_FONT_MONOSPACE_BOLD)"'
+CFLAGS += '-DNETSURF_FB_FONT_CURSIVE="$(NETSURF_FB_FONT_CURSIVE)"'
+CFLAGS += '-DNETSURF_FB_FONT_FANTASY="$(NETSURF_FB_FONT_FANTASY)"'
+
+CFLAGS += -std=c99 -g -Dsmall \
+ -D_BSD_SOURCE \
+ -D_DEFAULT_SOURCE \
+ -D_XOPEN_SOURCE=600 \
+ -D_POSIX_C_SOURCE=200809L
+
+LDFLAGS += -lm
+
+# non optional pkg-configed libs
+LDFLAGS += -Wl,--whole-archive
+$(eval $(call pkg_config_find_and_add,libnsfb,libnsfb))
+LDFLAGS += -Wl,--no-whole-archive
+
+# freetype is optional but does not use pkg-config
+ifeq ($(NETSURF_FB_FONTLIB),freetype)
+ CFLAGS += -DFB_USE_FREETYPE $(shell freetype-config --cflags)
+ LDFLAGS += $(shell freetype-config --libs)
+endif
+
+
+# ----------------------------------------------------------------------------
+# built-in resource setup
+# ----------------------------------------------------------------------------
+
+FB_IMAGE_left_arrow := icons/back.png
+FB_IMAGE_right_arrow := icons/forward.png
+FB_IMAGE_reload := icons/reload.png
+FB_IMAGE_stop_image := icons/stop.png
+FB_IMAGE_history_image := icons/history.png
+
+FB_IMAGE_left_arrow_g := icons/back_g.png
+FB_IMAGE_right_arrow_g := icons/forward_g.png
+FB_IMAGE_reload_g := icons/reload_g.png
+FB_IMAGE_stop_image_g := icons/stop_g.png
+FB_IMAGE_history_image_g := icons/history_g.png
+
+FB_IMAGE_scrolll := icons/scrolll.png
+FB_IMAGE_scrollr := icons/scrollr.png
+FB_IMAGE_scrollu := icons/scrollu.png
+FB_IMAGE_scrolld := icons/scrolld.png
+
+FB_IMAGE_osk_image := icons/osk.png
+
+FB_IMAGE_pointer_image := pointers/default.png
+FB_IMAGE_hand_image := pointers/point.png
+FB_IMAGE_caret_image := pointers/caret.png
+FB_IMAGE_menu_image := pointers/menu.png
+FB_IMAGE_progress_image := pointers/progress.png
+FB_IMAGE_move_image := pointers/move.png
+
+FB_IMAGE_throbber0 := throbber/throbber0.png
+FB_IMAGE_throbber1 := throbber/throbber1.png
+FB_IMAGE_throbber2 := throbber/throbber2.png
+FB_IMAGE_throbber3 := throbber/throbber3.png
+FB_IMAGE_throbber4 := throbber/throbber4.png
+FB_IMAGE_throbber5 := throbber/throbber5.png
+FB_IMAGE_throbber6 := throbber/throbber6.png
+FB_IMAGE_throbber7 := throbber/throbber7.png
+FB_IMAGE_throbber8 := throbber/throbber8.png
+
+# local compiler flags
+ifeq ($(HOST),OpenBSD)
+ HOST_CFLAGS += $(shell $(PKG_CONFIG) --cflags libpng)
+ HOST_LDFLAGS += $(shell $(PKG_CONFIG) --libs libpng)
+else
+ HOST_CFLAGS +=
+ HOST_LDFLAGS += -lpng
+endif
+
+# Host tool to convert image bitmaps to source code.
+#
+# convert_image dependd on fb_bitmap.h so that if we change that
+# header, we get new images built.
+$(TOOLROOT)/convert_image: $(TOOLROOT)/created $(FRONTEND_SOURCE_DIR)/convert_image.c $(FRONTEND_SOURCE_DIR)/fbtk.h
+ $(VQ)echo " HOST CC: $@"
+ $(Q)$(HOST_CC) $(HOST_CFLAGS) -o $@ $(FRONTEND_SOURCE_DIR)/convert_image.c $(HOST_LDFLAGS)
+
+# 1: input file
+# 2: output file
+# 3: bitmap name
+define convert_image
+
+S_IMAGES += $(2)
+
+$(2): $(1) $(TOOLROOT)/convert_image
+ $(Q)$(TOOLROOT)/convert_image $(1) $(2) $(3)
+
+endef
+
+S_IMAGES :=
+
+$(eval $(foreach V,$(filter FB_IMAGE_%,$(.VARIABLES)),$(call convert_image,$(FRONTEND_RESOURCES_DIR)/$($(V)),$(OBJROOT)/image-$(patsubst FB_IMAGE_%,%,$(V)).c,$(patsubst FB_IMAGE_%,%,$(V)))))
+
+
+# Internal fonts to generate
+FB_FONT_internal_ns-sans := fonts/glyph_data
+
+# Internal font conversion
+$(TOOLROOT)/convert_font: $(TOOLROOT)/created $(FRONTEND_SOURCE_DIR)/convert_font.c
+ $(VQ)echo " HOST CC: $@"
+ $(Q)$(HOST_CC) -o $@ $(FRONTEND_SOURCE_DIR)/convert_font.c
+
+# 1: input file
+# 2: output source code file
+# 3: output header file
+# 4: font name
+define convert_font
+
+S_FONTS += $(2)
+
+$(2): $(1) $(TOOLROOT)/convert_font
+ $(VQ)echo " FONT: $(1) ($(4))"
+ $(Q)$(TOOLROOT)/convert_font -H $(3) $(1) $(2)
+
+endef
+
+S_FONTS :=
+
+$(eval $(foreach V,$(filter FB_FONT_$(NETSURF_FB_FONTLIB)_%,$(.VARIABLES)),$(call convert_font,$(FRONTEND_RESOURCES_DIR)/$($(V)),$(OBJROOT)/font-$(patsubst FB_FONT_$(NETSURF_FB_FONTLIB)_%,%,$(V)).c,$(OBJROOT)/font-$(patsubst FB_FONT_$(NETSURF_FB_FONTLIB)_%,%,$(V)).h,$(patsubst FB_FONT_$(NETSURF_FB_FONTLIB)_%,%,$(V)))))
+
+# ----------------------------------------------------------------------------
+# Source file setup
+# ----------------------------------------------------------------------------
+
+# S_FRONTEND are sources purely for the framebuffer build
+S_FRONTEND := gui.c framebuffer.c schedule.c bitmap.c fetch.c \
+ findfile.c localhistory.c clipboard.c
+
+# toolkit sources
+S_FRAMEBUFFER_FBTK := fbtk.c event.c fill.c bitmap.c user.c window.c \
+ text.c scroll.c osk.c
+
+S_FRONTEND += font_$(NETSURF_FB_FONTLIB).c
+
+S_FRONTEND += $(addprefix fbtk/,$(S_FRAMEBUFFER_FBTK))
+
+# 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_FRONTEND) $(S_IMAGES) $(S_FONTS)
+EXETARGET := nsfb
+
+# ----------------------------------------------------------------------------
+# Install target
+# ----------------------------------------------------------------------------
+
+NETSURF_FRAMEBUFFER_RESOURCE_LIST := adblock.css credits.html \
+ default.css internal.css licence.html \
+ netsurf.png quirks.css welcome.html maps.html Messages
+
+install-framebuffer:
+ $(Q)$(MKDIR) -p $(DESTDIR)$(NETSURF_FRAMEBUFFER_BIN)
+ $(Q)$(MKDIR) -p $(DESTDIR)$(NETSURF_FRAMEBUFFER_RESOURCES)
+ $(Q)cp -v $(EXETARGET) $(DESTDIR)/$(NETSURF_FRAMEBUFFER_BIN)netsurf-fb
+ $(Q)for F in $(NETSURF_FRAMEBUFFER_RESOURCE_LIST); do cp -vL $(FRONTEND_RESOURCES_DIR)/$$F $(DESTDIR)/$(NETSURF_FRAMEBUFFER_RESOURCES); done
+ $(Q)$(SPLIT_MESSAGES) -l en -p fb -f messages resources/FatMessages | gzip -9n > $(DESTDIR)$(NETSURF_FRAMEBUFFER_RESOURCES)messages
+
+# ----------------------------------------------------------------------------
+# Package target
+# ----------------------------------------------------------------------------
+
+package-framebuffer:
diff --git a/frontends/kolibrios/fb/Makefile.defaults b/frontends/kolibrios/fb/Makefile.defaults
new file mode 100644
index 0000000..cc712e9
--- a/dev/null
+++ b/frontends/kolibrios/fb/Makefile.defaults
@@ -0,0 +1,51 @@
+# ----------------------------------------------------------------------------
+# Framebuffer-target-specific options
+# ----------------------------------------------------------------------------
+
+# Optimisation levels
+CFLAGS += -O2
+
+# Framebuffer default surface provider.
+# Valid values are: x, sdl, linux, vnc, able,
+NETSURF_FB_FRONTEND := sdl
+
+# Use libharu to enable PDF export and GTK printing support.
+# Valid options: YES, NO
+NETSURF_USE_HARU_PDF := NO
+
+# Enable NetSurf's use of libsvgtiny for displaying SVGs
+# Valid options: YES, NO, AUTO
+NETSURF_USE_NSSVG := AUTO
+
+# Enable NetSurf's use of librosprite for displaying RISC OS Sprites
+# Valid options: YES, NO, AUTO
+NETSURF_USE_ROSPRITE := AUTO
+
+# Library to use for font plotting
+# Valid options: internal, freetype
+NETSURF_FB_FONTLIB := internal
+
+# Default freetype font files
+NETSURF_FB_FONT_SANS_SERIF := DejaVuSans.ttf
+NETSURF_FB_FONT_SANS_SERIF_BOLD := DejaVuSans-Bold.ttf
+NETSURF_FB_FONT_SANS_SERIF_ITALIC := DejaVuSans-Oblique.ttf
+NETSURF_FB_FONT_SANS_SERIF_ITALIC_BOLD := DejaVuSans-BoldOblique.ttf
+NETSURF_FB_FONT_SERIF := DejaVuSerif.ttf
+NETSURF_FB_FONT_SERIF_BOLD := DejaVuSerif-Bold.ttf
+NETSURF_FB_FONT_MONOSPACE := DejaVuSansMono.ttf
+NETSURF_FB_FONT_MONOSPACE_BOLD := DejaVuSansMono-Bold.ttf
+NETSURF_FB_FONT_CURSIVE := Comic_Sans_MS.ttf
+NETSURF_FB_FONT_FANTASY := Impact.ttf
+
+# Default binary install path
+NETSURF_FRAMEBUFFER_BIN := $(PREFIX)/bin/
+
+# Default resource install path
+NETSURF_FRAMEBUFFER_RESOURCES := $(PREFIX)/share/netsurf/
+
+# Default framebuffer search path
+NETSURF_FB_RESPATH := $${HOME}/.netsurf/:$${NETSURFRES}:$(NETSURF_FRAMEBUFFER_RESOURCES):./frontends/framebuffer/res
+
+# freetype compiled in font serch path
+NETSURF_FB_FONTPATH := /usr/share/fonts/truetype/dejavu:/usr/share/fonts/truetype/msttcorefonts
+
diff --git a/frontends/kolibrios/fb/bitmap.c b/frontends/kolibrios/fb/bitmap.c
new file mode 100644
index 0000000..027e012
--- a/dev/null
+++ b/frontends/kolibrios/fb/bitmap.c
@@ -0,0 +1,352 @@
+/*
+ * Copyright 2008 Vincent Sanders <vince@simtec.co.uk>
+ *
+ * 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
+ * Framebuffer implementation of generic bitmap interface.
+ */
+
+#include <inttypes.h>
+#include <sys/types.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <libnsfb.h>
+#include <libnsfb_plot.h>
+
+#include "utils/log.h"
+#include "utils/utils.h"
+#include "netsurf/bitmap.h"
+#include "netsurf/plotters.h"
+#include "netsurf/content.h"
+
+#include "framebuffer/gui.h"
+#include "framebuffer/fbtk.h"
+#include "framebuffer/framebuffer.h"
+#include "framebuffer/bitmap.h"
+
+/**
+ * Create a bitmap.
+ *
+ * \param width width of image in pixels
+ * \param height width of image in pixels
+ * \param state a flag word indicating the initial state
+ * \return an opaque struct bitmap, or NULL on memory exhaustion
+ */
+static void *bitmap_create(int width, int height, unsigned int state)
+{
+ nsfb_t *bm;
+
+ LOG("width %d, height %d, state %u", width, height, state);
+
+ bm = nsfb_new(NSFB_SURFACE_RAM);
+ if (bm == NULL) {
+ return NULL;
+ }
+
+ if ((state & BITMAP_OPAQUE) == 0) {
+ nsfb_set_geometry(bm, width, height, NSFB_FMT_ABGR8888);
+ } else {
+ nsfb_set_geometry(bm, width, height, NSFB_FMT_XBGR8888);
+ }
+
+ if (nsfb_init(bm) == -1) {
+ nsfb_free(bm);
+ return NULL;
+ }
+
+ LOG("bitmap %p", bm);
+
+ return bm;
+}
+
+
+/**
+ * Return a pointer to the pixel data in a bitmap.
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ * \return pointer to the pixel buffer
+ *
+ * The pixel data is packed as BITMAP_FORMAT, possibly with padding at the end
+ * of rows. The width of a row in bytes is given by bitmap_get_rowstride().
+ */
+static unsigned char *bitmap_get_buffer(void *bitmap)
+{
+ nsfb_t *bm = bitmap;
+ unsigned char *bmpptr;
+
+ assert(bm != NULL);
+
+ nsfb_get_buffer(bm, &bmpptr, NULL);
+
+ return bmpptr;
+}
+
+
+/**
+ * Find the width of a pixel row in bytes.
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ * \return width of a pixel row in the bitmap
+ */
+static size_t bitmap_get_rowstride(void *bitmap)
+{
+ nsfb_t *bm = bitmap;
+ int bmpstride;
+
+ assert(bm != NULL);
+
+ nsfb_get_buffer(bm, NULL, &bmpstride);
+
+ return bmpstride;
+}
+
+
+/**
+ * Free a bitmap.
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ */
+static void bitmap_destroy(void *bitmap)
+{
+ nsfb_t *bm = bitmap;
+
+ assert(bm != NULL);
+
+ nsfb_free(bm);
+}
+
+
+/**
+ * Save a bitmap in the platform's native format.
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ * \param path pathname for file
+ * \param flags flags controlling how the bitmap is saved.
+ * \return true on success, false on error and error reported
+ */
+static bool bitmap_save(void *bitmap, const char *path, unsigned flags)
+{
+ return true;
+}
+
+
+/**
+ * The bitmap image has changed, so flush any persistant cache.
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ */
+static void bitmap_modified(void *bitmap) {
+}
+
+/**
+ * Sets wether a bitmap should be plotted opaque
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ * \param opaque whether the bitmap should be plotted opaque
+ */
+static void bitmap_set_opaque(void *bitmap, bool opaque)
+{
+ nsfb_t *bm = bitmap;
+
+ assert(bm != NULL);
+
+ if (opaque) {
+ nsfb_set_geometry(bm, 0, 0, NSFB_FMT_XBGR8888);
+ } else {
+ nsfb_set_geometry(bm, 0, 0, NSFB_FMT_ABGR8888);
+ }
+}
+
+
+/**
+ * Tests whether a bitmap has an opaque alpha channel
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ * \return whether the bitmap is opaque
+ */
+static bool bitmap_test_opaque(void *bitmap)
+{
+ int tst;
+ nsfb_t *bm = bitmap;
+ unsigned char *bmpptr;
+ int width;
+ int height;
+
+ assert(bm != NULL);
+
+ nsfb_get_buffer(bm, &bmpptr, NULL);
+
+ nsfb_get_geometry(bm, &width, &height, NULL);
+
+ tst = width * height;
+
+ while (tst-- > 0) {
+ if (bmpptr[(tst << 2) + 3] != 0xff) {
+ LOG("bitmap %p has transparency", bm);
+ return false;
+ }
+ }
+ LOG("bitmap %p is opaque", bm);
+ return true;
+}
+
+
+/**
+ * Gets weather a bitmap should be plotted opaque
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ */
+bool framebuffer_bitmap_get_opaque(void *bitmap)
+{
+ nsfb_t *bm = bitmap;
+ enum nsfb_format_e format;
+
+ assert(bm != NULL);
+
+ nsfb_get_geometry(bm, NULL, NULL, &format);
+
+ if (format == NSFB_FMT_ABGR8888)
+ return false;
+
+ return true;
+}
+
+static int bitmap_get_width(void *bitmap)
+{
+ nsfb_t *bm = bitmap;
+ int width;
+
+ assert(bm != NULL);
+
+ nsfb_get_geometry(bm, &width, NULL, NULL);
+
+ return(width);
+}
+
+static int bitmap_get_height(void *bitmap)
+{
+ nsfb_t *bm = bitmap;
+ int height;
+
+ assert(bm != NULL);
+
+ nsfb_get_geometry(bm, NULL, &height, NULL);
+
+ return(height);
+}
+
+/* get bytes per pixel */
+static size_t bitmap_get_bpp(void *bitmap)
+{
+ return 4;
+}
+
+/**
+ * Render content into a bitmap.
+ *
+ * \param bitmap the bitmap to draw to
+ * \param content content structure to render
+ * \return true on success and bitmap updated else false
+ */
+static nserror
+bitmap_render(struct bitmap *bitmap,
+ struct hlcache_handle *content)
+{
+ nsfb_t *tbm = (nsfb_t *)bitmap; /* target bitmap */
+ nsfb_t *bm; /* temporary bitmap */
+ nsfb_t *current; /* current main fb */
+ int width, height; /* target bitmap width height */
+ int cwidth, cheight;/* content width /height */
+ nsfb_bbox_t loc;
+
+ struct redraw_context ctx = {
+ .interactive = false,
+ .background_images = true,
+ .plot = &fb_plotters
+ };
+
+ nsfb_get_geometry(tbm, &width, &height, NULL);
+
+ LOG("width %d, height %d", width, height);
+
+ /* Calculate size of buffer to render the content into */
+ /* We get the width from the content width, unless it exceeds 1024,
+ * in which case we use 1024. This means we never create excessively
+ * large render buffers for huge contents, which would eat memory and
+ * cripple performance. */
+ cwidth = min(content_get_width(content), 1024);
+ /* The height is set in proportion with the width, according to the
+ * aspect ratio of the required thumbnail. */
+ cheight = ((cwidth * height) + (width / 2)) / width;
+
+ /* create temporary surface */
+ bm = nsfb_new(NSFB_SURFACE_RAM);
+ if (bm == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ nsfb_set_geometry(bm, cwidth, cheight, NSFB_FMT_XBGR8888);
+
+ if (nsfb_init(bm) == -1) {
+ nsfb_free(bm);
+ return NSERROR_NOMEM;
+ }
+
+ current = framebuffer_set_surface(bm);
+
+ /* render the content into temporary surface */
+ content_scaled_redraw(content, cwidth, cheight, &ctx);
+
+ framebuffer_set_surface(current);
+
+ loc.x0 = 0;
+ loc.y0 = 0;
+ loc.x1 = width;
+ loc.y1 = height;
+
+ nsfb_plot_copy(bm, NULL, tbm, &loc);
+
+ nsfb_free(bm);
+
+ return NSERROR_OK;
+}
+
+static struct gui_bitmap_table bitmap_table = {
+ .create = bitmap_create,
+ .destroy = bitmap_destroy,
+ .set_opaque = bitmap_set_opaque,
+ .get_opaque = framebuffer_bitmap_get_opaque,
+ .test_opaque = bitmap_test_opaque,
+ .get_buffer = bitmap_get_buffer,
+ .get_rowstride = bitmap_get_rowstride,
+ .get_width = bitmap_get_width,
+ .get_height = bitmap_get_height,
+ .get_bpp = bitmap_get_bpp,
+ .save = bitmap_save,
+ .modified = bitmap_modified,
+ .render = bitmap_render,
+};
+
+struct gui_bitmap_table *framebuffer_bitmap_table = &bitmap_table;
+
+
+/*
+ * Local Variables:
+ * c-basic-offset:8
+ * End:
+ */
diff --git a/frontends/kolibrios/fb/bitmap.h b/frontends/kolibrios/fb/bitmap.h
new file mode 100644
index 0000000..0a72f19
--- a/dev/null
+++ b/frontends/kolibrios/fb/bitmap.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2015 Vincent Sanders <vince@netsurf-browser.h>
+ *
+ * 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 NS_FB_BITMAP_H
+#define NS_FB_BITMAP_H
+
+extern struct gui_bitmap_table *framebuffer_bitmap_table;
+
+bool framebuffer_bitmap_get_opaque(void *bitmap);
+
+#endif /* NS_FB_BITMAP_H */
diff --git a/frontends/kolibrios/fb/clipboard.c b/frontends/kolibrios/fb/clipboard.c
new file mode 100644
index 0000000..1254c36
--- a/dev/null
+++ b/frontends/kolibrios/fb/clipboard.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2012 Michael Drake <tlsa@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * nsfb internal clipboard handling
+ */
+
+#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "utils/log.h"
+#include "netsurf/browser_window.h"
+#include "netsurf/clipboard.h"
+
+#include "framebuffer/gui.h"
+#include "framebuffer/clipboard.h"
+
+
+static struct gui_clipboard {
+ char *buffer;
+ size_t buffer_len;
+ size_t length;
+} gui_clipboard;
+
+
+/**
+ * Core asks front end for clipboard contents.
+ *
+ * \param buffer UTF-8 text, allocated by front end, ownership yeilded to core
+ * \param length Byte length of UTF-8 text in buffer
+ */
+static void gui_get_clipboard(char **buffer, size_t *length)
+{
+ *buffer = NULL;
+ *length = 0;
+
+ if (gui_clipboard.length > 0) {
+ assert(gui_clipboard.buffer != NULL);
+ LOG("Pasting %zd bytes: \"%s\"\n",
+ gui_clipboard.length, gui_clipboard.buffer);
+
+ *buffer = malloc(gui_clipboard.length);
+
+ if (*buffer != NULL) {
+ memcpy(*buffer, gui_clipboard.buffer,
+ gui_clipboard.length);
+ *length = gui_clipboard.length;
+ }
+ }
+}
+
+
+/**
+ * Core tells front end to put given text in clipboard
+ *
+ * \param buffer UTF-8 text, owned by core
+ * \param length Byte length of UTF-8 text in buffer
+ * \param styles Array of styles given to text runs, owned by core, or NULL
+ * \param n_styles Number of text run styles in array
+ */
+static void gui_set_clipboard(const char *buffer, size_t length,
+ nsclipboard_styles styles[], int n_styles)
+{
+ if (gui_clipboard.buffer_len < length + 1) {
+ /* Make buffer big enough */
+ char *new_buff;
+
+ new_buff = realloc(gui_clipboard.buffer, length + 1);
+ if (new_buff == NULL)
+ return;
+
+ gui_clipboard.buffer = new_buff;
+ gui_clipboard.buffer_len = length + 1;
+ }
+
+ gui_clipboard.length = 0;
+
+ memcpy(gui_clipboard.buffer, buffer, length);
+ gui_clipboard.length = length;
+ gui_clipboard.buffer[gui_clipboard.length] = '\0';
+}
+
+static struct gui_clipboard_table clipboard_table = {
+ .get = gui_get_clipboard,
+ .set = gui_set_clipboard,
+};
+
+struct gui_clipboard_table *framebuffer_clipboard_table = &clipboard_table;
diff --git a/frontends/kolibrios/fb/clipboard.h b/frontends/kolibrios/fb/clipboard.h
new file mode 100644
index 0000000..b5f7b0f
--- a/dev/null
+++ b/frontends/kolibrios/fb/clipboard.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2008 Vincent Sanders <vince@simtec.co.uk>
+ *
+ * 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_FB_CLIPBOARD_H
+#define NETSURF_FB_CLIPBOARD_H
+
+extern struct gui_clipboard_table *framebuffer_clipboard_table;
+
+#endif
diff --git a/frontends/kolibrios/fb/convert_font.c b/frontends/kolibrios/fb/convert_font.c
new file mode 100644
index 0000000..010af85
--- a/dev/null
+++ b/frontends/kolibrios/fb/convert_font.c
@@ -0,0 +1,1215 @@
+/*
+ * Copyright 2014 Michael Drake <tlsa@netsurf-browser.org>
+ * Copyright 2014 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of the convert_font tool used to convert font
+ * glyph data into a compilable representation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <unistd.h>
+#include <getopt.h>
+
+#define GLYPH_LEN 16
+#define BUCKETS 512
+#define CHUNK_SIZE (64 * 1024)
+#define HEADER_MAX 2000
+
+#define SECTION_SIZE (sizeof(uint16_t) * 256)
+
+const char *labels[4] = {
+ " Regular",
+ " Italic",
+ " Bold",
+ "Bold & Italic"
+};
+
+const char *var_lables[4] = {
+ "fb_regular",
+ "fb_italic",
+ "fb_bold",
+ "fb_bold_italic"
+};
+
+const char *short_labels[4] = {
+ " ",
+ " i",
+ "b ",
+ "bi"
+};
+
+enum font_style {
+ REGULAR = 0,
+ ITALIC = (1 << 0),
+ BOLD = (1 << 1),
+ ITALIC_BOLD = (1 << 2)
+};
+
+enum log_level {
+ LOG_DEBUG,
+ LOG_INFO,
+ LOG_RESULT,
+ LOG_WARNING,
+ LOG_ERROR
+};
+
+enum log_level level;
+
+typedef struct glyph_entry {
+ union {
+ uint32_t u32[GLYPH_LEN / 4];
+ uint8_t u8[GLYPH_LEN];
+ } data;
+ uint32_t index;
+ struct glyph_entry *next;
+} glyph_entry;
+
+/** Scratch glyph for generated code points */
+uint8_t code_point[GLYPH_LEN];
+
+/** Hash table */
+glyph_entry *ht[BUCKETS];
+
+#define LOG(lev, fmt, ...) \
+ if (lev >= level) \
+ printf(fmt, ##__VA_ARGS__);
+
+/**
+ * Get hash for glyph data
+ * \param g Glyph data (GLYPH_LEN bytes)
+ * \return glyph's hash
+ */
+static inline uint32_t glyph_hash(const uint8_t *g)
+{
+ uint32_t hash = 0x811c9dc5;
+ unsigned int len = GLYPH_LEN;
+
+ while (len > 0) {
+ hash *= 0x01000193;
+ hash ^= *g++;
+ len--;
+ }
+
+ return hash;
+}
+
+
+/**
+ * Check whether glyphs are identical (compares glyph data)
+ *
+ * \param g1 First glyph's data (GLYPH_LEN bytes)
+ * \param g2 Second glyph's data (GLYPH_LEN bytes)
+ * \return true iff both glyphs are identical, else false
+ */
+static inline bool glyphs_match(const uint8_t *g1, const uint8_t *g2)
+{
+ return (memcmp(g1, g2, GLYPH_LEN) == 0);
+}
+
+
+/**
+ * Add a glyph to a hash chain (or free, and return pointer to existing glyph)
+ *
+ * Note that if new glyph already exists in chain, it is freed and a pointer to
+ * the existing glyph is returned. If the glyph does not exist in the chain
+ * it is added and its pointer is returned.
+ *
+ * \param head Head of hash chain
+ * \param new New glyph to add (may be freed)
+ * \return pointer to glyph in hash chain
+ */
+static glyph_entry * glyph_add_to_chain(glyph_entry **head, glyph_entry *new)
+{
+ glyph_entry *e = *head;
+
+ if (*head == NULL) {
+ new->next = NULL;
+ *head = new;
+ return new;
+ }
+
+ do {
+ if (glyphs_match(new->data.u8, e->data.u8)) {
+ free(new);
+ return e;
+ }
+ if (e->next == NULL)
+ break;
+ e = e->next;
+ } while (1);
+
+ new->next = e->next;
+ e->next = new;
+ return new;
+}
+
+
+/**
+ * Free a glyph entry chain
+ *
+ * \param head Head of hash chain
+ */
+static void free_chain(glyph_entry *head)
+{
+ glyph_entry *e = head;
+
+ if (head == NULL)
+ return;
+
+ while (e != NULL) {
+ head = e->next;
+ free(e);
+ e = head;
+ };
+}
+
+
+/**
+ * Add new glyph to hash table (or free, and return pointer to existing glyph)
+ *
+ * Note that if new glyph already exists in table, it is freed and a pointer to
+ * the existing glyph is returned. If the glyph does not exist in the table
+ * it is added and its pointer is returned.
+ *
+ * \param new New glyph to add (may be freed)
+ * \return pointer to glyph in hash table
+ */
+static glyph_entry * glyph_add_to_table(glyph_entry *new)
+{
+ uint32_t hash = glyph_hash(new->data.u8);
+
+ return glyph_add_to_chain(&ht[hash % BUCKETS], new);
+}
+
+
+/**
+ * Free glyph table.
+ */
+static void free_table(void)
+{
+ int i;
+
+ for (i = 0; i < BUCKETS; i++) {
+ free_chain(ht[i]);
+ }
+}
+
+struct parse_context {
+ enum {
+ START,
+ IN_HEADER,
+ BEFORE_ID,
+ GLYPH_ID,
+ BEFORE_GLYPH_DATA,
+ IN_GLYPH_DATA
+ } state; /**< Current parser state */
+
+ union {
+ struct {
+ bool new_line;
+ } in_header;
+ struct {
+ bool new_line;
+ bool u;
+ } before_id;
+ struct {
+ int c;
+ } g_id;
+ struct {
+ bool new_line;
+ bool prev_h;
+ bool prev_s;
+ int c;
+ } before_gd;
+ struct {
+ int line;
+ int pos;
+ int styles;
+ int line_styles;
+ glyph_entry *e[4];
+ } in_gd;
+ } data; /**< The state specific data */
+
+ int id; /**< Current ID */
+
+ int codepoints; /**< Glyphs containing codepoints */
+ int count[4]; /**< Count of glyphs in file */
+};
+
+struct font_data {
+ char header[HEADER_MAX];
+ int header_len;
+
+ uint8_t section_table[4][256];
+ uint8_t sec_count[4];
+ uint16_t *sections[4];
+
+ glyph_entry *e[0xffff];
+ int glyphs;
+};
+
+bool generate_font_header(const char *path, struct font_data *data)
+{
+ FILE *fp;
+ int s;
+
+ fp = fopen(path, "wb");
+ if (fp == NULL) {
+ LOG(LOG_ERROR, "Couldn't open header file \"%s\"\n", path);
+ return false;
+ }
+
+ fprintf(fp, "/*\n");
+ fwrite(data->header, 1, data->header_len, fp);
+ fprintf(fp, " */\n\n");
+ fprintf(fp, "/* Don't edit this file, it was generated from the "
+ "plain text source data. */\n\n");
+
+
+ for (s = 0; s < 4; s++) {
+ fprintf(fp, "const uint8_t *%s_section_table;\n",
+ var_lables[s]);
+ fprintf(fp, "const uint16_t *%s_sections;\n",
+ var_lables[s]);
+
+ }
+
+ fprintf(fp, "const uint8_t *font_glyph_data;\n");
+
+ fprintf(fp, "\n\n");
+
+ fclose(fp);
+
+ return true;
+
+}
+
+bool generate_font_source(const char *path, struct font_data *data)
+{
+ int s, i, y;
+ int limit;
+ FILE *fp;
+
+ fp = fopen(path, "wb");
+ if (fp == NULL) {
+ LOG(LOG_ERROR, "Couldn't open output file \"%s\"\n", path);
+ return false;
+ }
+
+ fprintf(fp, "/*\n");
+ fwrite(data->header, 1, data->header_len, fp);
+ fprintf(fp, " */\n\n");
+ fprintf(fp, "/* Don't edit this file, it was generated from the "
+ "plain text source data. */\n\n");
+
+ fprintf(fp, "#include <stdint.h>\n");
+ fprintf(fp, "\n");
+
+ for (s = 0; s < 4; s++) {
+
+ fprintf(fp, "static const uint8_t %s_section_table_c[256] = {\n",
+ var_lables[s]);
+
+ for (i = 0; i < 256; i++) {
+ if (i == 255)
+ fprintf(fp, "0x%.2X\n",
+ data->section_table[s][i]);
+ else if (i % 8 == 7)
+ fprintf(fp, "0x%.2X,\n",
+ data->section_table[s][i]);
+ else if (i % 8 == 0)
+ fprintf(fp, "\t0x%.2X, ",
+ data->section_table[s][i]);
+ else
+ fprintf(fp, "0x%.2X, ",
+ data->section_table[s][i]);
+ }
+
+ fprintf(fp, "};\nconst uint8_t *%s_section_table = &%s_section_table_c[0];\n\n",
+ var_lables[s], var_lables[s]);
+ fprintf(fp, "static const uint16_t %s_sections_c[%i] = {\n",
+ var_lables[s], data->sec_count[s] * 256);
+
+ limit = data->sec_count[s] * 256;
+ for (i = 0; i < limit; i++) {
+ uint16_t offset = data->sections[s][i];
+ if (i == limit - 1)
+ fprintf(fp, "0x%.4X\n", offset);
+ else if (i % 4 == 3)
+ fprintf(fp, "0x%.4X,\n", offset);
+ else if (i % 4 == 0)
+ fprintf(fp, "\t0x%.4X, ", offset);
+ else
+ fprintf(fp, "0x%.4X, ", offset);
+ }
+
+ fprintf(fp, "};\nconst uint16_t *%s_sections = &%s_sections_c[0];\n\n", var_lables[s], var_lables[s]);
+ }
+
+ fprintf(fp, "static const uint8_t font_glyph_data_c[%i] = {\n",
+ (data->glyphs + 1) * 16);
+
+ fprintf(fp, "\t0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\n"
+ "\t0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\n");
+
+ limit = data->glyphs;
+ for (i = 0; i < limit; i++) {
+ glyph_entry *e = data->e[i];
+
+ for (y = 0; y < 16; y++) {
+ if (i == limit - 1 && y == 15)
+ fprintf(fp, "0x%.2X\n", e->data.u8[y]);
+ else if (y % 8 == 7)
+ fprintf(fp, "0x%.2X,\n", e->data.u8[y]);
+ else if (y % 8 == 0)
+ fprintf(fp, "\t0x%.2X, ", e->data.u8[y]);
+ else
+ fprintf(fp, "0x%.2X, ", e->data.u8[y]);
+ }
+ }
+
+ fprintf(fp, "};\n");
+ fprintf(fp, "const uint8_t *font_glyph_data = &font_glyph_data_c[0];\n\n");
+
+ fclose(fp);
+
+ return true;
+}
+
+static bool add_glyph_to_data(glyph_entry *add, int id, int style,
+ struct font_data *d)
+{
+ glyph_entry *e;
+ int offset;
+ int s;
+
+ /* Find out if 'add' is unique, and get its unique table entry */
+ e = glyph_add_to_table(add);
+ if (e == add) {
+ /* Unique glyph */
+ d->e[d->glyphs++] = e;
+ e->index = d->glyphs;
+ if (d->glyphs >= 0xfffd) {
+ LOG(LOG_ERROR, " Too many glyphs for internal data "
+ "representation\n");
+ return false;
+ }
+ } else {
+ /* Duplicate glyph */
+ LOG(LOG_DEBUG, " U+%.4X (%s) is duplicate\n",
+ id, short_labels[style]);
+ }
+
+ /* Find glyph's section */
+ s = id / 256;
+
+ /* Allocate section if needed */
+ if ((s == 0 && d->sections[style] == NULL) ||
+ (s != 0 && d->section_table[style][s] == 0)) {
+ size_t size = (d->sec_count[style] + 1) * SECTION_SIZE;
+ uint16_t *temp = realloc(d->sections[style], size);
+ if (temp == NULL) {
+ LOG(LOG_ERROR, " Couldn't increase sections "
+ "allocation\n");
+ return false;
+ }
+ memset(temp + d->sec_count[style] * 256, 0,
+ SECTION_SIZE);
+ d->section_table[style][s] = d->sec_count[style];
+ d->sections[style] = temp;
+ d->sec_count[style]++;
+ }
+
+ offset = d->section_table[style][s] * 256 + (id & 0xff);
+ d->sections[style][offset] = e->index;
+
+ return true;
+}
+
+
+static bool check_glyph_data_valid(int pos, char c)
+{
+ int offset = pos % 11;
+
+ if (pos == 44) {
+ if (c != '\n') {
+ LOG(LOG_ERROR, " Invalid glyph data: "
+ "expecting '\\n', got '%c' (%i)\n",
+ c, c);
+ return false;
+ } else {
+ return true;
+ }
+ } else if (pos < 3) {
+ if (c != ' ') {
+ LOG(LOG_ERROR, " Invalid glyph data: "
+ "expecting ' ', got '%c' (%i)\n",
+ c, c);
+ return false;
+ } else {
+ return true;
+ }
+ } else if (offset == 0) {
+ if (c != '\n' && c != ' ') {
+ LOG(LOG_ERROR, " Invalid glyph data: "
+ "expecting '\\n' or ' ', "
+ "got '%c' (%i)\n",
+ c, c);
+ return false;
+ } else {
+ return true;
+ }
+ } else if (offset < 3) {
+ if (c != ' ') {
+ LOG(LOG_ERROR, " Invalid glyph data: "
+ "expecting ' ', got '%c' (%i)\n",
+ c, c);
+ return false;
+ } else {
+ return true;
+ }
+ } else if (offset >= 3 && pos < 11) {
+ if (c != '.' && c != '#') {
+ LOG(LOG_ERROR, " Invalid glyph data: "
+ "expecting '.' or '#', "
+ "got '%c' (%i)\n",
+ c, c);
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ /* offset must be >=3 */
+ if (c != '.' && c != '#' && c != ' ') {
+ LOG(LOG_ERROR, " Invalid glyph data: "
+ "expecting '.', '#', or ' ', "
+ "got '%c' (%i)\n",
+ c, c);
+ return false;
+ }
+
+ return true;
+}
+
+#define SEVEN_SET ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | \
+ (1 << 4) | (1 << 5) | (1 << 6))
+
+#define THREE_SSS ((1 << 0) | (1 << 1) | (1 << 2))
+#define THREE_S_S ((1 << 0) | (1 << 2))
+#define THREE__SS ((1 << 0) | (1 << 1) )
+#define THREE_SS_ ( (1 << 1) | (1 << 2))
+#define THREE_S__ (1 << 2)
+#define THREE__S_ (1 << 1)
+#define THREE___S (1 << 0)
+
+uint8_t frag[16][5] = {
+ { THREE_SSS,
+ THREE_S_S,
+ THREE_S_S,
+ THREE_S_S,
+ THREE_SSS },
+
+ { THREE__S_,
+ THREE_SS_,
+ THREE__S_,
+ THREE__S_,
+ THREE_SSS },
+
+ { THREE_SS_,
+ THREE___S,
+ THREE__S_,
+ THREE_S__,
+ THREE_SSS },
+
+ { THREE_SS_,
+ THREE___S,
+ THREE_SS_,
+ THREE___S,
+ THREE_SS_ },
+
+ { THREE_S_S,
+ THREE_S_S,
+ THREE_SSS,
+ THREE___S,
+ THREE___S },
+
+ { THREE_SSS,
+ THREE_S__,
+ THREE_SSS,
+ THREE___S,
+ THREE_SSS },
+
+ { THREE__SS,
+ THREE_S__,
+ THREE_SSS,
+ THREE_S_S,
+ THREE_SSS },
+
+ { THREE_SSS,
+ THREE___S,
+ THREE__S_,
+ THREE__S_,
+ THREE__S_ },
+
+ { THREE_SSS,
+ THREE_S_S,
+ THREE_SSS,
+ THREE_S_S,
+ THREE_SSS },
+
+ { THREE_SSS,
+ THREE_S_S,
+ THREE_SSS,
+ THREE___S,
+ THREE___S },
+
+ { THREE__S_,
+ THREE_S_S,
+ THREE_SSS,
+ THREE_S_S,
+ THREE_S_S },
+
+ { THREE_SS_,
+ THREE_S_S,
+ THREE_SS_,
+ THREE_S_S,
+ THREE_SS_ },
+
+ { THREE__S_,
+ THREE_S_S,
+ THREE_S__,
+ THREE_S_S,
+ THREE__S_ },
+
+ { THREE_SS_,
+ THREE_S_S,
+ THREE_S_S,
+ THREE_S_S,
+ THREE_SS_ },
+
+ { THREE_SSS,
+ THREE_S__,
+ THREE_SS_,
+ THREE_S__,
+ THREE_SSS },
+
+ { THREE_SSS,
+ THREE_S__,
+ THREE_SS_,
+ THREE_S__,
+ THREE_S__ }
+};
+
+void build_codepoint(int id, bool italic, uint8_t *code_point)
+{
+ int shift = 0;
+ int l;
+ int r;
+
+ if (!italic)
+ shift = 1;
+
+ l = (id >> 12);
+ r = 0xf & (id >> 8);
+
+ code_point[ 0] = 0;
+ code_point[ 1] = SEVEN_SET << shift;
+ code_point[ 2] = 0;
+
+ code_point[ 3] = (frag[l][0] << (4 + shift)) | (frag[r][0] << shift);
+ code_point[ 4] = (frag[l][1] << (4 + shift)) | (frag[r][1] << shift);
+ code_point[ 5] = (frag[l][2] << (4 + shift)) | (frag[r][2] << shift);
+ code_point[ 6] = (frag[l][3] << (4 + shift)) | (frag[r][3] << shift);
+ code_point[ 7] = (frag[l][4] << (4 + shift)) | (frag[r][4] << shift);
+
+ code_point[ 8] = 0;
+
+ shift = 1;
+
+ l = 0xf & (id >> 4);
+ r = 0xf & id ;
+
+ code_point[ 9] = (frag[l][0] << (4 + shift)) | (frag[r][0] << shift);
+ code_point[10] = (frag[l][1] << (4 + shift)) | (frag[r][1] << shift);
+ code_point[11] = (frag[l][2] << (4 + shift)) | (frag[r][2] << shift);
+ code_point[12] = (frag[l][3] << (4 + shift)) | (frag[r][3] << shift);
+ code_point[13] = (frag[l][4] << (4 + shift)) | (frag[r][4] << shift);
+
+ code_point[14] = 0;
+ code_point[15] = SEVEN_SET << shift;
+}
+
+#undef SEVEN_SET
+#undef THREE_SSS
+#undef THREE_S_S
+#undef THREE__SS
+#undef THREE_SS_
+#undef THREE_S__
+#undef THREE__S_
+#undef THREE___S
+
+static bool glyph_is_codepoint(const glyph_entry *e, int id, int style)
+{
+ bool italic = false;
+
+ if (style == 1 || style == 3) {
+ italic = true;
+ }
+
+ build_codepoint(id, italic, code_point);
+
+ return glyphs_match(code_point, e->data.u8);
+}
+
+
+static bool parse_glyph_data(struct parse_context *ctx, char c,
+ struct font_data *d)
+{
+ int glyph = ctx->data.in_gd.pos / 11;
+ int g_pos = ctx->data.in_gd.pos % 11 - 3;
+ uint8_t *row;
+ bool ok;
+ int i;
+
+ /* Check that character is valid */
+ if (check_glyph_data_valid(ctx->data.in_gd.pos, c) == false) {
+ LOG(LOG_ERROR, " Error in U+%.4X data: "
+ "glyph line: %i, pos: %i\n",
+ ctx->id,
+ ctx->data.in_gd.line,
+ ctx->data.in_gd.pos);
+ goto error;
+ }
+
+ /* Allocate glyph data if needed */
+ if (ctx->data.in_gd.line == 0 &&
+ (c == '.' || c == '#')) {
+ if (ctx->data.in_gd.e[glyph] == NULL) {
+ ctx->data.in_gd.e[glyph] =
+ calloc(sizeof(struct glyph_entry), 1);
+ if (ctx->data.in_gd.e[glyph] == NULL) {
+ LOG(LOG_ERROR, " Couldn't allocate memory for "
+ "glyph entry\n");
+ goto error;
+ }
+
+ ctx->data.in_gd.styles |= 1 << glyph;
+ }
+ }
+
+ /* Build glyph data */
+ if (c == '#') {
+ row = &ctx->data.in_gd.e[glyph]->data.u8[ctx->data.in_gd.line];
+ *row += 1 << (7 - g_pos);
+
+ ctx->data.in_gd.line_styles |= 1 << glyph;
+ } else if (c == '.') {
+ ctx->data.in_gd.line_styles |= 1 << glyph;
+ }
+
+ /* Deal with current position */
+ if (c == '\n') {
+ if (ctx->data.in_gd.line == 0) {
+ if (ctx->data.in_gd.e[0] == NULL) {
+ LOG(LOG_ERROR, " Error in U+%.4X data: "
+ "\"Regular\" glyph style must "
+ "be present\n", ctx->id);
+ goto error;
+ }
+ } else if (ctx->data.in_gd.styles !=
+ ctx->data.in_gd.line_styles) {
+ LOG(LOG_ERROR, " Error in U+%.4X data: "
+ "glyph line: %i "
+ "styles don't match first line\n",
+ ctx->id,
+ ctx->data.in_gd.line);
+ goto error;
+ }
+
+ ctx->data.in_gd.pos = 0;
+ ctx->data.in_gd.line++;
+ ctx->data.in_gd.line_styles = 0;
+ } else {
+ ctx->data.in_gd.pos++;
+ }
+
+ /* If we've got all the glyph data, tidy up and advance state */
+ if (ctx->data.in_gd.line == 16) {
+ for (i = 0; i < 4; i++) {
+ if (ctx->data.in_gd.e[i] != NULL) {
+ ctx->count[i] += 1;
+ if (glyph_is_codepoint(ctx->data.in_gd.e[i],
+ ctx->id, i)) {
+ LOG(LOG_DEBUG, " U+%.4X (%s) is "
+ "codepoint\n",
+ ctx->id,
+ short_labels[i]);
+ ctx->codepoints += 1;
+ free(ctx->data.in_gd.e[i]);
+ ctx->data.in_gd.e[i] = NULL;
+ continue;
+ }
+
+ ok = add_glyph_to_data(ctx->data.in_gd.e[i],
+ ctx->id, i, d);
+ if (!ok) {
+ goto error;
+ }
+ }
+ }
+
+ ctx->data.before_id.new_line = false;
+ ctx->data.before_id.u = false;
+ ctx->state = BEFORE_ID;
+ }
+
+ return true;
+
+error:
+
+ for (i = 0; i < 4; i++) {
+ free(ctx->data.in_gd.e[i]);
+ }
+
+ return false;
+}
+
+static void parse_init(struct parse_context *ctx)
+{
+ memset(ctx, 0, sizeof(struct parse_context));
+}
+
+static bool get_hex_digit_value(char c, int *v)
+{
+ if (c >= '0' && c <= '9')
+ *v = (c - '0');
+ else if (c >= 'A' && c <= 'F')
+ *v = (10 + c - 'A');
+ else {
+ LOG(LOG_ERROR, "Invalid hex digit '%c' (%i)\n", c, c);
+ return false;
+ }
+
+ return true;
+}
+
+static bool assemble_codepoint(const char* c, int n, int *id)
+{
+ bool ok;
+ int v;
+
+ ok = get_hex_digit_value(*c, &v);
+ if (!ok) {
+ return false;
+ }
+
+ *id += v << (4 * (3 - n));
+
+ return true;
+}
+
+static bool parse_chunk(struct parse_context *ctx, const char *buf, size_t len,
+ struct font_data *d)
+{
+ int i;
+ bool ok;
+ int count[4];
+ const char *pos = buf;
+ const char *end = buf + len;
+
+ for (i = 0; i < 4; i++) {
+ count[i] = ctx->count[i];
+ }
+
+ while (pos < end) {
+ if (*pos == '\r') {
+ LOG(LOG_ERROR, "Detected \'\\r\': Bad line ending\n");
+ return false;
+ }
+
+ switch (ctx->state) {
+ case START:
+ if (*pos != '*') {
+ LOG(LOG_ERROR, "First character must be '*'\n");
+ printf("Got: %c (%i)\n", *pos, *pos);
+ return false;
+ }
+ d->header_len = 0;
+ ctx->data.in_header.new_line = true;
+ ctx->state = IN_HEADER;
+
+ /* Fall through */
+ case IN_HEADER:
+ if (ctx->data.in_header.new_line == true) {
+ if (*pos != '*') {
+ LOG(LOG_INFO, " Got header "
+ "(%i bytes)\n",
+ d->header_len);
+ LOG(LOG_DEBUG, " Header:\n\n%.*s\n",
+ d->header_len,
+ d->header);
+ ctx->data.before_id.new_line = false;
+ ctx->data.before_id.u = false;
+ ctx->state = BEFORE_ID;
+ continue;
+ } else if (*pos == '*') {
+ d->header[d->header_len++] = ' ';
+ }
+ ctx->data.in_header.new_line = false;
+
+ } else if (*pos == '\n') {
+ ctx->data.in_header.new_line = true;
+ }
+
+ if (d->header_len == HEADER_MAX) {
+ LOG(LOG_ERROR, " Header too long "
+ "(>%i bytes)\n",
+ d->header_len);
+ return false;
+ }
+
+ d->header[d->header_len++] = *pos;
+ break;
+
+ case BEFORE_ID:
+ if (*pos == '+' &&
+ ctx->data.before_id.new_line == true &&
+ ctx->data.before_id.u == true) {
+ ctx->data.g_id.c = 0;
+ ctx->id = 0;
+ ctx->state = GLYPH_ID;
+ break;
+
+ } else if (*pos == 'U' &&
+ ctx->data.before_id.new_line == true) {
+ ctx->data.before_id.u = true;
+
+ } else if (*pos == '\n') {
+ ctx->data.before_id.new_line = true;
+ ctx->data.before_id.u = false;
+
+ } else {
+ ctx->data.before_id.new_line = false;
+ ctx->data.before_id.u = false;
+ }
+ break;
+
+ case GLYPH_ID:
+ ok = assemble_codepoint(pos, ctx->data.g_id.c++,
+ &ctx->id);
+ if (!ok) {
+ LOG(LOG_ERROR, " Invalid glyph ID\n");
+ return false;
+ }
+
+ if (ctx->data.g_id.c == 4) {
+ ctx->data.before_gd.new_line = false;
+ ctx->data.before_gd.prev_h = false;
+ ctx->data.before_gd.prev_s = false;
+ ctx->data.before_gd.c = 0;
+ ctx->state = BEFORE_GLYPH_DATA;
+ break;
+ }
+ break;
+
+ case BEFORE_GLYPH_DATA:
+ /* Skip until end of dashed line */
+ if (*pos == '\n' && ctx->data.before_gd.c == 53) {
+ ctx->state = IN_GLYPH_DATA;
+ ctx->data.in_gd.e[0] = NULL;
+ ctx->data.in_gd.e[1] = NULL;
+ ctx->data.in_gd.e[2] = NULL;
+ ctx->data.in_gd.e[3] = NULL;
+ ctx->data.in_gd.line = 0;
+ ctx->data.in_gd.pos = 0;
+ ctx->data.in_gd.line_styles = 0;
+ ctx->data.in_gd.styles = 0;
+ break;
+
+ } else if (*pos == '\n') {
+ ctx->data.before_gd.new_line = true;
+ ctx->data.before_gd.prev_h = false;
+ ctx->data.before_gd.prev_s = false;
+ ctx->data.before_gd.c = 0;
+ } else if (*pos == '-' &&
+ ctx->data.before_gd.new_line == true) {
+ assert(ctx->data.before_gd.c == 0);
+ ctx->data.before_gd.new_line = false;
+ ctx->data.before_gd.c++;
+ ctx->data.before_gd.prev_h = true;
+ } else if (*pos == ' ' &&
+ ctx->data.before_gd.prev_h == true) {
+ assert(ctx->data.before_gd.prev_s == false);
+ ctx->data.before_gd.c++;
+ ctx->data.before_gd.prev_h = false;
+ ctx->data.before_gd.prev_s = true;
+ } else if (*pos == '-' &&
+ ctx->data.before_gd.prev_s == true) {
+ assert(ctx->data.before_gd.prev_h == false);
+ ctx->data.before_gd.c++;
+ ctx->data.before_gd.prev_h = true;
+ ctx->data.before_gd.prev_s = false;
+ } else {
+ ctx->data.before_gd.new_line = false;
+ ctx->data.before_gd.prev_h = false;
+ ctx->data.before_gd.prev_s = false;
+ ctx->data.before_gd.c = 0;
+ }
+ break;
+
+ case IN_GLYPH_DATA:
+ ok = parse_glyph_data(ctx, *pos, d);
+ if (!ok) {
+ return false;
+ }
+
+ break;
+ }
+
+ pos++;
+ }
+
+ for (i = 0; i < 4; i++) {
+ LOG(LOG_DEBUG, " %s: %i gylphs\n", labels[i],
+ ctx->count[i] - count[i]);
+ }
+
+ return true;
+}
+
+
+bool load_font(const char *path, struct font_data **data)
+{
+ struct parse_context ctx;
+ struct font_data *d;
+ size_t file_len;
+ size_t done;
+ size_t len;
+ int count;
+ char *buf;
+ FILE *fp;
+ bool ok;
+ int i;
+
+ *data = NULL;
+
+ fp = fopen(path, "rb");
+ if (fp == NULL) {
+ LOG(LOG_ERROR, "Couldn't open font data file\n");
+ return false;
+ }
+
+ d = calloc(sizeof(struct font_data), 1);
+ if (d == NULL) {
+ LOG(LOG_ERROR, "Couldn't allocate memory for font data\n");
+ fclose(fp);
+ return false;
+ }
+
+ /* Find filesize */
+ fseek(fp, 0L, SEEK_END);
+ file_len = ftell(fp);
+ if (file_len == -1) {
+ LOG(LOG_ERROR, "Could not size input file\n");
+ free(d);
+ fclose(fp);
+ return false;
+ }
+ fseek(fp, 0L, SEEK_SET);
+ LOG(LOG_DEBUG, "Input size: %zu bytes\n", file_len);
+
+ /* Allocate buffer for data chunks */
+ buf = malloc(CHUNK_SIZE);
+ if (buf == NULL) {
+ LOG(LOG_ERROR, "Couldn't allocate memory for input buffer\n");
+ free(d);
+ fclose(fp);
+ return false;
+ }
+
+ /* Initialise parser */
+ parse_init(&ctx);
+
+ LOG(LOG_DEBUG, "Using chunk size of %i bytes\n", CHUNK_SIZE);
+
+ /* Parse the input file in chunks */
+ for (done = 0; done < file_len; done += CHUNK_SIZE) {
+ LOG(LOG_INFO, "Parsing input chunk %zu\n", done / CHUNK_SIZE);
+
+ /* Read chunk */
+ len = fread(buf, 1, CHUNK_SIZE, fp);
+ if (file_len - done < CHUNK_SIZE &&
+ len != file_len - done) {
+ LOG(LOG_WARNING, "Last chunk has suspicious size\n");
+ } else if (file_len - done >= CHUNK_SIZE &&
+ len != CHUNK_SIZE) {
+ LOG(LOG_ERROR, "Problem reading file\n");
+ free(buf);
+ free(d);
+ fclose(fp);
+ return false;
+ }
+
+ /* Parse chunk */
+ ok = parse_chunk(&ctx, buf, len, d);
+ if (!ok) {
+ free(buf);
+ free(d);
+ fclose(fp);
+ return false;
+ }
+ LOG(LOG_DEBUG, "Parsed %zu bytes\n", done + len);
+ }
+
+ fclose(fp);
+
+ if (ctx.state != BEFORE_ID) {
+ LOG(LOG_ERROR, "Unexpected end of file\n");
+ free(buf);
+ free(d);
+ return false;
+ }
+
+ LOG(LOG_INFO, "Parsing complete:\n");
+ count = 0;
+ for (i = 0; i < 4; i++) {
+ LOG(LOG_INFO, " %s: %i gylphs\n", labels[i], ctx.count[i]);
+ count += ctx.count[i];
+ }
+
+ LOG(LOG_RESULT, " Total %i gylphs "
+ "(of which %i unique, %i codepoints, %i duplicates)\n",
+ count, d->glyphs, ctx.codepoints,
+ count - d->glyphs - ctx.codepoints);
+
+ free(buf);
+
+ *data = d;
+ return true;
+}
+
+static void log_usage(const char *argv0)
+{
+ level = LOG_INFO;
+ LOG(LOG_INFO,
+ "Usage:\n"
+ "\t%s [options] <in_file> <out_file>\n"
+ "\n"
+ "Options:\n"
+ "\t--help -h Display this text\n"
+ "\t--quiet -q Don't show warnings\n"
+ "\t--verbose -v Verbose output\n"
+ "\t--debug -d Full debug output\n",
+ argv0);
+}
+
+int main(int argc, char** argv)
+{
+ const char *in_path = NULL;
+ const char *out_path = NULL;
+ char *header_path = NULL;
+ struct font_data *data;
+ bool ok;
+ int i;
+ int opt;
+
+ level = LOG_RESULT;
+
+ /* Handle program arguments */
+ struct option long_options[] = {
+ { "help", no_argument, NULL, 'h' },
+ { "quiet", no_argument, NULL, 'q' },
+ { "verbose", no_argument, NULL, 'v' },
+ { "debug", no_argument, NULL, 'd' },
+ { "header", required_argument, NULL, 'H' },
+ };
+
+ while ((opt = getopt_long(argc, argv, "hqvdH:", long_options, NULL)) != -1) {
+ switch (opt) {
+ case 'q':
+ level = LOG_WARNING;
+ break;
+
+ case 'v':
+ level = LOG_INFO;
+ break;
+
+ case 'd':
+ level = LOG_DEBUG;
+ break;
+
+ case 'H':
+ header_path = strdup(optarg);
+ break;
+
+ case 'h':
+ log_usage(argv[0]);
+ free(header_path);
+ return EXIT_SUCCESS;
+
+ default:
+ log_usage(argv[0]);
+ free(header_path);
+ return EXIT_FAILURE;
+ }
+ }
+
+ if ((argc - optind) < 2) {
+ log_usage(argv[0]);
+ free(header_path);
+ return EXIT_FAILURE;
+ }
+
+ in_path = argv[optind];
+ out_path = argv[optind + 1];
+
+ LOG(LOG_DEBUG, "Using input path: \"%s\"\n", in_path);
+ LOG(LOG_DEBUG, "Using output path: \"%s\"\n", out_path);
+
+ ok = load_font(in_path, &data);
+ if (!ok) {
+ free_table();
+ free(header_path);
+ return EXIT_FAILURE;
+ }
+
+ ok = generate_font_source(out_path, data);
+ if (ok && (header_path != NULL)) {
+ ok = generate_font_header(header_path, data);
+ }
+ free(header_path);
+ free_table();
+ for (i = 0; i < 4; i++) {
+ free(data->sections[i]);
+ }
+ free(data);
+ if (!ok) {
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/frontends/kolibrios/fb/convert_image.c b/frontends/kolibrios/fb/convert_image.c
new file mode 100644
index 0000000..de772fc
--- a/dev/null
+++ b/frontends/kolibrios/fb/convert_image.c
@@ -0,0 +1,304 @@
+/*
+ * Copyright 2009 Daniel Silverstone <dsilvers@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdbool.h>
+#include <errno.h>
+#include <stdio.h>
+#include <png.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if PNG_LIBPNG_VER < 10209
+#define png_set_expand_gray_1_2_4_to_8(png) png_set_gray_1_2_4_to_8(png)
+#endif
+
+static png_structp png;
+static png_infop info;
+static int interlace;
+static size_t rowbytes;
+static int raw_width, raw_height;
+static int rowstride;
+static unsigned char *bitmap_data;
+static bool is_cursor = true;
+static int raw_hot_x, raw_hot_y;
+
+#define WIDTH (is_cursor?raw_width-1:raw_width)
+#define HEIGHT (is_cursor?raw_height-1:raw_height)
+
+#define HOT_X (is_cursor?raw_hot_x-1:0)
+#define HOT_Y (is_cursor?raw_hot_y-1:0)
+
+#define REAL(v) (is_cursor?v+1:v)
+
+#define PPIX_AT(x,y) ((bitmap_data + (rowstride * y)) + (x * 4))
+
+#define R_OFF 2
+#define G_OFF 1
+#define B_OFF 0
+#define A_OFF 3
+
+#define R_AT(x,y) *(PPIX_AT(x,y) + R_OFF)
+#define G_AT(x,y) *(PPIX_AT(x,y) + G_OFF)
+#define B_AT(x,y) *(PPIX_AT(x,y) + B_OFF)
+#define A_AT(x,y) *(PPIX_AT(x,y) + A_OFF)
+
+
+static void
+usage(void)
+{
+ fprintf(stderr, "usage: fb_convert_image input.png output.inc varname\n");
+}
+
+
+static void
+detect_hotspot(void)
+{
+ int i;
+ int greenpixels = 0;
+
+ for (i = 0; i < raw_width; ++i) {
+ if (A_AT(i, 0) == 255) {
+ if (G_AT(i, 0) == 255) {
+ greenpixels++;
+ raw_hot_x = i;
+ }
+ if ((B_AT(i, 0) != 0) || (R_AT(i, 0) != 0)) {
+ is_cursor = false;
+ return;
+ }
+ } else if (A_AT(i, 0) != 0) {
+ is_cursor = false;
+ return;
+ }
+ }
+ if (greenpixels != 1) {
+ is_cursor = false;
+ return;
+ }
+
+ for (i = 0; i < raw_height; ++i) {
+ if (A_AT(0, i) == 255) {
+ if (G_AT(0, i) == 255) {
+ greenpixels++;
+ raw_hot_y = i;
+ }
+ if ((B_AT(0, i) != 0) || (R_AT(0, i) != 0)) {
+ is_cursor = false;
+ return;
+ }
+ } else if (A_AT(0, i) != 0) {
+ is_cursor = false;
+ return;
+ }
+ }
+ if (greenpixels != 2) {
+ is_cursor = false;
+ return;
+ }
+ printf(" Pointer detected. Adjusted hotspot at %d, %d (0-based)\n",
+ raw_hot_x - 1, raw_hot_y - 1);
+}
+
+
+static void
+info_callback(png_structp png, png_infop info)
+{
+ int bit_depth, color_type, interlace, intent;
+ double gamma;
+ png_uint_32 width, height;
+
+ /* Read the PNG details */
+ png_get_IHDR(png, info, &width, &height, &bit_depth,
+ &color_type, &interlace, 0, 0);
+
+ /* Set up our transformations */
+ if (color_type == PNG_COLOR_TYPE_PALETTE)
+ png_set_palette_to_rgb(png);
+ if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
+ png_set_expand_gray_1_2_4_to_8(png);
+ if (png_get_valid(png, info, PNG_INFO_tRNS))
+ png_set_tRNS_to_alpha(png);
+ if (bit_depth == 16)
+ png_set_strip_16(png);
+ if (color_type == PNG_COLOR_TYPE_GRAY ||
+ color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+ png_set_gray_to_rgb(png);
+ if (!(color_type & PNG_COLOR_MASK_ALPHA))
+ png_set_filler(png, 0xff, PNG_FILLER_AFTER);
+ /* gamma correction - we use 2.2 as our screen gamma
+ * this appears to be correct (at least in respect to !Browse)
+ * see http://www.w3.org/Graphics/PNG/all_seven.html for a test case
+ */
+ if (png_get_sRGB(png, info, &intent))
+ png_set_gamma(png, 2.2, 0.45455);
+ else {
+ if (png_get_gAMA(png, info, &gamma))
+ png_set_gamma(png, 2.2, gamma);
+ else
+ png_set_gamma(png, 2.2, 0.45455);
+ }
+
+
+ png_read_update_info(png, info);
+
+ rowbytes = png_get_rowbytes(png, info);
+ interlace = (interlace == PNG_INTERLACE_ADAM7);
+ raw_width = width;
+ raw_height = height;
+
+ rowstride = raw_width * 4;
+ bitmap_data = malloc(rowstride * raw_height);
+}
+
+static unsigned int interlace_start[8] = {0, 16, 0, 8, 0, 4, 0};
+static unsigned int interlace_step[8] = {28, 28, 12, 12, 4, 4, 0};
+static unsigned int interlace_row_start[8] = {0, 0, 4, 0, 2, 0, 1};
+static unsigned int interlace_row_step[8] = {8, 8, 8, 4, 4, 2, 2};
+
+static void
+row_callback(png_structp png, png_bytep new_row,
+ png_uint_32 row_num, int pass)
+{
+ unsigned long i, j;
+ unsigned int start, step;
+ unsigned char *row = bitmap_data + (rowstride * row_num);
+
+ if (new_row == 0)
+ return;
+
+ if (interlace) {
+ start = interlace_start[pass];
+ step = interlace_step[pass];
+ row_num = interlace_row_start[pass] +
+ interlace_row_step[pass] * row_num;
+
+ /* Copy the data to our current row taking interlacing
+ * into consideration */
+ row = bitmap_data + (rowstride * row_num);
+ for (j = 0, i = start; i < rowbytes; i += step) {
+ row[i++] = new_row[j++];
+ row[i++] = new_row[j++];
+ row[i++] = new_row[j++];
+ row[i++] = new_row[j++];
+ }
+ } else {
+ memcpy(row, new_row, rowbytes);
+ }
+}
+
+static void
+end_callback(png_structp png, png_infop info)
+{
+}
+
+
+int
+main(int argc, char **argv)
+{
+ FILE *f;
+ unsigned char buffer[1024];
+ int br;
+ int x, y, c;
+
+ if (argc != 4) {
+ usage();
+ return 1;
+ }
+
+ printf(" CONVERT: %s (%s)\n", argv[1], argv[3]);
+
+ png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
+ info = png_create_info_struct(png);
+
+ png_set_progressive_read_fn(png, NULL, info_callback, row_callback, end_callback);
+
+ f = fopen(argv[1], "rb");
+ if (f == NULL) {
+ printf(" Unable to open %s\n", argv[1]);
+ return 1;
+ }
+
+ do {
+ br = fread(buffer, 1, 1024, f);
+ if (br > 0) {
+ png_process_data(png, info, buffer, br);
+ }
+ } while (br > 0);
+
+ if (br < 0) {
+ printf("Error reading input: %s\n", strerror(errno));
+ fclose(f);
+ return 1;
+ }
+
+ fclose(f);
+
+ detect_hotspot();
+
+ f = fopen(argv[2], "w");
+ if (f == NULL) {
+ printf(" Unable to open %s\n", argv[2]);
+ return 2;
+ }
+
+ fprintf(f, "/* This file is auto-generated from %s\n", argv[1]);
+ fprintf(f, " *\n * Do not edit this file directly.\n */\n\n");
+ fprintf(f, "#include <sys/types.h>\n\n");
+ fprintf(f, "#include <stdint.h>\n\n");
+ fprintf(f, "#include <stdbool.h>\n\n");
+ fprintf(f, "#include <libnsfb.h>\n\n");
+ fprintf(f, "#include \"netsurf/plot_style.h\"\n");
+ fprintf(f, "#include \"framebuffer/gui.h\"\n");
+ fprintf(f, "#include \"framebuffer/fbtk.h\"\n\n");
+
+ fprintf(f, "static uint8_t %s_pixdata[] = {\n", argv[3]);
+ for (y = 0; y < HEIGHT; ++y) {
+ unsigned char *rowptr = bitmap_data + (rowstride * y);
+ if (is_cursor) {
+ /* If it's a cursor, skip one row and one column */
+ rowptr += rowstride + 4;
+ }
+ fprintf(f, "\t");
+ for (x = 0; x < WIDTH; ++x) {
+ for (c = 0; c < 4; ++c) {
+ unsigned char b = *rowptr++;
+ fprintf(f, "0x%02x, ", b);
+ }
+ }
+ fprintf(f, "\n");
+ }
+ fprintf(f, "};\n\n");
+
+ fprintf(f, "struct fbtk_bitmap %s = {\n", argv[3]);
+ fprintf(f, "\t.width\t\t= %d,\n", WIDTH);
+ fprintf(f, "\t.height\t\t= %d,\n", HEIGHT);
+ fprintf(f, "\t.hot_x\t\t= %d,\n", HOT_X);
+ fprintf(f, "\t.hot_y\t\t= %d,\n", HOT_Y);
+ fprintf(f, "\t.pixdata\t= %s_pixdata,\n", argv[3]);
+
+ fprintf(f, "};\n\n");
+ fclose(f);
+
+ return 0;
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset:8
+ * End:
+ */
diff --git a/frontends/kolibrios/fb/fb_search.c b/frontends/kolibrios/fb/fb_search.c
new file mode 100644
index 0000000..19fefa8
--- a/dev/null
+++ b/frontends/kolibrios/fb/fb_search.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
+ *
+ * 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 <stdbool.h>
+#include <string.h>
+
+#include "utils/log.h"
+
+/* callback functions for search implementation */
+static void gui_search_set_status(bool found, void *p);
+static void gui_search_set_hourglass(bool active, void *p);
+static void gui_search_add_recent(const char *string, void *p);
+static void gui_search_set_forward_state(bool active, void *p);
+static void gui_search_set_back_state(bool active, void *p);
+
+/**
+* Change the displayed search status.
+* \param found search pattern matched in text
+* \param p the pointer sent to search_verify_new() / search_create_context()
+*/
+void gui_search_set_status(bool found, void *p)
+{
+}
+
+/**
+* display hourglass while searching
+* \param active start/stop indicator
+* \param p the pointer sent to search_verify_new() / search_create_context()
+*/
+void gui_search_set_hourglass(bool active, void *p)
+{
+}
+
+/**
+* add search string to recent searches list
+* \param string search pattern
+* \param p the pointer sent to search_verify_new() / search_create_context()
+*/
+void gui_search_add_recent(const char *string, void *p)
+{
+}
+
+/**
+* activate search forwards button in gui
+* \param active activate/inactivate
+* \param p the pointer sent to search_verify_new() / search_create_context()
+*/
+void gui_search_set_forward_state(bool active, void *p)
+{
+}
+
+/**
+* activate search forwards button in gui
+* \param active activate/inactivate
+* \param p the pointer sent to search_verify_new() / search_create_context()
+*/
+void gui_search_set_back_state(bool active, void *p)
+{
+}
diff --git a/frontends/kolibrios/fb/fbtk.h b/frontends/kolibrios/fb/fbtk.h
new file mode 100644
index 0000000..3cc326c
--- a/dev/null
+++ b/frontends/kolibrios/fb/fbtk.h
@@ -0,0 +1,618 @@
+/*
+ * Copyright 2008,2010 Vincent Sanders <vince@simtec.co.uk>
+ *
+ * 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_FB_FBTK_H
+#define NETSURF_FB_FBTK_H
+
+#include "netsurf/types.h"
+
+#ifdef FBTK_LOGGING
+#define FBTK_LOG(x) LOG(x)
+#else
+#define FBTK_LOG(x)
+#endif
+
+#define FB_SCROLL_COLOUR 0xFFAAAAAA
+#define FB_FRAME_COLOUR 0xFFDDDDDD
+#define FB_COLOUR_BLACK 0xFF000000
+#define FB_COLOUR_WHITE 0xFFFFFFFF
+
+#define FBTK_WIDGET_PADDING 30 /**< percentage of widget size used for padding */
+#define FBTK_DPI 90 /**< screen DPI */
+
+typedef struct fbtk_widget_s fbtk_widget_t;
+
+/** Widget Callback type */
+typedef enum fbtk_callback_type {
+ FBTK_CBT_START = 0,
+ FBTK_CBT_SCROLLX,
+ FBTK_CBT_SCROLLY,
+ FBTK_CBT_CLICK,
+ FBTK_CBT_INPUT,
+ FBTK_CBT_POINTERMOVE,
+ FBTK_CBT_POINTERLEAVE,
+ FBTK_CBT_POINTERENTER,
+ FBTK_CBT_REDRAW,
+ FBTK_CBT_DESTROY,
+ FBTK_CBT_USER,
+ FBTK_CBT_STRIP_FOCUS,
+ FBTK_CBT_END,
+} fbtk_callback_type;
+
+/** widget callback information */
+typedef struct fbtk_callback_info {
+ enum fbtk_callback_type type;
+ void *context;
+ nsfb_event_t *event;
+ int x;
+ int y;
+ char *text;
+ fbtk_widget_t *widget;
+} fbtk_callback_info;
+
+/** framebuffer toolkit bitmaps */
+struct fbtk_bitmap {
+ int width;
+ int height;
+ uint8_t *pixdata;
+ bool opaque;
+
+ /* The following two are only used for cursors */
+ int hot_x;
+ int hot_y;
+};
+
+/** Key modifier status */
+typedef enum fbtk_modifier_type {
+ FBTK_MOD_CLEAR = 0,
+ FBTK_MOD_LSHIFT = (1 << 0),
+ FBTK_MOD_RSHIFT = (1 << 1),
+ FBTK_MOD_LCTRL = (1 << 2),
+ FBTK_MOD_RCTRL = (1 << 3)
+} fbtk_modifier_type;
+
+typedef int (*fbtk_callback)(fbtk_widget_t *widget, fbtk_callback_info *cbi);
+
+/* enter pressed on writable icon */
+typedef int (*fbtk_enter_t)(void *pw, char *text);
+
+
+/************************ Core ****************************/
+
+
+/**
+ * Initialise widget toolkit.
+ *
+ * Initialises widget toolkit against a framebuffer.
+ *
+ * @param fb The underlying framebuffer.
+ * @return The root widget handle.
+ */
+fbtk_widget_t *fbtk_init(nsfb_t *fb);
+
+/**
+ * Retrieve the framebuffer library handle from toolkit widget.
+ *
+ * @param widget A fbtk widget.
+ * @return The underlying framebuffer.
+ */
+nsfb_t *fbtk_get_nsfb(fbtk_widget_t *widget);
+
+/** Perform any pending widget redraws.
+ *
+ * @param widget A fbtk widget.
+ */
+int fbtk_redraw(fbtk_widget_t *widget);
+
+/** Determine if there are any redraws pending for a widget.
+ *
+ * Mainly used by clients on the root widget to determine if they need
+ * to call ::fbtk_redraw
+ *
+ * @param widget to check.
+ */
+bool fbtk_get_redraw_pending(fbtk_widget_t *widget);
+
+/** clip a bounding box to a widgets area.
+ */
+bool fbtk_clip_to_widget(fbtk_widget_t *widget, bbox_t * restrict box);
+
+/** clip one bounding box to another.
+ */
+bool fbtk_clip_rect(const bbox_t * restrict clip, bbox_t * restrict box);
+
+/***************** Callback processing ********************/
+
+/** Helper function to allow simple calling of callbacks with parameters.
+ *
+ * @param widget The fbtk widget to post the callback to.
+ * @param cbt The type of callback to post
+ * @param ... Parameters appropriate for the callback type.
+ */
+int fbtk_post_callback(fbtk_widget_t *widget, fbtk_callback_type cbt, ...);
+
+/** Set a callback handler.
+ *
+ * Set a callback handler and the pointer to pass for a widget.
+ *
+ * @param widget The widget to set the handler for.
+ * @param cbt The type of callback to set.
+ * @param cb The callback.
+ * @param pw The private pointer to pass when calling the callback.
+ * @return The previous callback handler for the type or NULL.
+ */
+fbtk_callback fbtk_set_handler(fbtk_widget_t *widget, fbtk_callback_type cbt, fbtk_callback cb, void *pw);
+
+/** Get a callback handler.
+ */
+fbtk_callback fbtk_get_handler(fbtk_widget_t *widget, fbtk_callback_type cbt);
+
+
+/******************* Event processing **********************/
+
+/** Retrive events from the framebuffer input.
+ *
+ * Obtain events from the framebuffer input system with a
+ * timeout. Some events may be used by the toolkit instead of being
+ * returned to the caller.
+ *
+ * @param root An fbtk widget.
+ * @param event an event structure to update.
+ * @param timeout The number of miliseconds to wait for an event. 0
+ * means do not wait and -1 means wait foreevr.
+ * @return wether \a event has been updated.
+ */
+bool fbtk_event(fbtk_widget_t *root, nsfb_event_t *event, int timeout);
+
+/** Insert mouse button press into toolkit.
+ */
+void fbtk_click(fbtk_widget_t *widget, nsfb_event_t *event);
+
+/** Insert input into toolkit.
+ */
+void fbtk_input(fbtk_widget_t *widget, nsfb_event_t *event);
+
+/** Move pointer.
+ *
+ * Move the pointer cursor to a given location.
+ *
+ * @param widget any tookit widget.
+ * @param x movement in horizontal plane.
+ * @param y movement in vertical plane.
+ * @param relative Wheter the /a x and /a y should be considered relative to
+ * current pointer position.
+ */
+void fbtk_warp_pointer(fbtk_widget_t *widget, int x, int y, bool relative);
+
+/** Toggle pointer grab.
+ *
+ * Toggles the movement grab for a widget.
+ *
+ * @param widget The widget trying to grab the movement.
+ * @return true if the grab was ok, false if the grab failed (already grabbed).
+ */
+bool fbtk_tgrab_pointer(fbtk_widget_t *widget);
+
+/** Convert a framebuffer keycode to ucs4.
+ *
+ * Character mapping between keycode with modifier state and ucs-4.
+ */
+int fbtk_keycode_to_ucs4(int code, fbtk_modifier_type mods);
+
+
+/******************* Widget Information **********************/
+
+/** Obtain the widget at a point on screen.
+ *
+ * @param widget any tookit widget.
+ * @param x location in horizontal plane.
+ * @param y location in vertical plane.
+ * @return widget or NULL.
+ */
+fbtk_widget_t *fbtk_get_widget_at(fbtk_widget_t *widget, int x, int y);
+
+/** Get a widget's absolute horizontal screen co-ordinate.
+ *
+ * @param widget The widget to inspect.
+ * @return The absolute screen co-ordinate.
+ */
+int fbtk_get_absx(fbtk_widget_t *widget);
+
+/** Get a widget's absolute vertical screen co-ordinate.
+ *
+ * @param widget The widget to inspect.
+ * @return The absolute screen co-ordinate.
+ */
+int fbtk_get_absy(fbtk_widget_t *widget);
+
+/**
+ * Get a widget's width.
+ *
+ * @param widget The widget to inspect.
+ * @return The widget width.
+ */
+int fbtk_get_width(fbtk_widget_t *widget);
+
+/**
+ * Get a widget's height.
+ *
+ * @param widget The widget to inspect.
+ * @return The widget height.
+ */
+int fbtk_get_height(fbtk_widget_t *widget);
+
+/**
+ * Get a widget's bounding box in absolute screen co-ordinates.
+ *
+ * @param widget The widget to inspect.
+ * @param bbox The bounding box structure to update.
+ * @return If the \a bbox parameter has been updated.
+ */
+bool fbtk_get_bbox(fbtk_widget_t *widget, struct nsfb_bbox_s *bbox);
+
+/**
+ * Get a widget caret pos, if it owns caret.
+ *
+ * @param widget The widget to inspect.
+ * @param x If widget has caret, returns x-coord of caret within widget
+ * @param y If widget has caret, returns y-coord of caret within widget
+ * @param height If widget has caret, returns caret height
+ * @return true iff widget has caret
+ */
+bool fbtk_get_caret(fbtk_widget_t *widget, int *x, int *y, int *height);
+
+
+/******************* Widget Manipulation **********************/
+
+/**
+ * Change the widget's position and size. (Doesn't redraw)
+ *
+ */
+bool fbtk_set_pos_and_size(fbtk_widget_t *widget, int x, int y, int width, int height);
+
+/**
+ * Set caret owner and position
+ *
+ * @param widget widget to give caret to, or ensure caret is released from
+ * @param set true: caret to be set for widget, false: caret to be released
+ * @param x x-coordinate of caret top
+ * @param y y-coordinate of caret top
+ * @param height height of caret
+ * @param remove_caret callback when caret is removed.
+ */
+void fbtk_set_caret(fbtk_widget_t *widget, bool set, int x, int y, int height,
+ void (*remove_caret)(fbtk_widget_t *widget));
+
+/**
+ * Map a widget and request it is redrawn.
+ */
+int fbtk_set_mapping(fbtk_widget_t *widget, bool mapped);
+
+/**
+ * Set the z order of a widget.
+ */
+int fbtk_set_zorder(fbtk_widget_t *widget, int z);
+
+/**
+ * Indicate a widget should be redrawn.
+ */
+void fbtk_request_redraw(fbtk_widget_t *widget);
+
+/**
+ * Destroy a widget and all its descendants.
+ *
+ * Removes a widget from the hierachy and frees it and all its children.
+ *
+ * @param widget The widget to destroy.
+ * @return 0 on success or -1 on error.
+ */
+int fbtk_destroy_widget(fbtk_widget_t *widget);
+
+
+
+/********************************* Widgets *********************************/
+
+
+/**
+ * Create a window widget.
+ *
+ * @param parent The parent window or the root widget for a top level window.
+ * @param x The x location relative to the parent window.
+ * @param y the y location relative to the parent window.
+ * @param width The width of the window. 0 indicates parents width should be
+ * used. Negative value indicates parents width less the value
+ * should be used. The width is limited to lie within the parent
+ * window.
+ * @param height The height of the window limited in a similar way to the
+ * /a width.
+ * @param bg The background colour.
+ * @return new window widget handle or NULL on error.
+ */
+fbtk_widget_t *fbtk_create_window(fbtk_widget_t *parent, int x, int y, int width, int height, colour bg);
+
+
+
+/**
+ * Create a filled rectangle
+ *
+ * Create a widget which is a filled rectangle, usually used for backgrounds.
+ *
+ * @param window The window to add the filled area widget to.
+ * @param x X coordinate of widget.
+ * @param y Y coordinate of widget.
+ * @param width Width of the widget
+ * @param height Height of the widget
+ * @param c widget colour
+ * @return new widget handle or NULL on error.
+ */
+fbtk_widget_t *
+fbtk_create_fill(fbtk_widget_t *window, int x, int y, int width, int height, colour c);
+
+
+/**
+ * Create a horizontal scroll widget
+ *
+ * Create a horizontal scroll widget.
+ *
+ * @param window The window to add the filled area widget to.
+ * @param x X coordinate of widget.
+ * @param y Y coordinate of widget.
+ * @param width Width of the widget
+ * @param height Height of the widget
+ * @param bg background colour
+ * @param fg foreground colour
+ * @param callback Called on scroll
+ * @param context context passed to callback.
+ * @return new widget handle or NULL on error.
+ */
+fbtk_widget_t *
+fbtk_create_hscroll(fbtk_widget_t *window, int x, int y, int width, int height, colour fg, colour bg, fbtk_callback callback, void *context);
+
+/**
+ * Create a vertical scroll widget
+ *
+ * Create a vertical scroll widget.
+ *
+ * @param window The window to add the filled area widget to.
+ * @param x X coordinate of widget.
+ * @param y Y coordinate of widget.
+ * @param width Width of the widget
+ * @param height Height of the widget
+ * @param bg background colour
+ * @param fg foreground colour
+ * @param callback Called on scroll
+ * @param context context passed to callback.
+ * @return new widget handle or NULL on error.
+ */
+fbtk_widget_t *
+fbtk_create_vscroll(fbtk_widget_t *window, int x, int y, int width, int height, colour fg, colour bg, fbtk_callback callback, void *context);
+
+/**
+ * Set scoll widget parameters
+ *
+ * @param widget The widget to set the parameters for.
+ * @param min The minimum range value.
+ * @param max The maximum range value.
+ * @param thumb The size of the slider.
+ * @param page The amout to scroll for a page.
+ * @return true if the scroll parameter was set else false.
+ */
+bool fbtk_set_scroll_parameters(fbtk_widget_t *widget, int min, int max, int thumb, int page);
+
+/**
+ * set scroll widget position.
+ *
+ * @param widget The widget to set the position on.
+ * @param pos The position to set
+ * @return true if the scroll parameter was set else false.
+ */
+bool fbtk_set_scroll_position(fbtk_widget_t *widget, int pos);
+
+
+/**
+ * Move and/or resize a horizontal scroll widget
+ *
+ * @param scrollh the horizontal scroll widget
+ * @param x new x pos
+ * @param y new y pos
+ * @param width new width
+ * @param height new height
+ */
+void fbtk_reposition_hscroll(fbtk_widget_t *scrollh,
+ int x, int y, int width, int height);
+
+/**
+ * Move and/or resize a vertical scroll widget
+ *
+ * @param scrollv the vertical scroll widget
+ * @param x new x pos
+ * @param y new y pos
+ * @param width new width
+ * @param height new height
+ */
+void fbtk_reposition_vscroll(fbtk_widget_t *scrollv,
+ int x, int y, int width, int height);
+
+
+/**
+ * Create a user widget.
+ *
+ * Create a widget which is to be handled entirely by the calling application.
+ *
+ * @param window The window to add the user widget to.
+ * @param x X coordinate of widget.
+ * @param y Y coordinate of widget.
+ * @param width Width of the widget
+ * @param height Height of the widget
+ * @param pw The private pointer which can be read using ::fbtk_get_userpw
+ * @return new widget handle or NULL on error.
+ */
+fbtk_widget_t *fbtk_create_user(fbtk_widget_t *window, int x, int y, int width, int height, void *pw);
+
+
+/**
+ * Get the user context from a widget
+ *
+ * @param widget The widget to get the context from.
+ * @return The context or NULL.
+ */
+void *fbtk_get_userpw(fbtk_widget_t *widget);
+
+
+/**
+ * Create a bitmap widget.
+ *
+ * Create a widget which shows a bitmap.
+ *
+ * @param window The window to add the bitmap widget to.
+ * @param x X coordinate of widget.
+ * @param y Y coordinate of widget.
+ * @param width Width of the widget
+ * @param height Height of the widget
+ * @param c background colour
+ * @param image The bitmap to put in the widget
+ * @return new widget handle or NULL on error.
+ */
+fbtk_widget_t *fbtk_create_bitmap(fbtk_widget_t *window, int x, int y, int width, int height, colour c, struct fbtk_bitmap *image);
+
+
+/**
+ * Change the bitmap in a widget.
+ *
+ * @param widget The widget to get the context from.
+ * @param image The bitmap to put in the widget
+ */
+void fbtk_set_bitmap(fbtk_widget_t *widget, struct fbtk_bitmap *image);
+
+
+/**
+ * Create a button widget with an image.
+ *
+ * Helper function which creates a bitmap widget and associate a handler for
+ * when it is clicked.
+ *
+ * @param window The window to add the button widget to.
+ * @param x X coordinate of widget.
+ * @param y Y coordinate of widget.
+ * @param width Width of the widget
+ * @param height Height of the widget
+ * @param c background colour
+ * @param image The bitmap to put in the widget
+ * @param click The callback upon a click
+ * @param pw The context tp pass to the callback
+ * @return new widget handle or NULL on error.
+ */
+fbtk_widget_t *fbtk_create_button(fbtk_widget_t *window, int x, int y, int width, int height, colour c, struct fbtk_bitmap *image, fbtk_callback click, void *pw);
+
+
+/**
+ * Create a text widget.
+ *
+ * @param window The window to add the text widget to.
+ * @param x X coordinate of widget.
+ * @param y Y coordinate of widget.
+ * @param width Width of the widget
+ * @param height Height of the widget
+ * @param bg background colour
+ * @param fg foreground colour
+ * @param outline widget will have a border.
+ * @return new widget handle or NULL on error.
+ */
+fbtk_widget_t *fbtk_create_text(fbtk_widget_t *window, int x, int y, int width, int height, colour bg, colour fg, bool outline);
+
+
+/**
+ * Create a button with text.
+ *
+ * @param window The window to add the text widget to.
+ * @param x X coordinate of widget.
+ * @param y Y coordinate of widget.
+ * @param width Width of the widget
+ * @param height Height of the widget
+ * @param bg background colour
+ * @param fg foreground colour
+ * @param click The callback upon a click
+ * @param pw The context tp pass to the callback
+ * @return new widget handle or NULL on error.
+ */
+fbtk_widget_t *fbtk_create_text_button(fbtk_widget_t *window, int x, int y, int width, int height, colour bg, colour fg, fbtk_callback click, void *pw);
+
+
+/**
+ * Create a writable text widget.
+ *
+ * Helper function which creates a text widget and configures an input handler
+ * to create a writable text field. This call is equivalent to calling
+ * ::fbtk_create_text followed by ::fbtk_writable_text
+ *
+ * @param window The window to add the text widget to.
+ * @param x X coordinate of widget.
+ * @param y Y coordinate of widget.
+ * @param width Width of the widget
+ * @param height Height of the widget
+ * @param bg background colour
+ * @param fg foreground colour
+ * @param outline widget will have a border.
+ * @param enter Callback when enter is pressed in widget.
+ * @param pw Context pointer passed to entry callback.
+ * @return new widget handle or NULL on error.
+ */
+fbtk_widget_t *fbtk_create_writable_text(fbtk_widget_t *window, int x, int y, int width, int height, colour bg, colour fg, bool outline, fbtk_enter_t enter, void *pw);
+
+
+/**
+ * Alter a text widget to be writable.
+ *
+ * @param widget Text widget.
+ * @param enter The routine to call when enter is pressed.
+ * @param pw The context to pass to the enter callback routine.
+ */
+void fbtk_writable_text(fbtk_widget_t *widget, fbtk_enter_t enter, void *pw);
+
+
+/**
+ * Change the text of a text widget.
+ *
+ * @param widget Text widget.
+ * @param text The new UTF-8 text to put in the widget.
+ */
+void fbtk_set_text(fbtk_widget_t *widget, const char *text);
+
+
+/**
+ * Give widget input focus.
+ *
+ * @param widget Widget to be given input focus.
+ */
+void fbtk_set_focus(fbtk_widget_t *widget);
+
+
+/**
+ * enable the on screen keyboard for input
+ *
+ * @param widget Widget to be given input focus.
+ */
+void fbtk_enable_oskb(fbtk_widget_t *widget);
+
+
+/**
+ * show the osk.
+ */
+void map_osk(void);
+
+#endif
diff --git a/frontends/kolibrios/fb/fbtk/bitmap.c b/frontends/kolibrios/fb/fbtk/bitmap.c
new file mode 100644
index 0000000..759b626
--- a/dev/null
+++ b/frontends/kolibrios/fb/fbtk/bitmap.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2010 Vincent Sanders <vince@simtec.co.uk>
+ *
+ * Framebuffer windowing toolkit bitmaped image widget
+ *
+ * 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 <stdbool.h>
+#include <stdlib.h>
+
+#include <libnsfb.h>
+#include <libnsfb_plot.h>
+
+#include "netsurf/browser_window.h"
+
+#include "framebuffer/gui.h"
+#include "framebuffer/fbtk.h"
+#include "framebuffer/image_data.h"
+
+#include "widget.h"
+
+static int
+fb_redraw_bitmap(fbtk_widget_t *widget, fbtk_callback_info *cbi)
+{
+ nsfb_bbox_t bbox;
+ nsfb_bbox_t rect;
+ nsfb_t *nsfb;
+
+ nsfb = fbtk_get_nsfb(widget);
+
+ fbtk_get_bbox(widget, &bbox);
+
+ rect = bbox;
+
+ nsfb_claim(nsfb, &bbox);
+
+ /* clear background */
+ if ((widget->bg & 0xFF000000) != 0) {
+ /* transparent polygon filling isnt working so fake it */
+ nsfb_plot_rectangle_fill(nsfb, &bbox, widget->bg);
+ }
+
+ /* plot the image */
+ nsfb_plot_bitmap(nsfb,
+ &rect,
+ (nsfb_colour_t *)widget->u.bitmap.bitmap->pixdata,
+ widget->u.bitmap.bitmap->width,
+ widget->u.bitmap.bitmap->height,
+ widget->u.bitmap.bitmap->width,
+ !widget->u.bitmap.bitmap->opaque);
+
+ nsfb_update(nsfb, &bbox);
+
+ return 0;
+}
+
+/* exported function documented in fbtk.h */
+void
+fbtk_set_bitmap(fbtk_widget_t *widget, struct fbtk_bitmap *image)
+{
+ if ((widget == NULL) || (widget->type != FB_WIDGET_TYPE_BITMAP))
+ return;
+
+ widget->u.bitmap.bitmap = image;
+
+ fbtk_request_redraw(widget);
+}
+
+/* exported function documented in fbtk.h */
+fbtk_widget_t *
+fbtk_create_bitmap(fbtk_widget_t *parent,
+ int x,
+ int y,
+ int width,
+ int height,
+ colour c,
+ struct fbtk_bitmap *image)
+{
+ fbtk_widget_t *neww;
+
+ neww = fbtk_widget_new(parent, FB_WIDGET_TYPE_BITMAP, x, y, width, height);
+
+ neww->bg = c;
+ neww->mapped = true;
+ neww->u.bitmap.bitmap = image;
+
+ fbtk_set_handler(neww, FBTK_CBT_REDRAW, fb_redraw_bitmap, NULL);
+
+ return neww;
+}
+
+/* exported function documented in fbtk.h */
+fbtk_widget_t *
+fbtk_create_button(fbtk_widget_t *parent,
+ int x,
+ int y,
+ int width,
+ int height,
+ colour c,
+ struct fbtk_bitmap *image,
+ fbtk_callback click,
+ void *pw)
+{
+ fbtk_widget_t *neww;
+
+ neww = fbtk_widget_new(parent, FB_WIDGET_TYPE_BITMAP, x, y, width, height);
+
+ neww->bg = c;
+ neww->mapped = true;
+ neww->u.bitmap.bitmap = image;
+
+ fbtk_set_handler(neww, FBTK_CBT_REDRAW, fb_redraw_bitmap, NULL);
+ fbtk_set_handler(neww, FBTK_CBT_CLICK, click, pw);
+ fbtk_set_handler(neww, FBTK_CBT_POINTERENTER, fbtk_set_ptr, &hand_image);
+
+ return neww;
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset:8
+ * End:
+ */
diff --git a/frontends/kolibrios/fb/fbtk/event.c b/frontends/kolibrios/fb/fbtk/event.c
new file mode 100644
index 0000000..a48e638
--- a/dev/null
+++ b/frontends/kolibrios/fb/fbtk/event.c
@@ -0,0 +1,349 @@
+/*
+ * Copyright 2010 Vincent Sanders <vince@simtec.co.uk>
+ *
+ * Framebuffer windowing toolkit event processing.
+ *
+ * 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 <sys/types.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include <libnsfb.h>
+#include <libnsfb_plot.h>
+#include <libnsfb_plot_util.h>
+#include <libnsfb_event.h>
+#include <libnsfb_cursor.h>
+
+#include "utils/utils.h"
+#include "utils/log.h"
+#include "netsurf/browser_window.h"
+#include "netsurf/keypress.h"
+
+#include "framebuffer/gui.h"
+#include "framebuffer/fbtk.h"
+#include "framebuffer/image_data.h"
+
+#include "widget.h"
+
+/* exported function documented in fbtk.h */
+void
+fbtk_input(fbtk_widget_t *root, nsfb_event_t *event)
+{
+ fbtk_widget_t *input;
+
+ root = fbtk_get_root_widget(root);
+
+ /* obtain widget with input focus */
+ input = root->u.root.input;
+ if (input == NULL) {
+ LOG("No widget has input focus.");
+ return; /* no widget with input */
+ }
+
+ fbtk_post_callback(input, FBTK_CBT_INPUT, event);
+}
+
+/* exported function documented in fbtk.h */
+void
+fbtk_click(fbtk_widget_t *widget, nsfb_event_t *event)
+{
+ fbtk_widget_t *root;
+ fbtk_widget_t *clicked;
+ nsfb_bbox_t cloc;
+ int x, y;
+
+ /* ensure we have the root widget */
+ root = fbtk_get_root_widget(widget);
+
+ nsfb_cursor_loc_get(root->u.root.fb, &cloc);
+
+ clicked = fbtk_get_widget_at(root, cloc.x0, cloc.y0);
+
+ if (clicked == NULL)
+ return;
+
+ if (fbtk_get_handler(clicked, FBTK_CBT_INPUT) != NULL) {
+ fbtk_set_focus(clicked);
+ }
+
+ x = fbtk_get_absx(clicked);
+ y = fbtk_get_absy(clicked);
+
+ LOG("clicked %p at %d,%d", clicked, x, y);
+
+ /* post the click */
+ fbtk_post_callback(clicked, FBTK_CBT_CLICK, event, cloc.x0 - x, cloc.y0 - y);
+}
+
+/* exported function documented in fbtk.h */
+bool
+fbtk_tgrab_pointer(fbtk_widget_t *widget)
+{
+ fbtk_widget_t *root;
+
+ /* ensure we have the root widget */
+ root = fbtk_get_root_widget(widget);
+
+ if (root->u.root.grabbed == widget) {
+ /* release pointer grab */
+ root->u.root.grabbed = NULL;
+ return true;
+ } else if (root->u.root.grabbed == NULL) {
+ /* set pointer grab */
+ root->u.root.grabbed = widget;
+ return true;
+ }
+ /* pointer was already grabbed */
+ return false;
+}
+
+/* exported function documented in fbtk.h */
+void
+fbtk_warp_pointer(fbtk_widget_t *widget, int x, int y, bool relative)
+{
+ fbtk_widget_t *root;
+ fbtk_widget_t *moved;
+ nsfb_bbox_t cloc;
+
+ /* ensure we have the root widget */
+ root = fbtk_get_root_widget(widget);
+
+ if (relative) {
+ nsfb_cursor_loc_get(root->u.root.fb, &cloc);
+ cloc.x0 += x;
+ cloc.y0 += y;
+ } else {
+ cloc.x0 = x;
+ cloc.y0 = y;
+ }
+
+ /* ensure cursor location lies within the root widget */
+ if (cloc.x0 < root->x)
+ cloc.x0 = root->x;
+ if (cloc.x0 >= (root->x + root->width))
+ cloc.x0 = (root->x + root->width) - 1;
+ if (cloc.y0 < root->y)
+ cloc.y0 = root->y;
+ if (cloc.y0 >= (root->y + root->height))
+ cloc.y0 = (root->y + root->height) - 1;
+
+ if (root->u.root.grabbed == NULL) {
+ /* update the pointer cursor */
+ nsfb_cursor_loc_set(root->u.root.fb, &cloc);
+
+ moved = fbtk_get_widget_at(root, cloc.x0, cloc.y0);
+
+ x = fbtk_get_absx(moved);
+ y = fbtk_get_absy(moved);
+
+ /* post enter and leaving messages */
+ if (moved != root->u.root.prev) {
+ fbtk_post_callback(root->u.root.prev, FBTK_CBT_POINTERLEAVE);
+ root->u.root.prev = moved;
+ fbtk_post_callback(root->u.root.prev, FBTK_CBT_POINTERENTER);
+ }
+ } else {
+ /* pointer movement has been grabbed by a widget */
+ moved = root->u.root.grabbed;
+
+ /* ensure pointer remains within widget boundary */
+ x = fbtk_get_absx(moved);
+ y = fbtk_get_absy(moved);
+
+ if (cloc.x0 < x)
+ cloc.x0 = x;
+ if (cloc.y0 < y)
+ cloc.y0 = y;
+ if (cloc.x0 > (x + moved->width))
+ cloc.x0 = (x + moved->width);
+ if (cloc.y0 > (y + moved->height))
+ cloc.y0 = (y + moved->height);
+
+ /* update the pointer cursor */
+ nsfb_cursor_loc_set(root->u.root.fb, &cloc);
+ }
+
+ /* post the movement */
+ fbtk_post_callback(moved, FBTK_CBT_POINTERMOVE, cloc.x0 - x, cloc.y0 - y);
+
+}
+
+/* exported function documented in fbtk.h */
+bool
+fbtk_event(fbtk_widget_t *root, nsfb_event_t *event, int timeout)
+{
+ nsfb_bbox_t cloc;
+ bool unused = false; /* is the event available */
+ bool move_pointer = false; /* whether pointer move events occured */
+
+ /* ensure we have the root widget */
+ root = fbtk_get_root_widget(root);
+
+ do {
+ if (nsfb_event(root->u.root.fb, event, timeout) == false) {
+ if (move_pointer)
+ fbtk_warp_pointer(root, cloc.x0, cloc.y0,
+ false);
+ return false;
+ }
+
+ if (move_pointer && event->type != NSFB_EVENT_MOVE_RELATIVE &&
+ event->type != NSFB_EVENT_MOVE_ABSOLUTE) {
+ /* Flush the movements */
+ fbtk_warp_pointer(root, cloc.x0, cloc.y0, false);
+
+ } else if (!move_pointer &&
+ event->type == NSFB_EVENT_MOVE_RELATIVE) {
+ /* Get current pointer coords */
+ nsfb_cursor_loc_get(root->u.root.fb, &cloc);
+ }
+
+ switch (event->type) {
+ case NSFB_EVENT_KEY_DOWN:
+ case NSFB_EVENT_KEY_UP:
+ if ((event->value.keycode >= NSFB_KEY_MOUSE_1) &&
+ (event->value.keycode <= NSFB_KEY_MOUSE_5)) {
+ fbtk_click(root, event);
+ } else {
+ fbtk_input(root, event);
+ }
+ break;
+
+ case NSFB_EVENT_CONTROL:
+ unused = true;
+ break;
+
+ case NSFB_EVENT_MOVE_RELATIVE:
+ /* Consecutive move events are consolidated into a
+ * single pointer warp */
+ move_pointer = true;
+ cloc.x0 += event->value.vector.x;
+ cloc.y0 += event->value.vector.y;
+ timeout = 0;
+ break;
+
+ case NSFB_EVENT_MOVE_ABSOLUTE:
+ /* Consecutive move events are consolidated into a
+ * single pointer warp */
+ move_pointer = true;
+ cloc.x0 = event->value.vector.x;
+ cloc.y0 = event->value.vector.y;
+ timeout = 0;
+ break;
+
+ case NSFB_EVENT_RESIZE:
+ /* Try to resize framebuffer */
+ gui_resize(root,
+ event->value.resize.w,
+ event->value.resize.h);
+ break;
+
+ default:
+ break;
+ }
+ } while (event->type == NSFB_EVENT_MOVE_RELATIVE ||
+ event->type == NSFB_EVENT_MOVE_ABSOLUTE);
+ return unused;
+}
+
+static int keymap[] = {
+ /* 0 1 2 3 4 5 6 7 8 9 */
+ -1, -1, -1, -1, -1, -1, -1, -1, 8, 9, /* 0 - 9 */
+ -1, -1, -1, 13, -1, -1, -1, -1, -1, -1, /* 10 - 19 */
+ -1, -1, -1, -1, -1, -1, -1, 27, -1, -1, /* 20 - 29 */
+ -1, -1, ' ', '!', '"', '#', '$', -1, '&','\'', /* 30 - 39 */
+ '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', /* 40 - 49 */
+ '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', /* 50 - 59 */
+ '<', '=', '>', '?', '@', -1, -1, -1, -1, -1, /* 60 - 69 */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 70 - 79 */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 80 - 89 */
+ -1, '[','\\', ']', '~', '_', '`', 'a', 'b', 'c', /* 90 - 99 */
+ 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', /* 100 - 109 */
+ 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', /* 110 - 119 */
+ 'x', 'y', 'z', -1, -1, -1, -1, -1, -1, -1, /* 120 - 129 */
+};
+
+static int sh_keymap[] = {
+ /* 0 1 2 3 4 5 6 7 8 9 */
+ -1, -1, -1, -1, -1, -1, -1, -1, 8, 9, /* 0 - 9 */
+ -1, -1, -1, 13, -1, -1, -1, -1, -1, -1, /* 10 - 19 */
+ -1, -1, -1, -1, -1, -1, -1, 27, -1, -1, /* 20 - 29 */
+ -1, -1, ' ', '!', '"', '~', '$', -1, '&', '@', /* 30 - 39 */
+ '(', ')', '*', '+', '<', '_', '>', '?', ')', '!', /* 40 - 49 */
+ '"', 243, '$', '%', '^', '&', '*', '(', ';', ':', /* 50 - 59 */
+ '<', '+', '>', '?', '@', -1, -1, -1, -1, -1, /* 60 - 69 */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 70 - 79 */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 80 - 89 */
+ -1, '{', '|', '}', '~', '_', 254, 'A', 'B', 'C', /* 90 - 99 */
+ 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', /* 100 - 109 */
+ 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', /* 110 - 119 */
+ 'X', 'Y', 'Z', -1, -1, -1, -1, -1, -1, -1, /* 120 - 129 */
+};
+
+
+/* exported function documented in fbtk.h */
+int
+fbtk_keycode_to_ucs4(int code, fbtk_modifier_type mods)
+{
+ int ucs4 = -1;
+
+ if (mods & FBTK_MOD_LSHIFT || mods & FBTK_MOD_RSHIFT) {
+ if ((code >= 0) && (code < (int) NOF_ELEMENTS(sh_keymap)))
+ ucs4 = sh_keymap[code];
+
+ } else if (mods == FBTK_MOD_CLEAR) {
+ if ((code >= 0) && (code < (int) NOF_ELEMENTS(keymap)))
+ ucs4 = keymap[code];
+
+ } else if (mods & FBTK_MOD_LCTRL || mods & FBTK_MOD_RCTRL) {
+ switch (code) {
+ case NSFB_KEY_a:
+ ucs4 = NS_KEY_SELECT_ALL;
+ break;
+
+ case NSFB_KEY_c:
+ ucs4 = NS_KEY_COPY_SELECTION;
+ break;
+
+ case NSFB_KEY_u:
+ ucs4 = NS_KEY_DELETE_LINE;
+ break;
+
+ case NSFB_KEY_v:
+ ucs4 = NS_KEY_PASTE;
+ break;
+
+ case NSFB_KEY_x:
+ ucs4 = NS_KEY_CUT_SELECTION;
+ break;
+
+ case NSFB_KEY_z:
+ ucs4 = NS_KEY_CLEAR_SELECTION;
+ break;
+ default:
+ break;
+ }
+ }
+ return ucs4;
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset:8
+ * End:
+ */
diff --git a/frontends/kolibrios/fb/fbtk/fbtk.c b/frontends/kolibrios/fb/fbtk/fbtk.c
new file mode 100644
index 0000000..c63a6d8
--- a/dev/null
+++ b/frontends/kolibrios/fb/fbtk/fbtk.c
@@ -0,0 +1,830 @@
+/*
+ * Copyright 2008,2010 Vincent Sanders <vince@simtec.co.uk>
+ *
+ * Framebuffer windowing toolkit core.
+ *
+ * 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 <sys/types.h>
+#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdarg.h>
+
+#include <libnsfb.h>
+#include <libnsfb_plot.h>
+#include <libnsfb_plot_util.h>
+#include <libnsfb_event.h>
+#include <libnsfb_cursor.h>
+
+#include "utils/utils.h"
+#include "utils/log.h"
+#include "netsurf/browser_window.h"
+#include "netsurf/plotters.h"
+
+#include "framebuffer/gui.h"
+#include "framebuffer/fbtk.h"
+#include "framebuffer/image_data.h"
+
+#include "widget.h"
+
+#ifdef FBTK_LOGGING
+
+/* tree dump debug, also example of depth first tree walk */
+static void
+dump_tk_tree(fbtk_widget_t *widget)
+{
+ widget = fbtk_get_root_widget(widget);
+ int indent = 0;
+
+ while (widget != NULL) {
+ LOG("%*s%p", indent, "", widget);
+ if (widget->first_child != NULL) {
+ widget = widget->first_child;
+ indent += 6;
+ } else if (widget->next != NULL) {
+ widget = widget->next;
+ } else {
+ while ((widget->parent != NULL) &&
+ (widget->parent->next == NULL)) {
+ widget = widget->parent;
+ indent -= 6;
+ }
+ if (widget->parent != NULL) {
+ indent -= 6;
+ widget = widget->parent->next;
+ } else {
+ widget = NULL;
+ }
+ }
+ }
+}
+
+#endif
+
+/* exported function documented in fbtk.h */
+void
+fbtk_request_redraw(fbtk_widget_t *widget)
+{
+ fbtk_widget_t *cwidget;
+ fbtk_widget_t *pwidget;
+
+ assert(widget != NULL);
+
+ /* if widget not mapped do not try to redraw it */
+ pwidget = widget;
+ while (pwidget != NULL) {
+ if (pwidget->mapped == false)
+ return;
+ pwidget = pwidget->parent;
+ }
+
+ widget->redraw.needed = true;
+ widget->redraw.x = 0;
+ widget->redraw.y = 0;
+ widget->redraw.width = widget->width;
+ widget->redraw.height = widget->height;
+
+#ifdef FBTK_LOGGING
+ LOG("redrawing %p %d,%d %d,%d", widget, widget->redraw.x, widget->redraw.y, widget->redraw.width, widget->redraw.height);
+#endif
+
+ cwidget = widget->last_child;
+ while (cwidget != NULL) {
+ fbtk_request_redraw(cwidget);
+ cwidget = cwidget->prev;
+ }
+
+ while (widget->parent != NULL) {
+ widget = widget->parent;
+ widget->redraw.child = true;
+ }
+}
+
+
+
+/* exported function documented in fbtk.h */
+int
+fbtk_set_mapping(fbtk_widget_t *widget, bool map)
+{
+ LOG("setting mapping on %p to %d", widget, map);
+ widget->mapped = map;
+ if (map) {
+ fbtk_request_redraw(widget);
+ } else {
+ fbtk_request_redraw(widget->parent);
+ }
+ return 0;
+}
+
+/** swap the widget given with the next sibling.
+ *
+ * Swap a sibling widget with the next deepest in the hierachy
+ */
+static void
+swap_siblings(fbtk_widget_t *lw)
+{
+ fbtk_widget_t *rw = lw->next; /* the widget to swap lw with */
+ fbtk_widget_t *before;
+ fbtk_widget_t *after;
+
+ assert(rw != NULL);
+
+ LOG("Swapping %p with %p", lw, rw);
+ before = lw->prev;
+ after = rw->next;
+
+ if (before == NULL) {
+ /* left widget is currently the first child */
+ lw->parent->first_child = rw;
+ } else {
+ before->next = rw;
+ }
+ rw->prev = before;
+ rw->next = lw;
+
+ if (after == NULL) {
+ /* right widget is currently the last child */
+ rw->parent->last_child = lw;
+ } else {
+ after->prev = lw;
+ }
+ lw->next = after;
+ lw->prev = rw;
+}
+
+
+
+/* exported function documented in fbtk.h */
+int
+fbtk_set_zorder(fbtk_widget_t *widget, int z)
+{
+ while (z != 0) {
+ if (z < 0) {
+ if (widget->prev == NULL)
+ break; /* cannot go any shallower */
+
+ /* swap with previous entry */
+ swap_siblings(widget->prev);
+
+ z++;
+ } else {
+ if (widget->next == NULL)
+ break; /* cannot go any deeper */
+
+ /* swap with subsequent entry */
+ swap_siblings(widget);
+
+ z--;
+ }
+ }
+
+ return z;
+}
+
+
+/* exported function documented in fbtk.h */
+bool
+fbtk_set_pos_and_size(fbtk_widget_t *widget,
+ int x, int y,
+ int width, int height)
+{
+ if (widget->parent != NULL) {
+ fbtk_widget_t *parent = widget->parent;
+
+ /* make new window fit inside parent */
+ if (width == 0) {
+ width = parent->width - x;
+ } else if (width < 0) {
+ width = parent->width + width - x;
+ }
+ if ((width + x) > parent->width) {
+ width = parent->width - x;
+ }
+
+ if (height == 0) {
+ height = parent->height - y;
+ } else if (height < 0) {
+ height = parent->height + height - y;
+ }
+ if ((height + y) > parent->height) {
+ height = parent->height - y;
+ }
+ }
+
+ if ((widget->x != x) ||
+ (widget->y != y) ||
+ (widget->width != width) ||
+ (widget->height != height)) {
+ widget->x = x;
+ widget->y = y;
+ widget->width = width;
+ widget->height = height;
+ return true;
+ }
+ return false;
+}
+
+
+/* exported function docuemnted in fbtk.h */
+void
+fbtk_set_caret(fbtk_widget_t *widget, bool set,
+ int x, int y, int height,
+ void (*remove_caret)(fbtk_widget_t *widget))
+{
+ fbtk_widget_t *root;
+
+ assert(widget != NULL);
+ root = fbtk_get_root_widget(widget);
+
+ if (root->u.root.caret.owner != NULL &&
+ root->u.root.caret.remove_cb != NULL)
+ root->u.root.caret.remove_cb(widget);
+
+ if (set) {
+ assert(remove_caret != NULL);
+
+ root->u.root.caret.owner = widget;
+ root->u.root.caret.x = x;
+ root->u.root.caret.y = y;
+ root->u.root.caret.height = height;
+ root->u.root.caret.remove_cb = remove_caret;
+
+ } else {
+ root->u.root.caret.owner = NULL;
+ root->u.root.caret.remove_cb = NULL;
+ }
+}
+
+/* exported function documented in fbtk.h */
+int
+fbtk_destroy_widget(fbtk_widget_t *widget)
+{
+ fbtk_widget_t *parent;
+ int ret = 0;
+
+ ret = fbtk_post_callback(widget, FBTK_CBT_DESTROY);
+
+ while (widget->first_child != NULL) {
+ fbtk_destroy_widget(widget->first_child);
+ }
+
+ parent = widget->parent;
+ if (parent != NULL) {
+
+ /* unlink from siblings */
+ if (widget->prev != NULL) {
+ widget->prev->next = widget->next;
+ } else {
+ /* must be the first widget, unlink from parent */
+ parent->first_child = widget->next;
+ }
+ if (widget->next != NULL) {
+ widget->next->prev = widget->prev;
+ } else {
+ /* must be the last widget, unlink from parent */
+ parent->last_child = widget->prev;
+ }
+
+ free(widget);
+ }
+
+ return ret;
+}
+
+/* region coverage flags. */
+enum {
+ POINT_LEFTOF_REGION = 1,
+ POINT_RIGHTOF_REGION = 2,
+ POINT_ABOVE_REGION = 4,
+ POINT_BELOW_REGION = 8,
+};
+
+/* Computes where a point lies in respect to an area. */
+#define REGION(x,y,cx1,cx2,cy1,cy2) \
+ (( (y) > (cy2) ? POINT_BELOW_REGION : 0) | \
+ ( (y) < (cy1) ? POINT_ABOVE_REGION : 0) | \
+ ( (x) > (cx2) ? POINT_RIGHTOF_REGION : 0) | \
+ ( (x) < (cx1) ? POINT_LEFTOF_REGION : 0) )
+
+/* swap two integers */
+#define SWAP(a, b) do { int t; t=(a); (a)=(b); (b)=t; } while(0)
+
+/* exported function documented in fbtk.h */
+bool
+fbtk_clip_rect(const bbox_t * restrict clip, bbox_t * restrict box)
+{
+ uint8_t region1;
+ uint8_t region2;
+
+ /* ensure co-ordinates are in ascending order */
+ if (box->x1 < box->x0)
+ SWAP(box->x0, box->x1);
+ if (box->y1 < box->y0)
+ SWAP(box->y0, box->y1);
+
+ region1 = REGION(box->x0, box->y0, clip->x0, clip->x1 - 1, clip->y0, clip->y1 - 1);
+ region2 = REGION(box->x1, box->y1, clip->x0, clip->x1 - 1, clip->y0, clip->y1 - 1);
+
+ /* area lies entirely outside the clipping rectangle */
+ if ((region1 | region2) && (region1 & region2))
+ return false;
+
+ if (box->x0 < clip->x0)
+ box->x0 = clip->x0;
+ if (box->x0 > clip->x1)
+ box->x0 = clip->x1;
+
+ if (box->x1 < clip->x0)
+ box->x1 = clip->x0;
+ if (box->x1 > clip->x1)
+ box->x1 = clip->x1;
+
+ if (box->y0 < clip->y0)
+ box->y0 = clip->y0;
+ if (box->y0 > clip->y1)
+ box->y0 = clip->y1;
+
+ if (box->y1 < clip->y0)
+ box->y1 = clip->y0;
+ if (box->y1 > clip->y1)
+ box->y1 = clip->y1;
+
+ return true;
+}
+
+/* exported function documented in fbtk.h */
+bool
+fbtk_clip_to_widget(fbtk_widget_t *widget, bbox_t * restrict box)
+{
+ bbox_t wbox;
+ wbox.x0 = 0;
+ wbox.y0 = 0;
+ wbox.x1 = widget->width;
+ wbox.y1 = widget->height;
+ return fbtk_clip_rect(&wbox, box);
+}
+
+
+
+/* internally exported function documented in widget.h */
+int
+fbtk_set_ptr(fbtk_widget_t *widget, fbtk_callback_info *cbi)
+{
+ fbtk_widget_t *root = fbtk_get_root_widget(widget);
+ struct fbtk_bitmap *bm = cbi->context;
+
+ nsfb_cursor_set(root->u.root.fb,
+ (nsfb_colour_t *)bm->pixdata,
+ bm->width,
+ bm->height,
+ bm->width,
+ bm->hot_x,
+ bm->hot_y);
+
+ return 0;
+}
+
+
+
+/* internally exported function documented in widget.h */
+fbtk_widget_t *
+fbtk_get_root_widget(fbtk_widget_t *widget)
+{
+ while (widget->parent != NULL)
+ widget = widget->parent;
+
+ /* check root widget was found */
+ if (widget->type != FB_WIDGET_TYPE_ROOT) {
+ LOG("Widget with null parent that is not the root widget!");
+ return NULL;
+ }
+
+ return widget;
+}
+
+
+/* exported function documented in fbtk.h */
+int
+fbtk_get_absx(fbtk_widget_t *widget)
+{
+ int x = widget->x;
+
+ while (widget->parent != NULL) {
+ widget = widget->parent;
+ x += widget->x;
+ }
+
+ return x;
+}
+
+/* exported function documented in fbtk.h */
+int
+fbtk_get_absy(fbtk_widget_t *widget)
+{
+ int y = widget->y;
+
+ while (widget->parent != NULL) {
+ widget = widget->parent;
+ y += widget->y;
+ }
+
+ return y;
+}
+
+/* exported function documented in fbtk.h */
+int
+fbtk_get_height(fbtk_widget_t *widget)
+{
+ return widget->height;
+}
+
+/* exported function documented in fbtk.h */
+int
+fbtk_get_width(fbtk_widget_t *widget)
+{
+ return widget->width;
+}
+
+/* exported function documented in fbtk.h */
+bool
+fbtk_get_bbox(fbtk_widget_t *widget, nsfb_bbox_t *bbox)
+{
+ bbox->x0 = widget->x;
+ bbox->y0 = widget->y;
+ bbox->x1 = widget->x + widget->width;
+ bbox->y1 = widget->y + widget->height;
+
+ widget = widget->parent;
+ while (widget != NULL) {
+ bbox->x0 += widget->x;
+ bbox->y0 += widget->y;
+ bbox->x1 += widget->x;
+ bbox->y1 += widget->y;
+ widget = widget->parent;
+ }
+
+ return true;
+}
+
+bool
+fbtk_get_caret(fbtk_widget_t *widget, int *x, int *y, int *height)
+{
+ fbtk_widget_t *root = fbtk_get_root_widget(widget);
+
+ if (root->u.root.caret.owner == widget) {
+ *x = root->u.root.caret.x;
+ *y = root->u.root.caret.y;
+ *height = root->u.root.caret.height;
+
+ return true;
+
+ } else {
+ *x = 0;
+ *y = 0;
+ *height = 0;
+
+ return false;
+ }
+}
+
+/* exported function documented in fbtk.h */
+fbtk_widget_t *
+fbtk_get_widget_at(fbtk_widget_t *nwid, int x, int y)
+{
+ fbtk_widget_t *widget = NULL; /* found widget */
+
+ /* require the root widget to start */
+ nwid = fbtk_get_root_widget(nwid);
+
+ while (nwid != NULL) {
+ if ((nwid->mapped) &&
+ (x >= nwid->x) &&
+ (y >= nwid->y) &&
+ (x < (nwid->x + nwid->width)) &&
+ (y < (nwid->y + nwid->height))) {
+ widget = nwid;
+ x -= nwid->x;
+ y -= nwid->y;
+ nwid = nwid->first_child;
+ } else {
+ nwid = nwid->next;
+ }
+ }
+
+ return widget;
+}
+
+
+
+
+/* internally exported function documented in widget.h */
+fbtk_widget_t *
+fbtk_widget_new(fbtk_widget_t *parent,
+ enum fbtk_widgettype_e type,
+ int x,
+ int y,
+ int width,
+ int height)
+{
+ fbtk_widget_t *neww; /* new widget */
+
+ if (parent == NULL)
+ return NULL;
+
+ neww = calloc(1, sizeof(fbtk_widget_t));
+ if (neww == NULL)
+ return NULL;
+
+#ifdef FBTK_LOGGING
+ LOG("creating %p %d,%d %d,%d", neww, x, y, width, height);
+#endif
+
+ /* make new window fit inside parent */
+ if (width == 0) {
+ width = parent->width - x;
+ } else if (width < 0) {
+ width = parent->width + width - x;
+ }
+ if ((width + x) > parent->width) {
+ width = parent->width - x;
+ }
+
+ if (height == 0) {
+ height = parent->height - y;
+ } else if (height < 0) {
+ height = parent->height + height - y;
+ }
+ if ((height + y) > parent->height) {
+ height = parent->height - y;
+ }
+
+#ifdef FBTK_LOGGING
+ LOG("using %p %d,%d %d,%d", neww, x, y, width, height);
+#endif
+ /* set values */
+ neww->type = type;
+ neww->x = x;
+ neww->y = y;
+ neww->width = width;
+ neww->height = height;
+
+ /* insert into widget heiarchy */
+
+ neww->parent = parent;
+
+ if (parent->first_child == NULL) {
+ /* no child widgets yet */
+ parent->last_child = neww;
+ } else {
+ /* add new widget to front of sibling chain */
+ neww->next = parent->first_child;
+ neww->next->prev = neww;
+ }
+ parent->first_child = neww;
+
+ return neww;
+}
+
+/* exported function documented in fbtk.h */
+bool
+fbtk_get_redraw_pending(fbtk_widget_t *widget)
+{
+ fbtk_widget_t *root;
+
+ /* ensure we have the root widget */
+ root = fbtk_get_root_widget(widget);
+
+ return root->redraw.needed | root->redraw.child;
+}
+
+/** Perform a depth-first tree-walk, calling the redraw callback of the widgets in turn.
+ *
+ * This function makes no decisions of its own and simply walks the
+ * widget tree depth first calling widgets redraw callbacks if flagged
+ * to do so.
+ * The tree search is optimised with a flag to indicate wether the
+ * children of a node should be considered.
+ */
+static int
+do_redraw(nsfb_t *nsfb, fbtk_widget_t *widget)
+{
+ nsfb_bbox_t plot_ctx;
+ fbtk_widget_t *cwidget; /* child widget */
+
+ /* check if the widget requires redrawing */
+ if (widget->redraw.needed == true) {
+ plot_ctx.x0 = fbtk_get_absx(widget) + widget->redraw.x;
+ plot_ctx.y0 = fbtk_get_absy(widget) + widget->redraw.y;
+ plot_ctx.x1 = plot_ctx.x0 + widget->redraw.width;
+ plot_ctx.y1 = plot_ctx.y0 + widget->redraw.height;
+
+#ifdef FBTK_LOGGING
+ LOG("clipping %p %d,%d %d,%d", widget, plot_ctx.x0, plot_ctx.y0, plot_ctx.x1, plot_ctx.y1);
+#endif
+ if (nsfb_plot_set_clip(nsfb, &plot_ctx) == true) {
+ fbtk_post_callback(widget, FBTK_CBT_REDRAW);
+ }
+ widget->redraw.needed = false;
+ }
+
+ /* walk the widgets children if child flag is set */
+ if (widget->redraw.child) {
+ cwidget = widget->last_child;
+ while (cwidget != NULL) {
+ do_redraw(nsfb, cwidget);
+ cwidget = cwidget->prev;
+ }
+ widget->redraw.child = false;
+ }
+
+ return 1;
+}
+
+/* exported function documented in fbtk.h */
+int
+fbtk_redraw(fbtk_widget_t *widget)
+{
+ fbtk_widget_t *root;
+
+ /* ensure we have the root widget */
+ root = fbtk_get_root_widget(widget);
+
+ return do_redraw(root->u.root.fb, root);
+}
+
+/* exported function documented in fbtk.h */
+fbtk_callback
+fbtk_get_handler(fbtk_widget_t *widget, fbtk_callback_type cbt)
+{
+ if ((cbt <= FBTK_CBT_START) || (cbt >= FBTK_CBT_END)) {
+ /* type out of range, no way to report error so return NULL */
+ return NULL;
+ }
+
+ return widget->callback[cbt];
+}
+
+/* exported function documented in fbtk.h */
+fbtk_callback
+fbtk_set_handler(fbtk_widget_t *widget,
+ fbtk_callback_type cbt,
+ fbtk_callback cb,
+ void *context)
+{
+ fbtk_callback prevcb;
+
+ if ((cbt <= FBTK_CBT_START) || (cbt >= FBTK_CBT_END)) {
+ /* type out of range, no way to report error so return NULL */
+ return NULL;
+ }
+
+ prevcb = widget->callback[cbt];
+
+ widget->callback[cbt] = cb;
+ widget->callback_context[cbt] = context;
+
+ return prevcb;
+}
+
+/* exported function docuemnted in fbtk.h */
+int
+fbtk_post_callback(fbtk_widget_t *widget, fbtk_callback_type cbt, ...)
+{
+ fbtk_callback_info cbi;
+ int ret = 0;
+ va_list ap;
+
+ if (widget == NULL)
+ return -1;
+ /* if the widget is not mapped do not attempt to post any
+ * events to it
+ */
+ if (widget->mapped == false)
+ return ret;
+
+ if (widget->callback[cbt] != NULL) {
+ cbi.type = cbt;
+ cbi.context = widget->callback_context[cbt];
+
+ va_start(ap, cbt);
+
+ switch (cbt) {
+ case FBTK_CBT_SCROLLX:
+ cbi.x = va_arg(ap,int);
+ break;
+
+ case FBTK_CBT_SCROLLY:
+ cbi.y = va_arg(ap,int);
+ break;
+
+ case FBTK_CBT_CLICK:
+ cbi.event = va_arg(ap, void *);
+ cbi.x = va_arg(ap, int);
+ cbi.y = va_arg(ap, int);
+ break;
+
+ case FBTK_CBT_INPUT:
+ cbi.event = va_arg(ap, void *);
+ break;
+
+ case FBTK_CBT_POINTERMOVE:
+ cbi.x = va_arg(ap, int);
+ cbi.y = va_arg(ap, int);
+ break;
+
+ case FBTK_CBT_REDRAW:
+ break;
+
+ case FBTK_CBT_USER:
+ break;
+
+ case FBTK_CBT_STRIP_FOCUS:
+ break;
+
+ default:
+ break;
+ }
+ va_end(ap);
+
+ ret = (widget->callback[cbt])(widget, &cbi);
+ }
+
+ return ret;
+}
+
+/* exported function docuemnted in fbtk.h */
+void
+fbtk_set_focus(fbtk_widget_t *widget)
+{
+ fbtk_widget_t *root;
+
+ /* ensure we have the root widget */
+ root = fbtk_get_root_widget(widget);
+
+ if (root->u.root.input != NULL &&
+ root->u.root.input != widget) {
+ /* inform previous holder of focus that it's being stripped
+ * of focus */
+ fbtk_post_callback(root->u.root.input, FBTK_CBT_STRIP_FOCUS);
+ }
+
+ root->u.root.input = widget;
+}
+
+
+
+/* exported function docuemnted in fbtk.h */
+nsfb_t *
+fbtk_get_nsfb(fbtk_widget_t *widget)
+{
+ fbtk_widget_t *root;
+
+ /* ensure we have the root widget */
+ root = fbtk_get_root_widget(widget);
+
+ return root->u.root.fb;
+}
+
+/* exported function docuemnted in fbtk.h */
+fbtk_widget_t *
+fbtk_init(nsfb_t *fb)
+{
+ fbtk_widget_t *root;
+
+ /* create and configure root widget */
+ root = calloc(1, sizeof(fbtk_widget_t));
+ if (root == NULL)
+ return NULL;
+
+ root->type = FB_WIDGET_TYPE_ROOT;
+ root->u.root.fb = fb;
+ root->u.root.caret.owner = NULL;
+
+ nsfb_get_geometry(fb, &root->width, &root->height, NULL);
+
+ root->mapped = true;
+
+ return root;
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset:8
+ * End:
+ */
diff --git a/frontends/kolibrios/fb/fbtk/fill.c b/frontends/kolibrios/fb/fbtk/fill.c
new file mode 100644
index 0000000..9377933
--- a/dev/null
+++ b/frontends/kolibrios/fb/fbtk/fill.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2010 Vincent Sanders <vince@simtec.co.uk>
+ *
+ * Framebuffer windowing toolkit filled area widget
+ *
+ * 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 <stdbool.h>
+#include <stdlib.h>
+
+#include <libnsfb.h>
+#include <libnsfb_plot.h>
+
+#include "netsurf/browser_window.h"
+
+#include "framebuffer/gui.h"
+#include "framebuffer/fbtk.h"
+
+#include "widget.h"
+
+static int
+fb_redraw_fill(fbtk_widget_t *widget, fbtk_callback_info *cbi)
+{
+ nsfb_bbox_t bbox;
+ nsfb_t *nsfb;
+
+ nsfb = fbtk_get_nsfb(widget);
+
+ fbtk_get_bbox(widget, &bbox);
+
+ nsfb_claim(nsfb, &bbox);
+
+ /* clear background */
+ if ((widget->bg & 0xFF000000) != 0) {
+ /* transparent polygon filling isnt working so fake it */
+ nsfb_plot_rectangle_fill(nsfb, &bbox, widget->bg);
+ }
+
+ nsfb_update(nsfb, &bbox);
+
+ return 0;
+}
+
+/* exported function documented in fbtk.h */
+fbtk_widget_t *
+fbtk_create_fill(fbtk_widget_t *parent,
+ int x,
+ int y,
+ int width,
+ int height,
+ colour c)
+{
+ fbtk_widget_t *neww;
+
+ neww = fbtk_widget_new(parent, FB_WIDGET_TYPE_FILL, x, y, width, height);
+ neww->bg = c;
+ neww->mapped = true;
+
+ fbtk_set_handler(neww, FBTK_CBT_REDRAW, fb_redraw_fill, NULL);
+
+ return neww;
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset:8
+ * End:
+ */
diff --git a/frontends/kolibrios/fb/fbtk/osk.c b/frontends/kolibrios/fb/fbtk/osk.c
new file mode 100644
index 0000000..628fe9a
--- a/dev/null
+++ b/frontends/kolibrios/fb/fbtk/osk.c
@@ -0,0 +1,199 @@
+/*
+ * Copyright 2010 Vincent Sanders <vince@simtec.co.uk>
+ *
+ * Framebuffer windowing toolkit on screen keyboard.
+ *
+ * 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 <stdbool.h>
+#include <limits.h>
+
+#include <libnsfb.h>
+#include <libnsfb_plot.h>
+#include <libnsfb_event.h>
+#include <libnsfb_cursor.h>
+
+#include "utils/log.h"
+#include "netsurf/browser_window.h"
+
+#include "framebuffer/gui.h"
+#include "framebuffer/fbtk.h"
+#include "framebuffer/image_data.h"
+
+#include "widget.h"
+
+struct kbd_button_s {
+ int x;
+ int y;
+ int w;
+ int h;
+ const char *t;
+ enum nsfb_key_code_e keycode;
+};
+
+#define KEYCOUNT 58
+
+static struct kbd_button_s kbdbase[KEYCOUNT] = {
+ { 0, 0, 20, 15, "`", NSFB_KEY_BACKQUOTE},
+ { 20, 0, 20, 15, "1", NSFB_KEY_1},
+ { 40, 0, 20, 15, "2", NSFB_KEY_2},
+ { 60, 0, 20, 15, "3", NSFB_KEY_3},
+ { 80, 0, 20, 15, "4", NSFB_KEY_4},
+ { 100, 0, 20, 15, "5", NSFB_KEY_5},
+ { 120, 0, 20, 15, "6", NSFB_KEY_6},
+ { 140, 0, 20, 15, "7", NSFB_KEY_7},
+ { 160, 0, 20, 15, "8", NSFB_KEY_8},
+ { 180, 0, 20, 15, "9", NSFB_KEY_9},
+ { 200, 0, 20, 15, "0", NSFB_KEY_0},
+ { 220, 0, 20, 15, "-", NSFB_KEY_MINUS},
+ { 240, 0, 20, 15, "=", NSFB_KEY_EQUALS},
+ { 260, 0, 40, 15, "\xe2\x8c\xab", NSFB_KEY_BACKSPACE},
+ { 0, 15, 30, 15, "\xe2\x86\xb9", NSFB_KEY_TAB},
+ { 30, 15, 20, 15, "q", NSFB_KEY_q},
+ { 50, 15, 20, 15, "w", NSFB_KEY_w},
+ { 70, 15, 20, 15, "e", NSFB_KEY_e},
+ { 90, 15, 20, 15, "r", NSFB_KEY_r},
+ { 110, 15, 20, 15, "t", NSFB_KEY_t},
+ { 130, 15, 20, 15, "y", NSFB_KEY_y},
+ { 150, 15, 20, 15, "u", NSFB_KEY_u},
+ { 170, 15, 20, 15, "i", NSFB_KEY_i},
+ { 190, 15, 20, 15, "o", NSFB_KEY_o},
+ { 210, 15, 20, 15, "p", NSFB_KEY_p},
+ { 230, 15, 20, 15, "[", NSFB_KEY_LEFTBRACKET},
+ { 250, 15, 20, 15, "]", NSFB_KEY_RIGHTBRACKET},
+ { 275, 15, 25, 30, "\xe2\x8f\x8e", NSFB_KEY_RETURN},
+ { 35, 30, 20, 15, "a", NSFB_KEY_a},
+ { 55, 30, 20, 15, "s", NSFB_KEY_s},
+ { 75, 30, 20, 15, "d", NSFB_KEY_d},
+ { 95, 30, 20, 15, "f", NSFB_KEY_f},
+ { 115, 30, 20, 15, "g", NSFB_KEY_g},
+ { 135, 30, 20, 15, "h", NSFB_KEY_h},
+ { 155, 30, 20, 15, "j", NSFB_KEY_j},
+ { 175, 30, 20, 15, "k", NSFB_KEY_k},
+ { 195, 30, 20, 15, "l", NSFB_KEY_l},
+ { 215, 30, 20, 15, ";", NSFB_KEY_SEMICOLON},
+ { 235, 30, 20, 15, "'", NSFB_KEY_l},
+ { 255, 30, 20, 15, "#", NSFB_KEY_HASH},
+ { 0, 45, 25, 15, "\xe2\x87\xa7", NSFB_KEY_LSHIFT},
+ { 25, 45, 20, 15, "\\", NSFB_KEY_SLASH},
+ { 45, 45, 20, 15, "z", NSFB_KEY_z},
+ { 65, 45, 20, 15, "x", NSFB_KEY_x},
+ { 85, 45, 20, 15, "c", NSFB_KEY_c},
+ { 105, 45, 20, 15, "v", NSFB_KEY_v},
+ { 125, 45, 20, 15, "b", NSFB_KEY_b},
+ { 145, 45, 20, 15, "n", NSFB_KEY_n},
+ { 165, 45, 20, 15, "m", NSFB_KEY_m},
+ { 185, 45, 20, 15, ",", NSFB_KEY_COMMA},
+ { 205, 45, 20, 15, ".", NSFB_KEY_PERIOD},
+ { 225, 45, 20, 15, "/", NSFB_KEY_BACKSLASH},
+ { 245, 45, 55, 15, "\xe2\x87\xa7", NSFB_KEY_RSHIFT},
+ { 40, 67, 185, 15, "", NSFB_KEY_SPACE},
+ { 250, 60, 20, 15, "\xe2\x96\xb2", NSFB_KEY_UP},
+ { 230, 67, 20, 15, "\xe2\x97\x80", NSFB_KEY_LEFT},
+ { 270, 67, 20, 15, "\xe2\x96\xb6", NSFB_KEY_RIGHT},
+ { 250, 75, 20, 15, "\xe2\x96\xbc", NSFB_KEY_DOWN},
+};
+
+static fbtk_widget_t *osk;
+
+static int
+osk_close(fbtk_widget_t *widget, fbtk_callback_info *cbi)
+{
+ if (cbi->event->type != NSFB_EVENT_KEY_UP)
+ return 0;
+
+ fbtk_set_mapping(osk, false);
+
+ return 0;
+}
+
+static int
+osk_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
+{
+ nsfb_event_t event;
+ struct kbd_button_s *kbd_button = cbi->context;
+
+ event.type = cbi->event->type;
+ event.value.keycode = kbd_button->keycode;
+ fbtk_input(widget, &event);
+
+ return 0;
+}
+
+/* exported function documented in fbtk.h */
+void
+fbtk_enable_oskb(fbtk_widget_t *fbtk)
+{
+ fbtk_widget_t *widget;
+ int kloop;
+ int maxx = 0;
+ int maxy = 0;
+ int ww;
+ int wh;
+ fbtk_widget_t *root = fbtk_get_root_widget(fbtk);
+ int furniture_width = 18;
+
+ for (kloop=0; kloop < KEYCOUNT; kloop++) {
+ if ((kbdbase[kloop].x + kbdbase[kloop].w) > maxx)
+ maxx=kbdbase[kloop].x + kbdbase[kloop].w;
+ if ((kbdbase[kloop].y + kbdbase[kloop].h) > maxy)
+ maxy=kbdbase[kloop].y + kbdbase[kloop].h;
+ }
+
+ ww = fbtk_get_width(root);
+
+ /* scale window height apropriately */
+ wh = (maxy * ww) / maxx;
+
+ osk = fbtk_create_window(root, 0, fbtk_get_height(root) - wh, 0, wh, 0xff202020);
+
+ for (kloop=0; kloop < KEYCOUNT; kloop++) {
+ widget = fbtk_create_text_button(osk,
+ (kbdbase[kloop].x * ww) / maxx,
+ (kbdbase[kloop].y * ww) / maxx,
+ (kbdbase[kloop].w * ww) / maxx,
+ (kbdbase[kloop].h *ww) / maxx,
+ FB_FRAME_COLOUR,
+ FB_COLOUR_BLACK,
+ osk_click,
+ &kbdbase[kloop]);
+ fbtk_set_text(widget, kbdbase[kloop].t);
+ }
+
+ widget = fbtk_create_button(osk,
+ fbtk_get_width(osk) - furniture_width,
+ fbtk_get_height(osk) - furniture_width,
+ furniture_width,
+ furniture_width,
+ FB_FRAME_COLOUR,
+ &osk_image,
+ osk_close,
+ NULL);
+}
+
+/* exported function documented in fbtk.h */
+void
+map_osk(void)
+{
+ fbtk_set_zorder(osk, INT_MIN);
+ fbtk_set_mapping(osk, true);
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset:8
+ * End:
+ */
diff --git a/frontends/kolibrios/fb/fbtk/scroll.c b/frontends/kolibrios/fb/fbtk/scroll.c
new file mode 100644
index 0000000..cc98fb2
--- a/dev/null
+++ b/frontends/kolibrios/fb/fbtk/scroll.c
@@ -0,0 +1,589 @@
+/*
+ * Copyright 2010 Vincent Sanders <vince@simtec.co.uk>
+ *
+ * Framebuffer windowing toolkit scrollbar widgets
+ *
+ * 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 <stdbool.h>
+
+#include <libnsfb.h>
+#include <libnsfb_plot.h>
+#include <libnsfb_event.h>
+#include <libnsfb_cursor.h>
+
+#include "utils/log.h"
+#include "netsurf/browser_window.h"
+
+#include "framebuffer/gui.h"
+#include "framebuffer/fbtk.h"
+#include "framebuffer/image_data.h"
+
+#include "widget.h"
+
+/* Vertical scroll widget */
+
+static int
+vscroll_redraw(fbtk_widget_t *widget, fbtk_callback_info *cbi)
+{
+ int vscroll;
+ int vpos;
+
+ nsfb_bbox_t bbox;
+ nsfb_bbox_t rect;
+ fbtk_widget_t *root = fbtk_get_root_widget(widget);
+
+ fbtk_get_bbox(widget, &bbox);
+
+ nsfb_claim(root->u.root.fb, &bbox);
+
+ rect = bbox;
+
+ /* background */
+ nsfb_plot_rectangle_fill(root->u.root.fb, &rect, widget->bg);
+
+ /* scroll well */
+ rect.x0 = bbox.x0 + 2;
+ rect.y0 = bbox.y0 + 1;
+ rect.x1 = bbox.x1 - 3;
+ rect.y1 = bbox.y1 - 2;
+
+ nsfb_plot_rectangle_fill(root->u.root.fb, &rect, widget->fg);
+ nsfb_plot_rectangle(root->u.root.fb, &rect, 1, 0xFF999999, false, false);
+
+ /* scroll bar */
+ if ((widget->u.scroll.maximum - widget->u.scroll.minimum) > 0) {
+ vscroll = ((widget->height - 4) * widget->u.scroll.thumb) /
+ (widget->u.scroll.maximum - widget->u.scroll.minimum) ;
+ vpos = ((widget->height - 4) * widget->u.scroll.position) /
+ (widget->u.scroll.maximum - widget->u.scroll.minimum) ;
+ } else {
+ vscroll = (widget->height - 4);
+ vpos = 0;
+ }
+
+ rect.x0 = bbox.x0 + 5;
+ rect.y0 = bbox.y0 + 3 + vpos;
+ rect.x1 = bbox.x0 + widget->width - 5;
+ rect.y1 = bbox.y0 + vscroll + vpos;
+
+ nsfb_plot_rectangle_fill(root->u.root.fb, &rect, widget->bg);
+
+ nsfb_update(root->u.root.fb, &bbox);
+
+ return 0;
+}
+
+static int
+vscroll_drag(fbtk_widget_t *widget, fbtk_callback_info *cbi)
+{
+ int newpos;
+ fbtk_widget_t *scrollw = cbi->context;
+
+ newpos = ((widget->u.scroll.drag_position +
+ (cbi->y - widget->u.scroll.drag)) *
+ (widget->u.scroll.maximum - widget->u.scroll.minimum)) /
+ (widget->height - 4);
+
+ if (newpos < scrollw->u.scroll.minimum)
+ newpos = scrollw->u.scroll.minimum;
+
+ if (newpos > (scrollw->u.scroll.maximum - scrollw->u.scroll.thumb ))
+ newpos = (scrollw->u.scroll.maximum - scrollw->u.scroll.thumb);
+
+ if (newpos == scrollw->u.scroll.position)
+ return 0;
+
+ return fbtk_post_callback(widget, FBTK_CBT_SCROLLY, newpos);
+}
+
+static int
+vscrollu_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
+{
+ int newpos;
+ fbtk_widget_t *scrollw = cbi->context;
+
+ if (cbi->event->type != NSFB_EVENT_KEY_DOWN)
+ return 0;
+
+ newpos = scrollw->u.scroll.position - scrollw->u.scroll.page;
+ if (newpos < scrollw->u.scroll.minimum)
+ newpos = scrollw->u.scroll.minimum;
+
+ if (newpos == scrollw->u.scroll.position)
+ return 0;
+
+ return fbtk_post_callback(scrollw, FBTK_CBT_SCROLLY, newpos);
+}
+
+static int
+vscrolld_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
+{
+ int newpos;
+ fbtk_widget_t *scrollw = cbi->context;
+
+ if (cbi->event->type != NSFB_EVENT_KEY_DOWN)
+ return 0;
+
+ newpos = scrollw->u.scroll.position + scrollw->u.scroll.page;
+ if (newpos > (scrollw->u.scroll.maximum - scrollw->u.scroll.thumb ))
+ newpos = (scrollw->u.scroll.maximum - scrollw->u.scroll.thumb);
+
+ if (newpos == scrollw->u.scroll.position)
+ return 0;
+
+ return fbtk_post_callback(scrollw, FBTK_CBT_SCROLLY, newpos);
+}
+
+static int
+vscrollarea_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
+{
+ int vscroll;
+ int vpos;
+ int newpos;
+ int ret = 0;
+
+ if (cbi->event->type != NSFB_EVENT_KEY_DOWN) {
+ /* end all drags, just in case */
+ if (fbtk_set_handler(widget, FBTK_CBT_POINTERMOVE, NULL, NULL) != NULL)
+ fbtk_tgrab_pointer(widget);
+ return 0;
+ }
+
+ switch (cbi->event->value.keycode) {
+
+ case NSFB_KEY_MOUSE_4:
+ /* scroll up */
+ newpos = widget->u.scroll.position - widget->u.scroll.page;
+ if (newpos < widget->u.scroll.minimum)
+ newpos = widget->u.scroll.minimum;
+ ret = fbtk_post_callback(cbi->context, FBTK_CBT_SCROLLY, newpos);
+ break;
+
+ case NSFB_KEY_MOUSE_5:
+ /* scroll down */
+ newpos = widget->u.scroll.position + widget->u.scroll.page;
+ if (newpos > widget->u.scroll.maximum)
+ newpos = widget->u.scroll.maximum;
+ ret = fbtk_post_callback(cbi->context, FBTK_CBT_SCROLLY, newpos);
+ break;
+
+ default:
+
+ if ((widget->u.scroll.maximum - widget->u.scroll.minimum) > 0) {
+ vscroll = ((widget->height - 4) * widget->u.scroll.thumb) /
+ (widget->u.scroll.maximum - widget->u.scroll.minimum) ;
+ vpos = ((widget->height - 4) * widget->u.scroll.position) /
+ (widget->u.scroll.maximum - widget->u.scroll.minimum) ;
+ } else {
+ vscroll = (widget->height - 4);
+ vpos = 0;
+ }
+
+ if (cbi->y < vpos) {
+ /* above bar */
+ newpos = widget->u.scroll.position - widget->u.scroll.thumb;
+ if (newpos < widget->u.scroll.minimum)
+ newpos = widget->u.scroll.minimum;
+ ret = fbtk_post_callback(cbi->context, FBTK_CBT_SCROLLY, newpos);
+ } else if (cbi->y > (vpos + vscroll)) {
+ /* below bar */
+ newpos = widget->u.scroll.position + widget->u.scroll.thumb;
+ if (newpos > widget->u.scroll.maximum)
+ newpos = widget->u.scroll.maximum;
+ ret = fbtk_post_callback(cbi->context, FBTK_CBT_SCROLLY, newpos);
+ } else {
+ /* on bar - start drag */
+ widget->u.scroll.drag = cbi->y;
+ widget->u.scroll.drag_position = vpos;
+ fbtk_set_handler(widget, FBTK_CBT_POINTERMOVE, vscroll_drag, widget);
+ fbtk_tgrab_pointer(widget);
+ }
+ }
+ return ret;
+}
+
+
+/* exported function documented in fbtk.h */
+fbtk_widget_t *
+fbtk_create_vscroll(fbtk_widget_t *parent,
+ int x,
+ int y,
+ int width,
+ int height,
+ colour fg,
+ colour bg,
+ fbtk_callback callback,
+ void *context)
+{
+ fbtk_widget_t *neww;
+
+ neww = fbtk_widget_new(parent,
+ FB_WIDGET_TYPE_VSCROLL,
+ x,
+ y + scrollu.height,
+ width,
+ height - scrollu.height - scrolld.height);
+
+ neww->fg = fg;
+ neww->bg = bg;
+ neww->mapped = true;
+
+ fbtk_set_handler(neww, FBTK_CBT_REDRAW, vscroll_redraw, NULL);
+
+ fbtk_set_handler(neww, FBTK_CBT_CLICK, vscrollarea_click, neww);
+
+ fbtk_set_handler(neww, FBTK_CBT_SCROLLY, callback, context);
+
+ neww->u.scroll.btnul = fbtk_create_button(parent,
+ x,
+ y,
+ width,
+ scrollu.height,
+ fg,
+ &scrollu,
+ vscrollu_click,
+ neww);
+
+ neww->u.scroll.btndr = fbtk_create_button(parent,
+ x,
+ y + height - scrolld.height,
+ width,
+ scrolld.height,
+ fg,
+ &scrolld,
+ vscrolld_click,
+ neww);
+
+
+ return neww;
+}
+
+
+/* exported function documented in fbtk.h */
+void
+fbtk_reposition_vscroll(fbtk_widget_t *vscroll,
+ int x,
+ int y,
+ int width,
+ int height)
+{
+ assert(vscroll->type == FB_WIDGET_TYPE_VSCROLL);
+
+ fbtk_set_pos_and_size(vscroll, x, y + scrollu.height,
+ width, height - scrollu.height - scrolld.height);
+ fbtk_set_pos_and_size(vscroll->u.scroll.btnul,
+ x, y, width, scrollu.height);
+ fbtk_set_pos_and_size(vscroll->u.scroll.btndr,
+ x, y + height - scrolld.height,
+ width, scrolld.height);
+}
+
+/* Horizontal scroll widget */
+
+static int
+hscroll_redraw(fbtk_widget_t *widget, fbtk_callback_info *cbi)
+{
+ int hscroll;
+ int hpos;
+ nsfb_bbox_t bbox;
+ nsfb_bbox_t rect;
+ fbtk_widget_t *root = fbtk_get_root_widget(widget);
+
+ fbtk_get_bbox(widget, &bbox);
+
+ nsfb_claim(root->u.root.fb, &bbox);
+
+ rect = bbox;
+
+ /* background */
+ nsfb_plot_rectangle_fill(root->u.root.fb, &rect, widget->bg);
+
+ /* scroll well */
+ rect.x0 = bbox.x0 + 1;
+ rect.y0 = bbox.y0 + 2;
+ rect.x1 = bbox.x1 - 2;
+ rect.y1 = bbox.y1 - 3;
+ nsfb_plot_rectangle_fill(root->u.root.fb, &rect, widget->fg);
+
+ /* scroll well outline */
+ nsfb_plot_rectangle(root->u.root.fb, &rect, 1, 0xFF999999, false, false);
+
+ if ((widget->u.scroll.maximum - widget->u.scroll.minimum) > 0) {
+ hscroll = ((widget->width - 4) * widget->u.scroll.thumb) /
+ (widget->u.scroll.maximum - widget->u.scroll.minimum) ;
+ hpos = ((widget->width - 4) * widget->u.scroll.position) /
+ (widget->u.scroll.maximum - widget->u.scroll.minimum) ;
+ } else {
+ hscroll = (widget->width - 4);
+ hpos = 0;
+ }
+
+ LOG("hscroll %d", hscroll);
+
+ rect.x0 = bbox.x0 + 3 + hpos;
+ rect.y0 = bbox.y0 + 5;
+ rect.x1 = bbox.x0 + hscroll + hpos;
+ rect.y1 = bbox.y0 + widget->height - 5;
+
+ nsfb_plot_rectangle_fill(root->u.root.fb, &rect, widget->bg);
+
+ nsfb_update(root->u.root.fb, &bbox);
+
+ return 0;
+}
+
+static int
+hscrolll_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
+{
+ int newpos;
+ fbtk_widget_t *scrollw = cbi->context;
+
+ if (cbi->event->type != NSFB_EVENT_KEY_DOWN)
+ return 0;
+
+ newpos = scrollw->u.scroll.position - scrollw->u.scroll.page;
+ if (newpos < scrollw->u.scroll.minimum)
+ newpos = scrollw->u.scroll.minimum;
+
+ if (newpos == scrollw->u.scroll.position) {
+ LOG("horiz scroll was the same %d", newpos);
+ return 0;
+ }
+
+ return fbtk_post_callback(scrollw, FBTK_CBT_SCROLLX, newpos);
+}
+
+static int
+hscrollr_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
+{
+ int newpos;
+ fbtk_widget_t *scrollw = cbi->context;
+
+ if (cbi->event->type != NSFB_EVENT_KEY_DOWN)
+ return 0;
+
+ newpos = scrollw->u.scroll.position + scrollw->u.scroll.page;
+ if (newpos > (scrollw->u.scroll.maximum - scrollw->u.scroll.thumb ))
+ newpos = (scrollw->u.scroll.maximum - scrollw->u.scroll.thumb);
+
+ if (newpos == scrollw->u.scroll.position)
+ return 0;
+
+ return fbtk_post_callback(scrollw, FBTK_CBT_SCROLLX, newpos);
+}
+
+static int
+hscroll_drag(fbtk_widget_t *widget, fbtk_callback_info *cbi)
+{
+ int newpos;
+ fbtk_widget_t *scrollw = cbi->context;
+
+ newpos = ((widget->u.scroll.drag_position +
+ (cbi->x - widget->u.scroll.drag)) *
+ (widget->u.scroll.maximum - widget->u.scroll.minimum)) /
+ (widget->width - 4);
+
+ if (newpos < scrollw->u.scroll.minimum)
+ newpos = scrollw->u.scroll.minimum;
+
+ if (newpos > (scrollw->u.scroll.maximum - scrollw->u.scroll.thumb ))
+ newpos = (scrollw->u.scroll.maximum - scrollw->u.scroll.thumb);
+
+ if (newpos == scrollw->u.scroll.position)
+ return 0;
+
+ return fbtk_post_callback(widget, FBTK_CBT_SCROLLX, newpos);
+}
+
+static int
+hscrollarea_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
+{
+ int hscroll;
+ int hpos;
+ int newpos;
+ int ret = 0;
+
+ if (cbi->event->type != NSFB_EVENT_KEY_DOWN) {
+ /* end all drags, just in case */
+ if (fbtk_set_handler(widget, FBTK_CBT_POINTERMOVE, NULL, NULL) != NULL)
+ fbtk_tgrab_pointer(widget);
+ return 0;
+ }
+
+ if ((widget->u.scroll.maximum - widget->u.scroll.minimum) > 0) {
+ hscroll = ((widget->width - 4) * widget->u.scroll.thumb) /
+ (widget->u.scroll.maximum - widget->u.scroll.minimum) ;
+ hpos = ((widget->width - 4) * widget->u.scroll.position) /
+ (widget->u.scroll.maximum - widget->u.scroll.minimum) ;
+ } else {
+ hscroll = (widget->width - 4);
+ hpos = 0;
+ }
+
+ if (cbi->x < hpos) {
+ /* left of bar */
+ newpos = widget->u.scroll.position - widget->u.scroll.page;
+ if (newpos < widget->u.scroll.minimum)
+ newpos = widget->u.scroll.minimum;
+ ret = fbtk_post_callback(cbi->context, FBTK_CBT_SCROLLX, newpos);
+ } else if (cbi->x > (hpos + hscroll)) {
+ /* right of bar */
+ newpos = widget->u.scroll.position + widget->u.scroll.page;
+ if (newpos > widget->u.scroll.maximum)
+ newpos = widget->u.scroll.maximum;
+ ret = fbtk_post_callback(cbi->context, FBTK_CBT_SCROLLX, newpos);
+ } else {
+ /* on bar - start drag */
+ widget->u.scroll.drag = cbi->x;
+ widget->u.scroll.drag_position = hpos;
+ fbtk_set_handler(widget, FBTK_CBT_POINTERMOVE, hscroll_drag, widget);
+ fbtk_tgrab_pointer(widget);
+ }
+ return ret;
+}
+
+/* exported function documented in fbtk.h */
+fbtk_widget_t *
+fbtk_create_hscroll(fbtk_widget_t *parent,
+ int x,
+ int y,
+ int width,
+ int height,
+ colour fg,
+ colour bg,
+ fbtk_callback callback,
+ void *context)
+{
+ fbtk_widget_t *neww;
+
+ neww = fbtk_widget_new(parent,
+ FB_WIDGET_TYPE_HSCROLL,
+ x + scrolll.width,
+ y,
+ width - scrolll.width - scrollr.width,
+ height);
+
+ neww->fg = fg;
+ neww->bg = bg;
+ neww->mapped = true;
+
+ fbtk_set_handler(neww, FBTK_CBT_REDRAW, hscroll_redraw, NULL);
+ fbtk_set_handler(neww, FBTK_CBT_CLICK, hscrollarea_click, neww);
+ fbtk_set_handler(neww, FBTK_CBT_SCROLLX, callback, context);
+
+ neww->u.scroll.btnul = fbtk_create_button(parent,
+ x,
+ y,
+ scrolll.width,
+ height,
+ fg,
+ &scrolll,
+ hscrolll_click,
+ neww);
+
+ neww->u.scroll.btndr = fbtk_create_button(parent,
+ x + width - scrollr.width,
+ y,
+ scrollr.width,
+ height,
+ fg,
+ &scrollr,
+ hscrollr_click,
+ neww);
+
+ return neww;
+}
+
+/* exported function documented in fbtk.h */
+void
+fbtk_reposition_hscroll(fbtk_widget_t *scrollh,
+ int x,
+ int y,
+ int width,
+ int height)
+{
+ assert(scrollh->type == FB_WIDGET_TYPE_HSCROLL);
+
+ fbtk_set_pos_and_size(scrollh, x + scrolll.width, y,
+ width - scrolll.width - scrollr.width, height);
+ fbtk_set_pos_and_size(scrollh->u.scroll.btnul,
+ x, y, scrolll.width, height);
+ fbtk_set_pos_and_size(scrollh->u.scroll.btndr,
+ x + width - scrollr.width, y,
+ scrollr.width, height);
+}
+
+
+/* exported function documented in fbtk.h */
+bool
+fbtk_set_scroll_parameters(fbtk_widget_t *widget,
+ int min,
+ int max,
+ int thumb,
+ int page)
+{
+ if (widget == NULL)
+ return false;
+
+ if ((widget->type != FB_WIDGET_TYPE_HSCROLL) &&
+ (widget->type != FB_WIDGET_TYPE_VSCROLL))
+ return false;
+
+ widget->u.scroll.minimum = min;
+ widget->u.scroll.maximum = max;
+ widget->u.scroll.thumb = thumb;
+ widget->u.scroll.page = page;
+
+ if (widget->u.scroll.position > max)
+ widget->u.scroll.position = max;
+ if (widget->u.scroll.position < min)
+ widget->u.scroll.position = min;
+
+ fbtk_request_redraw(widget);
+
+ return true;
+}
+
+/* exported function documented in fbtk.h */
+bool
+fbtk_set_scroll_position(fbtk_widget_t *widget, int position)
+{
+ if (widget == NULL)
+ return false;
+
+ if ((widget->type != FB_WIDGET_TYPE_HSCROLL) &&
+ (widget->type != FB_WIDGET_TYPE_VSCROLL))
+ return false;
+
+ if ((position < widget->u.scroll.minimum) ||
+ (position > widget->u.scroll.maximum))
+ return false;
+
+ widget->u.scroll.position = position;
+
+ fbtk_request_redraw(widget);
+
+ return true;
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset:8
+ * End:
+ */
diff --git a/frontends/kolibrios/fb/fbtk/text.c b/frontends/kolibrios/fb/fbtk/text.c
new file mode 100644
index 0000000..31417c2
--- a/dev/null
+++ b/frontends/kolibrios/fb/fbtk/text.c
@@ -0,0 +1,654 @@
+/*
+ * Copyright 2010 Vincent Sanders <vince@simtec.co.uk>
+ *
+ * Framebuffer windowing toolkit scrollbar widgets.
+ *
+ * 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 <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libnsfb.h>
+#include <libnsfb_plot.h>
+#include <libnsfb_plot_util.h>
+#include <libnsfb_event.h>
+
+#include "utils/log.h"
+#include "netsurf/browser_window.h"
+#include "netsurf/plotters.h"
+
+#include "framebuffer/gui.h"
+#include "framebuffer/fbtk.h"
+#include "framebuffer/font.h"
+#include "framebuffer/framebuffer.h"
+#include "framebuffer/image_data.h"
+
+#include "widget.h"
+
+//#define TEXT_WIDGET_BORDER 3 /**< The pixel border round a text widget. */
+
+/* Lighten a colour by taking seven eights of each channel's intensity
+ * and adding a full eighth
+ */
+#define brighten_colour(c1) \
+ (((((7 * ((c1 >> 16) & 0xff)) >> 3) + 32) << 16) | \
+ ((((7 * ((c1 >> 8) & 0xff)) >> 3) + 32) << 8) | \
+ ((((7 * (c1 & 0xff)) >> 3) + 32) << 0))
+
+/* Convert pixels to points, assuming a DPI of 90 */
+#define px_to_pt(x) (((x) * 72) / FBTK_DPI)
+
+/* Get a font style for a text input */
+static inline void
+fb_text_font_style(fbtk_widget_t *widget, int *font_height, int *padding,
+ plot_font_style_t *font_style)
+{
+ if (widget->u.text.outline)
+ *padding = 1;
+ else
+ *padding = 0;
+
+#ifdef FB_USE_FREETYPE
+ *padding += widget->height / 6;
+ *font_height = widget->height - *padding - *padding;
+#else
+ *font_height = FB_FONT_HEIGHT;
+ *padding = (widget->height - *padding - *font_height) / 2;
+#endif
+
+ font_style->family = PLOT_FONT_FAMILY_SANS_SERIF;
+ font_style->size = px_to_pt(*font_height * FONT_SIZE_SCALE);
+ font_style->weight = 400;
+ font_style->flags = FONTF_NONE;
+ font_style->background = widget->bg;
+ font_style->foreground = widget->fg;
+}
+
+/** Text redraw callback.
+ *
+ * Called when a text widget requires redrawing.
+ *
+ * @param widget The widget to be redrawn.
+ * @param cbi The callback parameters.
+ * @return The callback result.
+ */
+static int
+fb_redraw_text(fbtk_widget_t *widget, fbtk_callback_info *cbi )
+{
+ nsfb_bbox_t bbox;
+ nsfb_bbox_t rect;
+ fbtk_widget_t *root;
+ plot_font_style_t font_style;
+ int caret_x, caret_y, caret_h;
+ int fh;
+ int padding;
+ int scroll = 0;
+ bool caret = false;
+ struct redraw_context ctx = {
+ .interactive = true,
+ .background_images = true,
+ .plot = &fb_plotters
+ };
+
+ fb_text_font_style(widget, &fh, &padding, &font_style);
+
+ if (fbtk_get_caret(widget, &caret_x, &caret_y, &caret_h)) {
+ caret = true;
+ }
+
+ root = fbtk_get_root_widget(widget);
+
+ fbtk_get_bbox(widget, &bbox);
+
+ rect = bbox;
+
+ nsfb_claim(root->u.root.fb, &bbox);
+
+ /* clear background */
+ if ((widget->bg & 0xFF000000) != 0) {
+ /* transparent polygon filling isnt working so fake it */
+ nsfb_plot_rectangle_fill(root->u.root.fb, &bbox, widget->bg);
+ }
+
+ /* widget can have a single pixel outline border */
+ if (widget->u.text.outline) {
+ rect.x1--;
+ rect.y1--;
+ nsfb_plot_rectangle(root->u.root.fb, &rect, 1,
+ 0x00000000, false, false);
+ }
+
+ if (widget->u.text.text != NULL) {
+ int x = bbox.x0 + padding;
+ int y = bbox.y0 + ((fh * 3 + 2) / 4) + padding;
+
+#ifdef FB_USE_FREETYPE
+ /* Freetype renders text higher */
+ y += 1;
+#endif
+
+ if (caret && widget->width - padding - padding < caret_x) {
+ scroll = (widget->width - padding - padding) - caret_x;
+ x += scroll;
+ }
+
+ /* Call the fb text plotting, baseline is 3/4 down the font */
+ ctx.plot->text(&ctx,
+ &font_style,
+ x, y,
+ widget->u.text.text,
+ widget->u.text.len);
+ }
+
+ if (caret) {
+ /* This widget has caret, so render it */
+ nsfb_t *nsfb = fbtk_get_nsfb(widget);
+ nsfb_bbox_t line;
+ nsfb_plot_pen_t pen;
+
+ line.x0 = bbox.x0 + caret_x + scroll;
+ line.y0 = bbox.y0 + caret_y;
+ line.x1 = bbox.x0 + caret_x + scroll;
+ line.y1 = bbox.y0 + caret_y + caret_h;
+
+ pen.stroke_type = NFSB_PLOT_OPTYPE_SOLID;
+ pen.stroke_width = 1;
+ pen.stroke_colour = 0xFF0000FF;
+
+ nsfb_plot_line(nsfb, &line, &pen);
+ }
+
+ nsfb_update(root->u.root.fb, &bbox);
+
+ return 0;
+}
+
+/** Text destroy callback.
+ *
+ * Called when a text widget is destroyed.
+ *
+ * @param widget The widget being destroyed.
+ * @param cbi The callback parameters.
+ * @return The callback result.
+ */
+static int fb_destroy_text(fbtk_widget_t *widget, fbtk_callback_info *cbi)
+{
+ if ((widget == NULL) || (widget->type != FB_WIDGET_TYPE_TEXT)) {
+ return 0;
+ }
+
+ if (widget->u.text.text != NULL) {
+ free(widget->u.text.text);
+ }
+
+ return 0;
+}
+
+/** Text button redraw callback.
+ *
+ * Called when a text widget requires redrawing.
+ *
+ * @param widget The widget to be redrawn.
+ * @param cbi The callback parameters.
+ * @return The callback result.
+ */
+static int
+fb_redraw_text_button(fbtk_widget_t *widget, fbtk_callback_info *cbi )
+{
+ nsfb_bbox_t bbox;
+ nsfb_bbox_t rect;
+ nsfb_bbox_t line;
+ nsfb_plot_pen_t pen;
+ plot_font_style_t font_style;
+ int fh;
+ int border;
+ fbtk_widget_t *root = fbtk_get_root_widget(widget);
+ struct redraw_context ctx = {
+ .interactive = true,
+ .background_images = true,
+ .plot = &fb_plotters
+ };
+
+ fb_text_font_style(widget, &fh, &border, &font_style);
+
+ pen.stroke_type = NFSB_PLOT_OPTYPE_SOLID;
+ pen.stroke_width = 1;
+ pen.stroke_colour = brighten_colour(widget->bg);
+
+ fbtk_get_bbox(widget, &bbox);
+
+ rect = bbox;
+ rect.x1--;
+ rect.y1--;
+
+ nsfb_claim(root->u.root.fb, &bbox);
+
+ /* clear background */
+ if ((widget->bg & 0xFF000000) != 0) {
+ /* transparent polygon filling isnt working so fake it */
+ nsfb_plot_rectangle_fill(root->u.root.fb, &rect, widget->bg);
+ }
+
+ if (widget->u.text.outline) {
+ line.x0 = rect.x0;
+ line.y0 = rect.y0;
+ line.x1 = rect.x0;
+ line.y1 = rect.y1;
+ nsfb_plot_line(root->u.root.fb, &line, &pen);
+ line.x0 = rect.x0;
+ line.y0 = rect.y0;
+ line.x1 = rect.x1;
+ line.y1 = rect.y0;
+ nsfb_plot_line(root->u.root.fb, &line, &pen);
+ pen.stroke_colour = darken_colour(widget->bg);
+ line.x0 = rect.x0;
+ line.y0 = rect.y1;
+ line.x1 = rect.x1;
+ line.y1 = rect.y1;
+ nsfb_plot_line(root->u.root.fb, &line, &pen);
+ line.x0 = rect.x1;
+ line.y0 = rect.y0;
+ line.x1 = rect.x1;
+ line.y1 = rect.y1;
+ nsfb_plot_line(root->u.root.fb, &line, &pen);
+ }
+
+ if (widget->u.text.text != NULL) {
+ /* Call the fb text plotting, baseline is 3/4 down the font */
+ ctx.plot->text(&ctx,
+ &font_style,
+ bbox.x0 + border,
+ bbox.y0 + ((fh * 3) / 4) + border,
+ widget->u.text.text,
+ widget->u.text.len);
+ }
+
+ nsfb_update(root->u.root.fb, &bbox);
+
+ return 0;
+}
+
+static void
+fb_text_input_remove_caret_cb(fbtk_widget_t *widget)
+{
+ int c_x, c_y, c_h;
+
+ if (fbtk_get_caret(widget, &c_x, &c_y, &c_h)) {
+ fbtk_request_redraw(widget);
+ }
+}
+
+/** Routine called when text events occour in writeable widget.
+ *
+ * @param widget The widget reciving input events.
+ * @param cbi The callback parameters.
+ * @return The callback result.
+ */
+static int
+text_input(fbtk_widget_t *widget, fbtk_callback_info *cbi)
+{
+ int value;
+ static fbtk_modifier_type modifier = FBTK_MOD_CLEAR;
+ char *temp;
+ plot_font_style_t font_style;
+ int fh;
+ int border;
+ bool caret_moved = false;
+
+ fb_text_font_style(widget, &fh, &border, &font_style);
+
+ if (cbi->event == NULL) {
+ /* gain focus */
+ if (widget->u.text.text == NULL)
+ widget->u.text.text = calloc(1,1);
+
+ return 0;
+ }
+
+ value = cbi->event->value.keycode;
+
+ if (cbi->event->type != NSFB_EVENT_KEY_DOWN) {
+ switch (value) {
+ case NSFB_KEY_RSHIFT:
+ modifier &= ~FBTK_MOD_RSHIFT;
+ break;
+
+ case NSFB_KEY_LSHIFT:
+ modifier &= ~FBTK_MOD_LSHIFT;
+ break;
+
+ case NSFB_KEY_RCTRL:
+ modifier &= ~FBTK_MOD_RCTRL;
+ break;
+
+ case NSFB_KEY_LCTRL:
+ modifier &= ~FBTK_MOD_LCTRL;
+ break;
+
+ default:
+ break;
+ }
+ return 0;
+ }
+
+ switch (value) {
+ case NSFB_KEY_BACKSPACE:
+ if (widget->u.text.idx <= 0)
+ break;
+ memmove(widget->u.text.text + widget->u.text.idx - 1,
+ widget->u.text.text + widget->u.text.idx,
+ widget->u.text.len - widget->u.text.idx);
+ widget->u.text.idx--;
+ widget->u.text.len--;
+ widget->u.text.text[widget->u.text.len] = 0;
+
+ fb_font_width(&font_style, widget->u.text.text,
+ widget->u.text.len, &widget->u.text.width);
+
+ caret_moved = true;
+ break;
+
+ case NSFB_KEY_RETURN:
+ widget->u.text.enter(widget->u.text.pw, widget->u.text.text);
+ break;
+
+ case NSFB_KEY_RIGHT:
+ if (widget->u.text.idx < widget->u.text.len) {
+ if (modifier == FBTK_MOD_CLEAR)
+ widget->u.text.idx++;
+ else
+ widget->u.text.idx = widget->u.text.len;
+
+ caret_moved = true;
+ }
+ break;
+
+ case NSFB_KEY_LEFT:
+ if (widget->u.text.idx > 0) {
+ if (modifier == FBTK_MOD_CLEAR)
+ widget->u.text.idx--;
+ else
+ widget->u.text.idx = 0;
+
+ caret_moved = true;
+ }
+ break;
+
+ case NSFB_KEY_PAGEUP:
+ case NSFB_KEY_PAGEDOWN:
+ case NSFB_KEY_UP:
+ case NSFB_KEY_DOWN:
+ /* Not handling any of these correctly yet, but avoid putting
+ * charcters in the text widget when they're pressed. */
+ break;
+
+ case NSFB_KEY_RSHIFT:
+ modifier |= FBTK_MOD_RSHIFT;
+ break;
+
+ case NSFB_KEY_LSHIFT:
+ modifier |= FBTK_MOD_LSHIFT;
+ break;
+
+ case NSFB_KEY_RCTRL:
+ modifier |= FBTK_MOD_RCTRL;
+ break;
+
+ case NSFB_KEY_LCTRL:
+ modifier |= FBTK_MOD_LCTRL;
+ break;
+
+ default:
+ if (modifier & FBTK_MOD_LCTRL || modifier & FBTK_MOD_RCTRL) {
+ /* CTRL pressed, don't enter any text */
+ if (value == NSFB_KEY_u) {
+ /* CTRL+U: clear writable */
+ widget->u.text.idx = 0;
+ widget->u.text.len = 0;
+ widget->u.text.text[widget->u.text.len] = '\0';
+ widget->u.text.width = 0;
+ caret_moved = true;
+ }
+ break;
+ }
+
+ /* allow for new character and null */
+ temp = realloc(widget->u.text.text, widget->u.text.len + 2);
+ if (temp == NULL) {
+ break;
+ }
+
+ widget->u.text.text = temp;
+ memmove(widget->u.text.text + widget->u.text.idx + 1,
+ widget->u.text.text + widget->u.text.idx,
+ widget->u.text.len - widget->u.text.idx);
+ widget->u.text.text[widget->u.text.idx] =
+ fbtk_keycode_to_ucs4(value, modifier);
+ widget->u.text.idx++;
+ widget->u.text.len++;
+ widget->u.text.text[widget->u.text.len] = '\0';
+
+ fb_font_width(&font_style, widget->u.text.text,
+ widget->u.text.len, &widget->u.text.width);
+ caret_moved = true;
+ break;
+ }
+
+ if (caret_moved) {
+ fb_font_width(&font_style, widget->u.text.text,
+ widget->u.text.idx, &widget->u.text.idx_offset);
+ fbtk_set_caret(widget, true,
+ widget->u.text.idx_offset + border,
+ border,
+ widget->height - border - border,
+ fb_text_input_remove_caret_cb);
+ }
+
+ fbtk_request_redraw(widget);
+
+ return 0;
+}
+
+/** Routine called when click events occour in writeable widget.
+ *
+ * @param widget The widget reciving click events.
+ * @param cbi The callback parameters.
+ * @return The callback result.
+ */
+static int
+text_input_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
+{
+ plot_font_style_t font_style;
+ int fh;
+ int border;
+ size_t idx;
+
+ fb_text_font_style(widget, &fh, &border, &font_style);
+
+ widget->u.text.idx = widget->u.text.len;
+
+ fb_font_position(&font_style, widget->u.text.text,
+ widget->u.text.len, cbi->x - border,
+ &idx,
+ &widget->u.text.idx_offset);
+ widget->u.text.idx = idx;
+ fbtk_set_caret(widget, true,
+ widget->u.text.idx_offset + border,
+ border,
+ widget->height - border - border,
+ fb_text_input_remove_caret_cb);
+
+ fbtk_request_redraw(widget);
+
+ return 0;
+}
+
+/** Routine called when "stripped of focus" event occours for writeable widget.
+ *
+ * @param widget The widget reciving "stripped of focus" event.
+ * @param cbi The callback parameters.
+ * @return The callback result.
+ */
+static int
+text_input_strip_focus(fbtk_widget_t *widget, fbtk_callback_info *cbi)
+{
+ fbtk_set_caret(widget, false, 0, 0, 0, NULL);
+
+ return 0;
+}
+
+/* exported function documented in fbtk.h */
+void
+fbtk_writable_text(fbtk_widget_t *widget, fbtk_enter_t enter, void *pw)
+{
+ widget->u.text.enter = enter;
+ widget->u.text.pw = pw;
+
+ fbtk_set_handler(widget, FBTK_CBT_INPUT, text_input, widget);
+}
+
+/* exported function documented in fbtk.h */
+void
+fbtk_set_text(fbtk_widget_t *widget, const char *text)
+{
+ plot_font_style_t font_style;
+ int c_x, c_y, c_h;
+ int fh;
+ int border;
+
+ if ((widget == NULL) || (widget->type != FB_WIDGET_TYPE_TEXT))
+ return;
+ if (widget->u.text.text != NULL) {
+ if (strcmp(widget->u.text.text, text) == 0)
+ return; /* text is being set to the same thing */
+ free(widget->u.text.text);
+ }
+ widget->u.text.text = strdup(text);
+ widget->u.text.len = strlen(text);
+ widget->u.text.idx = widget->u.text.len;
+
+
+ fb_text_font_style(widget, &fh, &border, &font_style);
+ fb_font_width(&font_style, widget->u.text.text,
+ widget->u.text.len, &widget->u.text.width);
+ fb_font_width(&font_style, widget->u.text.text,
+ widget->u.text.idx, &widget->u.text.idx_offset);
+
+ if (fbtk_get_caret(widget, &c_x, &c_y, &c_h)) {
+ /* Widget has caret; move it to end of new string */
+ fbtk_set_caret(widget, true,
+ widget->u.text.idx_offset + border,
+ border,
+ widget->height - border - border,
+ fb_text_input_remove_caret_cb);
+ }
+
+ fbtk_request_redraw(widget);
+}
+
+/* exported function documented in fbtk.h */
+fbtk_widget_t *
+fbtk_create_text(fbtk_widget_t *parent,
+ int x,
+ int y,
+ int width,
+ int height,
+ colour bg,
+ colour fg,
+ bool outline)
+{
+ fbtk_widget_t *neww;
+
+ neww = fbtk_widget_new(parent, FB_WIDGET_TYPE_TEXT, x, y, width, height);
+ neww->fg = fg;
+ neww->bg = bg;
+ neww->mapped = true;
+ neww->u.text.outline = outline;
+
+ fbtk_set_handler(neww, FBTK_CBT_REDRAW, fb_redraw_text, NULL);
+ fbtk_set_handler(neww, FBTK_CBT_DESTROY, fb_destroy_text, NULL);
+
+ return neww;
+}
+
+/* exported function documented in fbtk.h */
+fbtk_widget_t *
+fbtk_create_writable_text(fbtk_widget_t *parent,
+ int x,
+ int y,
+ int width,
+ int height,
+ colour bg,
+ colour fg,
+ bool outline,
+ fbtk_enter_t enter,
+ void *pw)
+{
+ fbtk_widget_t *neww;
+
+ neww = fbtk_widget_new(parent, FB_WIDGET_TYPE_TEXT, x, y, width, height);
+ neww->fg = fg;
+ neww->bg = bg;
+ neww->mapped = true;
+
+ neww->u.text.outline = outline;
+ neww->u.text.enter = enter;
+ neww->u.text.pw = pw;
+
+ fbtk_set_handler(neww, FBTK_CBT_REDRAW, fb_redraw_text, NULL);
+ fbtk_set_handler(neww, FBTK_CBT_DESTROY, fb_destroy_text, NULL);
+ fbtk_set_handler(neww, FBTK_CBT_CLICK, text_input_click, pw);
+ fbtk_set_handler(neww, FBTK_CBT_STRIP_FOCUS, text_input_strip_focus, NULL);
+ fbtk_set_handler(neww, FBTK_CBT_INPUT, text_input, neww);
+
+ return neww;
+}
+
+/* exported function documented in fbtk.h */
+fbtk_widget_t *
+fbtk_create_text_button(fbtk_widget_t *parent,
+ int x,
+ int y,
+ int width,
+ int height,
+ colour bg,
+ colour fg,
+ fbtk_callback click,
+ void *pw)
+{
+ fbtk_widget_t *neww;
+
+ neww = fbtk_widget_new(parent, FB_WIDGET_TYPE_TEXT, x, y, width, height);
+ neww->fg = fg;
+ neww->bg = bg;
+ neww->mapped = true;
+
+ neww->u.text.outline = true;
+
+ fbtk_set_handler(neww, FBTK_CBT_REDRAW, fb_redraw_text_button, NULL);
+ fbtk_set_handler(neww, FBTK_CBT_DESTROY, fb_destroy_text, NULL);
+ fbtk_set_handler(neww, FBTK_CBT_CLICK, click, pw);
+ fbtk_set_handler(neww, FBTK_CBT_POINTERENTER, fbtk_set_ptr, &hand_image);
+
+ return neww;
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset:8
+ * End:
+ */
diff --git a/frontends/kolibrios/fb/fbtk/user.c b/frontends/kolibrios/fb/fbtk/user.c
new file mode 100644
index 0000000..de547ab
--- a/dev/null
+++ b/frontends/kolibrios/fb/fbtk/user.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2010 Vincent Sanders <vince@simtec.co.uk>
+ *
+ * Framebuffer windowing toolkit user widget.
+ *
+ * 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 <stdbool.h>
+#include <libnsfb.h>
+
+#include "framebuffer/gui.h"
+#include "framebuffer/fbtk.h"
+
+#include "widget.h"
+
+/* exported function documented in fbtk.h */
+void *
+fbtk_get_userpw(fbtk_widget_t *widget)
+{
+ if ((widget == NULL) ||
+ (widget->type != FB_WIDGET_TYPE_USER))
+ return NULL;
+
+ return widget->u.user.pw;
+}
+
+/* exported function documented in fbtk.h */
+fbtk_widget_t *
+fbtk_create_user(fbtk_widget_t *parent,
+ int x,
+ int y,
+ int width,
+ int height,
+ void *pw)
+{
+ fbtk_widget_t *neww;
+
+ neww = fbtk_widget_new(parent, FB_WIDGET_TYPE_USER, x, y, width, height);
+ neww->u.user.pw = pw;
+ neww->mapped = true;
+
+ return neww;
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset:8
+ * End:
+ */
diff --git a/frontends/kolibrios/fb/fbtk/widget.h b/frontends/kolibrios/fb/fbtk/widget.h
new file mode 100644
index 0000000..5622723
--- a/dev/null
+++ b/frontends/kolibrios/fb/fbtk/widget.h
@@ -0,0 +1,259 @@
+/*
+ * Copyright 2010 Vincent Sanders <vince@simtec.co.uk>
+ *
+ * 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_FB_FBTK_WIDGET_H
+#define NETSURF_FB_FBTK_WIDGET_H
+
+#include <stdbool.h>
+
+enum fbtk_widgettype_e {
+ FB_WIDGET_TYPE_ROOT = 0,
+ FB_WIDGET_TYPE_WINDOW,
+ FB_WIDGET_TYPE_BITMAP,
+ FB_WIDGET_TYPE_FILL,
+ FB_WIDGET_TYPE_TEXT,
+ FB_WIDGET_TYPE_HSCROLL,
+ FB_WIDGET_TYPE_VSCROLL,
+ FB_WIDGET_TYPE_USER,
+};
+
+
+/** Widget description.
+ *
+ * A widget is an entry in a tree structure which represents a
+ * rectangular area with co-ordinates relative to its parent widget.
+ * This area has a distinct set of callback operations for handling
+ * events which occour within its boundries. A widget may have an
+ * arbitrary number of child widgets. The order within the tree
+ * determines a widgets z order.
+ *
+ * ---
+ * A
+ * |
+ * +----------+
+ * +--->| Button 3 |
+ * | +----------+
+ * | | A
+ * | V |
+ * | +----------+
+ * | | Button 2 |
+ * | +----------+
+ * | | A
+ * | V |
+ * | +----------+
+ * | | Button 1 |
+ * | +----------+
+ * | | A
+ * | V |
+ * --- | +----------+
+ * A | +->| Filled |
+ * | | | +----------+
+ * +----------+ | | |
+ * +---->| |-+ | V
+ * | | Window 1 | | --- ---
+ * | | |---+ A
+ * | +----------+ |
+ * | | A +----------+ ---
+ * | | | +--->| Button 2 | A
+ * | | | | +----------+ |
+ * | | | | | A +-------------+
+ * | | | | | | +--->| Button Up |
+ * | | | | | | | +-------------+
+ * | | | | | | | | A
+ * | | | | | | | V |
+ * | | | | | | | +-------------+
+ * | | | | | | | | Button Down |
+ * | | | | | | | +-------------+
+ * | | | | | | | | A
+ * | | | | | | | V |
+ * | | | | | | | +-------------+
+ * | | | | | | | +->| Scroller |
+ * | | | | V | | | +-------------+
+ * | | | | +----------+ | | |
+ * | | | | | |-+ | V
+ * | | | | | V Scroll | | ---
+ * | | | | | |---+
+ * | | | | +----------+
+ * | | | | | A
+ * | | | | V |
+ * | | | | +----------+
+ * | | | | +->| Button 1 |
+ * | | | | | +----------+
+ * | +----------+ | | |
+ * | | |-+ | V
+ * | | Window 2 | | ---
+ * | | |---+
+ * | +----------+
+ * | | A
+ * | V |
+ * | +------------+
+ * --- | | Background |
+ * A | +->| Bitmap |
+ * | | | +------------+
+ * +------+ | | |
+ * | |-+ | V
+ * | Root | | ---
+ * | |---+
+ * +------+
+ * |
+ * V
+ * ---
+ *
+ * Every widget is contained within this generic wrapper. The
+ * integrated union provides for data specific to a widget type.
+ */
+struct fbtk_widget_s {
+ struct fbtk_widget_s *next; /* next lower z ordered widget in tree */
+ struct fbtk_widget_s *prev; /* next higher z ordered widget in tree */
+
+ struct fbtk_widget_s *parent; /* parent widget */
+
+ struct fbtk_widget_s *first_child; /* first child widget */
+ struct fbtk_widget_s *last_child; /* last child widget */
+
+ /* flags */
+ bool mapped; /**< The widget is mapped/visible . */
+
+ /* Generic properties */
+ int x;
+ int y;
+ int width;
+ int height;
+ colour bg;
+ colour fg;
+
+ /* event callback handlers */
+ fbtk_callback callback[FBTK_CBT_END];
+ void *callback_context[FBTK_CBT_END];
+
+ /* widget redraw */
+ struct {
+ bool child; /* A child of this widget requires redrawing */
+ bool needed; /* the widget requires redrawing */
+ int x;
+ int y;
+ int width;
+ int height;
+ } redraw;
+
+ enum fbtk_widgettype_e type; /**< The type of the widget */
+
+
+ union {
+ /* toolkit base handle */
+ struct {
+ nsfb_t *fb;
+ struct fbtk_widget_s *prev; /* previous widget pointer wasin */
+ struct fbtk_widget_s *grabbed; /* widget that has grabbed pointer movement. */
+ struct fbtk_widget_s *input;
+
+ /* caret */
+ struct {
+ struct fbtk_widget_s *owner; /* widget / NULL */
+ int x; /* relative to owner */
+ int y; /* relative to owner */
+ int height;
+ void (*remove_cb)(fbtk_widget_t *widget);
+ } caret;
+ } root;
+
+ /* bitmap */
+ struct {
+ struct fbtk_bitmap *bitmap;
+ } bitmap;
+
+ /* text */
+ struct {
+ char* text;
+ bool outline;
+ fbtk_enter_t enter;
+ void *pw;
+ int idx; /* caret pos in text */
+ int len; /* text length */
+ int width; /* text width in px */
+ int idx_offset; /* caret pos in pixels */
+ } text;
+
+ /* application driven widget */
+ struct {
+ void *pw; /* private data for user widget */
+ } user;
+
+ struct {
+ int minimum; /* lowest value of scrollbar */
+ int maximum; /* highest value of scrollbar */
+ int thumb; /* size of bar representing a page */
+ int page; /* amount to page document */
+ int position; /* position of bar */
+ int drag; /* offset to start of drag */
+ int drag_position; /* indicator bar pos at drag start */
+ struct fbtk_widget_s *btnul; /* scroll button up/left */
+ struct fbtk_widget_s *btndr; /* scroll button down/right*/
+ } scroll;
+
+ } u;
+};
+
+
+/* These functions are not considered part of the public API but are
+ * not static as they are used by the higher level widget provision
+ * routines
+ */
+
+
+/** creates a new widget and insert it into to hierachy.
+ *
+ * The widget is set to defaults of false, 0 or NULL.
+ *
+ * @param parent The parent widget. The new widget will be added with
+ * the shallowest z order relative to its siblings.
+ * @param type The type of the widget.
+ * @param x The x co-ordinate relative to the parent widget.
+ * @param y The y co-ordinate relative to the parent widget.
+ * @param width the widgets width. This will be clipped to the parent, if
+ * the value is 0 the largest extent which can fit within the parent
+ * is used, if the value is negative the largest value that will fit
+ * within the parent less the value given will be used.
+ * @param height the widgets width. This will be clipped to the parent, if
+ * the value is 0 the largest extent which can fit within the parent
+ * is used, if the value is negative the largest value that will fit
+ * within the parent less the value given will be used.
+ */
+fbtk_widget_t *fbtk_widget_new(fbtk_widget_t *parent, enum fbtk_widgettype_e type, int x, int y, int width, int height);
+
+/** find the root widget from any widget in the toolkit hierarchy.
+ *
+ * @param widget Any widget.
+ * @return The root widget or NULL if \a widget was not valid.
+ */
+fbtk_widget_t *fbtk_get_root_widget(fbtk_widget_t *widget);
+
+/** set pointer to bitmap in context.
+ *
+ * widget helper callback to set cursor image to the bitmap passed in
+ * the callbacks private data.
+ */
+int fbtk_set_ptr(fbtk_widget_t *widget, fbtk_callback_info *cbi);
+
+#endif
+
+/*
+ * Local Variables:
+ * c-basic-offset:8
+ * End:
+ */
diff --git a/frontends/kolibrios/fb/fbtk/window.c b/frontends/kolibrios/fb/fbtk/window.c
new file mode 100644
index 0000000..b385e8e
--- a/dev/null
+++ b/frontends/kolibrios/fb/fbtk/window.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2010 Vincent Sanders <vince@simtec.co.uk>
+ *
+ * Framebuffer windowing toolkit window widget.
+ *
+ * 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 <stdbool.h>
+#include <stdlib.h>
+
+#include <libnsfb.h>
+#include <libnsfb_plot.h>
+
+#include "netsurf/browser_window.h"
+
+#include "framebuffer/gui.h"
+#include "framebuffer/fbtk.h"
+
+#include "widget.h"
+
+/** Window redraw callback.
+ *
+ * Called when a window requires redrawing.
+ *
+ * @param widget The widget to be redrawn.
+ * @param cbi The callback parameters.
+ * @return The callback result.
+ */
+static int
+fb_redraw_window(fbtk_widget_t *widget, fbtk_callback_info *cbi)
+{
+ nsfb_bbox_t bbox;
+ nsfb_t *nsfb;
+
+ if ((widget->bg & 0xFF000000) == 0)
+ return 0;
+
+ nsfb = fbtk_get_nsfb(widget);
+
+ fbtk_get_bbox(widget, &bbox);
+
+ nsfb_claim(nsfb, &bbox);
+
+ nsfb_plot_rectangle_fill(nsfb, &bbox, widget->bg);
+
+ nsfb_update(nsfb, &bbox);
+
+ return 0;
+}
+
+/* exported function documented in fbtk.h */
+fbtk_widget_t *
+fbtk_create_window(fbtk_widget_t *parent,
+ int x,
+ int y,
+ int width,
+ int height,
+ colour bg)
+{
+ fbtk_widget_t *neww;
+
+ if (parent == NULL)
+ return NULL;
+
+ neww = fbtk_widget_new(parent, FB_WIDGET_TYPE_WINDOW, x, y, width, height);
+
+ neww->bg = bg;
+
+ fbtk_set_handler(neww, FBTK_CBT_REDRAW, fb_redraw_window, NULL);
+
+ return neww;
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset:8
+ * End:
+ */
diff --git a/frontends/kolibrios/fb/fetch.c b/frontends/kolibrios/fb/fetch.c
new file mode 100644
index 0000000..801b87a
--- a/dev/null
+++ b/frontends/kolibrios/fb/fetch.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2014 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Interfaces for fetch table.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#include "utils/nsurl.h"
+#include "utils/log.h"
+#include "utils/filepath.h"
+#include "utils/file.h"
+#include "netsurf/fetch.h"
+
+#include "framebuffer/findfile.h"
+#include "framebuffer/fetch.h"
+
+
+/**
+ * Translate resource to full url.
+ *
+ * Transforms a resource: 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 string containing the full URL of the target object or
+ * NULL if no suitable resource can be found.
+ */
+static nsurl *get_resource_url(const char *path)
+{
+ char buf[PATH_MAX];
+ nsurl *url = NULL;
+
+ if (strcmp(path, "favicon.ico") == 0)
+ path = "favicon.png";
+
+ netsurf_path_to_nsurl(filepath_sfind(respaths, buf, path), &url);
+
+ return url;
+}
+
+/**
+ * filetype -- determine the MIME type of a local file
+ */
+static const char *fetch_filetype(const char *unix_path)
+{
+ int l;
+ LOG("unix path %s", unix_path);
+ l = strlen(unix_path);
+ if (2 < l && strcasecmp(unix_path + l - 3, "css") == 0)
+ return "text/css";
+ if (2 < l && strcasecmp(unix_path + l - 3, "f79") == 0)
+ return "text/css";
+ if (2 < l && strcasecmp(unix_path + l - 3, "jpg") == 0)
+ return "image/jpeg";
+ if (3 < l && strcasecmp(unix_path + l - 4, "jpeg") == 0)
+ return "image/jpeg";
+ if (2 < l && strcasecmp(unix_path + l - 3, "gif") == 0)
+ return "image/gif";
+ if (2 < l && strcasecmp(unix_path + l - 3, "png") == 0)
+ return "image/png";
+ if (2 < l && strcasecmp(unix_path + l - 3, "b60") == 0)
+ return "image/png";
+ if (2 < l && strcasecmp(unix_path + l - 3, "jng") == 0)
+ return "image/jng";
+ if (2 < l && strcasecmp(unix_path + l - 3, "svg") == 0)
+ return "image/svg";
+ if (2 < l && strcasecmp(unix_path + l - 3, "bmp") == 0)
+ return "image/bmp";
+ return "text/html";
+}
+
+/* table for fetch operations */
+static struct gui_fetch_table fetch_table = {
+ .filetype = fetch_filetype,
+
+ .get_resource_url = get_resource_url,
+};
+
+struct gui_fetch_table *framebuffer_fetch_table = &fetch_table;
diff --git a/frontends/kolibrios/fb/fetch.h b/frontends/kolibrios/fb/fetch.h
new file mode 100644
index 0000000..718b083
--- a/dev/null
+++ b/frontends/kolibrios/fb/fetch.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2014 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef NETSURF_FB_FETCH_H
+#define NETSURF_FB_FETCH_H
+
+struct gui_fetch_table *framebuffer_fetch_table;
+
+#endif
diff --git a/frontends/kolibrios/fb/findfile.c b/frontends/kolibrios/fb/findfile.c
new file mode 100644
index 0000000..67312f4
--- a/dev/null
+++ b/frontends/kolibrios/fb/findfile.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2008 Daniel Silverstone <dsilvers@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+
+#include "utils/filepath.h"
+
+#include "framebuffer/findfile.h"
+
+char **respaths; /** resource search path vector */
+
+/** 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.
+ */
+char **
+fb_init_resource(const char *resource_path)
+{
+ char **pathv; /* resource path string vector */
+ char **respath; /* resource paths vector */
+ const char *lang = NULL;
+
+ pathv = filepath_path_to_strvec(resource_path);
+
+ respath = filepath_generate(pathv, &lang);
+
+ filepath_free_strvec(pathv);
+
+ return respath;
+}
+
+
+
+/*
+ * Local Variables:
+ * c-basic-offset: 8
+ * End:
+ */
+
diff --git a/frontends/kolibrios/fb/findfile.h b/frontends/kolibrios/fb/findfile.h
new file mode 100644
index 0000000..1f3db6e
--- a/dev/null
+++ b/frontends/kolibrios/fb/findfile.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2008 Daniel Silverstone <dsilvers@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NETSURF_FB_FINDFILE_H
+#define NETSURF_FB_FINDFILE_H
+
+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.
+ */
+char **fb_init_resource(const char *resource_path);
+
+#endif /* NETSURF_FB_FINDFILE_H */
diff --git a/frontends/kolibrios/fb/font.h b/frontends/kolibrios/fb/font.h
new file mode 100644
index 0000000..8513c93
--- a/dev/null
+++ b/frontends/kolibrios/fb/font.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2008 Vincent Sanders <vince@simtec.co.uk>
+ *
+ * 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_FB_FONT_H
+#define NETSURF_FB_FONT_H
+
+extern struct gui_layout_table *framebuffer_layout_table;
+extern struct gui_utf8_table *framebuffer_utf8_table;
+
+/**
+ * Initialise framebuffer font handling.
+ */
+bool fb_font_init(void);
+
+/**
+ * Finalise framebuffer font handling.
+ */
+bool fb_font_finalise(void);
+
+/**
+ * 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
+ */
+nserror fb_font_position(const struct plot_font_style *fstyle, const char *string, size_t length, int x, size_t *char_offset, int *actual_x);
+
+/**
+ * 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
+ */
+nserror fb_font_width(const struct plot_font_style *fstyle, const char *string, size_t length, int *width);
+
+
+#ifdef KOLIBRI_USE_FREETYPE
+#include "kolibrios/fb/font_freetype.h"
+#else
+#include "kolibrios/fb/font_internal.h"
+#endif
+
+#endif /* NETSURF_FB_FONT_H */
+
diff --git a/frontends/kolibrios/fb/font_freetype.c b/frontends/kolibrios/fb/font_freetype.c
new file mode 100644
index 0000000..e7c07f5
--- a/dev/null
+++ b/frontends/kolibrios/fb/font_freetype.c
@@ -0,0 +1,566 @@
+/*
+ * Copyright 2005 James Bursa <bursa@users.sourceforge.net>
+ * 2008 Vincent Sanders <vince@simtec.co.uk>
+ *
+ * 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 <ft2build.h>
+#include FT_CACHE_H
+
+#include "netsurf/inttypes.h"
+#include "utils/filepath.h"
+#include "utils/utf8.h"
+#include "utils/log.h"
+#include "utils/nsoption.h"
+#include "netsurf/utf8.h"
+#include "netsurf/layout.h"
+#include "netsurf/browser_window.h"
+#include "netsurf/plot_style.h"
+
+#include "framebuffer/gui.h"
+#include "framebuffer/font.h"
+#include "framebuffer/findfile.h"
+
+/* glyph cache minimum size */
+#define CACHE_MIN_SIZE (100 * 1024)
+
+#define BOLD_WEIGHT 700
+
+static FT_Library library;
+static FTC_Manager ft_cmanager;
+static FTC_CMapCache ft_cmap_cache ;
+static FTC_ImageCache ft_image_cache;
+
+int ft_load_type;
+
+/* cache manager faceID data to create freetype faceid on demand */
+typedef struct fb_faceid_s {
+ char *fontfile; /* path to font */
+ int index; /* index of font */
+ int cidx; /* character map index for unicode */
+} fb_faceid_t;
+
+
+enum fb_face_e {
+ FB_FACE_SANS_SERIF = 0,
+ FB_FACE_SANS_SERIF_BOLD,
+ FB_FACE_SANS_SERIF_ITALIC,
+ FB_FACE_SANS_SERIF_ITALIC_BOLD,
+ FB_FACE_SERIF,
+ FB_FACE_SERIF_BOLD,
+ FB_FACE_MONOSPACE,
+ FB_FACE_MONOSPACE_BOLD,
+ FB_FACE_CURSIVE,
+ FB_FACE_FANTASY,
+ FB_FACE_COUNT
+};
+
+/* defines for accesing the faces */
+#define FB_FACE_DEFAULT 0
+
+static fb_faceid_t *fb_faces[FB_FACE_COUNT];
+
+/**
+ * map cache manager handle to face id
+ */
+static FT_Error
+ft_face_requester(FTC_FaceID face_id,
+ FT_Library library,
+ FT_Pointer request_data,
+ FT_Face *face )
+{
+ FT_Error error;
+ fb_faceid_t *fb_face = (fb_faceid_t *)face_id;
+ int cidx;
+
+ error = FT_New_Face(library, fb_face->fontfile, fb_face->index, face);
+ if (error) {
+ LOG("Could not find font (code %d)", error);
+ } else {
+
+ error = FT_Select_Charmap(*face, FT_ENCODING_UNICODE);
+ if (error) {
+ LOG("Could not select charmap (code %d)", error);
+ } else {
+ for (cidx = 0; cidx < (*face)->num_charmaps; cidx++) {
+ if ((*face)->charmap == (*face)->charmaps[cidx]) {
+ fb_face->cidx = cidx;
+ break;
+ }
+ }
+ }
+ }
+ LOG("Loaded face from %s", fb_face->fontfile);
+
+ return error;
+}
+
+/**
+ * create new framebuffer face and cause it to be loaded to check its ok
+ */
+static fb_faceid_t *
+fb_new_face(const char *option, const char *resname, const char *fontname)
+{
+ fb_faceid_t *newf;
+ FT_Error error;
+ FT_Face aface;
+ char buf[PATH_MAX];
+
+ newf = calloc(1, sizeof(fb_faceid_t));
+
+ if (option != NULL) {
+ newf->fontfile = strdup(option);
+ } else {
+ filepath_sfind(respaths, buf, fontname);
+ newf->fontfile = strdup(buf);
+ }
+
+ error = FTC_Manager_LookupFace(ft_cmanager, (FTC_FaceID)newf, &aface);
+ if (error) {
+ LOG("Could not find font face %s (code %d)", fontname, error);
+ free(newf->fontfile);
+ free(newf);
+ newf = NULL;
+ }
+
+ return newf;
+}
+
+/* exported interface documented in framebuffer/font.h */
+bool fb_font_init(void)
+{
+ FT_Error error;
+ FT_ULong max_cache_size;
+ FT_UInt max_faces = 6;
+ fb_faceid_t *fb_face;
+
+ /* freetype library initialise */
+ error = FT_Init_FreeType( &library );
+ if (error) {
+ LOG("Freetype could not initialised (code %d)", error);
+ return false;
+ }
+
+ /* set the Glyph cache size up */
+ max_cache_size = nsoption_int(fb_font_cachesize) * 1024;
+
+ if (max_cache_size < CACHE_MIN_SIZE) {
+ max_cache_size = CACHE_MIN_SIZE;
+ }
+
+ /* cache manager initialise */
+ error = FTC_Manager_New(library,
+ max_faces,
+ 0,
+ max_cache_size,
+ ft_face_requester,
+ NULL,
+ &ft_cmanager);
+ if (error) {
+ LOG("Freetype could not initialise cache manager (code %d)", error);
+ FT_Done_FreeType(library);
+ return false;
+ }
+
+ error = FTC_CMapCache_New(ft_cmanager, &ft_cmap_cache);
+
+ error = FTC_ImageCache_New(ft_cmanager, &ft_image_cache);
+
+ /* need to obtain the generic font faces */
+
+ /* Start with the sans serif font */
+ fb_face = fb_new_face(nsoption_charp(fb_face_sans_serif),
+ "sans_serif.ttf",
+ NETSURF_FB_FONT_SANS_SERIF);
+ if (fb_face == NULL) {
+ /* The sans serif font is the default and must be found. */
+ LOG("Could not find the default font");
+ FTC_Manager_Done(ft_cmanager);
+ FT_Done_FreeType(library);
+ return false;
+ } else {
+ fb_faces[FB_FACE_SANS_SERIF] = fb_face;
+ }
+
+ /* Bold sans serif face */
+ fb_face = fb_new_face(nsoption_charp(fb_face_sans_serif_bold),
+ "sans_serif_bold.ttf",
+ NETSURF_FB_FONT_SANS_SERIF_BOLD);
+ if (fb_face == NULL) {
+ /* seperate bold face unavailabe use the normal weight version */
+ fb_faces[FB_FACE_SANS_SERIF_BOLD] = fb_faces[FB_FACE_SANS_SERIF];
+ } else {
+ fb_faces[FB_FACE_SANS_SERIF_BOLD] = fb_face;
+ }
+
+ /* Italic sans serif face */
+ fb_face = fb_new_face(nsoption_charp(fb_face_sans_serif_italic),
+ "sans_serif_italic.ttf",
+ NETSURF_FB_FONT_SANS_SERIF_ITALIC);
+ if (fb_face == NULL) {
+ /* seperate italic face unavailabe use the normal weight version */
+ fb_faces[FB_FACE_SANS_SERIF_ITALIC] = fb_faces[FB_FACE_SANS_SERIF];
+ } else {
+ fb_faces[FB_FACE_SANS_SERIF_ITALIC] = fb_face;
+ }
+
+ /* Bold italic sans serif face */
+ fb_face = fb_new_face(nsoption_charp(fb_face_sans_serif_italic_bold),
+ "sans_serif_italic_bold.ttf",
+ NETSURF_FB_FONT_SANS_SERIF_ITALIC_BOLD);
+ if (fb_face == NULL) {
+ /* seperate italic face unavailabe use the normal weight version */
+ fb_faces[FB_FACE_SANS_SERIF_ITALIC_BOLD] = fb_faces[FB_FACE_SANS_SERIF];
+ } else {
+ fb_faces[FB_FACE_SANS_SERIF_ITALIC_BOLD] = fb_face;
+ }
+
+ /* serif face */
+ fb_face = fb_new_face(nsoption_charp(fb_face_serif),
+ "serif.ttf",
+ NETSURF_FB_FONT_SERIF);
+ if (fb_face == NULL) {
+ /* serif face unavailabe use the default */
+ fb_faces[FB_FACE_SERIF] = fb_faces[FB_FACE_SANS_SERIF];
+ } else {
+ fb_faces[FB_FACE_SERIF] = fb_face;
+ }
+
+ /* bold serif face*/
+ fb_face = fb_new_face(nsoption_charp(fb_face_serif_bold),
+ "serif_bold.ttf",
+ NETSURF_FB_FONT_SERIF_BOLD);
+ if (fb_face == NULL) {
+ /* bold serif face unavailabe use the normal weight */
+ fb_faces[FB_FACE_SERIF_BOLD] = fb_faces[FB_FACE_SERIF];
+ } else {
+ fb_faces[FB_FACE_SERIF_BOLD] = fb_face;
+ }
+
+
+ /* monospace face */
+ fb_face = fb_new_face(nsoption_charp(fb_face_monospace),
+ "monospace.ttf",
+ NETSURF_FB_FONT_MONOSPACE);
+ if (fb_face == NULL) {
+ /* serif face unavailabe use the default */
+ fb_faces[FB_FACE_MONOSPACE] = fb_faces[FB_FACE_SANS_SERIF];
+ } else {
+ fb_faces[FB_FACE_MONOSPACE] = fb_face;
+ }
+
+ /* bold monospace face*/
+ fb_face = fb_new_face(nsoption_charp(fb_face_monospace_bold),
+ "monospace_bold.ttf",
+ NETSURF_FB_FONT_MONOSPACE_BOLD);
+ if (fb_face == NULL) {
+ /* bold serif face unavailabe use the normal weight */
+ fb_faces[FB_FACE_MONOSPACE_BOLD] = fb_faces[FB_FACE_MONOSPACE];
+ } else {
+ fb_faces[FB_FACE_MONOSPACE_BOLD] = fb_face;
+ }
+
+ /* cursive face */
+ fb_face = fb_new_face(nsoption_charp(fb_face_cursive),
+ "cursive.ttf",
+ NETSURF_FB_FONT_CURSIVE);
+ if (fb_face == NULL) {
+ /* cursive face unavailabe use the default */
+ fb_faces[FB_FACE_CURSIVE] = fb_faces[FB_FACE_SANS_SERIF];
+ } else {
+ fb_faces[FB_FACE_CURSIVE] = fb_face;
+ }
+
+ /* fantasy face */
+ fb_face = fb_new_face(nsoption_charp(fb_face_fantasy),
+ "fantasy.ttf",
+ NETSURF_FB_FONT_FANTASY);
+ if (fb_face == NULL) {
+ /* fantasy face unavailabe use the default */
+ fb_faces[FB_FACE_FANTASY] = fb_faces[FB_FACE_SANS_SERIF];
+ } else {
+ fb_faces[FB_FACE_FANTASY] = fb_face;
+ }
+
+
+ /* set the default render mode */
+ if (nsoption_bool(fb_font_monochrome) == true)
+ ft_load_type = FT_LOAD_MONOCHROME; /* faster but less pretty */
+ else
+ ft_load_type = 0;
+
+ return true;
+}
+
+/* exported interface documented in framebuffer/font.h */
+bool fb_font_finalise(void)
+{
+ int i, j;
+
+ FTC_Manager_Done(ft_cmanager);
+ FT_Done_FreeType(library);
+
+ for (i = 0; i < FB_FACE_COUNT; i++) {
+ if (fb_faces[i] == NULL)
+ continue;
+
+ /* Unset any faces that duplicate this one */
+ for (j = i + 1; j < FB_FACE_COUNT; j++) {
+ if (fb_faces[i] == fb_faces[j])
+ fb_faces[j] = NULL;
+ }
+
+ free(fb_faces[i]->fontfile);
+ free(fb_faces[i]);
+
+ fb_faces[i] = NULL;
+ }
+
+ return true;
+}
+
+/**
+ * fill freetype scalar
+ */
+static void fb_fill_scalar(const plot_font_style_t *fstyle, FTC_Scaler srec)
+{
+ int selected_face = FB_FACE_DEFAULT;
+
+ switch (fstyle->family) {
+
+ case PLOT_FONT_FAMILY_SERIF:
+ if (fstyle->weight >= BOLD_WEIGHT) {
+ selected_face = FB_FACE_SERIF_BOLD;
+ } else {
+ selected_face = FB_FACE_SERIF;
+ }
+ break;
+
+ case PLOT_FONT_FAMILY_MONOSPACE:
+ if (fstyle->weight >= BOLD_WEIGHT) {
+ selected_face = FB_FACE_MONOSPACE_BOLD;
+ } else {
+ selected_face = FB_FACE_MONOSPACE;
+ }
+ break;
+
+ case PLOT_FONT_FAMILY_CURSIVE:
+ selected_face = FB_FACE_CURSIVE;
+ break;
+
+ case PLOT_FONT_FAMILY_FANTASY:
+ selected_face = FB_FACE_FANTASY;
+ break;
+
+ case PLOT_FONT_FAMILY_SANS_SERIF:
+ default:
+ if ((fstyle->flags & FONTF_ITALIC) ||
+ (fstyle->flags & FONTF_OBLIQUE)) {
+ if (fstyle->weight >= BOLD_WEIGHT) {
+ selected_face = FB_FACE_SANS_SERIF_ITALIC_BOLD;
+ } else {
+ selected_face = FB_FACE_SANS_SERIF_ITALIC;
+ }
+ } else {
+ if (fstyle->weight >= BOLD_WEIGHT) {
+ selected_face = FB_FACE_SANS_SERIF_BOLD;
+ } else {
+ selected_face = FB_FACE_SANS_SERIF;
+ }
+ }
+ }
+
+ srec->face_id = (FTC_FaceID)fb_faces[selected_face];
+
+ srec->width = srec->height = (fstyle->size * 64) / FONT_SIZE_SCALE;
+ srec->pixel = 0;
+
+ srec->x_res = srec->y_res = browser_get_dpi();
+}
+
+/* exported interface documented in framebuffer/freetype_font.h */
+FT_Glyph fb_getglyph(const plot_font_style_t *fstyle, uint32_t ucs4)
+{
+ FT_UInt glyph_index;
+ FTC_ScalerRec srec;
+ FT_Glyph glyph;
+ FT_Error error;
+ fb_faceid_t *fb_face;
+
+ fb_fill_scalar(fstyle, &srec);
+
+ fb_face = (fb_faceid_t *)srec.face_id;
+
+ glyph_index = FTC_CMapCache_Lookup(ft_cmap_cache, srec.face_id,
+ fb_face->cidx, ucs4);
+
+ error = FTC_ImageCache_LookupScaler(ft_image_cache,
+ &srec,
+ FT_LOAD_RENDER |
+ FT_LOAD_FORCE_AUTOHINT |
+ ft_load_type,
+ glyph_index,
+ &glyph,
+ NULL);
+ if (error != 0)
+ return NULL;
+
+ return glyph;
+}
+
+
+/* exported interface documented in framebuffer/freetype_font.h */
+nserror
+fb_font_width(const plot_font_style_t *fstyle,
+ const char *string, size_t length,
+ int *width)
+{
+ uint32_t ucs4;
+ size_t nxtchr = 0;
+ FT_Glyph glyph;
+
+ *width = 0;
+ while (nxtchr < length) {
+ ucs4 = utf8_to_ucs4(string + nxtchr, length - nxtchr);
+ nxtchr = utf8_next(string, length, nxtchr);
+
+ glyph = fb_getglyph(fstyle, ucs4);
+ if (glyph == NULL)
+ continue;
+
+ *width += glyph->advance.x >> 16;
+ }
+ return NSERROR_OK;
+}
+
+
+/* exported interface documented in framebuffer/freetype_font.h */
+nserror
+fb_font_position(const plot_font_style_t *fstyle,
+ const char *string, size_t length,
+ int x, size_t *char_offset, int *actual_x)
+{
+ uint32_t ucs4;
+ size_t nxtchr = 0;
+ FT_Glyph glyph;
+ int prev_x = 0;
+
+ *actual_x = 0;
+ while (nxtchr < length) {
+ ucs4 = utf8_to_ucs4(string + nxtchr, length - nxtchr);
+
+ glyph = fb_getglyph(fstyle, ucs4);
+ if (glyph == NULL)
+ continue;
+
+ *actual_x += glyph->advance.x >> 16;
+ if (*actual_x > x)
+ break;
+
+ prev_x = *actual_x;
+ nxtchr = utf8_next(string, length, nxtchr);
+ }
+
+ /* choose nearest of previous and last x */
+ if (abs(*actual_x - x) > abs(prev_x - x))
+ *actual_x = prev_x;
+
+ *char_offset = nxtchr;
+ return NSERROR_OK;
+}
+
+
+/**
+ * Find where to split a string to make it fit a width.
+ *
+ * \param fstyle style for this text
+ * \param string UTF-8 string to measure
+ * \param length length of string, in bytes
+ * \param x width available
+ * \param char_offset updated to offset in string of actual_x, [1..length]
+ * \param actual_x updated to x coordinate of character closest to x
+ * \return true on success, false on error and error reported
+ *
+ * On exit, char_offset indicates first character after split point.
+ *
+ * Note: char_offset of 0 should 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
+fb_font_split(const plot_font_style_t *fstyle,
+ const char *string, size_t length,
+ int x, size_t *char_offset, int *actual_x)
+{
+ uint32_t ucs4;
+ size_t nxtchr = 0;
+ int last_space_x = 0;
+ int last_space_idx = 0;
+ FT_Glyph glyph;
+
+ *actual_x = 0;
+ while (nxtchr < length) {
+ ucs4 = utf8_to_ucs4(string + nxtchr, length - nxtchr);
+
+ glyph = fb_getglyph(fstyle, ucs4);
+ if (glyph == NULL)
+ continue;
+
+ if (ucs4 == 0x20) {
+ last_space_x = *actual_x;
+ last_space_idx = nxtchr;
+ }
+
+ *actual_x += glyph->advance.x >> 16;
+ if (*actual_x > x && last_space_idx != 0) {
+ /* string has exceeded available width and we've
+ * found a space; return previous space */
+ *actual_x = last_space_x;
+ *char_offset = last_space_idx;
+ return NSERROR_OK;
+ }
+
+ nxtchr = utf8_next(string, length, nxtchr);
+ }
+
+ *char_offset = nxtchr;
+
+ return NSERROR_OK;
+}
+
+static struct gui_layout_table layout_table = {
+ .width = fb_font_width,
+ .position = fb_font_position,
+ .split = fb_font_split,
+};
+
+struct gui_layout_table *framebuffer_layout_table = &layout_table;
+
+
+struct gui_utf8_table *framebuffer_utf8_table = NULL;
+
+/*
+ * Local Variables:
+ * c-basic-offset:8
+ * End:
+ */
diff --git a/frontends/kolibrios/fb/font_freetype.h b/frontends/kolibrios/fb/font_freetype.h
new file mode 100644
index 0000000..cbc6d82
--- a/dev/null
+++ b/frontends/kolibrios/fb/font_freetype.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2008 Vincent Sanders <vince@simtec.co.uk>
+ *
+ * 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_FB_FONT_FREETYPE_H
+#define NETSURF_FB_FONT_FREETYPE_H
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_GLYPH_H
+
+extern int ft_load_type;
+
+FT_Glyph fb_getglyph(const plot_font_style_t *fstyle, uint32_t ucs4);
+
+#endif /* NETSURF_FB_FONT_FREETYPE_H */
diff --git a/frontends/kolibrios/fb/font_internal.c b/frontends/kolibrios/fb/font_internal.c
new file mode 100644
index 0000000..3b8a1c4
--- a/dev/null
+++ b/frontends/kolibrios/fb/font_internal.c
@@ -0,0 +1,492 @@
+/*
+ * Copyright 2005 James Bursa <bursa@users.sourceforge.net>
+ * 2008 Vincent Sanders <vince@simtec.co.uk>
+ *
+ * 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 <inttypes.h>
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include "utils/nsoption.h"
+#include "utils/utf8.h"
+#include "netsurf/utf8.h"
+#include "netsurf/layout.h"
+#include "netsurf/plot_style.h"
+
+#include "framebuffer/gui.h"
+#include "framebuffer/font.h"
+
+#include <font-ns-sans.h>
+
+#define GLYPH_LEN 16
+
+uint8_t code_point[GLYPH_LEN];
+uint8_t glyph_x2[GLYPH_LEN * 4];
+
+#define SEVEN_SET ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | \
+ (1 << 4) | (1 << 5) | (1 << 6))
+
+#define THREE_SSS ((1 << 0) | (1 << 1) | (1 << 2))
+#define THREE_S_S ((1 << 0) | (1 << 2))
+#define THREE__SS ((1 << 0) | (1 << 1) )
+#define THREE_SS_ ( (1 << 1) | (1 << 2))
+#define THREE_S__ (1 << 2)
+#define THREE__S_ (1 << 1)
+#define THREE___S (1 << 0)
+
+uint8_t frag[16][5] = {
+ { THREE_SSS,
+ THREE_S_S,
+ THREE_S_S,
+ THREE_S_S,
+ THREE_SSS },
+
+ { THREE__S_,
+ THREE_SS_,
+ THREE__S_,
+ THREE__S_,
+ THREE_SSS },
+
+ { THREE_SS_,
+ THREE___S,
+ THREE__S_,
+ THREE_S__,
+ THREE_SSS },
+
+ { THREE_SS_,
+ THREE___S,
+ THREE_SS_,
+ THREE___S,
+ THREE_SS_ },
+
+ { THREE_S_S,
+ THREE_S_S,
+ THREE_SSS,
+ THREE___S,
+ THREE___S },
+
+ { THREE_SSS,
+ THREE_S__,
+ THREE_SSS,
+ THREE___S,
+ THREE_SSS },
+
+ { THREE__SS,
+ THREE_S__,
+ THREE_SSS,
+ THREE_S_S,
+ THREE_SSS },
+
+ { THREE_SSS,
+ THREE___S,
+ THREE__S_,
+ THREE__S_,
+ THREE__S_ },
+
+ { THREE_SSS,
+ THREE_S_S,
+ THREE_SSS,
+ THREE_S_S,
+ THREE_SSS },
+
+ { THREE_SSS,
+ THREE_S_S,
+ THREE_SSS,
+ THREE___S,
+ THREE___S },
+
+ { THREE__S_,
+ THREE_S_S,
+ THREE_SSS,
+ THREE_S_S,
+ THREE_S_S },
+
+ { THREE_SS_,
+ THREE_S_S,
+ THREE_SS_,
+ THREE_S_S,
+ THREE_SS_ },
+
+ { THREE__S_,
+ THREE_S_S,
+ THREE_S__,
+ THREE_S_S,
+ THREE__S_ },
+
+ { THREE_SS_,
+ THREE_S_S,
+ THREE_S_S,
+ THREE_S_S,
+ THREE_SS_ },
+
+ { THREE_SSS,
+ THREE_S__,
+ THREE_SS_,
+ THREE_S__,
+ THREE_SSS },
+
+ { THREE_SSS,
+ THREE_S__,
+ THREE_SS_,
+ THREE_S__,
+ THREE_S__ }
+};
+
+static uint8_t * get_codepoint(uint32_t id, bool italic)
+{
+ int shift = 0;
+ int l;
+ int r;
+
+ if (!italic)
+ shift = 1;
+
+ l = (id >> 12);
+ r = 0xf & (id >> 8);
+
+ code_point[ 0] = SEVEN_SET << shift;
+
+ code_point[ 2] = (frag[l][0] << (4 + shift)) | (frag[r][0] << shift);
+ code_point[ 3] = (frag[l][1] << (4 + shift)) | (frag[r][1] << shift);
+ code_point[ 4] = (frag[l][2] << (4 + shift)) | (frag[r][2] << shift);
+ code_point[ 5] = (frag[l][3] << (4 + shift)) | (frag[r][3] << shift);
+ code_point[ 6] = (frag[l][4] << (4 + shift)) | (frag[r][4] << shift);
+
+ shift = 1;
+
+ l = 0xf & (id >> 4);
+ r = 0xf & id;
+
+ code_point[ 8] = (frag[l][0] << (4 + shift)) | (frag[r][0] << shift);
+ code_point[ 9] = (frag[l][1] << (4 + shift)) | (frag[r][1] << shift);
+ code_point[10] = (frag[l][2] << (4 + shift)) | (frag[r][2] << shift);
+ code_point[11] = (frag[l][3] << (4 + shift)) | (frag[r][3] << shift);
+ code_point[12] = (frag[l][4] << (4 + shift)) | (frag[r][4] << shift);
+
+ code_point[14] = SEVEN_SET << shift;
+
+ return (uint8_t *)code_point;
+}
+
+
+bool fb_font_init(void)
+{
+ return true;
+}
+
+bool fb_font_finalise(void)
+{
+ return true;
+}
+
+enum fb_font_style
+fb_get_font_style(const plot_font_style_t *fstyle)
+{
+ enum fb_font_style style = FB_REGULAR;
+
+ if (fstyle->weight >= 700)
+ style |= FB_BOLD;
+ if ((fstyle->flags & FONTF_ITALIC) || (fstyle->flags & FONTF_OBLIQUE))
+ style |= FB_ITALIC;
+
+ return style;
+}
+
+int
+fb_get_font_size(const plot_font_style_t *fstyle)
+{
+ int size = fstyle->size * 10 /
+ (((nsoption_int(font_min_size) * 3 +
+ nsoption_int(font_size)) / 4) * FONT_SIZE_SCALE);
+ if (size > 2)
+ size = 2;
+ else if (size <= 0)
+ size = 1;
+
+ return size;
+}
+
+/** Lookup table to scale 4 bits to 8 bits, so e.g. 0101 --> 00110011 */
+const uint8_t glyph_lut[16] = {
+ 0x00, 0x03, 0x0c, 0x0f,
+ 0x30, 0x33, 0x3c, 0x3f,
+ 0xc0, 0xc3, 0xcc, 0xcf,
+ 0xf0, 0xf3, 0xfc, 0xff
+};
+
+static const uint8_t *
+glyph_scale_2(const uint8_t *glyph_data)
+{
+ const uint8_t *glyph_max = glyph_data + GLYPH_LEN;
+ uint8_t *pos = glyph_x2;
+
+ do {
+ *pos++ = glyph_lut[*glyph_data >> 4];
+ *pos++ = glyph_lut[*glyph_data & 0xf];
+ *pos++ = glyph_lut[*glyph_data >> 4];
+ *pos++ = glyph_lut[*glyph_data & 0xf];
+ } while (++glyph_data < glyph_max);
+
+ return glyph_x2;
+}
+
+const uint8_t *
+fb_get_glyph(uint32_t ucs4, enum fb_font_style style, int scale)
+{
+ const uint8_t *glyph_data;
+ unsigned int section;
+ unsigned int offset;
+ uint16_t g_offset;
+
+ /* Internal font has no glyphs beyond U+FFFF and there isn't
+ * space to render a >4 digit codepoint; just show replacement
+ * character. */
+ if (ucs4 > 0xffff)
+ ucs4 = 0xfffd;
+
+ switch (style) {
+ case FB_BOLD_ITALIC:
+ section = fb_bold_italic_section_table[ucs4 / 256];
+ if (section != 0 || ucs4 / 256 == 0) {
+ offset = section * 256 + (ucs4 & 0xff);
+ g_offset = fb_bold_italic_sections[offset] * 16;
+ if (g_offset != 0) {
+ glyph_data = &font_glyph_data[g_offset];
+ break;
+ }
+ }
+ case FB_BOLD:
+ section = fb_bold_section_table[ucs4 / 256];
+ if (section != 0 || ucs4 / 256 == 0) {
+ offset = section * 256 + (ucs4 & 0xff);
+ g_offset = fb_bold_sections[offset] * 16;
+ if (g_offset != 0) {
+ glyph_data = &font_glyph_data[g_offset];
+ break;
+ }
+ }
+ case FB_ITALIC:
+ section = fb_italic_section_table[ucs4 / 256];
+ if (section != 0 || ucs4 / 256 == 0) {
+ offset = section * 256 + (ucs4 & 0xff);
+ g_offset = fb_italic_sections[offset] * 16;
+ if (g_offset != 0) {
+ glyph_data = &font_glyph_data[g_offset];
+ break;
+ }
+ }
+ case FB_REGULAR:
+ section = fb_regular_section_table[ucs4 / 256];
+ if (section != 0 || ucs4 / 256 == 0) {
+ offset = section * 256 + (ucs4 & 0xff);
+ g_offset = fb_regular_sections[offset] * 16;
+ if (g_offset != 0) {
+ glyph_data = &font_glyph_data[g_offset];
+ break;
+ }
+ }
+ default:
+ glyph_data = get_codepoint(ucs4, style & FB_ITALIC);
+ break;
+ }
+
+ switch (scale) {
+ case 1:
+ break;
+ case 2:
+ glyph_data = glyph_scale_2(glyph_data);
+ break;
+ default:
+ assert(scale >= 1 && scale <= 2);
+ break;
+ }
+
+ return glyph_data;
+}
+
+static nserror utf8_to_local(const char *string,
+ size_t len,
+ char **result)
+{
+ return utf8_to_enc(string, "CP1252", len, result);
+
+}
+
+static nserror utf8_from_local(const char *string,
+ size_t len,
+ char **result)
+{
+ *result = malloc(len + 1);
+ if (*result == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ memcpy(*result, string, len);
+
+ (*result)[len] = '\0';
+
+ return NSERROR_OK;
+}
+
+
+/* exported interface documented in framebuffer/freetype_font.h */
+nserror
+fb_font_width(const plot_font_style_t *fstyle,
+ const char *string,
+ size_t length,
+ int *width)
+{
+ size_t nxtchr = 0;
+
+ *width = 0;
+ while (nxtchr < length) {
+ uint32_t ucs4;
+ ucs4 = utf8_to_ucs4(string + nxtchr, length - nxtchr);
+ if (codepoint_displayable(ucs4)) {
+ *width += FB_FONT_WIDTH;
+ }
+
+ nxtchr = utf8_next(string, length, nxtchr);
+ }
+
+ *width *= fb_get_font_size(fstyle);
+ return NSERROR_OK;
+}
+
+
+/* exported interface documented in framebuffer/freetype_font.h */
+nserror
+fb_font_position(const plot_font_style_t *fstyle,
+ const char *string,
+ size_t length,
+ int x,
+ size_t *char_offset,
+ int *actual_x)
+{
+ const int width = fb_get_font_size(fstyle) * FB_FONT_WIDTH;
+ size_t nxtchr = 0;
+ int x_pos = 0;
+
+ while (nxtchr < length) {
+ uint32_t ucs4;
+ if (abs(x_pos - x) <= (width / 2))
+ break;
+
+ ucs4 = utf8_to_ucs4(string + nxtchr, length - nxtchr);
+ if (codepoint_displayable(ucs4)) {
+ x_pos += width;
+ }
+
+ nxtchr = utf8_next(string, length, nxtchr);
+ }
+
+ *actual_x = x_pos;
+
+ *char_offset = nxtchr;
+ return NSERROR_OK;
+}
+
+
+/**
+ * Find where to split a string to make it fit a width.
+ *
+ * \param fstyle style for this text
+ * \param string UTF-8 string to measure
+ * \param length length of string, in bytes
+ * \param x width available
+ * \param char_offset updated to offset in string of actual_x, [1..length]
+ * \param actual_x updated to x coordinate of character closest to x
+ * \return true on success, false on error and error reported
+ *
+ * On exit, char_offset indicates first character after split point.
+ *
+ * Note: char_offset of 0 should 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
+fb_font_split(const plot_font_style_t *fstyle,
+ const char *string,
+ size_t length,
+ int x,
+ size_t *char_offset,
+ int *actual_x)
+{
+ const int width = fb_get_font_size(fstyle) * FB_FONT_WIDTH;
+ size_t nxtchr = 0;
+ int last_space_x = 0;
+ int last_space_idx = 0;
+
+ *actual_x = 0;
+ while (nxtchr < length) {
+ uint32_t ucs4;
+
+ if (string[nxtchr] == ' ') {
+ last_space_x = *actual_x;
+ last_space_idx = nxtchr;
+ }
+
+ ucs4 = utf8_to_ucs4(string + nxtchr, length - nxtchr);
+ if (codepoint_displayable(ucs4)) {
+ *actual_x += width;
+ }
+
+ if (*actual_x > x && last_space_idx != 0) {
+ /* string has exceeded available width and we've
+ * found a space; return previous space */
+ *actual_x = last_space_x;
+ *char_offset = last_space_idx;
+ return NSERROR_OK;
+ }
+
+ nxtchr = utf8_next(string, length, nxtchr);
+ }
+
+ *char_offset = nxtchr;
+
+ return NSERROR_OK;
+}
+
+
+static struct gui_layout_table layout_table = {
+ .width = fb_font_width,
+ .position = fb_font_position,
+ .split = fb_font_split,
+};
+
+struct gui_layout_table *framebuffer_layout_table = &layout_table;
+
+
+static struct gui_utf8_table utf8_table = {
+ .utf8_to_local = utf8_to_local,
+ .local_to_utf8 = utf8_from_local,
+};
+
+struct gui_utf8_table *framebuffer_utf8_table = &utf8_table;
+
+
+/*
+ * Local Variables:
+ * c-basic-offset:8
+ * End:
+ */
diff --git a/frontends/kolibrios/fb/font_internal.h b/frontends/kolibrios/fb/font_internal.h
new file mode 100644
index 0000000..f25df8d
--- a/dev/null
+++ b/frontends/kolibrios/fb/font_internal.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2008 Vincent Sanders <vince@simtec.co.uk>
+ *
+ * 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_FB_FONT_INTERNAL_H
+#define NETSURF_FB_FONT_INTERNAL_H
+
+#include <stdbool.h>
+
+struct fb_font_desc {
+ const char *name;
+ int width, height, pitch;
+};
+
+#define FB_FONT_WIDTH 8
+#define FB_FONT_HEIGHT 16
+#define FB_FONT_PITCH 8
+
+enum fb_font_style {
+ FB_REGULAR = 0,
+ FB_ITALIC = (1 << 0),
+ FB_BOLD = (1 << 1),
+ FB_BOLD_ITALIC = (FB_ITALIC | FB_BOLD)
+};
+
+enum fb_font_style fb_get_font_style(const plot_font_style_t *fstyle);
+int fb_get_font_size(const plot_font_style_t *fstyle);
+
+#define codepoint_displayable(u) \
+ (!(u >= 0x200b && u <= 0x200f))
+
+const uint8_t *fb_get_glyph(uint32_t ucs4, enum fb_font_style style, int scale);
+
+#endif /* NETSURF_FB_FONT_INTERNAL_H */
+
diff --git a/frontends/kolibrios/fb/framebuffer.c b/frontends/kolibrios/fb/framebuffer.c
new file mode 100644
index 0000000..649862a
--- a/dev/null
+++ b/frontends/kolibrios/fb/framebuffer.c
@@ -0,0 +1,651 @@
+/*
+ * Copyright 2008 Vincent Sanders <vince@simtec.co.uk>
+ *
+ * Framebuffer interface
+ *
+ * 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 <stdio.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libnsfb.h>
+#include <libnsfb_plot.h>
+#include <libnsfb_event.h>
+#include <libnsfb_cursor.h>
+
+#include "utils/utils.h"
+#include "utils/log.h"
+#include "utils/utf8.h"
+#include "netsurf/browser_window.h"
+#include "netsurf/plotters.h"
+#include "netsurf/bitmap.h"
+
+#include "framebuffer/gui.h"
+#include "framebuffer/fbtk.h"
+#include "framebuffer/framebuffer.h"
+#include "framebuffer/font.h"
+#include "framebuffer/bitmap.h"
+
+/* netsurf framebuffer library handle */
+static nsfb_t *nsfb;
+
+
+/**
+ * \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
+framebuffer_plot_clip(const struct redraw_context *ctx, const struct rect *clip)
+{
+ nsfb_bbox_t nsfb_clip;
+ nsfb_clip.x0 = clip->x0;
+ nsfb_clip.y0 = clip->y0;
+ nsfb_clip.x1 = clip->x1;
+ nsfb_clip.y1 = clip->y1;
+
+ if (!nsfb_plot_set_clip(nsfb, &nsfb_clip)) {
+ return NSERROR_INVALID;
+ }
+ 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
+framebuffer_plot_arc(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ int x, int y, int radius, int angle1, int angle2)
+{
+ if (!nsfb_plot_arc(nsfb, x, y, radius, angle1, angle2, style->fill_colour)) {
+ return NSERROR_INVALID;
+ }
+ 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
+framebuffer_plot_disc(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ int x, int y, int radius)
+{
+ nsfb_bbox_t ellipse;
+ ellipse.x0 = x - radius;
+ ellipse.y0 = y - radius;
+ ellipse.x1 = x + radius;
+ ellipse.y1 = y + radius;
+
+ if (style->fill_type != PLOT_OP_TYPE_NONE) {
+ nsfb_plot_ellipse_fill(nsfb, &ellipse, style->fill_colour);
+ }
+
+ if (style->stroke_type != PLOT_OP_TYPE_NONE) {
+ nsfb_plot_ellipse(nsfb, &ellipse, style->stroke_colour);
+ }
+ 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
+framebuffer_plot_line(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ const struct rect *line)
+{
+ nsfb_bbox_t rect;
+ nsfb_plot_pen_t pen;
+
+ rect.x0 = line->x0;
+ rect.y0 = line->y0;
+ rect.x1 = line->x1;
+ rect.y1 = line->y1;
+
+ if (style->stroke_type != PLOT_OP_TYPE_NONE) {
+
+ if (style->stroke_type == PLOT_OP_TYPE_DOT) {
+ pen.stroke_type = NFSB_PLOT_OPTYPE_PATTERN;
+ pen.stroke_pattern = 0xAAAAAAAA;
+ } else if (style->stroke_type == PLOT_OP_TYPE_DASH) {
+ pen.stroke_type = NFSB_PLOT_OPTYPE_PATTERN;
+ pen.stroke_pattern = 0xF0F0F0F0;
+ } else {
+ pen.stroke_type = NFSB_PLOT_OPTYPE_SOLID;
+ }
+
+ pen.stroke_colour = style->stroke_colour;
+ pen.stroke_width = style->stroke_width;
+ nsfb_plot_line(nsfb, &rect, &pen);
+ }
+
+ 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 nsrect A rectangle defining the line to be drawn
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+framebuffer_plot_rectangle(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ const struct rect *nsrect)
+{
+ nsfb_bbox_t rect;
+ bool dotted = false;
+ bool dashed = false;
+
+ rect.x0 = nsrect->x0;
+ rect.y0 = nsrect->y0;
+ rect.x1 = nsrect->x1;
+ rect.y1 = nsrect->y1;
+
+ if (style->fill_type != PLOT_OP_TYPE_NONE) {
+ nsfb_plot_rectangle_fill(nsfb, &rect, style->fill_colour);
+ }
+
+ if (style->stroke_type != PLOT_OP_TYPE_NONE) {
+ if (style->stroke_type == PLOT_OP_TYPE_DOT) {
+ dotted = true;
+ }
+
+ if (style->stroke_type == PLOT_OP_TYPE_DASH) {
+ dashed = true;
+ }
+
+ nsfb_plot_rectangle(nsfb, &rect, style->stroke_width, style->stroke_colour, dotted, dashed);
+ }
+ 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
+framebuffer_plot_polygon(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ const int *p,
+ unsigned int n)
+{
+ if (!nsfb_plot_polygon(nsfb, p, n, style->fill_colour)) {
+ return NSERROR_INVALID;
+ }
+ 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 width The width of the path
+ * \param transform A transform to apply to the path.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+framebuffer_plot_path(const struct redraw_context *ctx,
+ const plot_style_t *pstyle,
+ const float *p,
+ unsigned int n,
+ float width,
+ const float transform[6])
+{
+ LOG("path unimplemented");
+ 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
+framebuffer_plot_bitmap(const struct redraw_context *ctx,
+ struct bitmap *bitmap,
+ int x, int y,
+ int width,
+ int height,
+ colour bg,
+ bitmap_flags_t flags)
+{
+ nsfb_bbox_t loc;
+ nsfb_bbox_t clipbox;
+ bool repeat_x = (flags & BITMAPF_REPEAT_X);
+ bool repeat_y = (flags & BITMAPF_REPEAT_Y);
+ int bmwidth;
+ int bmheight;
+ int bmstride;
+ enum nsfb_format_e bmformat;
+ unsigned char *bmptr;
+ nsfb_t *bm = (nsfb_t *)bitmap;
+
+ /* x and y define coordinate of top left of of the initial explicitly
+ * placed tile. The width and height are the image scaling and the
+ * bounding box defines the extent of the repeat (which may go in all
+ * four directions from the initial tile).
+ */
+
+ if (!(repeat_x || repeat_y)) {
+ /* Not repeating at all, so just plot it */
+ loc.x0 = x;
+ loc.y0 = y;
+ loc.x1 = loc.x0 + width;
+ loc.y1 = loc.y0 + height;
+
+ return nsfb_plot_copy(bm, NULL, nsfb, &loc);
+ }
+
+ nsfb_plot_get_clip(nsfb, &clipbox);
+ nsfb_get_geometry(bm, &bmwidth, &bmheight, &bmformat);
+ nsfb_get_buffer(bm, &bmptr, &bmstride);
+
+ /* Optimise tiled plots of 1x1 bitmaps by replacing with a flat fill
+ * of the area. Can only be done when image is fully opaque. */
+ if ((bmwidth == 1) && (bmheight == 1)) {
+ if ((*(nsfb_colour_t *)bmptr & 0xff000000) != 0) {
+ if (!nsfb_plot_rectangle_fill(nsfb, &clipbox,
+ *(nsfb_colour_t *)bmptr)) {
+ return NSERROR_INVALID;
+ }
+ return NSERROR_OK;
+ }
+ }
+
+ /* Optimise tiled plots of bitmaps scaled to 1x1 by replacing with
+ * a flat fill of the area. Can only be done when image is fully
+ * opaque. */
+ if ((width == 1) && (height == 1)) {
+ if (framebuffer_bitmap_get_opaque(bm)) {
+ /** TODO: Currently using top left pixel. Maybe centre
+ * pixel or average value would be better. */
+ if (!nsfb_plot_rectangle_fill(nsfb, &clipbox,
+ *(nsfb_colour_t *)bmptr)) {
+ return NSERROR_INVALID;
+ }
+ return NSERROR_OK;
+ }
+ }
+
+ /* get left most tile position */
+ if (repeat_x) {
+ for (; x > clipbox.x0; x -= width);
+ }
+
+ /* get top most tile position */
+ if (repeat_y) {
+ for (; y > clipbox.y0; y -= height);
+ }
+
+ /* set up top left tile location */
+ loc.x0 = x;
+ loc.y0 = y;
+ loc.x1 = loc.x0 + width;
+ loc.y1 = loc.y0 + height;
+
+ /* plot tiling across and down to extents */
+ nsfb_plot_bitmap_tiles(nsfb, &loc,
+ repeat_x ? ((clipbox.x1 - x) + width - 1) / width : 1,
+ repeat_y ? ((clipbox.y1 - y) + height - 1) / height : 1,
+ (nsfb_colour_t *)bmptr, bmwidth, bmheight,
+ bmstride * 8 / 32, bmformat == NSFB_FMT_ABGR8888);
+
+ return NSERROR_OK;
+}
+
+
+#ifdef FB_USE_FREETYPE
+/**
+ * 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
+framebuffer_plot_text(const struct redraw_context *ctx,
+ const struct plot_font_style *fstyle,
+ int x,
+ int y,
+ const char *text,
+ size_t length)
+{
+ uint32_t ucs4;
+ size_t nxtchr = 0;
+ FT_Glyph glyph;
+ FT_BitmapGlyph bglyph;
+ nsfb_bbox_t loc;
+
+ while (nxtchr < length) {
+ ucs4 = utf8_to_ucs4(text + nxtchr, length - nxtchr);
+ nxtchr = utf8_next(text, length, nxtchr);
+
+ glyph = fb_getglyph(fstyle, ucs4);
+ if (glyph == NULL)
+ continue;
+
+ if (glyph->format == FT_GLYPH_FORMAT_BITMAP) {
+ bglyph = (FT_BitmapGlyph)glyph;
+
+ loc.x0 = x + bglyph->left;
+ loc.y0 = y - bglyph->top;
+ loc.x1 = loc.x0 + bglyph->bitmap.width;
+ loc.y1 = loc.y0 + bglyph->bitmap.rows;
+
+ /* now, draw to our target surface */
+ if (bglyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO) {
+ nsfb_plot_glyph1(nsfb,
+ &loc,
+ bglyph->bitmap.buffer,
+ bglyph->bitmap.pitch,
+ fstyle->foreground);
+ } else {
+ nsfb_plot_glyph8(nsfb,
+ &loc,
+ bglyph->bitmap.buffer,
+ bglyph->bitmap.pitch,
+ fstyle->foreground);
+ }
+ }
+ x += glyph->advance.x >> 16;
+
+ }
+ return NSERROR_OK;
+
+}
+
+#else
+
+/**
+ * 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
+framebuffer_plot_text(const struct redraw_context *ctx,
+ const struct plot_font_style *fstyle,
+ int x,
+ int y,
+ const char *text,
+ size_t length)
+{
+ enum fb_font_style style = fb_get_font_style(fstyle);
+ int size = fb_get_font_size(fstyle);
+ const uint8_t *chrp;
+ size_t nxtchr = 0;
+ nsfb_bbox_t loc;
+ uint32_t ucs4;
+ int p = FB_FONT_PITCH * size;
+ int w = FB_FONT_WIDTH * size;
+ int h = FB_FONT_HEIGHT * size;
+
+ y -= ((h * 3) / 4);
+ /* the coord is the bottom-left of the pixels offset by 1 to make
+ * it work since fb coords are the top-left of pixels */
+ y += 1;
+
+ while (nxtchr < length) {
+ ucs4 = utf8_to_ucs4(text + nxtchr, length - nxtchr);
+ nxtchr = utf8_next(text, length, nxtchr);
+
+ if (!codepoint_displayable(ucs4))
+ continue;
+
+ loc.x0 = x;
+ loc.y0 = y;
+ loc.x1 = loc.x0 + w;
+ loc.y1 = loc.y0 + h;
+
+ chrp = fb_get_glyph(ucs4, style, size);
+ nsfb_plot_glyph1(nsfb, &loc, chrp, p, fstyle->foreground);
+
+ x += w;
+
+ }
+
+ return NSERROR_OK;
+}
+#endif
+
+
+/** framebuffer plot operation table */
+const struct plotter_table fb_plotters = {
+ .clip = framebuffer_plot_clip,
+ .arc = framebuffer_plot_arc,
+ .disc = framebuffer_plot_disc,
+ .line = framebuffer_plot_line,
+ .rectangle = framebuffer_plot_rectangle,
+ .polygon = framebuffer_plot_polygon,
+ .path = framebuffer_plot_path,
+ .bitmap = framebuffer_plot_bitmap,
+ .text = framebuffer_plot_text,
+ .option_knockout = true,
+};
+
+
+static bool framebuffer_format_from_bpp(int bpp, enum nsfb_format_e *fmt)
+{
+ switch (bpp) {
+ case 32:
+ *fmt = NSFB_FMT_XRGB8888;
+ break;
+
+ case 24:
+ *fmt = NSFB_FMT_RGB888;
+ break;
+
+ case 16:
+ *fmt = NSFB_FMT_RGB565;
+ break;
+
+ case 8:
+ *fmt = NSFB_FMT_I8;
+ break;
+
+ case 4:
+ *fmt = NSFB_FMT_I4;
+ break;
+
+ case 1:
+ *fmt = NSFB_FMT_I1;
+ break;
+
+ default:
+ LOG("Bad bits per pixel (%d)\n", bpp);
+ return false;
+ }
+
+ return true;
+}
+
+
+
+nsfb_t *
+framebuffer_initialise(const char *fename, int width, int height, int bpp)
+{
+ enum nsfb_type_e fbtype;
+ enum nsfb_format_e fbfmt;
+
+ /* bpp is a proxy for the framebuffer format */
+ if (framebuffer_format_from_bpp(bpp, &fbfmt) == false) {
+ return NULL;
+ }
+
+ fbtype = nsfb_type_from_name(fename);
+ if (fbtype == NSFB_SURFACE_NONE) {
+ LOG("The %s surface is not available from libnsfb\n", fename);
+ return NULL;
+ }
+
+ nsfb = nsfb_new(fbtype);
+ if (nsfb == NULL) {
+ LOG("Unable to create %s fb surface\n", fename);
+ return NULL;
+ }
+
+ if (nsfb_set_geometry(nsfb, width, height, fbfmt) == -1) {
+ LOG("Unable to set surface geometry\n");
+ nsfb_free(nsfb);
+ return NULL;
+ }
+
+ nsfb_cursor_init(nsfb);
+
+ if (nsfb_init(nsfb) == -1) {
+ LOG("Unable to initialise nsfb surface\n");
+ nsfb_free(nsfb);
+ return NULL;
+ }
+
+ return nsfb;
+
+}
+
+bool
+framebuffer_resize(nsfb_t *nsfb, int width, int height, int bpp)
+{
+ enum nsfb_format_e fbfmt;
+
+ /* bpp is a proxy for the framebuffer format */
+ if (framebuffer_format_from_bpp(bpp, &fbfmt) == false) {
+ return false;
+ }
+
+ if (nsfb_set_geometry(nsfb, width, height, fbfmt) == -1) {
+ LOG("Unable to change surface geometry\n");
+ return false;
+ }
+
+ return true;
+
+}
+
+void
+framebuffer_finalise(void)
+{
+ nsfb_free(nsfb);
+}
+
+bool
+framebuffer_set_cursor(struct fbtk_bitmap *bm)
+{
+ return nsfb_cursor_set(nsfb, (nsfb_colour_t *)bm->pixdata, bm->width, bm->height, bm->width, bm->hot_x, bm->hot_y);
+}
+
+nsfb_t *framebuffer_set_surface(nsfb_t *new_nsfb)
+{
+ nsfb_t *old_nsfb;
+ old_nsfb = nsfb;
+ nsfb = new_nsfb;
+ return old_nsfb;
+}
diff --git a/frontends/kolibrios/fb/framebuffer.h b/frontends/kolibrios/fb/framebuffer.h
new file mode 100644
index 0000000..d99049f
--- a/dev/null
+++ b/frontends/kolibrios/fb/framebuffer.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2008 Vincent Sanders <vince@simtec.co.uk>
+ *
+ * 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
+ * framebuffer interface.
+ */
+
+#ifndef NETSURF_FB_FRAMEBUFFER_H
+#define NETSURF_FB_FRAMEBUFFER_H
+
+extern const struct plotter_table fb_plotters;
+
+nsfb_t *framebuffer_initialise(const char *fename, int width, int height, int bpp);
+bool framebuffer_resize(nsfb_t *nsfb, int width, int height, int bpp);
+void framebuffer_finalise(void);
+bool framebuffer_set_cursor(struct fbtk_bitmap *bm);
+
+/** Set framebuffer surface to render into
+ *
+ * @return return old surface
+ */
+nsfb_t *framebuffer_set_surface(nsfb_t *new_nsfb);
+
+#endif
diff --git a/frontends/kolibrios/fb/gui.c b/frontends/kolibrios/fb/gui.c
new file mode 100644
index 0000000..4d4c733
--- a/dev/null
+++ b/frontends/kolibrios/fb/gui.c
@@ -0,0 +1,2226 @@
+/*
+ * Copyright 2008, 2014 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdint.h>
+#include <limits.h>
+#include <getopt.h>
+#include <assert.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <nsutils/time.h>
+
+#include <libnsfb.h>
+#include <libnsfb_plot.h>
+#include <libnsfb_event.h>
+
+#include "utils/utils.h"
+#include "utils/nsoption.h"
+#include "utils/filepath.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "netsurf/browser_window.h"
+#include "netsurf/keypress.h"
+#include "desktop/browser_history.h"
+#include "netsurf/plotters.h"
+#include "netsurf/window.h"
+#include "netsurf/misc.h"
+#include "netsurf/netsurf.h"
+#include "netsurf/cookie_db.h"
+#include "content/fetch.h"
+
+#include "framebuffer/gui.h"
+#include "framebuffer/fbtk.h"
+#include "framebuffer/framebuffer.h"
+#include "framebuffer/schedule.h"
+#include "framebuffer/findfile.h"
+#include "framebuffer/image_data.h"
+#include "framebuffer/font.h"
+#include "framebuffer/clipboard.h"
+#include "framebuffer/fetch.h"
+#include "framebuffer/bitmap.h"
+
+
+#define NSFB_TOOLBAR_DEFAULT_LAYOUT "blfsrutc"
+
+fbtk_widget_t *fbtk;
+
+static bool fb_complete = false;
+
+struct gui_window *input_window = NULL;
+struct gui_window *search_current_window;
+struct gui_window *window_list = NULL;
+
+/* private data for browser user widget */
+struct browser_widget_s {
+ struct browser_window *bw; /**< The browser window connected to this gui window */
+ int scrollx, scrolly; /**< scroll offsets. */
+
+ /* Pending window redraw state. */
+ bool redraw_required; /**< flag indicating the foreground loop
+ * needs to redraw the browser widget.
+ */
+ bbox_t redraw_box; /**< Area requiring redraw. */
+ bool pan_required; /**< flag indicating the foreground loop
+ * needs to pan the window.
+ */
+ int panx, pany; /**< Panning required. */
+};
+
+static struct gui_drag {
+ enum state {
+ GUI_DRAG_NONE,
+ GUI_DRAG_PRESSED,
+ GUI_DRAG_DRAG
+ } state;
+ int button;
+ int x;
+ int y;
+ bool grabbed_pointer;
+} gui_drag;
+
+
+/**
+ * Cause an abnormal program termination.
+ *
+ * \note This never returns and is intended to terminate without any cleanup.
+ *
+ * \param error The message to display to the user.
+ */
+static void die(const char *error)
+{
+ fprintf(stderr, "%s\n", error);
+ exit(1);
+}
+
+
+/**
+ * Warn the user of an event.
+ *
+ * \param[in] warning A warning looked up in the message translation table
+ * \param[in] detail Additional text to be displayed or NULL.
+ * \return NSERROR_OK on success or error code if there was a
+ * faliure displaying the message to the user.
+ */
+static nserror fb_warn_user(const char *warning, const char *detail)
+{
+ LOG("%s %s", warning, detail);
+ return NSERROR_OK;
+}
+
+/* queue a redraw operation, co-ordinates are relative to the window */
+static void
+fb_queue_redraw(struct fbtk_widget_s *widget, int x0, int y0, int x1, int y1)
+{
+ struct browser_widget_s *bwidget = fbtk_get_userpw(widget);
+
+ bwidget->redraw_box.x0 = min(bwidget->redraw_box.x0, x0);
+ bwidget->redraw_box.y0 = min(bwidget->redraw_box.y0, y0);
+ bwidget->redraw_box.x1 = max(bwidget->redraw_box.x1, x1);
+ bwidget->redraw_box.y1 = max(bwidget->redraw_box.y1, y1);
+
+ if (fbtk_clip_to_widget(widget, &bwidget->redraw_box)) {
+ bwidget->redraw_required = true;
+ fbtk_request_redraw(widget);
+ } else {
+ bwidget->redraw_box.y0 = bwidget->redraw_box.x0 = INT_MAX;
+ bwidget->redraw_box.y1 = bwidget->redraw_box.x1 = -(INT_MAX);
+ bwidget->redraw_required = false;
+ }
+}
+
+/* queue a window scroll */
+static void
+widget_scroll_y(struct gui_window *gw, int y, bool abs)
+{
+ struct browser_widget_s *bwidget = fbtk_get_userpw(gw->browser);
+ int content_width, content_height;
+ int height;
+
+ LOG("window scroll");
+ if (abs) {
+ bwidget->pany = y - bwidget->scrolly;
+ } else {
+ bwidget->pany += y;
+ }
+
+ browser_window_get_extents(gw->bw, true,
+ &content_width, &content_height);
+
+ height = fbtk_get_height(gw->browser);
+
+ /* dont pan off the top */
+ if ((bwidget->scrolly + bwidget->pany) < 0)
+ bwidget->pany = -bwidget->scrolly;
+
+ /* do not pan off the bottom of the content */
+ if ((bwidget->scrolly + bwidget->pany) > (content_height - height))
+ bwidget->pany = (content_height - height) - bwidget->scrolly;
+
+ if (bwidget->pany == 0)
+ return;
+
+ bwidget->pan_required = true;
+
+ fbtk_request_redraw(gw->browser);
+
+ fbtk_set_scroll_position(gw->vscroll, bwidget->scrolly + bwidget->pany);
+}
+
+/* queue a window scroll */
+static void
+widget_scroll_x(struct gui_window *gw, int x, bool abs)
+{
+ struct browser_widget_s *bwidget = fbtk_get_userpw(gw->browser);
+ int content_width, content_height;
+ int width;
+
+ if (abs) {
+ bwidget->panx = x - bwidget->scrollx;
+ } else {
+ bwidget->panx += x;
+ }
+
+ browser_window_get_extents(gw->bw, true,
+ &content_width, &content_height);
+
+ width = fbtk_get_width(gw->browser);
+
+ /* dont pan off the left */
+ if ((bwidget->scrollx + bwidget->panx) < 0)
+ bwidget->panx = - bwidget->scrollx;
+
+ /* do not pan off the right of the content */
+ if ((bwidget->scrollx + bwidget->panx) > (content_width - width))
+ bwidget->panx = (content_width - width) - bwidget->scrollx;
+
+ if (bwidget->panx == 0)
+ return;
+
+ bwidget->pan_required = true;
+
+ fbtk_request_redraw(gw->browser);
+
+ fbtk_set_scroll_position(gw->hscroll, bwidget->scrollx + bwidget->panx);
+}
+
+static void
+fb_pan(fbtk_widget_t *widget,
+ struct browser_widget_s *bwidget,
+ struct browser_window *bw)
+{
+ int x;
+ int y;
+ int width;
+ int height;
+ nsfb_bbox_t srcbox;
+ nsfb_bbox_t dstbox;
+
+ nsfb_t *nsfb = fbtk_get_nsfb(widget);
+
+ height = fbtk_get_height(widget);
+ width = fbtk_get_width(widget);
+
+ LOG("panning %d, %d", bwidget->panx, bwidget->pany);
+
+ x = fbtk_get_absx(widget);
+ y = fbtk_get_absy(widget);
+
+ /* if the pan exceeds the viewport size just redraw the whole area */
+ if (bwidget->pany >= height || bwidget->pany <= -height ||
+ bwidget->panx >= width || bwidget->panx <= -width) {
+
+ bwidget->scrolly += bwidget->pany;
+ bwidget->scrollx += bwidget->panx;
+ fb_queue_redraw(widget, 0, 0, width, height);
+
+ /* ensure we don't try to scroll again */
+ bwidget->panx = 0;
+ bwidget->pany = 0;
+ bwidget->pan_required = false;
+ return;
+ }
+
+ if (bwidget->pany < 0) {
+ /* pan up by less then viewport height */
+ srcbox.x0 = x;
+ srcbox.y0 = y;
+ srcbox.x1 = srcbox.x0 + width;
+ srcbox.y1 = srcbox.y0 + height + bwidget->pany;
+
+ dstbox.x0 = x;
+ dstbox.y0 = y - bwidget->pany;
+ dstbox.x1 = dstbox.x0 + width;
+ dstbox.y1 = dstbox.y0 + height + bwidget->pany;
+
+ /* move part that remains visible up */
+ nsfb_plot_copy(nsfb, &srcbox, nsfb, &dstbox);
+
+ /* redraw newly exposed area */
+ bwidget->scrolly += bwidget->pany;
+ fb_queue_redraw(widget, 0, 0, width, - bwidget->pany);
+
+ } else if (bwidget->pany > 0) {
+ /* pan down by less then viewport height */
+ srcbox.x0 = x;
+ srcbox.y0 = y + bwidget->pany;
+ srcbox.x1 = srcbox.x0 + width;
+ srcbox.y1 = srcbox.y0 + height - bwidget->pany;
+
+ dstbox.x0 = x;
+ dstbox.y0 = y;
+ dstbox.x1 = dstbox.x0 + width;
+ dstbox.y1 = dstbox.y0 + height - bwidget->pany;
+
+ /* move part that remains visible down */
+ nsfb_plot_copy(nsfb, &srcbox, nsfb, &dstbox);
+
+ /* redraw newly exposed area */
+ bwidget->scrolly += bwidget->pany;
+ fb_queue_redraw(widget, 0, height - bwidget->pany,
+ width, height);
+ }
+
+ if (bwidget->panx < 0) {
+ /* pan left by less then viewport width */
+ srcbox.x0 = x;
+ srcbox.y0 = y;
+ srcbox.x1 = srcbox.x0 + width + bwidget->panx;
+ srcbox.y1 = srcbox.y0 + height;
+
+ dstbox.x0 = x - bwidget->panx;
+ dstbox.y0 = y;
+ dstbox.x1 = dstbox.x0 + width + bwidget->panx;
+ dstbox.y1 = dstbox.y0 + height;
+
+ /* move part that remains visible left */
+ nsfb_plot_copy(nsfb, &srcbox, nsfb, &dstbox);
+
+ /* redraw newly exposed area */
+ bwidget->scrollx += bwidget->panx;
+ fb_queue_redraw(widget, 0, 0, -bwidget->panx, height);
+
+ } else if (bwidget->panx > 0) {
+ /* pan right by less then viewport width */
+ srcbox.x0 = x + bwidget->panx;
+ srcbox.y0 = y;
+ srcbox.x1 = srcbox.x0 + width - bwidget->panx;
+ srcbox.y1 = srcbox.y0 + height;
+
+ dstbox.x0 = x;
+ dstbox.y0 = y;
+ dstbox.x1 = dstbox.x0 + width - bwidget->panx;
+ dstbox.y1 = dstbox.y0 + height;
+
+ /* move part that remains visible right */
+ nsfb_plot_copy(nsfb, &srcbox, nsfb, &dstbox);
+
+ /* redraw newly exposed area */
+ bwidget->scrollx += bwidget->panx;
+ fb_queue_redraw(widget, width - bwidget->panx, 0,
+ width, height);
+ }
+
+ bwidget->pan_required = false;
+ bwidget->panx = 0;
+ bwidget->pany = 0;
+}
+
+static void
+fb_redraw(fbtk_widget_t *widget,
+ struct browser_widget_s *bwidget,
+ struct browser_window *bw)
+{
+ int x;
+ int y;
+ int caret_x, caret_y, caret_h;
+ struct rect clip;
+ struct redraw_context ctx = {
+ .interactive = true,
+ .background_images = true,
+ .plot = &fb_plotters
+ };
+ nsfb_t *nsfb = fbtk_get_nsfb(widget);
+ float scale = browser_window_get_scale(bw);
+
+ x = fbtk_get_absx(widget);
+ y = fbtk_get_absy(widget);
+
+ /* adjust clipping co-ordinates according to window location */
+ bwidget->redraw_box.y0 += y;
+ bwidget->redraw_box.y1 += y;
+ bwidget->redraw_box.x0 += x;
+ bwidget->redraw_box.x1 += x;
+
+ nsfb_claim(nsfb, &bwidget->redraw_box);
+
+ /* redraw bounding box is relative to window */
+ clip.x0 = bwidget->redraw_box.x0;
+ clip.y0 = bwidget->redraw_box.y0;
+ clip.x1 = bwidget->redraw_box.x1;
+ clip.y1 = bwidget->redraw_box.y1;
+
+ browser_window_redraw(bw,
+ (x - bwidget->scrollx) / scale,
+ (y - bwidget->scrolly) / scale,
+ &clip, &ctx);
+
+ if (fbtk_get_caret(widget, &caret_x, &caret_y, &caret_h)) {
+ /* This widget has caret, so render it */
+ nsfb_bbox_t line;
+ nsfb_plot_pen_t pen;
+
+ line.x0 = x - bwidget->scrollx + caret_x;
+ line.y0 = y - bwidget->scrolly + caret_y;
+ line.x1 = x - bwidget->scrollx + caret_x;
+ line.y1 = y - bwidget->scrolly + caret_y + caret_h;
+
+ pen.stroke_type = NFSB_PLOT_OPTYPE_SOLID;
+ pen.stroke_width = 1;
+ pen.stroke_colour = 0xFF0000FF;
+
+ nsfb_plot_line(nsfb, &line, &pen);
+ }
+
+ nsfb_update(fbtk_get_nsfb(widget), &bwidget->redraw_box);
+
+ bwidget->redraw_box.y0 = bwidget->redraw_box.x0 = INT_MAX;
+ bwidget->redraw_box.y1 = bwidget->redraw_box.x1 = INT_MIN;
+ bwidget->redraw_required = false;
+}
+
+static int
+fb_browser_window_redraw(fbtk_widget_t *widget, fbtk_callback_info *cbi)
+{
+ struct gui_window *gw = cbi->context;
+ struct browser_widget_s *bwidget;
+
+ bwidget = fbtk_get_userpw(widget);
+ if (bwidget == NULL) {
+ LOG("browser widget from widget %p was null", widget);
+ return -1;
+ }
+
+ if (bwidget->pan_required) {
+ fb_pan(widget, bwidget, gw->bw);
+ }
+
+ if (bwidget->redraw_required) {
+ fb_redraw(widget, bwidget, gw->bw);
+ } else {
+ bwidget->redraw_box.x0 = 0;
+ bwidget->redraw_box.y0 = 0;
+ bwidget->redraw_box.x1 = fbtk_get_width(widget);
+ bwidget->redraw_box.y1 = fbtk_get_height(widget);
+ fb_redraw(widget, bwidget, gw->bw);
+ }
+ return 0;
+}
+
+static int fb_browser_window_destroy(fbtk_widget_t *widget,
+ fbtk_callback_info *cbi)
+{
+ struct browser_widget_s *browser_widget;
+
+ if (widget == NULL) {
+ return 0;
+ }
+
+ /* Free private data */
+ browser_widget = fbtk_get_userpw(widget);
+ free(browser_widget);
+
+ return 0;
+}
+
+
+static const char *fename;
+static int febpp;
+static int fewidth;
+static int feheight;
+static const char *feurl;
+
+static bool
+process_cmdline(int argc, char** argv)
+{
+ int opt;
+ int option_index;
+ static struct option long_options[] = {
+ {0, 0, 0, 0 }
+ }; /* no long options */
+
+ LOG("argc %d, argv %p", argc, argv);
+
+ fename = "sdl";
+ febpp = 32;
+
+ fewidth = nsoption_int(window_width);
+ if (fewidth <= 0) {
+ fewidth = 800;
+ }
+ feheight = nsoption_int(window_height);
+ if (feheight <= 0) {
+ feheight = 600;
+ }
+
+ if ((nsoption_charp(homepage_url) != NULL) &&
+ (nsoption_charp(homepage_url)[0] != '\0')) {
+ feurl = nsoption_charp(homepage_url);
+ } else {
+ feurl = NETSURF_HOMEPAGE;
+ }
+
+ while((opt = getopt_long(argc, argv, "f:b:w:h:",
+ long_options, &option_index)) != -1) {
+ switch (opt) {
+ case 'f':
+ fename = optarg;
+ break;
+
+ case 'b':
+ febpp = atoi(optarg);
+ break;
+
+ case 'w':
+ fewidth = atoi(optarg);
+ break;
+
+ case 'h':
+ feheight = atoi(optarg);
+ break;
+
+ default:
+ fprintf(stderr,
+ "Usage: %s [-f frontend] [-b bpp] url\n",
+ argv[0]);
+ return false;
+ }
+ }
+
+ if (optind < argc) {
+ feurl = argv[optind];
+ }
+
+ return true;
+}
+
+/**
+ * Set option defaults for framebuffer frontend
+ *
+ * @param defaults The option table to update.
+ * @return error status.
+ */
+static nserror set_defaults(struct nsoption_s *defaults)
+{
+ /* Set defaults for absent option strings */
+ nsoption_setnull_charp(cookie_file, strdup("~/.netsurf/Cookies"));
+ nsoption_setnull_charp(cookie_jar, strdup("~/.netsurf/Cookies"));
+
+ if (nsoption_charp(cookie_file) == NULL ||
+ nsoption_charp(cookie_jar) == NULL) {
+ LOG("Failed initialising cookie options");
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ /* set system colours for framebuffer ui */
+ nsoption_set_colour(sys_colour_ActiveBorder, 0x00000000);
+ nsoption_set_colour(sys_colour_ActiveCaption, 0x00ddddcc);
+ nsoption_set_colour(sys_colour_AppWorkspace, 0x00eeeeee);
+ nsoption_set_colour(sys_colour_Background, 0x00aa0000);
+ nsoption_set_colour(sys_colour_ButtonFace, 0x00dddddd);
+ nsoption_set_colour(sys_colour_ButtonHighlight, 0x00cccccc);
+ nsoption_set_colour(sys_colour_ButtonShadow, 0x00bbbbbb);
+ nsoption_set_colour(sys_colour_ButtonText, 0x00000000);
+ nsoption_set_colour(sys_colour_CaptionText, 0x00000000);
+ nsoption_set_colour(sys_colour_GrayText, 0x00777777);
+ nsoption_set_colour(sys_colour_Highlight, 0x00ee0000);
+ nsoption_set_colour(sys_colour_HighlightText, 0x00000000);
+ nsoption_set_colour(sys_colour_InactiveBorder, 0x00000000);
+ nsoption_set_colour(sys_colour_InactiveCaption, 0x00ffffff);
+ nsoption_set_colour(sys_colour_InactiveCaptionText, 0x00cccccc);
+ nsoption_set_colour(sys_colour_InfoBackground, 0x00aaaaaa);
+ nsoption_set_colour(sys_colour_InfoText, 0x00000000);
+ nsoption_set_colour(sys_colour_Menu, 0x00aaaaaa);
+ nsoption_set_colour(sys_colour_MenuText, 0x00000000);
+ nsoption_set_colour(sys_colour_Scrollbar, 0x00aaaaaa);
+ nsoption_set_colour(sys_colour_ThreeDDarkShadow, 0x00555555);
+ nsoption_set_colour(sys_colour_ThreeDFace, 0x00dddddd);
+ nsoption_set_colour(sys_colour_ThreeDHighlight, 0x00aaaaaa);
+ nsoption_set_colour(sys_colour_ThreeDLightShadow, 0x00999999);
+ nsoption_set_colour(sys_colour_ThreeDShadow, 0x00777777);
+ nsoption_set_colour(sys_colour_Window, 0x00aaaaaa);
+ nsoption_set_colour(sys_colour_WindowFrame, 0x00000000);
+ nsoption_set_colour(sys_colour_WindowText, 0x00000000);
+
+ 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;
+}
+
+static void framebuffer_run(void)
+{
+ nsfb_event_t event;
+ int timeout; /* timeout in miliseconds */
+
+ while (fb_complete != true) {
+ /* run the scheduler and discover how long to wait for
+ * the next event.
+ */
+ timeout = schedule_run();
+
+ /* if redraws are pending do not wait for event,
+ * return immediately
+ */
+ if (fbtk_get_redraw_pending(fbtk))
+ timeout = 0;
+
+ if (fbtk_event(fbtk, &event, timeout)) {
+ if ((event.type == NSFB_EVENT_CONTROL) &&
+ (event.value.controlcode == NSFB_CONTROL_QUIT))
+ fb_complete = true;
+ }
+
+ fbtk_redraw(fbtk);
+ }
+}
+
+static void gui_quit(void)
+{
+ LOG("gui_quit");
+
+ urldb_save_cookies(nsoption_charp(cookie_jar));
+
+ framebuffer_finalise();
+}
+
+/* called back when click in browser window */
+static int
+fb_browser_window_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
+{
+ struct gui_window *gw = cbi->context;
+ struct browser_widget_s *bwidget = fbtk_get_userpw(widget);
+ browser_mouse_state mouse;
+ float scale = browser_window_get_scale(gw->bw);
+ int x = (cbi->x + bwidget->scrollx) / scale;
+ int y = (cbi->y + bwidget->scrolly) / scale;
+ uint64_t time_now;
+ static struct {
+ enum { CLICK_SINGLE, CLICK_DOUBLE, CLICK_TRIPLE } type;
+ uint64_t time;
+ } last_click;
+
+ if (cbi->event->type != NSFB_EVENT_KEY_DOWN &&
+ cbi->event->type != NSFB_EVENT_KEY_UP)
+ return 0;
+
+ LOG("browser window clicked at %d,%d", cbi->x, cbi->y);
+
+ switch (cbi->event->type) {
+ case NSFB_EVENT_KEY_DOWN:
+ switch (cbi->event->value.keycode) {
+ case NSFB_KEY_MOUSE_1:
+ browser_window_mouse_click(gw->bw,
+ BROWSER_MOUSE_PRESS_1, x, y);
+ gui_drag.state = GUI_DRAG_PRESSED;
+ gui_drag.button = 1;
+ gui_drag.x = x;
+ gui_drag.y = y;
+ break;
+
+ case NSFB_KEY_MOUSE_3:
+ browser_window_mouse_click(gw->bw,
+ BROWSER_MOUSE_PRESS_2, x, y);
+ gui_drag.state = GUI_DRAG_PRESSED;
+ gui_drag.button = 2;
+ gui_drag.x = x;
+ gui_drag.y = y;
+ break;
+
+ case NSFB_KEY_MOUSE_4:
+ /* scroll up */
+ if (browser_window_scroll_at_point(gw->bw, x, y,
+ 0, -100) == false)
+ widget_scroll_y(gw, -100, false);
+ break;
+
+ case NSFB_KEY_MOUSE_5:
+ /* scroll down */
+ if (browser_window_scroll_at_point(gw->bw, x, y,
+ 0, 100) == false)
+ widget_scroll_y(gw, 100, false);
+ break;
+
+ default:
+ break;
+
+ }
+
+ break;
+ case NSFB_EVENT_KEY_UP:
+
+ mouse = 0;
+ nsu_getmonotonic_ms(&time_now);
+
+ switch (cbi->event->value.keycode) {
+ case NSFB_KEY_MOUSE_1:
+ if (gui_drag.state == GUI_DRAG_DRAG) {
+ /* End of a drag, rather than click */
+
+ if (gui_drag.grabbed_pointer) {
+ /* need to ungrab pointer */
+ fbtk_tgrab_pointer(widget);
+ gui_drag.grabbed_pointer = false;
+ }
+
+ gui_drag.state = GUI_DRAG_NONE;
+
+ /* Tell core */
+ browser_window_mouse_track(gw->bw, 0, x, y);
+ break;
+ }
+ /* This is a click;
+ * clear PRESSED state and pass to core */
+ gui_drag.state = GUI_DRAG_NONE;
+ mouse = BROWSER_MOUSE_CLICK_1;
+ break;
+
+ case NSFB_KEY_MOUSE_3:
+ if (gui_drag.state == GUI_DRAG_DRAG) {
+ /* End of a drag, rather than click */
+ gui_drag.state = GUI_DRAG_NONE;
+
+ if (gui_drag.grabbed_pointer) {
+ /* need to ungrab pointer */
+ fbtk_tgrab_pointer(widget);
+ gui_drag.grabbed_pointer = false;
+ }
+
+ /* Tell core */
+ browser_window_mouse_track(gw->bw, 0, x, y);
+ break;
+ }
+ /* This is a click;
+ * clear PRESSED state and pass to core */
+ gui_drag.state = GUI_DRAG_NONE;
+ mouse = BROWSER_MOUSE_CLICK_2;
+ break;
+
+ default:
+ break;
+
+ }
+
+ /* Determine if it's a double or triple click, allowing
+ * 0.5 seconds (500ms) between clicks
+ */
+ if ((time_now < (last_click.time + 500)) &&
+ (cbi->event->value.keycode != NSFB_KEY_MOUSE_4) &&
+ (cbi->event->value.keycode != NSFB_KEY_MOUSE_5)) {
+ if (last_click.type == CLICK_SINGLE) {
+ /* Set double click */
+ mouse |= BROWSER_MOUSE_DOUBLE_CLICK;
+ last_click.type = CLICK_DOUBLE;
+
+ } else if (last_click.type == CLICK_DOUBLE) {
+ /* Set triple click */
+ mouse |= BROWSER_MOUSE_TRIPLE_CLICK;
+ last_click.type = CLICK_TRIPLE;
+ } else {
+ /* Set normal click */
+ last_click.type = CLICK_SINGLE;
+ }
+ } else {
+ last_click.type = CLICK_SINGLE;
+ }
+
+ if (mouse) {
+ browser_window_mouse_click(gw->bw, mouse, x, y);
+ }
+
+ last_click.time = time_now;
+
+ break;
+ default:
+ break;
+
+ }
+ return 1;
+}
+
+/* called back when movement in browser window */
+static int
+fb_browser_window_move(fbtk_widget_t *widget, fbtk_callback_info *cbi)
+{
+ browser_mouse_state mouse = 0;
+ struct gui_window *gw = cbi->context;
+ struct browser_widget_s *bwidget = fbtk_get_userpw(widget);
+ float scale = browser_window_get_scale(gw->bw);
+ int x = (cbi->x + bwidget->scrollx) / scale;
+ int y = (cbi->y + bwidget->scrolly) / scale;
+
+ if (gui_drag.state == GUI_DRAG_PRESSED &&
+ (abs(x - gui_drag.x) > 5 ||
+ abs(y - gui_drag.y) > 5)) {
+ /* Drag started */
+ if (gui_drag.button == 1) {
+ browser_window_mouse_click(gw->bw,
+ BROWSER_MOUSE_DRAG_1,
+ gui_drag.x, gui_drag.y);
+ } else {
+ browser_window_mouse_click(gw->bw,
+ BROWSER_MOUSE_DRAG_2,
+ gui_drag.x, gui_drag.y);
+ }
+ gui_drag.grabbed_pointer = fbtk_tgrab_pointer(widget);
+ gui_drag.state = GUI_DRAG_DRAG;
+ }
+
+ if (gui_drag.state == GUI_DRAG_DRAG) {
+ /* set up mouse state */
+ mouse |= BROWSER_MOUSE_DRAG_ON;
+
+ if (gui_drag.button == 1)
+ mouse |= BROWSER_MOUSE_HOLDING_1;
+ else
+ mouse |= BROWSER_MOUSE_HOLDING_2;
+ }
+
+ browser_window_mouse_track(gw->bw, mouse, x, y);
+
+ return 0;
+}
+
+
+static int
+fb_browser_window_input(fbtk_widget_t *widget, fbtk_callback_info *cbi)
+{
+ struct gui_window *gw = cbi->context;
+ static fbtk_modifier_type modifier = FBTK_MOD_CLEAR;
+ int ucs4 = -1;
+
+ LOG("got value %d", cbi->event->value.keycode);
+
+ switch (cbi->event->type) {
+ case NSFB_EVENT_KEY_DOWN:
+ switch (cbi->event->value.keycode) {
+
+ case NSFB_KEY_DELETE:
+ browser_window_key_press(gw->bw, NS_KEY_DELETE_RIGHT);
+ break;
+
+ case NSFB_KEY_PAGEUP:
+ if (browser_window_key_press(gw->bw,
+ NS_KEY_PAGE_UP) == false)
+ widget_scroll_y(gw, -fbtk_get_height(
+ gw->browser), false);
+ break;
+
+ case NSFB_KEY_PAGEDOWN:
+ if (browser_window_key_press(gw->bw,
+ NS_KEY_PAGE_DOWN) == false)
+ widget_scroll_y(gw, fbtk_get_height(
+ gw->browser), false);
+ break;
+
+ case NSFB_KEY_RIGHT:
+ if (modifier & FBTK_MOD_RCTRL ||
+ modifier & FBTK_MOD_LCTRL) {
+ /* CTRL held */
+ if (browser_window_key_press(gw->bw,
+ NS_KEY_LINE_END) == false)
+ widget_scroll_x(gw, INT_MAX, true);
+
+ } else if (modifier & FBTK_MOD_RSHIFT ||
+ modifier & FBTK_MOD_LSHIFT) {
+ /* SHIFT held */
+ if (browser_window_key_press(gw->bw,
+ NS_KEY_WORD_RIGHT) == false)
+ widget_scroll_x(gw, fbtk_get_width(
+ gw->browser), false);
+
+ } else {
+ /* no modifier */
+ if (browser_window_key_press(gw->bw,
+ NS_KEY_RIGHT) == false)
+ widget_scroll_x(gw, 100, false);
+ }
+ break;
+
+ case NSFB_KEY_LEFT:
+ if (modifier & FBTK_MOD_RCTRL ||
+ modifier & FBTK_MOD_LCTRL) {
+ /* CTRL held */
+ if (browser_window_key_press(gw->bw,
+ NS_KEY_LINE_START) == false)
+ widget_scroll_x(gw, 0, true);
+
+ } else if (modifier & FBTK_MOD_RSHIFT ||
+ modifier & FBTK_MOD_LSHIFT) {
+ /* SHIFT held */
+ if (browser_window_key_press(gw->bw,
+ NS_KEY_WORD_LEFT) == false)
+ widget_scroll_x(gw, -fbtk_get_width(
+ gw->browser), false);
+
+ } else {
+ /* no modifier */
+ if (browser_window_key_press(gw->bw,
+ NS_KEY_LEFT) == false)
+ widget_scroll_x(gw, -100, false);
+ }
+ break;
+
+ case NSFB_KEY_UP:
+ if (browser_window_key_press(gw->bw,
+ NS_KEY_UP) == false)
+ widget_scroll_y(gw, -100, false);
+ break;
+
+ case NSFB_KEY_DOWN:
+ if (browser_window_key_press(gw->bw,
+ NS_KEY_DOWN) == false)
+ widget_scroll_y(gw, 100, false);
+ break;
+
+ case NSFB_KEY_RSHIFT:
+ modifier |= FBTK_MOD_RSHIFT;
+ break;
+
+ case NSFB_KEY_LSHIFT:
+ modifier |= FBTK_MOD_LSHIFT;
+ break;
+
+ case NSFB_KEY_RCTRL:
+ modifier |= FBTK_MOD_RCTRL;
+ break;
+
+ case NSFB_KEY_LCTRL:
+ modifier |= FBTK_MOD_LCTRL;
+ break;
+
+ case NSFB_KEY_y:
+ case NSFB_KEY_z:
+ if (cbi->event->value.keycode == NSFB_KEY_z &&
+ (modifier & FBTK_MOD_RCTRL ||
+ modifier & FBTK_MOD_LCTRL) &&
+ (modifier & FBTK_MOD_RSHIFT ||
+ modifier & FBTK_MOD_LSHIFT)) {
+ /* Z pressed with CTRL and SHIFT held */
+ browser_window_key_press(gw->bw, NS_KEY_REDO);
+ break;
+
+ } else if (cbi->event->value.keycode == NSFB_KEY_z &&
+ (modifier & FBTK_MOD_RCTRL ||
+ modifier & FBTK_MOD_LCTRL)) {
+ /* Z pressed with CTRL held */
+ browser_window_key_press(gw->bw, NS_KEY_UNDO);
+ break;
+
+ } else if (cbi->event->value.keycode == NSFB_KEY_y &&
+ (modifier & FBTK_MOD_RCTRL ||
+ modifier & FBTK_MOD_LCTRL)) {
+ /* Y pressed with CTRL held */
+ browser_window_key_press(gw->bw, NS_KEY_REDO);
+ break;
+ }
+ /* Z or Y pressed but not undo or redo;
+ * Fall through to default handling */
+
+ default:
+ ucs4 = fbtk_keycode_to_ucs4(cbi->event->value.keycode,
+ modifier);
+ if (ucs4 != -1)
+ browser_window_key_press(gw->bw, ucs4);
+ break;
+ }
+ break;
+
+ case NSFB_EVENT_KEY_UP:
+ switch (cbi->event->value.keycode) {
+ case NSFB_KEY_RSHIFT:
+ modifier &= ~FBTK_MOD_RSHIFT;
+ break;
+
+ case NSFB_KEY_LSHIFT:
+ modifier &= ~FBTK_MOD_LSHIFT;
+ break;
+
+ case NSFB_KEY_RCTRL:
+ modifier &= ~FBTK_MOD_RCTRL;
+ break;
+
+ case NSFB_KEY_LCTRL:
+ modifier &= ~FBTK_MOD_LCTRL;
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static void
+fb_update_back_forward(struct gui_window *gw)
+{
+ struct browser_window *bw = gw->bw;
+
+ fbtk_set_bitmap(gw->back,
+ (browser_window_back_available(bw)) ?
+ &left_arrow : &left_arrow_g);
+ fbtk_set_bitmap(gw->forward,
+ (browser_window_forward_available(bw)) ?
+ &right_arrow : &right_arrow_g);
+}
+
+/* left icon click routine */
+static int
+fb_leftarrow_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
+{
+ struct gui_window *gw = cbi->context;
+ struct browser_window *bw = gw->bw;
+
+ if (cbi->event->type != NSFB_EVENT_KEY_UP)
+ return 0;
+
+ if (browser_window_back_available(bw))
+ browser_window_history_back(bw, false);
+
+ fb_update_back_forward(gw);
+
+ return 1;
+}
+
+/* right arrow icon click routine */
+static int
+fb_rightarrow_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
+{
+ struct gui_window *gw = cbi->context;
+ struct browser_window *bw = gw->bw;
+
+ if (cbi->event->type != NSFB_EVENT_KEY_UP)
+ return 0;
+
+ if (browser_window_forward_available(bw))
+ browser_window_history_forward(bw, false);
+
+ fb_update_back_forward(gw);
+ return 1;
+
+}
+
+/* reload icon click routine */
+static int
+fb_reload_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
+{
+ struct browser_window *bw = cbi->context;
+
+ if (cbi->event->type != NSFB_EVENT_KEY_UP)
+ return 0;
+
+ browser_window_reload(bw, true);
+ return 1;
+}
+
+/* stop icon click routine */
+static int
+fb_stop_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
+{
+ struct browser_window *bw = cbi->context;
+
+ if (cbi->event->type != NSFB_EVENT_KEY_UP)
+ return 0;
+
+ browser_window_stop(bw);
+ return 0;
+}
+
+static int
+fb_osk_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
+{
+
+ if (cbi->event->type != NSFB_EVENT_KEY_UP)
+ return 0;
+
+ map_osk();
+
+ return 0;
+}
+
+/* close browser window icon click routine */
+static int
+fb_close_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
+{
+ if (cbi->event->type != NSFB_EVENT_KEY_UP)
+ return 0;
+
+ fb_complete = true;
+
+ return 0;
+}
+
+static int
+fb_scroll_callback(fbtk_widget_t *widget, fbtk_callback_info *cbi)
+{
+ struct gui_window *gw = cbi->context;
+
+ switch (cbi->type) {
+ case FBTK_CBT_SCROLLY:
+ widget_scroll_y(gw, cbi->y, true);
+ break;
+
+ case FBTK_CBT_SCROLLX:
+ widget_scroll_x(gw, cbi->x, true);
+ break;
+
+ default:
+ break;
+ }
+ return 0;
+}
+
+static int
+fb_url_enter(void *pw, char *text)
+{
+ struct browser_window *bw = pw;
+ nsurl *url;
+ nserror error;
+
+ error = nsurl_create(text, &url);
+ if (error != NSERROR_OK) {
+ fb_warn_user(messages_get_errorcode(error), 0);
+ } else {
+ browser_window_navigate(bw, url, NULL, BW_NAVIGATE_HISTORY,
+ NULL, NULL, NULL);
+ nsurl_unref(url);
+ }
+
+ return 0;
+}
+
+static int
+fb_url_move(fbtk_widget_t *widget, fbtk_callback_info *cbi)
+{
+ framebuffer_set_cursor(&caret_image);
+ return 0;
+}
+
+static int
+set_ptr_default_move(fbtk_widget_t *widget, fbtk_callback_info *cbi)
+{
+ framebuffer_set_cursor(&pointer_image);
+ return 0;
+}
+
+static int
+fb_localhistory_btn_clik(fbtk_widget_t *widget, fbtk_callback_info *cbi)
+{
+ struct gui_window *gw = cbi->context;
+
+ if (cbi->event->type != NSFB_EVENT_KEY_UP)
+ return 0;
+
+ fb_localhistory_map(gw->localhistory);
+
+ return 0;
+}
+
+
+/** Create a toolbar window and populate it with buttons.
+ *
+ * The toolbar layout uses a character to define buttons type and position:
+ * b - back
+ * l - local history
+ * f - forward
+ * s - stop
+ * r - refresh
+ * u - url bar expands to fit remaining space
+ * t - throbber/activity indicator
+ * c - close the current window
+ *
+ * The default layout is "blfsrut" there should be no more than a
+ * single url bar entry or behaviour will be undefined.
+ *
+ * @param gw Parent window
+ * @param toolbar_height The height in pixels of the toolbar
+ * @param padding The padding in pixels round each element of the toolbar
+ * @param frame_col Frame colour.
+ * @param toolbar_layout A string defining which buttons and controls
+ * should be added to the toolbar. May be empty
+ * string to disable the bar..
+ *
+ */
+static fbtk_widget_t *
+create_toolbar(struct gui_window *gw,
+ int toolbar_height,
+ int padding,
+ colour frame_col,
+ const char *toolbar_layout)
+{
+ fbtk_widget_t *toolbar;
+ fbtk_widget_t *widget;
+
+ int xpos; /* The position of the next widget. */
+ int xlhs = 0; /* extent of the left hand side widgets */
+ int xdir = 1; /* the direction of movement + or - 1 */
+ const char *itmtype; /* type of the next item */
+
+ if (toolbar_layout == NULL) {
+ toolbar_layout = NSFB_TOOLBAR_DEFAULT_LAYOUT;
+ }
+
+ LOG("Using toolbar layout %s", toolbar_layout);
+
+ itmtype = toolbar_layout;
+
+ /* check for the toolbar being disabled */
+ if ((*itmtype == 0) || (*itmtype == 'q')) {
+ return NULL;
+ }
+
+ toolbar = fbtk_create_window(gw->window, 0, 0, 0,
+ toolbar_height,
+ frame_col);
+
+ if (toolbar == NULL) {
+ return NULL;
+ }
+
+ fbtk_set_handler(toolbar,
+ FBTK_CBT_POINTERENTER,
+ set_ptr_default_move,
+ NULL);
+
+
+ xpos = padding;
+
+ /* loop proceeds creating widget on the left hand side until
+ * it runs out of layout or encounters a url bar declaration
+ * wherupon it works backwards from the end of the layout
+ * untill the space left is for the url bar
+ */
+ while ((itmtype >= toolbar_layout) &&
+ (*itmtype != 0) &&
+ (xdir !=0)) {
+
+ LOG("toolbar adding %c", *itmtype);
+
+
+ switch (*itmtype) {
+
+ case 'b': /* back */
+ widget = fbtk_create_button(toolbar,
+ (xdir == 1) ? xpos :
+ xpos - left_arrow.width,
+ padding,
+ left_arrow.width,
+ -padding,
+ frame_col,
+ &left_arrow,
+ fb_leftarrow_click,
+ gw);
+ gw->back = widget; /* keep reference */
+ break;
+
+ case 'l': /* local history */
+ widget = fbtk_create_button(toolbar,
+ (xdir == 1) ? xpos :
+ xpos - history_image.width,
+ padding,
+ history_image.width,
+ -padding,
+ frame_col,
+ &history_image,
+ fb_localhistory_btn_clik,
+ gw);
+ gw->history = widget;
+ break;
+
+ case 'f': /* forward */
+ widget = fbtk_create_button(toolbar,
+ (xdir == 1)?xpos :
+ xpos - right_arrow.width,
+ padding,
+ right_arrow.width,
+ -padding,
+ frame_col,
+ &right_arrow,
+ fb_rightarrow_click,
+ gw);
+ gw->forward = widget;
+ break;
+
+ case 'c': /* close the current window */
+ widget = fbtk_create_button(toolbar,
+ (xdir == 1)?xpos :
+ xpos - stop_image_g.width,
+ padding,
+ stop_image_g.width,
+ -padding,
+ frame_col,
+ &stop_image_g,
+ fb_close_click,
+ gw->bw);
+ gw->close = widget;
+ break;
+
+ case 's': /* stop */
+ widget = fbtk_create_button(toolbar,
+ (xdir == 1)?xpos :
+ xpos - stop_image.width,
+ padding,
+ stop_image.width,
+ -padding,
+ frame_col,
+ &stop_image,
+ fb_stop_click,
+ gw->bw);
+ gw->stop = widget;
+ break;
+
+ case 'r': /* reload */
+ widget = fbtk_create_button(toolbar,
+ (xdir == 1)?xpos :
+ xpos - reload.width,
+ padding,
+ reload.width,
+ -padding,
+ frame_col,
+ &reload,
+ fb_reload_click,
+ gw->bw);
+ gw->reload = widget;
+ break;
+
+ case 't': /* throbber/activity indicator */
+ widget = fbtk_create_bitmap(toolbar,
+ (xdir == 1)?xpos :
+ xpos - throbber0.width,
+ padding,
+ throbber0.width,
+ -padding,
+ frame_col,
+ &throbber0);
+ gw->throbber = widget;
+ break;
+
+
+ case 'u': /* url bar*/
+ if (xdir == -1) {
+ /* met the u going backwards add url
+ * now we know available extent
+ */
+
+ widget = fbtk_create_writable_text(toolbar,
+ xlhs,
+ padding,
+ xpos - xlhs,
+ -padding,
+ FB_COLOUR_WHITE,
+ FB_COLOUR_BLACK,
+ true,
+ fb_url_enter,
+ gw->bw);
+
+ fbtk_set_handler(widget,
+ FBTK_CBT_POINTERENTER,
+ fb_url_move, gw->bw);
+
+ gw->url = widget; /* keep reference */
+
+ /* toolbar is complete */
+ xdir = 0;
+ break;
+ }
+ /* met url going forwards, note position and
+ * reverse direction
+ */
+ itmtype = toolbar_layout + strlen(toolbar_layout);
+ xdir = -1;
+ xlhs = xpos;
+ xpos = (2 * fbtk_get_width(toolbar));
+ widget = toolbar;
+ break;
+
+ default:
+ widget = NULL;
+ xdir = 0;
+ LOG("Unknown element %c in toolbar layout", *itmtype);
+ break;
+
+ }
+
+ if (widget != NULL) {
+ xpos += (xdir * (fbtk_get_width(widget) + padding));
+ }
+
+ LOG("xpos is %d", xpos);
+
+ itmtype += xdir;
+ }
+
+ fbtk_set_mapping(toolbar, true);
+
+ return toolbar;
+}
+
+
+/** Resize a toolbar.
+ *
+ * @param gw Parent window
+ * @param toolbar_height The height in pixels of the toolbar
+ * @param padding The padding in pixels round each element of the toolbar
+ * @param toolbar_layout A string defining which buttons and controls
+ * should be added to the toolbar. May be empty
+ * string to disable the bar.
+ */
+static void
+resize_toolbar(struct gui_window *gw,
+ int toolbar_height,
+ int padding,
+ const char *toolbar_layout)
+{
+ fbtk_widget_t *widget;
+
+ int xpos; /* The position of the next widget. */
+ int xlhs = 0; /* extent of the left hand side widgets */
+ int xdir = 1; /* the direction of movement + or - 1 */
+ const char *itmtype; /* type of the next item */
+ int x = 0, y = 0, w = 0, h = 0;
+
+ if (gw->toolbar == NULL) {
+ return;
+ }
+
+ if (toolbar_layout == NULL) {
+ toolbar_layout = NSFB_TOOLBAR_DEFAULT_LAYOUT;
+ }
+
+ itmtype = toolbar_layout;
+
+ if (*itmtype == 0) {
+ return;
+ }
+
+ fbtk_set_pos_and_size(gw->toolbar, 0, 0, 0, toolbar_height);
+
+ xpos = padding;
+
+ /* loop proceeds creating widget on the left hand side until
+ * it runs out of layout or encounters a url bar declaration
+ * wherupon it works backwards from the end of the layout
+ * untill the space left is for the url bar
+ */
+ while (itmtype >= toolbar_layout && xdir != 0) {
+
+ switch (*itmtype) {
+ case 'b': /* back */
+ widget = gw->back;
+ x = (xdir == 1) ? xpos : xpos - left_arrow.width;
+ y = padding;
+ w = left_arrow.width;
+ h = -padding;
+ break;
+
+ case 'l': /* local history */
+ widget = gw->history;
+ x = (xdir == 1) ? xpos : xpos - history_image.width;
+ y = padding;
+ w = history_image.width;
+ h = -padding;
+ break;
+
+ case 'f': /* forward */
+ widget = gw->forward;
+ x = (xdir == 1) ? xpos : xpos - right_arrow.width;
+ y = padding;
+ w = right_arrow.width;
+ h = -padding;
+ break;
+
+ case 'c': /* close the current window */
+ widget = gw->close;
+ x = (xdir == 1) ? xpos : xpos - stop_image_g.width;
+ y = padding;
+ w = stop_image_g.width;
+ h = -padding;
+ break;
+
+ case 's': /* stop */
+ widget = gw->stop;
+ x = (xdir == 1) ? xpos : xpos - stop_image.width;
+ y = padding;
+ w = stop_image.width;
+ h = -padding;
+ break;
+
+ case 'r': /* reload */
+ widget = gw->reload;
+ x = (xdir == 1) ? xpos : xpos - reload.width;
+ y = padding;
+ w = reload.width;
+ h = -padding;
+ break;
+
+ case 't': /* throbber/activity indicator */
+ widget = gw->throbber;
+ x = (xdir == 1) ? xpos : xpos - throbber0.width;
+ y = padding;
+ w = throbber0.width;
+ h = -padding;
+ break;
+
+
+ case 'u': /* url bar*/
+ if (xdir == -1) {
+ /* met the u going backwards add url
+ * now we know available extent
+ */
+ widget = gw->url;
+ x = xlhs;
+ y = padding;
+ w = xpos - xlhs;
+ h = -padding;
+
+ /* toolbar is complete */
+ xdir = 0;
+ break;
+ }
+ /* met url going forwards, note position and
+ * reverse direction
+ */
+ itmtype = toolbar_layout + strlen(toolbar_layout);
+ xdir = -1;
+ xlhs = xpos;
+ w = fbtk_get_width(gw->toolbar);
+ xpos = 2 * w;
+ widget = gw->toolbar;
+ break;
+
+ default:
+ widget = NULL;
+ break;
+
+ }
+
+ if (widget != NULL) {
+ if (widget != gw->toolbar)
+ fbtk_set_pos_and_size(widget, x, y, w, h);
+ xpos += xdir * (w + padding);
+ }
+
+ itmtype += xdir;
+ }
+}
+
+/** Routine called when "stripped of focus" event occours for browser widget.
+ *
+ * @param widget The widget reciving "stripped of focus" event.
+ * @param cbi The callback parameters.
+ * @return The callback result.
+ */
+static int
+fb_browser_window_strip_focus(fbtk_widget_t *widget, fbtk_callback_info *cbi)
+{
+ fbtk_set_caret(widget, false, 0, 0, 0, NULL);
+
+ return 0;
+}
+
+static void
+create_browser_widget(struct gui_window *gw, int toolbar_height, int furniture_width)
+{
+ struct browser_widget_s *browser_widget;
+ browser_widget = calloc(1, sizeof(struct browser_widget_s));
+
+ gw->browser = fbtk_create_user(gw->window,
+ 0,
+ toolbar_height,
+ -furniture_width,
+ -furniture_width,
+ browser_widget);
+
+ fbtk_set_handler(gw->browser, FBTK_CBT_REDRAW, fb_browser_window_redraw, gw);
+ fbtk_set_handler(gw->browser, FBTK_CBT_DESTROY, fb_browser_window_destroy, gw);
+ fbtk_set_handler(gw->browser, FBTK_CBT_INPUT, fb_browser_window_input, gw);
+ fbtk_set_handler(gw->browser, FBTK_CBT_CLICK, fb_browser_window_click, gw);
+ fbtk_set_handler(gw->browser, FBTK_CBT_STRIP_FOCUS, fb_browser_window_strip_focus, gw);
+ fbtk_set_handler(gw->browser, FBTK_CBT_POINTERMOVE, fb_browser_window_move, gw);
+}
+
+static void
+resize_browser_widget(struct gui_window *gw, int x, int y,
+ int width, int height)
+{
+ fbtk_set_pos_and_size(gw->browser, x, y, width, height);
+ browser_window_reformat(gw->bw, false, width, height);
+}
+
+static void
+create_normal_browser_window(struct gui_window *gw, int furniture_width)
+{
+ fbtk_widget_t *widget;
+ fbtk_widget_t *toolbar;
+ int statusbar_width = 0;
+ int toolbar_height = nsoption_int(fb_toolbar_size);
+
+ LOG("Normal window");
+
+ gw->window = fbtk_create_window(fbtk, 0, 0, 0, 0, 0);
+
+ statusbar_width = nsoption_int(toolbar_status_size) *
+ fbtk_get_width(gw->window) / 10000;
+
+ /* toolbar */
+ toolbar = create_toolbar(gw,
+ toolbar_height,
+ 2,
+ FB_FRAME_COLOUR,
+ nsoption_charp(fb_toolbar_layout));
+ gw->toolbar = toolbar;
+
+ /* set the actually created toolbar height */
+ if (toolbar != NULL) {
+ toolbar_height = fbtk_get_height(toolbar);
+ } else {
+ toolbar_height = 0;
+ }
+
+ /* status bar */
+ gw->status = fbtk_create_text(gw->window,
+ 0,
+ fbtk_get_height(gw->window) - furniture_width,
+ statusbar_width, furniture_width,
+ FB_FRAME_COLOUR, FB_COLOUR_BLACK,
+ false);
+ fbtk_set_handler(gw->status, FBTK_CBT_POINTERENTER, set_ptr_default_move, NULL);
+
+ LOG("status bar %p at %d,%d", gw->status, fbtk_get_absx(gw->status), fbtk_get_absy(gw->status));
+
+ /* create horizontal scrollbar */
+ gw->hscroll = fbtk_create_hscroll(gw->window,
+ statusbar_width,
+ fbtk_get_height(gw->window) - furniture_width,
+ fbtk_get_width(gw->window) - statusbar_width - furniture_width,
+ furniture_width,
+ FB_SCROLL_COLOUR,
+ FB_FRAME_COLOUR,
+ fb_scroll_callback,
+ gw);
+
+ /* fill bottom right area */
+
+ if (nsoption_bool(fb_osk) == true) {
+ widget = fbtk_create_text_button(gw->window,
+ fbtk_get_width(gw->window) - furniture_width,
+ fbtk_get_height(gw->window) - furniture_width,
+ furniture_width,
+ furniture_width,
+ FB_FRAME_COLOUR, FB_COLOUR_BLACK,
+ fb_osk_click,
+ NULL);
+ widget = fbtk_create_button(gw->window,
+ fbtk_get_width(gw->window) - furniture_width,
+ fbtk_get_height(gw->window) - furniture_width,
+ furniture_width,
+ furniture_width,
+ FB_FRAME_COLOUR,
+ &osk_image,
+ fb_osk_click,
+ NULL);
+ } else {
+ widget = fbtk_create_fill(gw->window,
+ fbtk_get_width(gw->window) - furniture_width,
+ fbtk_get_height(gw->window) - furniture_width,
+ furniture_width,
+ furniture_width,
+ FB_FRAME_COLOUR);
+
+ fbtk_set_handler(widget, FBTK_CBT_POINTERENTER, set_ptr_default_move, NULL);
+ }
+
+ gw->bottom_right = widget;
+
+ /* create vertical scrollbar */
+ gw->vscroll = fbtk_create_vscroll(gw->window,
+ fbtk_get_width(gw->window) - furniture_width,
+ toolbar_height,
+ furniture_width,
+ fbtk_get_height(gw->window) - toolbar_height - furniture_width,
+ FB_SCROLL_COLOUR,
+ FB_FRAME_COLOUR,
+ fb_scroll_callback,
+ gw);
+
+ /* browser widget */
+ create_browser_widget(gw, toolbar_height, nsoption_int(fb_furniture_size));
+
+ /* Give browser_window's user widget input focus */
+ fbtk_set_focus(gw->browser);
+}
+
+static void
+resize_normal_browser_window(struct gui_window *gw, int furniture_width)
+{
+ bool resized;
+ int width, height;
+ int statusbar_width;
+ int toolbar_height = fbtk_get_height(gw->toolbar);
+
+ /* Resize the main window widget */
+ resized = fbtk_set_pos_and_size(gw->window, 0, 0, 0, 0);
+ if (!resized)
+ return;
+
+ width = fbtk_get_width(gw->window);
+ height = fbtk_get_height(gw->window);
+ statusbar_width = nsoption_int(toolbar_status_size) * width / 10000;
+
+ resize_toolbar(gw, toolbar_height, 2,
+ nsoption_charp(fb_toolbar_layout));
+ fbtk_set_pos_and_size(gw->status,
+ 0, height - furniture_width,
+ statusbar_width, furniture_width);
+ fbtk_reposition_hscroll(gw->hscroll,
+ statusbar_width, height - furniture_width,
+ width - statusbar_width - furniture_width,
+ furniture_width);
+ fbtk_set_pos_and_size(gw->bottom_right,
+ width - furniture_width, height - furniture_width,
+ furniture_width, furniture_width);
+ fbtk_reposition_vscroll(gw->vscroll,
+ width - furniture_width,
+ toolbar_height, furniture_width,
+ height - toolbar_height - furniture_width);
+ resize_browser_widget(gw,
+ 0, toolbar_height,
+ width - furniture_width,
+ height - furniture_width - toolbar_height);
+}
+
+static void gui_window_add_to_window_list(struct gui_window *gw)
+{
+ gw->next = NULL;
+ gw->prev = NULL;
+
+ if (window_list == NULL) {
+ window_list = gw;
+ } else {
+ window_list->prev = gw;
+ gw->next = window_list;
+ window_list = gw;
+ }
+}
+
+static void gui_window_remove_from_window_list(struct gui_window *gw)
+{
+ struct gui_window *list;
+
+ for (list = window_list; list != NULL; list = list->next) {
+ if (list != gw)
+ continue;
+
+ if (list == window_list) {
+ window_list = list->next;
+ if (window_list != NULL)
+ window_list->prev = NULL;
+ } else {
+ list->prev->next = list->next;
+ if (list->next != NULL) {
+ list->next->prev = list->prev;
+ }
+ }
+ break;
+ }
+}
+
+
+static struct gui_window *
+gui_window_create(struct browser_window *bw,
+ struct gui_window *existing,
+ gui_window_create_flags flags)
+{
+ struct gui_window *gw;
+
+ gw = calloc(1, sizeof(struct gui_window));
+
+ if (gw == NULL)
+ return NULL;
+
+ /* associate the gui window with the underlying browser window
+ */
+ gw->bw = bw;
+
+ create_normal_browser_window(gw, nsoption_int(fb_furniture_size));
+ gw->localhistory = fb_create_localhistory(bw, fbtk, nsoption_int(fb_furniture_size));
+
+ /* map and request redraw of gui window */
+ fbtk_set_mapping(gw->window, true);
+
+ /* Add it to the window list */
+ gui_window_add_to_window_list(gw);
+
+ return gw;
+}
+
+static void
+gui_window_destroy(struct gui_window *gw)
+{
+ gui_window_remove_from_window_list(gw);
+
+ fbtk_destroy_widget(gw->window);
+
+ free(gw);
+}
+
+static void
+gui_window_redraw_window(struct gui_window *g)
+{
+ fb_queue_redraw(g->browser, 0, 0, fbtk_get_width(g->browser), fbtk_get_height(g->browser) );
+}
+
+static void
+gui_window_update_box(struct gui_window *g, const struct rect *rect)
+{
+ struct browser_widget_s *bwidget = fbtk_get_userpw(g->browser);
+ fb_queue_redraw(g->browser,
+ rect->x0 - bwidget->scrollx,
+ rect->y0 - bwidget->scrolly,
+ rect->x1 - bwidget->scrollx,
+ rect->y1 - bwidget->scrolly);
+}
+
+static bool
+gui_window_get_scroll(struct gui_window *g, int *sx, int *sy)
+{
+ struct browser_widget_s *bwidget = fbtk_get_userpw(g->browser);
+ float scale = browser_window_get_scale(g->bw);
+
+ *sx = bwidget->scrollx / scale;
+ *sy = bwidget->scrolly / scale;
+
+ return true;
+}
+
+static void
+gui_window_set_scroll(struct gui_window *gw, int sx, int sy)
+{
+ struct browser_widget_s *bwidget = fbtk_get_userpw(gw->browser);
+ float scale = browser_window_get_scale(gw->bw);
+
+ assert(bwidget);
+
+ widget_scroll_x(gw, sx * scale, true);
+ widget_scroll_y(gw, sy * scale, true);
+}
+
+
+static void
+gui_window_get_dimensions(struct gui_window *g,
+ int *width,
+ int *height,
+ bool scaled)
+{
+ float scale = browser_window_get_scale(g->bw);
+
+ *width = fbtk_get_width(g->browser);
+ *height = fbtk_get_height(g->browser);
+
+ if (scaled) {
+ *width /= scale;
+ *height /= scale;
+ }
+}
+
+static void
+gui_window_update_extent(struct gui_window *gw)
+{
+ int w, h;
+ browser_window_get_extents(gw->bw, true, &w, &h);
+
+ fbtk_set_scroll_parameters(gw->hscroll, 0, w,
+ fbtk_get_width(gw->browser), 100);
+
+ fbtk_set_scroll_parameters(gw->vscroll, 0, h,
+ fbtk_get_height(gw->browser), 100);
+}
+
+static void
+gui_window_set_status(struct gui_window *g, const char *text)
+{
+ fbtk_set_text(g->status, text);
+}
+
+static void
+gui_window_set_pointer(struct gui_window *g, gui_pointer_shape shape)
+{
+ switch (shape) {
+ case GUI_POINTER_POINT:
+ framebuffer_set_cursor(&hand_image);
+ break;
+
+ case GUI_POINTER_CARET:
+ framebuffer_set_cursor(&caret_image);
+ break;
+
+ case GUI_POINTER_MENU:
+ framebuffer_set_cursor(&menu_image);
+ break;
+
+ case GUI_POINTER_PROGRESS:
+ framebuffer_set_cursor(&progress_image);
+ break;
+
+ case GUI_POINTER_MOVE:
+ framebuffer_set_cursor(&move_image);
+ break;
+
+ default:
+ framebuffer_set_cursor(&pointer_image);
+ break;
+ }
+}
+
+static nserror
+gui_window_set_url(struct gui_window *g, nsurl *url)
+{
+ fbtk_set_text(g->url, nsurl_access(url));
+ return NSERROR_OK;
+}
+
+static void
+throbber_advance(void *pw)
+{
+ struct gui_window *g = pw;
+ struct fbtk_bitmap *image;
+
+ switch (g->throbber_index) {
+ case 0:
+ image = &throbber1;
+ g->throbber_index = 1;
+ break;
+
+ case 1:
+ image = &throbber2;
+ g->throbber_index = 2;
+ break;
+
+ case 2:
+ image = &throbber3;
+ g->throbber_index = 3;
+ break;
+
+ case 3:
+ image = &throbber4;
+ g->throbber_index = 4;
+ break;
+
+ case 4:
+ image = &throbber5;
+ g->throbber_index = 5;
+ break;
+
+ case 5:
+ image = &throbber6;
+ g->throbber_index = 6;
+ break;
+
+ case 6:
+ image = &throbber7;
+ g->throbber_index = 7;
+ break;
+
+ case 7:
+ image = &throbber8;
+ g->throbber_index = 0;
+ break;
+
+ default:
+ return;
+ }
+
+ if (g->throbber_index >= 0) {
+ fbtk_set_bitmap(g->throbber, image);
+ framebuffer_schedule(100, throbber_advance, g);
+ }
+}
+
+static void
+gui_window_start_throbber(struct gui_window *g)
+{
+ g->throbber_index = 0;
+ framebuffer_schedule(100, throbber_advance, g);
+}
+
+static void
+gui_window_stop_throbber(struct gui_window *gw)
+{
+ gw->throbber_index = -1;
+ fbtk_set_bitmap(gw->throbber, &throbber0);
+
+ fb_update_back_forward(gw);
+
+}
+
+static void
+gui_window_remove_caret_cb(fbtk_widget_t *widget)
+{
+ struct browser_widget_s *bwidget = fbtk_get_userpw(widget);
+ int c_x, c_y, c_h;
+
+ if (fbtk_get_caret(widget, &c_x, &c_y, &c_h)) {
+ /* browser window already had caret:
+ * redraw its area to remove it first */
+ fb_queue_redraw(widget,
+ c_x - bwidget->scrollx,
+ c_y - bwidget->scrolly,
+ c_x + 1 - bwidget->scrollx,
+ c_y + c_h - bwidget->scrolly);
+ }
+}
+
+static void
+gui_window_place_caret(struct gui_window *g, int x, int y, int height,
+ const struct rect *clip)
+{
+ struct browser_widget_s *bwidget = fbtk_get_userpw(g->browser);
+
+ /* set new pos */
+ fbtk_set_caret(g->browser, true, x, y, height,
+ gui_window_remove_caret_cb);
+
+ /* redraw new caret pos */
+ fb_queue_redraw(g->browser,
+ x - bwidget->scrollx,
+ y - bwidget->scrolly,
+ x + 1 - bwidget->scrollx,
+ y + height - bwidget->scrolly);
+}
+
+static void
+gui_window_remove_caret(struct gui_window *g)
+{
+ int c_x, c_y, c_h;
+
+ if (fbtk_get_caret(g->browser, &c_x, &c_y, &c_h)) {
+ /* browser window owns the caret, so can remove it */
+ fbtk_set_caret(g->browser, false, 0, 0, 0, NULL);
+ }
+}
+
+static void framebuffer_window_reformat(struct gui_window *gw)
+{
+ /** @todo if we ever do zooming reformat should be implemented */
+ LOG("window:%p", gw);
+
+ /*
+ browser_window_reformat(gw->bw, false, width, height);
+ */
+}
+
+static struct gui_window_table framebuffer_window_table = {
+ .create = gui_window_create,
+ .destroy = gui_window_destroy,
+ .redraw = gui_window_redraw_window,
+ .update = gui_window_update_box,
+ .get_scroll = gui_window_get_scroll,
+ .set_scroll = gui_window_set_scroll,
+ .get_dimensions = gui_window_get_dimensions,
+ .update_extent = gui_window_update_extent,
+ .reformat = framebuffer_window_reformat,
+
+ .set_url = gui_window_set_url,
+ .set_status = gui_window_set_status,
+ .set_pointer = gui_window_set_pointer,
+ .place_caret = gui_window_place_caret,
+ .remove_caret = gui_window_remove_caret,
+ .start_throbber = gui_window_start_throbber,
+ .stop_throbber = gui_window_stop_throbber,
+};
+
+
+static struct gui_misc_table framebuffer_misc_table = {
+ .schedule = framebuffer_schedule,
+ .warning = fb_warn_user,
+
+ .quit = gui_quit,
+};
+
+/** Entry point from OS.
+ *
+ * /param argc The number of arguments in the string vector.
+ * /param argv The argument string vector.
+ * /return The return code to the OS
+ */
+int
+main(int argc, char** argv)
+{
+ struct browser_window *bw;
+ char *options;
+ char *messages;
+ nsurl *url;
+ nserror ret;
+ nsfb_t *nsfb;
+ struct netsurf_table framebuffer_table = {
+ .misc = &framebuffer_misc_table,
+ .window = &framebuffer_window_table,
+ .clipboard = framebuffer_clipboard_table,
+ .fetch = framebuffer_fetch_table,
+ .utf8 = framebuffer_utf8_table,
+ .bitmap = framebuffer_bitmap_table,
+ .layout = framebuffer_layout_table,
+ };
+
+ ret = netsurf_register(&framebuffer_table);
+ if (ret != NSERROR_OK) {
+ die("NetSurf operation table failed registration");
+ }
+
+ respaths = fb_init_resource(NETSURF_FB_RESPATH":"NETSURF_FB_FONTPATH);
+
+ /* initialise logging. Not fatal if it fails but not much we
+ * can do about it either.
+ */
+ nslog_init(nslog_stream_configure, &argc, argv);
+
+ /* user options setup */
+ ret = nsoption_init(set_defaults, &nsoptions, &nsoptions_default);
+ if (ret != NSERROR_OK) {
+ die("Options failed to initialise");
+ }
+ options = filepath_find(respaths, "Choices");
+ nsoption_read(options, nsoptions);
+ free(options);
+ nsoption_commandline(&argc, argv, nsoptions);
+
+ /* message init */
+ messages = filepath_find(respaths, "Messages");
+ ret = messages_add_from_file(messages);
+ free(messages);
+ if (ret != NSERROR_OK) {
+ fprintf(stderr, "Message translations failed to load\n");
+ }
+
+ /* common initialisation */
+ ret = netsurf_init(NULL);
+ if (ret != NSERROR_OK) {
+ die("NetSurf failed to initialise");
+ }
+
+ /* Override, since we have no support for non-core SELECT menu */
+ nsoption_set_bool(core_select_menu, true);
+
+ if (process_cmdline(argc,argv) != true)
+ die("unable to process command line.\n");
+
+ nsfb = framebuffer_initialise(fename, fewidth, feheight, febpp);
+ if (nsfb == NULL)
+ die("Unable to initialise framebuffer");
+
+ framebuffer_set_cursor(&pointer_image);
+
+ if (fb_font_init() == false)
+ die("Unable to initialise the font system");
+
+ fbtk = fbtk_init(nsfb);
+
+ fbtk_enable_oskb(fbtk);
+
+ urldb_load_cookies(nsoption_charp(cookie_file));
+
+ /* create an initial browser window */
+
+ LOG("calling browser_window_create");
+
+ ret = nsurl_create(feurl, &url);
+ if (ret == NSERROR_OK) {
+ ret = browser_window_create(BW_CREATE_HISTORY,
+ url,
+ NULL,
+ NULL,
+ &bw);
+ nsurl_unref(url);
+ }
+ if (ret != NSERROR_OK) {
+ fb_warn_user(messages_get_errorcode(ret), 0);
+ } else {
+ framebuffer_run();
+
+ browser_window_destroy(bw);
+ }
+
+ netsurf_exit();
+
+ if (fb_font_finalise() == false)
+ LOG("Font finalisation failed.");
+
+ /* finalise options */
+ nsoption_finalise(nsoptions, nsoptions_default);
+
+ return 0;
+}
+
+void gui_resize(fbtk_widget_t *root, int width, int height)
+{
+ struct gui_window *gw;
+ nsfb_t *nsfb = fbtk_get_nsfb(root);
+
+ /* Enforce a minimum */
+ if (width < 300)
+ width = 300;
+ if (height < 200)
+ height = 200;
+
+ if (framebuffer_resize(nsfb, width, height, febpp) == false) {
+ return;
+ }
+
+ fbtk_set_pos_and_size(root, 0, 0, width, height);
+
+ fewidth = width;
+ feheight = height;
+
+ for (gw = window_list; gw != NULL; gw = gw->next) {
+ resize_normal_browser_window(gw,
+ nsoption_int(fb_furniture_size));
+ }
+
+ fbtk_request_redraw(root);
+}
+
+
+/*
+ * Local Variables:
+ * c-basic-offset:8
+ * End:
+ */
diff --git a/frontends/kolibrios/fb/gui.h b/frontends/kolibrios/fb/gui.h
new file mode 100644
index 0000000..0de1add
--- a/dev/null
+++ b/frontends/kolibrios/fb/gui.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2008 Vincent Sanders <vince@simtec.co.uk>
+ *
+ * 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_FB_GUI_H
+#define NETSURF_FB_GUI_H
+
+
+struct fbtk_widget_s;
+
+typedef struct fb_cursor_s fb_cursor_t;
+
+/* bounding box */
+typedef struct nsfb_bbox_s bbox_t;
+
+struct gui_localhistory {
+ struct browser_window *bw;
+
+ struct fbtk_widget_s *window;
+ struct fbtk_widget_s *hscroll;
+ struct fbtk_widget_s *vscroll;
+ struct fbtk_widget_s *history;
+
+ int scrollx, scrolly; /**< scroll offsets. */
+};
+
+struct gui_window {
+ struct browser_window *bw;
+
+ struct fbtk_widget_s *window;
+ struct fbtk_widget_s *back;
+ struct fbtk_widget_s *forward;
+ struct fbtk_widget_s *history;
+ struct fbtk_widget_s *stop;
+ struct fbtk_widget_s *reload;
+ struct fbtk_widget_s *close;
+ struct fbtk_widget_s *url;
+ struct fbtk_widget_s *status;
+ struct fbtk_widget_s *throbber;
+ struct fbtk_widget_s *hscroll;
+ struct fbtk_widget_s *vscroll;
+ struct fbtk_widget_s *browser;
+ struct fbtk_widget_s *toolbar;
+ struct fbtk_widget_s *bottom_right;
+
+ int throbber_index;
+
+ struct gui_localhistory *localhistory;
+
+ struct gui_window *next;
+ struct gui_window *prev;
+};
+
+
+extern struct gui_window *window_list;
+
+struct gui_localhistory *fb_create_localhistory(struct browser_window *bw,
+ struct fbtk_widget_s *parent, int furniture_width);
+void fb_localhistory_map(struct gui_localhistory * glh);
+
+void gui_resize(struct fbtk_widget_s *root, int width, int height);
+
+
+#endif /* NETSURF_FB_GUI_H */
+
+/*
+ * Local Variables:
+ * c-basic-offset:8
+ * End:
+ */
diff --git a/frontends/kolibrios/fb/image_data.h b/frontends/kolibrios/fb/image_data.h
new file mode 100644
index 0000000..cf349f5
--- a/dev/null
+++ b/frontends/kolibrios/fb/image_data.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2008 Vincent Sanders <vince@simtec.co.uk>
+ *
+ * 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 FB_IMAGE_DATA
+#define FB_IMAGE_DATA
+
+#include "framebuffer/fbtk.h"
+
+extern struct fbtk_bitmap left_arrow;
+extern struct fbtk_bitmap right_arrow;
+extern struct fbtk_bitmap reload;
+extern struct fbtk_bitmap stop_image;
+extern struct fbtk_bitmap history_image;
+
+extern struct fbtk_bitmap left_arrow_g;
+extern struct fbtk_bitmap right_arrow_g;
+extern struct fbtk_bitmap reload_g;
+extern struct fbtk_bitmap stop_image_g;
+extern struct fbtk_bitmap history_image_g;
+
+extern struct fbtk_bitmap scrolll;
+extern struct fbtk_bitmap scrollr;
+extern struct fbtk_bitmap scrollu;
+extern struct fbtk_bitmap scrolld;
+
+extern struct fbtk_bitmap osk_image;
+
+extern struct fbtk_bitmap pointer_image;
+extern struct fbtk_bitmap hand_image;
+extern struct fbtk_bitmap caret_image;
+extern struct fbtk_bitmap menu_image;
+extern struct fbtk_bitmap move_image;
+extern struct fbtk_bitmap progress_image;
+
+extern struct fbtk_bitmap throbber0;
+extern struct fbtk_bitmap throbber1;
+extern struct fbtk_bitmap throbber2;
+extern struct fbtk_bitmap throbber3;
+extern struct fbtk_bitmap throbber4;
+extern struct fbtk_bitmap throbber5;
+extern struct fbtk_bitmap throbber6;
+extern struct fbtk_bitmap throbber7;
+extern struct fbtk_bitmap throbber8;
+
+#endif /* FB_IMAGE_DATA */
diff --git a/frontends/kolibrios/fb/localhistory.c b/frontends/kolibrios/fb/localhistory.c
new file mode 100644
index 0000000..3192f07
--- a/dev/null
+++ b/frontends/kolibrios/fb/localhistory.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2010 Vincent Sanders <vince@simtec.co.uk>
+ *
+ * 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 <stdbool.h>
+#include <stdlib.h>
+#include <limits.h>
+
+#include <libnsfb.h>
+#include <libnsfb_plot.h>
+#include <libnsfb_event.h>
+
+#include "desktop/browser_history.h"
+#include "netsurf/plotters.h"
+
+#include "framebuffer/gui.h"
+#include "framebuffer/fbtk.h"
+#include "framebuffer/framebuffer.h"
+
+static int
+localhistory_redraw(fbtk_widget_t *widget, fbtk_callback_info *cbi)
+{
+ struct gui_localhistory *glh = cbi->context;
+ nsfb_bbox_t rbox;
+
+ struct redraw_context ctx = {
+ .interactive = true,
+ .background_images = true,
+ .plot = &fb_plotters
+ };
+
+ rbox.x0 = fbtk_get_absx(widget);
+ rbox.y0 = fbtk_get_absy(widget);
+
+ rbox.x1 = rbox.x0 + fbtk_get_width(widget);
+ rbox.y1 = rbox.y0 + fbtk_get_height(widget);
+
+ nsfb_claim(fbtk_get_nsfb(widget), &rbox);
+
+ nsfb_plot_rectangle_fill(fbtk_get_nsfb(widget), &rbox, 0xffffffff);
+
+ browser_window_history_redraw_rectangle(glh->bw,
+ glh->scrollx,
+ glh->scrolly,
+ fbtk_get_width(widget) + glh->scrollx,
+ fbtk_get_height(widget) + glh->scrolly,
+ 0, 0, &ctx);
+
+ nsfb_update(fbtk_get_nsfb(widget), &rbox);
+
+ return 0;
+}
+
+static int
+localhistory_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
+{
+ struct gui_localhistory *glh = cbi->context;
+
+ if (cbi->event->type != NSFB_EVENT_KEY_UP)
+ return 0;
+
+ browser_window_history_click(glh->bw, cbi->x, cbi->y, false);
+
+ fbtk_set_mapping(glh->window, false);
+
+ return 1;
+}
+
+struct gui_localhistory *
+fb_create_localhistory(struct browser_window *bw,
+ fbtk_widget_t *parent,
+ int furniture_width)
+{
+ struct gui_localhistory *glh;
+ glh = calloc(1, sizeof(struct gui_localhistory));
+
+ if (glh == NULL)
+ return NULL;
+
+ glh->bw = bw;
+
+ /* container window */
+ glh->window = fbtk_create_window(parent, 0, 0, 0, 0, 0);
+
+ glh->history = fbtk_create_user(glh->window, 0, 0, -furniture_width, -furniture_width, glh);
+
+ fbtk_set_handler(glh->history, FBTK_CBT_REDRAW, localhistory_redraw, glh);
+ fbtk_set_handler(glh->history, FBTK_CBT_CLICK, localhistory_click, glh);
+ /*
+ fbtk_set_handler(gw->localhistory, FBTK_CBT_INPUT, fb_browser_window_input, gw);
+ fbtk_set_handler(gw->localhistory, FBTK_CBT_POINTERMOVE, fb_browser_window_move, bw);
+ */
+
+ /* create horizontal scrollbar */
+ glh->hscroll = fbtk_create_hscroll(glh->window,
+ 0,
+ fbtk_get_height(glh->window) - furniture_width,
+ fbtk_get_width(glh->window) - furniture_width,
+ furniture_width,
+ FB_SCROLL_COLOUR,
+ FB_FRAME_COLOUR,
+ NULL,
+ NULL);
+
+ glh->vscroll = fbtk_create_vscroll(glh->window,
+ fbtk_get_width(glh->window) - furniture_width,
+ 0,
+ furniture_width,
+ fbtk_get_height(glh->window) - furniture_width,
+ FB_SCROLL_COLOUR,
+ FB_FRAME_COLOUR,
+ NULL,
+ NULL);
+
+ fbtk_create_fill(glh->window,
+ fbtk_get_width(glh->window) - furniture_width,
+ fbtk_get_height(glh->window) - furniture_width,
+ furniture_width,
+ furniture_width,
+ FB_FRAME_COLOUR);
+
+ return glh;
+}
+
+void
+fb_localhistory_map(struct gui_localhistory * glh)
+{
+ fbtk_set_zorder(glh->window, INT_MIN);
+ fbtk_set_mapping(glh->window, true);
+}
diff --git a/frontends/kolibrios/fb/options.h b/frontends/kolibrios/fb/options.h
new file mode 100644
index 0000000..eee6f4b
--- a/dev/null
+++ b/frontends/kolibrios/fb/options.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2012 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _NETSURF_FRAMEBUFFER_OPTIONS_H_
+#define _NETSURF_FRAMEBUFFER_OPTIONS_H_
+
+/* currently nothing here */
+
+#endif
+
+/***** surface options *****/
+
+NSOPTION_INTEGER(fb_depth, 32)
+NSOPTION_INTEGER(fb_refresh, 70)
+NSOPTION_STRING(fb_device, NULL)
+NSOPTION_STRING(fb_input_devpath, NULL)
+NSOPTION_STRING(fb_input_glob, NULL)
+
+/***** toolkit options *****/
+
+/** toolkit furniture size */
+NSOPTION_INTEGER(fb_furniture_size, 18)
+/** toolbar furniture size */
+NSOPTION_INTEGER(fb_toolbar_size, 30)
+/** toolbar layout */
+NSOPTION_STRING(fb_toolbar_layout, NULL)
+/** enable on screen keyboard */
+NSOPTION_BOOL(fb_osk, false)
+
+/***** font options *****/
+
+/** render all fonts monochrome */
+NSOPTION_BOOL(fb_font_monochrome, false)
+/** size of font glyph cache in kilobytes. */
+NSOPTION_INTEGER(fb_font_cachesize, 2048)
+
+/* Font face paths. These are treated as absolute paths if they start
+ * with a / otherwise the compile time resource path is searched.
+ */
+NSOPTION_STRING(fb_face_sans_serif, NULL)
+NSOPTION_STRING(fb_face_sans_serif_bold, NULL)
+NSOPTION_STRING(fb_face_sans_serif_italic, NULL)
+NSOPTION_STRING(fb_face_sans_serif_italic_bold, NULL)
+NSOPTION_STRING(fb_face_serif, NULL)
+NSOPTION_STRING(fb_face_serif_bold, NULL)
+NSOPTION_STRING(fb_face_monospace, NULL)
+NSOPTION_STRING(fb_face_monospace_bold, NULL)
+NSOPTION_STRING(fb_face_cursive, NULL)
+NSOPTION_STRING(fb_face_fantasy, NULL)
+
+/*
+ * Local Variables:
+ * c-basic-offset:8
+ * End:
+ */
diff --git a/frontends/kolibrios/fb/schedule.c b/frontends/kolibrios/fb/schedule.c
new file mode 100644
index 0000000..3a3bda6
--- a/dev/null
+++ b/frontends/kolibrios/fb/schedule.c
@@ -0,0 +1,254 @@
+/*
+ * Copyright 2008 Vincent Sanders <vince@simtec.co.uk>
+ *
+ * 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 _TARGET_IS_KOLIBRIOS
+#define _TARGET_IS_KOLIBRIOS
+#endif
+
+#ifdef _TARGET_IS_KOLIBRIOS
+
+
+#define timerclear(tvp) ((tvp)->tv_sec = (tvp)->tv_usec = 0)
+#define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec)
+#define timercmp(tvp, uvp, cmp) \
+ (((tvp)->tv_sec == (uvp)->tv_sec) ? \
+ ((tvp)->tv_usec cmp (uvp)->tv_usec) : \
+ ((tvp)->tv_sec cmp (uvp)->tv_sec))
+#define timeradd(tvp, uvp, vvp) \
+ do { \
+ (vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec; \
+ (vvp)->tv_usec = (tvp)->tv_usec + (uvp)->tv_usec; \
+ if ((vvp)->tv_usec >= 1000000) { \
+ (vvp)->tv_sec++; \
+ (vvp)->tv_usec -= 1000000; \
+ } \
+ } while (0)
+#define timersub(tvp, uvp, vvp) \
+ do { \
+ (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \
+ (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \
+ if ((vvp)->tv_usec < 0) { \
+ (vvp)->tv_sec--; \
+ (vvp)->tv_usec += 1000000; \
+ } \
+ } while (0)
+
+#endif
+
+#include <time.h>
+#include <stdlib.h>
+
+#include "utils/sys_time.h"
+#include "utils/log.h"
+
+#include "framebuffer/schedule.h"
+
+#ifdef DEBUG_SCHEDULER
+#define SRLOG(x...) LOG(x)
+#else
+#define SRLOG(x...) ((void) 0)
+#endif
+
+/* 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;
+};
+
+/**
+ * Unschedule a callback.
+ *
+ * \param callback callback function
+ * \param p user parameter, passed to callback function
+ *
+ * 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;
+
+ /* check there is something on the list to remove */
+ if (schedule_list == NULL) {
+ return NSERROR_OK;
+ }
+
+ SRLOG("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 */
+
+ SRLOG("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);
+ } else {
+ /* move to next element */
+ prev_nscb = cur_nscb;
+ cur_nscb = prev_nscb->next;
+ }
+ }
+
+ return NSERROR_OK;
+}
+
+/* exported function documented in framebuffer/schedule.h */
+nserror framebuffer_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) || (ret != NSERROR_OK)) {
+ return ret;
+ }
+
+ SRLOG("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 = 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;
+}
+
+/* exported function documented in framebuffer/schedule.h */
+int 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);
+
+ SRLOG("returning time to next event as %ldms",(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);
+}
+
+void list_schedule(void)
+{
+ struct timeval tv;
+ struct nscallback *cur_nscb;
+
+ gettimeofday(&tv, NULL);
+
+ LOG("schedule list at %ld:%ld", tv.tv_sec, tv.tv_usec);
+
+ cur_nscb = schedule_list;
+
+ while (cur_nscb != NULL) {
+ LOG("Schedule %p at %ld:%ld", cur_nscb, cur_nscb->tv.tv_sec, cur_nscb->tv.tv_usec);
+ cur_nscb = cur_nscb->next;
+ }
+}
+
+
+/*
+ * Local Variables:
+ * c-basic-offset:8
+ * End:
+ */
diff --git a/frontends/kolibrios/fb/schedule.h b/frontends/kolibrios/fb/schedule.h
new file mode 100644
index 0000000..4e94da6
--- a/dev/null
+++ b/frontends/kolibrios/fb/schedule.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2008 Vincent Sanders <vince@simtec.co.uk>
+ *
+ * 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 FRAMEBUFFER_SCHEDULE_H
+#define FRAMEBUFFER_SCHEDULE_H
+
+/**
+ * Schedule a callback.
+ *
+ * \param tival interval before the callback should be made in ms
+ * \param callback callback function
+ * \param p user parameter, passed to callback function
+ *
+ * The callback function will be called as soon as possible after t ms have
+ * passed.
+ */
+
+nserror framebuffer_schedule(int tival, void (*callback)(void *p), void *p);
+
+/**
+ * Process scheduled callbacks up to current time.
+ *
+ * @return The number of milliseconds untill the next scheduled event
+ * or -1 for no event.
+ */
+int schedule_run(void);
+
+void list_schedule(void);
+
+#endif
diff --git a/frontends/kolibrios/gui_fetch_table.h b/frontends/kolibrios/gui_fetch_table.h
new file mode 100644
index 0000000..a578115
--- a/dev/null
+++ b/frontends/kolibrios/gui_fetch_table.h
@@ -0,0 +1,42 @@
+/* ------------------------------ */
+/* Part about GUI FETCHER table. Will contain all functions required as well. */
+/* ------------------------------ */
+
+const char *kolibri_get_mimetype_file(const char *unix_path)
+{
+
+}
+
+
+struct nsurl* kolibri_get_resource_url(const char *path)
+{
+
+}
+
+ /* Can be used to always load some .html file probably */
+
+nserror kolibri_get_resource_data(const char *path, const uint8_t **data, size_t *data_len)
+{
+
+}
+
+
+nserror kolibri_release_resource_data(const uint8_t *data)
+{
+
+}
+
+ /*get_ and release_ functions work in unison one after another*/
+
+char *kolibri_find_mimetype_file(const char *ro_path)
+{
+
+}
+
+struct gui_fetch_table kolibri_fetch_table = {
+ .filetype = kolibri_get_mimetype_file,
+ .get_resource_url = kolibri_get_resource_url,
+ .get_resource_data = kolibri_get_resource_data,
+ .release_resource_data = kolibri_release_resource_data,
+ .mimetype = kolibri_find_mimetype_file
+};
diff --git a/frontends/kolibrios/gui_file_table.h b/frontends/kolibrios/gui_file_table.h
new file mode 100644
index 0000000..2c0795f
--- a/dev/null
+++ b/frontends/kolibrios/gui_file_table.h
@@ -0,0 +1,37 @@
+/* ------------------------------ */
+/* Part about GUI FILE TABLE. Will contain all functions required as well. */
+/* ------------------------------ */
+nserror kolibri_mkpath(char **str, size_t *size, size_t nemb, va_list ap)
+{
+
+}
+
+nserror kolibri_basename(const char *path, char **str, size_t *size)
+{
+
+}
+
+nserror kolibri_nsurl_to_path(struct nsurl *url, char **path)
+{
+
+}
+
+nserror kolibri_path_to_nsurl(const char *path, struct nsurl **url)
+{
+
+}
+
+nserror kolibri_mkdir_all(const char *fname)
+{
+
+}
+
+
+struct gui_file_table kolibri_gui_file_table = {
+ /* Mandantory entries */
+ .mkpath = kolibri_mkpath,
+ .basename = kolibri_basename,
+ .nsurl_to_path = kolibri_nsurl_to_path,
+ .path_to_nsurl = kolibri_path_to_nsurl,
+ .mkdir_all = kolibri_mkdir_all
+};
diff --git a/frontends/kolibrios/gui_llcache_table.h b/frontends/kolibrios/gui_llcache_table.h
new file mode 100644
index 0000000..c7995e5
--- a/dev/null
+++ b/frontends/kolibrios/gui_llcache_table.h
@@ -0,0 +1,49 @@
+/* ------------------------------ */
+/* Part about GUI LLCACHE TABLE. Will contain all functions required as well. */
+/* ------------------------------ */
+nserror kolibri_initialise(const struct llcache_store_parameters *parameters)
+{
+
+}
+
+
+nserror kolibri_finalise(void)
+{
+
+}
+
+
+nserror kolibri_store(struct nsurl *url, enum backing_store_flags flags,
+ uint8_t *data, const size_t datalen)
+{
+
+}
+
+
+nserror kolibri_fetch(struct nsurl *url, enum backing_store_flags flags,
+ uint8_t **data, size_t *datalen)
+{
+
+}
+
+
+nserror kolibri_release(struct nsurl *url, enum backing_store_flags flags)
+{
+
+}
+
+
+nserror kolibri_invalidate(struct nsurl *url)
+{
+
+}
+
+
+struct gui_llcache_table kolibri_gui_llcache_table = {
+ .initialise = kolibri_initialise,
+ .finalise = kolibri_finalise,
+ .store = kolibri_store,
+ .fetch = kolibri_fetch,
+ .release = kolibri_release,
+ .invalidate = kolibri_invalidate
+};
diff --git a/frontends/kolibrios/gui_search_table.h b/frontends/kolibrios/gui_search_table.h
new file mode 100644
index 0000000..2cb361a
--- a/dev/null
+++ b/frontends/kolibrios/gui_search_table.h
@@ -0,0 +1,38 @@
+/* ------------------------------ */
+/* Part about GUI SEARCH TABLE. Will contain all functions required as well. */
+/* ------------------------------ */
+
+void kolibri_status(bool found, void *p)
+{
+
+}
+
+void kolibri_hourglass(bool active, void *p)
+{
+
+}
+
+void kolibri_add_recent(const char *string, void *p)
+{
+
+}
+
+void kolibri_forward_state(bool active, void *p)
+{
+
+}
+
+void kolibri_back_state(bool active, void *p)
+{
+
+}
+
+
+
+struct gui_search_table kolibri_gui_search_table = {
+ .status = kolibri_status,
+ .hourglass = kolibri_hourglass,
+ .add_recent = kolibri_add_recent,
+ .forward_state = kolibri_forward_state,
+ .back_state = kolibri_back_state
+};
diff --git a/frontends/kolibrios/gui_search_web_table.h b/frontends/kolibrios/gui_search_web_table.h
new file mode 100644
index 0000000..1ef3206
--- a/dev/null
+++ b/frontends/kolibrios/gui_search_web_table.h
@@ -0,0 +1,11 @@
+/* ------------------------------ */
+/* Part about GUI SEARCH WEB TABLE. Will contain all functions required as well. */
+/* ------------------------------ */
+nserror kolibri_search_provider_update(const char *provider_name, struct bitmap *ico_bitmap)
+{
+
+}
+
+struct gui_search_web_table kolibri_search_web_table = {
+ .provider_update = kolibri_search_provider_update
+};
diff --git a/frontends/kolibrios/gui_utf8_table.h b/frontends/kolibrios/gui_utf8_table.h
new file mode 100644
index 0000000..42a0c2b
--- a/dev/null
+++ b/frontends/kolibrios/gui_utf8_table.h
@@ -0,0 +1,18 @@
+/* ------------------------------ */
+/* Part about GUI UTF8 TABLE. Will contain all functions required as well. */
+/* ------------------------------ */
+
+nserror kolibri_utf8_to_local(const char *string, size_t len, char **result)
+{
+
+}
+
+nserror kolibri_local_to_utf8(const char *string, size_t len, char **result)
+{
+
+}
+
+struct gui_utf8_table kolibri_gui_utf8_table = {
+ .utf8_to_local = kolibri_utf8_to_local,
+ .local_to_utf8 = kolibri_local_to_utf8
+};
diff --git a/frontends/kolibrios/kolibri_boxlib.h b/frontends/kolibrios/kolibri_boxlib.h
new file mode 100644
index 0000000..b820788
--- a/dev/null
+++ b/frontends/kolibrios/kolibri_boxlib.h
@@ -0,0 +1,18 @@
+#ifndef KOLIBRI_BOXLIB_H
+#define KOLIBRI_BOXLIB_H
+
+extern int init_boxlib_asm(void);
+
+int kolibri_boxlib_init(void)
+{
+ int asm_init_status = init_boxlib_asm();
+
+ /* just return asm_init_status? or return init_boxlib_asm() ?*/
+
+ if(asm_init_status == 0)
+ return 0;
+ else
+ return 1;
+}
+
+#endif /* KOLIBRI_BOXLIB_H */
diff --git a/frontends/kolibrios/kolibri_button.h b/frontends/kolibrios/kolibri_button.h
new file mode 100644
index 0000000..fa5a868
--- a/dev/null
+++ b/frontends/kolibrios/kolibri_button.h
@@ -0,0 +1,46 @@
+#ifndef KOLIBRI_BUTTON_H
+#define KOLIBRI_BUTTON_H
+
+struct kolibri_button {
+ unsigned int x65536sizex;
+ unsigned int y65536sizey;
+ unsigned int color;
+ unsigned int identifier;
+ unsigned int XY;
+};
+
+struct kolibri_button *kolibri_new_button(unsigned int tlx, unsigned int tly, unsigned int sizex, unsigned int sizey,
+ unsigned int identifier, unsigned int color)
+{
+ struct kolibri_button* new_button = (struct kolibri_button *)malloc(sizeof(struct kolibri_button));
+ new_button -> x65536sizex = (tlx << 16) + sizex;
+ new_button -> y65536sizey = (tly << 16) + sizey;
+ new_button -> color = color;
+ new_button -> identifier = identifier;
+ new_button -> XY = 0;
+}
+
+void draw_button(struct kolibri_button *some_button)
+{
+ define_button(some_button -> x65536sizex, some_button -> y65536sizey, some_button -> identifier, some_button -> color);
+}
+
+unsigned int kolibri_button_get_identifier(void)
+{
+ unsigned int identifier;
+
+ __asm__ __volatile__(
+ "int $0x40"
+ :"=a"(identifier)
+ :"a"(17)
+ );
+ /* If no button pressed, returns 1 */
+ /* Otherwise, returns identifier of button */
+
+ if(identifier != 1) /* Button was detected indeed */
+ return identifier>>8;
+ else
+ return identifier; /* No button detected */
+}
+
+#endif /* KOLIBRI_BUTTON_H */
diff --git a/frontends/kolibrios/kolibri_checkbox.h b/frontends/kolibrios/kolibri_checkbox.h
new file mode 100644
index 0000000..cc02481
--- a/dev/null
+++ b/frontends/kolibrios/kolibri_checkbox.h
@@ -0,0 +1,43 @@
+#ifndef KOLIBRI_CHECKBOX_H
+#define KOLIBRI_CHECKBOX_H
+
+#include "kolibri_colors.h"
+
+enum CHECKBOX_FLAGS {
+ CHECKBOX_IS_SET = 0x00000002
+ /* Add more flags later */
+};
+
+struct check_box {
+ unsigned int left_s;
+ unsigned int top_s;
+ unsigned int ch_text_margin;
+ unsigned int color;
+ unsigned int border_color;
+ unsigned int text_color;
+ char *text;
+ unsigned int flags;
+
+ /* Users can use members above this */
+ unsigned int size_of_str;
+};
+
+struct check_box* kolibri_new_check_box(unsigned int tlx, unsigned int tly, unsigned int sizex, unsigned int sizey, char *label_text)
+{
+ struct check_box* new_checkbox = (struct check_box *)malloc(sizeof(struct check_box));
+ new_checkbox -> left_s = (tlx << 16) + sizex;
+ new_checkbox -> top_s = (tly << 16) + sizey;
+ new_checkbox -> ch_text_margin = 10;
+ new_checkbox -> color = 0xFFFFFFFF;
+ new_checkbox -> border_color = kolibri_color_table.color_work_graph;
+ new_checkbox -> text_color = kolibri_color_table.color_work_text;
+ new_checkbox -> text = label_text;
+ new_checkbox -> flags = 0x00000008;
+
+ return new_checkbox;
+}
+
+extern void (*check_box_draw2)(struct check_box *) __attribute__((__stdcall__));
+extern void (*check_box_mouse2)(struct check_box *)__attribute__((__stdcall__));
+
+#endif /* KOLIBRI_CHECKBOX_H */
diff --git a/frontends/kolibrios/kolibri_colors.h b/frontends/kolibrios/kolibri_colors.h
new file mode 100644
index 0000000..7a16a40
--- a/dev/null
+++ b/frontends/kolibrios/kolibri_colors.h
@@ -0,0 +1,28 @@
+#ifndef KOLIBRI_COLORS_H
+#define KOLIBRI_COLORS_H
+struct kolibri_system_colors {
+ unsigned int color_frame_area;
+ unsigned int color_grab_bar;
+ unsigned int color_grab_bar_button;
+ unsigned int color_grab_button_text;
+ unsigned int color_grab_text;
+ unsigned int color_work_area;
+ unsigned int color_work_button;
+ unsigned int color_work_button_text;
+ unsigned int color_work_text;
+ unsigned int color_work_graph;
+};
+
+struct kolibri_system_colors kolibri_color_table;
+
+void kolibri_get_system_colors(struct kolibri_system_colors *color_table)
+{
+ __asm__ volatile ("int $0x40"
+ :
+ :"a"(48),"b"(3),"c"(color_table),"d"(40)
+ );
+
+ /* color_table should point to the system color table */
+}
+
+#endif /* KOLIBRI_COLORS_H */
diff --git a/frontends/kolibrios/kolibri_debug.c b/frontends/kolibrios/kolibri_debug.c
new file mode 100644
index 0000000..5e97d40
--- a/dev/null
+++ b/frontends/kolibrios/kolibri_debug.c
@@ -0,0 +1,28 @@
+#include "kolibrios/kolibri_debug.h"
+#include <stdarg.h>
+
+/* Write a printf() like function (variable argument list) for
+ writing to debug board TODO*/
+
+void debug_board_write_byte(const char ch){
+ __asm__ __volatile__(
+ "int $0x40"
+ :
+ :"a"(63), "b"(1), "c"(ch));
+}
+
+void debug_board_write_str(const char* str){
+ while(*str)
+ debug_board_write_byte(*str++);
+}
+
+void debug_board_printf(const char *format,...)
+{
+ va_list ap;
+ char log_board[300];
+
+ va_start (ap, format);
+ vsprintf(log_board, format, ap);
+ va_end(ap);
+ debug_board_write_str(log_board);
+}
diff --git a/frontends/kolibrios/kolibri_debug.h b/frontends/kolibrios/kolibri_debug.h
new file mode 100644
index 0000000..a6dc61e
--- a/dev/null
+++ b/frontends/kolibrios/kolibri_debug.h
@@ -0,0 +1,11 @@
+#ifndef KOLIBRI_DEBUG_H
+#define KOLIBRI_DEBUG_H
+
+/* Write a printf() like function (variable argument list) for
+ writing to debug board */
+
+void debug_board_write_byte(const char ch);
+void debug_board_write_str(const char* str);
+void debug_board_printf(const char *format, ...);
+
+#endif /* KOLIBRI_DEBUG_H */
diff --git a/frontends/kolibrios/kolibri_debug.o b/frontends/kolibrios/kolibri_debug.o
new file mode 100644
index 0000000..567b97c
--- a/dev/null
+++ b/frontends/kolibrios/kolibri_debug.o
Binary files differ
diff --git a/frontends/kolibrios/kolibri_editbox.h b/frontends/kolibrios/kolibri_editbox.h
new file mode 100644
index 0000000..a281ad7
--- a/dev/null
+++ b/frontends/kolibrios/kolibri_editbox.h
@@ -0,0 +1,90 @@
+#ifndef KOLIBRI_EDITBOX_H
+#define KOLIBRI_EDITBOX_H
+
+#include "kolibri_colors.h"
+
+struct edit_box {
+ unsigned int width;
+ unsigned int left;
+ unsigned int top;
+ unsigned int color;
+ unsigned int shift_color;
+ unsigned int focus_border_color;
+ unsigned int blur_border_color;
+ unsigned int text_color;
+ unsigned int max;
+ char *text;
+ unsigned int mouse_variable;
+ unsigned int flags;
+
+/* The following struct members are not used by the users of API */
+ unsigned int size;
+ unsigned int pos;
+ unsigned int offset;
+ unsigned int cl_curs_x;
+ unsigned int cl_curs_y;
+ unsigned int shift;
+ unsigned int shift_old;
+};
+
+/* Initializes an Editbox with sane settings, sufficient for most use.
+ This will let you create a box and position it somewhere on the screen.
+ The text_buffer is a pointer to a character array and needs to be as long as
+ AT LEAST MAX_CHARS + 1.If the text_buffer is smaller, it will crash if user
+ types more characters than what will fit into the text buffer.
+
+ Allocating buffer space automatically so that programmer can be carefree now.
+ This also automatically adjusts the size of edit box so that it can hold enough characters.
+
+ All you need is :
+
+ tlx,tly = Coordinates of the beginning of the edit box.
+ max_chars = Limit of number of characters user can enter into edit box.
+*/
+
+struct edit_box* kolibri_new_edit_box(unsigned int tlx, unsigned int tly, unsigned int max_chars)
+{
+ unsigned int PIXELS_PER_CHAR = 7;
+ struct edit_box *new_textbox = (struct edit_box *)malloc(sizeof(struct edit_box));
+ char *text_buffer = (char *)calloc(max_chars + 1, sizeof(char));
+
+ /* Update blur_border_color and shift_color from box_lib.mac macro */
+ /* edit_boxes_set_sys_color */
+
+ new_textbox -> width = max_chars * PIXELS_PER_CHAR;
+ new_textbox -> left = tlx;
+ new_textbox -> top = tly;
+ new_textbox -> color = 0xFFFFFF; /* Always make white edit boxes */
+ new_textbox -> shift_color = 0x6a9480;
+ new_textbox -> focus_border_color = kolibri_color_table.color_work_graph;
+ new_textbox -> blur_border_color = 0x6a9480;
+ new_textbox -> text_color = kolibri_color_table.color_work_text; /* Always black text when typing */
+ new_textbox -> max = max_chars;
+ new_textbox -> text = text_buffer;
+ new_textbox -> mouse_variable = 1; /* let the mouse take control? */
+ new_textbox -> flags = 0x00004002; /*ed_focus + ed_always_focus */
+
+ /* If these lines are uncommented, the executable will crash for no reason at start */
+ /* Even though these lines are not ever read it ALWAYS causes a crash, even crashes MTDBG. What gives? */
+
+ new_textbox -> size = 0;
+ new_textbox -> pos = 0;
+ new_textbox -> offset = 0;
+ new_textbox -> cl_curs_x = 0;
+ new_textbox -> cl_curs_y = 0;
+ new_textbox -> shift = 0;
+ new_textbox -> shift_old = 0;
+
+ return new_textbox;
+}
+
+extern void (*edit_box_draw)(struct edit_box *) __attribute__((__stdcall__));
+
+/* editbox_key is a wrapper written in assembly to handle key press events for editboxes */
+/* because inline assembly in GCC is a PITA and interferes with the EAX (AH) register */
+/* which edit_box_key requires */
+extern void editbox_key(struct edit_box *) __attribute__((__stdcall__));
+
+extern void (*edit_box_mouse)(struct edit_box *) __attribute__((__stdcall__));
+
+#endif /* KOLIBRI_EDITBOX_H */
diff --git a/frontends/kolibrios/kolibri_filebrowser.h b/frontends/kolibrios/kolibri_filebrowser.h
new file mode 100644
index 0000000..8eecf5f
--- a/dev/null
+++ b/frontends/kolibrios/kolibri_filebrowser.h
@@ -0,0 +1,4 @@
+#ifndef KOLIBRI_FILEBROWSER_H
+#define KOLIBRI_FILEBROWSER_H
+
+#endif /* KOLIBRI_FILEBROWSER_H */
diff --git a/frontends/kolibrios/kolibri_filesystem.c b/frontends/kolibrios/kolibri_filesystem.c
new file mode 100644
index 0000000..65a5f41
--- a/dev/null
+++ b/frontends/kolibrios/kolibri_filesystem.c
@@ -0,0 +1,45 @@
+#include "kolibri_filesystem.h"
+#include <sys/types.h>
+
+int mkdir(char *dirname, long mode) {
+
+}
+
+
+DIR *opendir(char *path) {
+
+}
+
+
+struct dirent *readdir(DIR* dirp) {
+
+}
+
+int scandir(const char *dirp, struct dirent ***namelist,
+ int (*filter)(const struct dirent *),
+ int (*compar)(const struct dirent **, const struct dirent **)) {
+
+}
+
+char *realpath(const char *path, char *resolved_path) {
+
+}
+
+int closedir(DIR* opened_dir) {
+
+}
+
+/* int access(const char *pathname, int mode) { */
+
+/* } */
+
+/* ssize_t pread(int fd, void *buf, size_t count, off_t offset) */
+/* { */
+
+/* } */
+
+/* ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset) */
+/* { */
+
+/* } */
+
diff --git a/frontends/kolibrios/kolibri_filesystem.h b/frontends/kolibrios/kolibri_filesystem.h
new file mode 100644
index 0000000..c056cef
--- a/dev/null
+++ b/frontends/kolibrios/kolibri_filesystem.h
@@ -0,0 +1,22 @@
+struct dirent {
+
+};
+
+struct stat {
+
+};
+
+struct DIR {
+
+};
+
+typedef struct DIR DIR;
+
+int mkdir(char *dirname, long mode);
+DIR *opendir(char *path);
+int stat(char *, struct stat *);
+int closedir(DIR *dirp);
+struct dirent *readdir(DIR* dirp);
+int scandir(const char *dirp, struct dirent ***namelist,
+ int (*filter)(const struct dirent *),
+ int (*compar)(const struct dirent **, const struct dirent **));
diff --git a/frontends/kolibrios/kolibri_gui.h b/frontends/kolibrios/kolibri_gui.h
new file mode 100644
index 0000000..f2acc8b
--- a/dev/null
+++ b/frontends/kolibrios/kolibri_gui.h
@@ -0,0 +1,130 @@
+#ifndef KOLIBRI_GUI_H
+#define KOLIBRI_GUI_H
+
+#include "stdlib.h" /* for malloc() */
+#include "kos32sys.h"
+#include "kolibri_debug.h" /* work with debug board */
+
+/* boxlib loader */
+#include "kolibri_boxlib.h"
+
+/* All supported GUI elements included */
+#include "kolibri_gui_elements.h"
+
+enum KOLIBRI_GUI_EVENTS {
+ KOLIBRI_EVENT_REDRAW = 1, /* Window and window elements should be redrawn */
+ KOLIBRI_EVENT_KEY = 2, /* A key on the keyboard was pressed */
+ KOLIBRI_EVENT_BUTTON = 3, /* A button was clicked with the mouse */
+ KOLIBRI_EVENT_MOUSE = 6 /* Mouse activity (movement, button press) was detected */
+};
+
+void kolibri_handle_event_redraw(struct kolibri_window* some_window)
+{
+ /* Draw windows with system color table. */
+
+ BeginDraw();
+
+ DrawWindow(some_window->topleftx, some_window->toplefty,
+ some_window->sizex, some_window->sizey,
+ some_window->window_title,
+ kolibri_color_table.color_work_area, some_window->XY);
+
+ /* Enumerate and draw all window elements here */
+ if(some_window->elements) /* Draw all elements added to window */
+ {
+ struct kolibri_window_element* current_element = some_window -> elements;
+
+ do
+ {
+ /* The redraw_fn serves as draw_fn on initial draw */
+ if(kolibri_gui_op_table[current_element -> type].redraw_fn)
+ kolibri_gui_op_table[current_element -> type].redraw_fn(current_element -> element);
+
+ switch(current_element -> type)
+ {
+ case KOLIBRI_EDIT_BOX:
+ case KOLIBRI_CHECK_BOX:
+ __asm__ volatile("push $0x13371337"::); /* Random value pushed to balance stack */
+ /* otherwise edit_box_draw leaves stack unbalanced */
+ /* and GCC jumps like a crazy motha' fucka' */
+ break;
+ }
+
+ current_element = current_element -> next;
+
+ } while(current_element != some_window->elements); /* Have we covered all elements? */
+ }
+}
+
+void kolibri_handle_event_key(struct kolibri_window* some_window)
+{
+ /* Enumerate and trigger key handling functions of window elements here */
+ if(some_window->elements)
+ {
+ struct kolibri_window_element *current_element = some_window -> elements;
+
+ do
+ {
+ /* Only execute if the function pointer isn't NULL */
+ if(kolibri_gui_op_table[current_element -> type].key_fn)
+ kolibri_gui_op_table[current_element -> type].key_fn(current_element -> element);
+
+ current_element = current_element -> next;
+ } while(current_element != some_window->elements); /* Have we covered all elements? */
+ }
+}
+
+void kolibri_handle_event_mouse(struct kolibri_window* some_window)
+{
+ /* Enumerate and trigger mouse handling functions of window elements here */
+ if(some_window->elements)
+ {
+ struct kolibri_window_element *current_element = some_window -> elements;
+
+ do
+ {
+
+ if(kolibri_gui_op_table[current_element -> type].mouse_fn)
+ kolibri_gui_op_table[current_element -> type].mouse_fn(current_element -> element);
+
+ current_element = current_element -> next;
+ } while(current_element != some_window->elements); /* Have we covered all elements? */
+ }
+}
+
+void kolibri_exit(void)
+{
+ __asm__ volatile ("int $0x40"::"a"(-1));
+}
+
+int kolibri_gui_init(void)
+{
+ int boxlib_init_status = kolibri_boxlib_init();
+
+ if(boxlib_init_status == 0)
+ debug_board_write_str("ashmew2 is happy: Kolibri GUI Successfully Initialized.\n");
+ else
+ {
+ debug_board_write_str("ashmew2 is sad: Kolibri GUI Failed to initialize.\n");
+ kolibri_exit();
+ }
+
+ /* Initialize the global operation table which handles event functions of */
+ /* each individual element type */
+ kolibri_init_gui_op_table();
+
+ /* Get the current color table for Kolibri and store in global table*/
+ kolibri_get_system_colors(&kolibri_color_table);
+
+ /* Set up system events for buttons, mouse and keyboard and redraw */
+ /* Also set filters so that window receives mouse events only when active
+ and mouse inside window */
+ __asm__ volatile("int $0x40"::"a"(40), "b"(0xC0000027));
+
+ return 0;
+}
+
+/* Note: The current implementation tries to automatically colors
+ GUI elements with system theme */
+
+#endif /* KOLIBRI_GUI_H */
diff --git a/frontends/kolibrios/kolibri_gui_elements.h b/frontends/kolibrios/kolibri_gui_elements.h
new file mode 100644
index 0000000..d82b734
--- a/dev/null
+++ b/frontends/kolibrios/kolibri_gui_elements.h
@@ -0,0 +1,126 @@
+#ifndef KOLIBRI_GUI_ELEMENTS_H
+#define KOLIBRI_GUI_ELEMENTS_H
+
+/* GUI Elements being used */
+#include "kolibri_editbox.h"
+#include "kolibri_checkbox.h"
+#include "kolibri_button.h"
+
+/* enum KOLIBRI_GUI_ELEMENT_TYPE contains all available GUI items from box_lib */
+/* More elements can be added from other libraries as required */
+enum KOLIBRI_GUI_ELEMENT_TYPE {
+ KOLIBRI_EDIT_BOX,
+ KOLIBRI_CHECK_BOX,
+ KOLIBRI_RADIO_BUTTON,
+ KOLIBRI_SCROLL_BAR,
+ KOLIBRI_DYNAMIC_BUTTON,
+ KOLIBRI_MENU_BAR,
+ KOLIBRI_FILE_BROWSER,
+ KOLIBRI_TREE_LIST,
+ KOLIBRI_PATH_SHOW,
+ KOLIBRI_TEXT_EDITOR,
+ KOLIBRI_FRAME,
+ KOLIBRI_PROGRESS_BAR,
+
+ KOLIBRI_BUTTON,
+
+ /* Add elements above this element in order to let KOLIBRI_NUM_GUI_ELEMENTS */
+ /* stay at correct value */
+
+ KOLIBRI_NUM_GUI_ELEMENTS
+};
+
+/* Linked list which connects together all the elements drawn inside a GUI window */
+struct kolibri_window_element {
+ enum KOLIBRI_GUI_ELEMENT_TYPE type;
+ void *element;
+ struct kolibri_window_element *next, *prev;
+};
+
+/* Generic structure for supporting functions on various elements of Kolibri's GUI */
+struct kolibri_element_operations {
+ void (*redraw_fn)(void *);
+ void (*mouse_fn)(void *);
+ void (*key_fn)(void *);
+};
+
+/* Structure for a GUI Window on Kolibri. It also contains all the elements drawn in window */
+struct kolibri_window {
+ unsigned int topleftx, toplefty;
+ unsigned int sizex, sizey;
+ char *window_title;
+
+ /* Refer to sysfuncs, value to be stored in EDX (Function 0) */
+ unsigned int XY;
+
+ struct kolibri_window_element *elements;
+};
+
+/*---------------------End of Structure and enum definitions---------------*/
+/*---------------------Define various functions for initializing GUI-------*/
+
+/* Master table containing operations for various GUI elements in one place */
+struct kolibri_element_operations kolibri_gui_op_table[KOLIBRI_NUM_GUI_ELEMENTS];
+
+void kolibri_init_gui_op_table(void)
+{
+/* Setting up functions for edit box GUI elements*/
+kolibri_gui_op_table[KOLIBRI_EDIT_BOX].redraw_fn = edit_box_draw;
+kolibri_gui_op_table[KOLIBRI_EDIT_BOX].mouse_fn = edit_box_mouse;
+kolibri_gui_op_table[KOLIBRI_EDIT_BOX].key_fn = editbox_key;
+
+/* Setting up functions for check box GUI elements*/
+kolibri_gui_op_table[KOLIBRI_CHECK_BOX].redraw_fn = check_box_draw2;
+kolibri_gui_op_table[KOLIBRI_CHECK_BOX].mouse_fn = check_box_mouse2;
+kolibri_gui_op_table[KOLIBRI_CHECK_BOX].key_fn = NULL;
+
+/* Setting up functions for Kolibri Buttons ( SysFunc 8 )*/
+kolibri_gui_op_table[KOLIBRI_BUTTON].redraw_fn = draw_button;
+kolibri_gui_op_table[KOLIBRI_BUTTON].mouse_fn = NULL;
+kolibri_gui_op_table[KOLIBRI_BUTTON].key_fn = NULL;
+}
+
+/* Create a new main GUI window for KolibriOS */
+/* tl stands for TOP LEFT. x and y are coordinates. */
+
+struct kolibri_window * kolibri_new_window(int tlx, int tly, int sizex, int sizey, char *title)
+{
+ struct kolibri_window *new_win = (struct kolibri_window *)malloc(sizeof(struct kolibri_window));
+
+ new_win->topleftx = tlx;
+ new_win->toplefty = tly;
+ new_win->sizex = sizex;
+ new_win->sizey = sizey;
+ new_win->window_title = title;
+ new_win->XY = 0x00000013; /* All windows are skinned windows with caption for now */
+ new_win->elements = NULL;
+
+ return new_win;
+}
+
+/* Add an element to an existing window */
+void kolibri_window_add_element(struct kolibri_window *some_window, enum KOLIBRI_GUI_ELEMENT_TYPE element_type, void *some_gui_element)
+{
+ struct kolibri_window_element *new_element = (struct kolibri_window_element *)malloc(sizeof(struct kolibri_window_element));
+
+ new_element -> type = element_type;
+ new_element -> element = some_gui_element;
+
+ if(!(some_window->elements)) /* No elements in window yet */
+ {
+ some_window->elements = new_element;
+ some_window->elements -> prev = some_window->elements;
+ some_window->elements -> next = some_window->elements;
+ }
+ else
+ {
+ struct kolibri_window_element *last_element = some_window -> elements -> prev;
+
+ last_element -> next = new_element;
+ new_element -> next = some_window -> elements; /* start of linked list */
+ some_window -> elements -> prev = new_element;
+ new_element -> prev = last_element;
+ }
+}
+
+#endif /* KOLIBRI_GUI_ELEMENTS_H */
diff --git a/frontends/kolibrios/kolibri_http.c b/frontends/kolibrios/kolibri_http.c
new file mode 100644
index 0000000..dda28a6
--- a/dev/null
+++ b/frontends/kolibrios/kolibri_http.c
@@ -0,0 +1,36 @@
+#include "kolibri_http.h"
+
+int kolibri_http_init(void)
+{
+ int asm_init_status = init_network_asm();
+
+ if(asm_init_status == 0)
+ return 0;
+ else
+ return 1;
+}
+
+void http_send(struct http_msg *handle, char *data, int remaining_length) {
+
+ int sent = 0;
+ int total_sent = 0;
+ int retries_left = 5;
+
+ while(remaining_length > 0) {
+ sent = http_send_asm(handle, data + total_sent, remaining_length);
+
+ if(sent == -1) {
+ --retries_left;
+
+ if(retries_left)
+ continue;
+ else {
+ debug_board_write_str("ERROR: HTTP LIBRARY : Could not send data.\n");
+ __asm__ __volatile__("int3");
+ }
+ }
+
+ remaining_length -= sent;
+ total_sent += sent;
+ }
+}
diff --git a/frontends/kolibrios/kolibri_http.h b/frontends/kolibrios/kolibri_http.h
new file mode 100644
index 0000000..c53ef9a
--- a/dev/null
+++ b/frontends/kolibrios/kolibri_http.h
@@ -0,0 +1,81 @@
+#ifndef KOLIBRI_HTTP_H
+#define KOLIBRI_HTTP_H
+
+/* kolibri_http.h: Defines C style functions for using the underlying Kolibri HTTP library.
+ Defines functions for performing HTTP and related routines.
+
+ Interface intended to make life of C programmers easy in order to use the http.obj library
+ which serves as the HTTP library for KolibriOS on top of the network stack.
+
+ Read description of kolibri_http_init() for more information.
+ Read documentation of procedures in http.asm ($SVN/kolibrios/programs/develop/libraries/http/)
+ for even more information on the procedures.
+
+ Copyright hidnplayr , GPL v2
+ Copyright ashmew2 , GPL v2
+*/
+
+
+struct http_msg{
+ /* Internal library use only */
+ unsigned int socket;
+ unsigned int flags;
+ unsigned int write_ptr;
+ unsigned int buffer_length;
+ unsigned int chunk_ptr;
+ unsigned int timestamp;
+
+ /* Available for use */
+ unsigned int status;
+ unsigned int header_length;
+ char * content_ptr;
+ unsigned int content_length;
+ unsigned int content_received;
+ unsigned int http_header;
+};
+
+/* C - assembly wrapper to initialize and load the http.obj DLL at runtime */
+extern int init_network_asm(void);
+
+/* Procedures found in http.obj */
+extern struct http_msg* (*http_get_asm)(char *, struct http_msg *, unsigned int, char *) __attribute__((__stdcall__));
+extern int (*http_receive_asm)(struct http_msg *) __attribute__((__stdcall__));
+extern void (*http_disconnect_asm)(struct http_msg *) __attribute__((__stdcall__));
+extern void (*http_free_asm)(struct http_msg *) __attribute__((__stdcall__));
+extern struct http_msg* (*http_head_asm)(char *, struct http_msg *, unsigned int, char *) __attribute__((__stdcall__));
+extern struct http_post* (*http_post_asm)(char *, struct http_msg *, unsigned int, char *, char *, unsigned int) __attribute__((__stdcall__));
+extern int (*http_send_asm)(struct http_msg *, char *, unsigned int) __attribute__((__stdcall__));
+extern char * (*http_find_header_field_asm)(struct http_msg *, char *) __attribute__((__stdcall__));
+extern char * (*http_escape_asm)(char *, unsigned int) __attribute__((__stdcall__));
+extern char * (*http_unescape_asm)(char *, unsigned int) __attribute__((__stdcall__));
+
+/* A C Programmer calls *ONLY* this function for initializing http.obj library at runtime */
+/* After successfully returning from kolibri_http_init(), all http_*_asm functions can be used. */
+/* Returns 0 on successful init */
+
+int kolibri_http_init(void);
+
+#define HTTP_HTTP11 1 << 0
+#define HTTP_GOT_HEADER 1 << 1
+#define HTTP_GOT_ALL_DATA 1 << 2
+#define HTTP_CONTENT_LENGTH 1 << 3
+#define HTTP_CHUNKED 1 << 4
+#define HTTP_CONNECTED 1 << 5
+
+/* Flags for user options */
+#define HTTP_KEEPALIVE 1 << 8
+#define HTTP_STREAM 1 << 9
+#define HTTP_REUSE_BUFFER 1 << 10
+#define HTTP_BLOCK 1 << 11
+
+/* Flags for HTTP Errors */
+#define HTTP_INVALID_HEADER 1 << 16
+#define HTTP_NO_RAM 1 << 17
+#define HTTP_SOCKET_ERROR 1 << 18
+#define HTTP_TIMEOUT_ERROR 1 << 19
+#define HTTP_TRANSFER_FAILED 1 << 20
+
+void http_send(struct http_msg *handle, char *data, int remaining_length);
+
+#endif /* KOLIBRI_HTTP_H */
+
diff --git a/frontends/kolibrios/kolibri_iconv.c b/frontends/kolibrios/kolibri_iconv.c
new file mode 100644
index 0000000..cf5f2d3
--- a/dev/null
+++ b/frontends/kolibrios/kolibri_iconv.c
@@ -0,0 +1,12 @@
+/*The libiconv.a file that we have in built-libs defines these functions as libiconv_*()
+Maybe best is to call the libiconv() functions from here rather than hacking NS sources.
+As this is a KolibriOS dependent issue.
+*/
+#include<iconv.h>
+int iconv_close (iconv_t __cd)
+{
+
+}
+
+
+
diff --git a/frontends/kolibrios/kolibri_misc.c b/frontends/kolibrios/kolibri_misc.c
new file mode 100644
index 0000000..56d2559
--- a/dev/null
+++ b/frontends/kolibrios/kolibri_misc.c
@@ -0,0 +1,27 @@
+#include "desktop/font.h"
+#include <time.h>
+
+static bool kolibrios_font_position_in_string(const plot_font_style_t * fstyle,const char *string,
+ size_t length,int x, size_t *char_offset, int *actual_x )
+{
+}
+
+static bool kolibrios_font_split( const plot_font_style_t * fstyle, const char *string,
+ size_t length,int x, size_t *char_offset, int *actual_x )
+{
+
+}
+
+static bool kolibrios_font_width( const plot_font_style_t *fstyle, const char * str,
+ size_t length, int * width )
+{
+
+}
+
+char *strptime(const char *s, const char *format, struct tm *tm) {
+
+}
+
+int atexit(void (*function)(void)) {
+
+}
diff --git a/frontends/kolibrios/kolibri_misc.o b/frontends/kolibrios/kolibri_misc.o
new file mode 100644
index 0000000..4a7feee
--- a/dev/null
+++ b/frontends/kolibrios/kolibri_misc.o
Binary files differ
diff --git a/frontends/kolibrios/kolibri_regex.c b/frontends/kolibrios/kolibri_regex.c
new file mode 100644
index 0000000..49bf58e
--- a/dev/null
+++ b/frontends/kolibrios/kolibri_regex.c
@@ -0,0 +1,24 @@
+#include<sys/types.h>
+#include<regex.h>
+int regcomp(regex_t * regexp, const char *str, int val)
+{
+
+}
+
+
+size_t regerror(int val, const regex_t *r, char *c, size_t t)
+{
+
+}
+
+
+int regexec(const regex_t *r, const char *c, size_t s, regmatch_t regm[], int i)
+{
+
+}
+
+
+void regfree(regex_t *r)
+{
+
+}
diff --git a/frontends/kolibrios/kos32sys.h b/frontends/kolibrios/kos32sys.h
new file mode 100644
index 0000000..de4bf6a
--- a/dev/null
+++ b/frontends/kolibrios/kos32sys.h
@@ -0,0 +1,557 @@
+#ifndef __KOS_32_SYS_H__
+#define __KOS_32_SYS_H__
+
+#include <newlib.h>
+#include <stdint.h>
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//#ifdef CONFIG_DEBUF
+// #define DBG(format,...) printf(format,##__VA_ARGS__)
+//#else
+// #define DBG(format,...)
+//#endif
+
+#define TYPE_3_BORDER_WIDTH 5
+#define WIN_STATE_MINIMIZED 0x02
+#define WIN_STATE_ROLLED 0x04
+
+typedef unsigned int color_t;
+
+typedef union __attribute__((packed))
+{
+ uint32_t val;
+ struct
+ {
+ short x;
+ short y;
+ };
+}pos_t;
+
+typedef union __attribute__((packed))
+{
+ uint32_t val;
+ struct
+ {
+ uint8_t state;
+ uint8_t code;
+ uint16_t ctrl_key;
+ };
+}oskey_t;
+
+typedef struct
+{
+ unsigned handle;
+ unsigned io_code;
+ void *input;
+ int inp_size;
+ void *output;
+ int out_size;
+}ioctl_t;
+
+
+static inline
+void define_button(uint32_t x_w, uint32_t y_h, uint32_t id, uint32_t color)
+{
+ __asm__ __volatile__(
+ "int $0x40"
+ ::"a"(8),
+ "b"(x_w),
+ "c"(y_h),
+ "d"(id),
+ "S"(color));
+};
+static inline void DefineButton(void) __attribute__ ((alias ("define_button")));
+
+static inline
+uint32_t get_skin_height(void)
+{
+ uint32_t height;
+
+ __asm__ __volatile__(
+ "int $0x40 \n\t"
+ :"=a"(height)
+ :"a"(48),"b"(4));
+ return height;
+};
+static inline uint32_t GetSkinHeight(void) __attribute__ ((alias ("get_skin_height")));
+
+static inline
+void BeginDraw(void)
+{
+ __asm__ __volatile__(
+ "int $0x40" ::"a"(12),"b"(1));
+};
+
+static inline
+void EndDraw(void)
+{
+ __asm__ __volatile__(
+ "int $0x40" ::"a"(12),"b"(2));
+};
+
+static inline void DrawWindow(int x, int y, int w, int h, const char *name,
+ color_t workcolor, uint32_t style)
+{
+
+ __asm__ __volatile__(
+ "int $0x40"
+ ::"a"(0),
+ "b"((x << 16) | ((w-1) & 0xFFFF)),
+ "c"((y << 16) | ((h-1) & 0xFFFF)),
+ "d"((style << 24) | (workcolor & 0xFFFFFF)),
+ "D"(name),
+ "S"(0) : "memory");
+};
+
+#define POS_SCREEN 0
+#define POS_WINDOW 1
+
+static inline
+pos_t get_mouse_pos(int origin)
+{
+ pos_t val;
+
+ __asm__ __volatile__(
+ "int $0x40 \n\t"
+ "rol $16, %%eax"
+ :"=a"(val)
+ :"a"(37),"b"(origin));
+ return val;
+}
+static inline pos_t GetMousePos(int origin) __attribute__ ((alias ("get_mouse_pos")));
+
+static inline
+uint32_t get_mouse_buttons(void)
+{
+ uint32_t val;
+
+ __asm__ __volatile__(
+ "int $0x40"
+ :"=a"(val)
+ :"a"(37),"b"(2));
+ return val;
+};
+static inline uint32_t GetMouseButtons(void) __attribute__ ((alias ("get_mouse_buttons")));
+
+static inline
+uint32_t get_mouse_wheels(void)
+{
+ uint32_t val;
+
+ __asm__ __volatile__(
+ "int $0x40 \n\t"
+ :"=a"(val)
+ :"a"(37),"b"(7));
+ return val;
+};
+static inline uint32_t GetMouseWheels(void) __attribute__ ((alias ("get_mouse_wheels")));
+
+static inline
+uint32_t wait_for_event(uint32_t time)
+{
+ uint32_t val;
+ __asm__ __volatile__(
+ "int $0x40"
+ :"=a"(val)
+ :"a"(23), "b"(time));
+ return val;
+};
+
+static inline uint32_t check_os_event()
+{
+ uint32_t val;
+ __asm__ __volatile__(
+ "int $0x40"
+ :"=a"(val)
+ :"a"(11));
+ return val;
+};
+
+static inline uint32_t get_os_event()
+{
+ uint32_t val;
+ __asm__ __volatile__(
+ "int $0x40"
+ :"=a"(val)
+ :"a"(10));
+ return val;
+};
+static inline uint32_t GetOsEvent(void) __attribute__ ((alias ("get_os_event")));
+
+static inline
+uint32_t get_tick_count(void)
+{
+ uint32_t val;
+ __asm__ __volatile__(
+ "int $0x40"
+ :"=a"(val)
+ :"a"(26),"b"(9));
+ return val;
+};
+
+static inline
+uint64_t get_ns_count(void)
+{
+ uint64_t val;
+ __asm__ __volatile__(
+ "int $0x40"
+ :"=A"(val)
+ :"a"(26), "b"(10));
+ return val;
+};
+
+static inline
+oskey_t get_key(void)
+{
+ oskey_t val;
+ __asm__ __volatile__(
+ "int $0x40"
+ :"=a"(val)
+ :"a"(2));
+ return val;
+}
+
+static inline
+uint32_t get_os_button()
+{
+ uint32_t val;
+ __asm__ __volatile__(
+ "int $0x40"
+ :"=a"(val)
+ :"a"(17));
+ return val>>8;
+};
+
+static inline uint32_t get_service(char *name)
+{
+ uint32_t retval = 0;
+ __asm__ __volatile__(
+ "int $0x40"
+ :"=a"(retval)
+ :"a"(68),"b"(16),"c"(name)
+ :"memory");
+
+ return retval;
+};
+
+static inline int call_service(ioctl_t *io)
+{
+ int retval;
+
+ __asm__ __volatile__(
+ "int $0x40"
+ :"=a"(retval)
+ :"a"(68),"b"(17),"c"(io)
+ :"memory","cc");
+
+ return retval;
+};
+
+
+static inline
+void draw_line(int xs, int ys, int xe, int ye, color_t color)
+{
+ __asm__ __volatile__(
+ "int $0x40"
+ ::"a"(38), "d"(color),
+ "b"((xs << 16) | xe),
+ "c"((ys << 16) | ye));
+}
+
+
+
+static inline
+void draw_bar(int x, int y, int w, int h, color_t color)
+{
+ __asm__ __volatile__(
+ "int $0x40"
+ ::"a"(13), "d"(color),
+ "b"((x << 16) | w),
+ "c"((y << 16) | h));
+}
+
+static inline
+void draw_bitmap(void *bitmap, int x, int y, int w, int h)
+{
+ __asm__ __volatile__(
+ "int $0x40"
+ ::"a"(7), "b"(bitmap),
+ "c"((w << 16) | h),
+ "d"((x << 16) | y));
+}
+
+static inline
+void draw_text_sys(const char *text, int x, int y, int len, color_t color)
+{
+ __asm__ __volatile__(
+ "int $0x40"
+ ::"a"(4),"d"(text),
+ "b"((x << 16) | y),
+ "S"(len),"c"(color)
+ :"memory");
+}
+
+static inline void yield(void)
+{
+ __asm__ __volatile__(
+ "int $0x40"
+ ::"a"(68), "b"(1));
+};
+
+static inline void delay(uint32_t time)
+{
+ __asm__ __volatile__(
+ "int $0x40"
+ ::"a"(5), "b"(time)
+ :"memory");
+};
+
+static inline
+void *user_alloc(size_t size)
+{
+ void *val;
+ __asm__ __volatile__(
+ "int $0x40"
+ :"=a"(val)
+ :"a"(68),"b"(12),"c"(size));
+ return val;
+}
+static inline void *UserAlloc(size_t size) __attribute__ ((alias ("user_alloc")));
+
+static inline
+int user_free(void *mem)
+{
+ int val;
+ __asm__ __volatile__(
+ "int $0x40"
+ :"=a"(val)
+ :"a"(68),"b"(13),"c"(mem));
+ return val;
+}
+static inline int UserFree(void *mem) __attribute__ ((alias ("user_free")));
+
+static inline
+int *user_unmap(void *base, size_t offset, size_t size)
+{
+ int *val;
+ __asm__ __volatile__(
+ "int $0x40"
+ :"=a"(val)
+ :"a"(68),"b"(26),"c"(base),"d"(offset),"S"(size));
+ return val;
+};
+static inline int *UserUnmap(void *base, size_t offset, size_t size) __attribute__ ((alias ("user_unmap")));
+
+typedef union
+{
+ struct
+ {
+ void *data;
+ size_t size;
+ };
+ unsigned long long raw;
+}ufile_t;
+
+
+static inline ufile_t load_file(const char *path)
+{
+ ufile_t uf;
+
+ __asm__ __volatile__ (
+ "int $0x40"
+ :"=A"(uf.raw)
+ :"a" (68), "b"(27),"c"(path));
+
+ return uf;
+};
+static inline ufile_t LoadFile(const char *path) __attribute__ ((alias ("load_file")));
+
+static inline int GetScreenSize()
+{
+ int retval;
+
+ __asm__ __volatile__(
+ "int $0x40"
+ :"=a"(retval)
+ :"a"(61), "b"(1));
+ return retval;
+}
+
+static inline
+uint32_t load_cursor(void *path, uint32_t flags)
+{
+ uint32_t val;
+ __asm__ __volatile__(
+ "int $0x40"
+ :"=a"(val)
+ :"a"(37), "b"(4), "c"(path), "d"(flags));
+ return val;
+}
+static inline
+uint32_t LoadCursor(void *path, uint32_t flags) __attribute__ ((alias ("load_cursor")));
+
+static inline
+uint32_t set_cursor(uint32_t cursor)
+{
+ uint32_t old;
+ __asm__ __volatile__(
+ "int $0x40"
+ :"=a"(old)
+ :"a"(37), "b"(5), "c"(cursor));
+ return old;
+};
+static inline uint32_t SetCursor(uint32_t cursor) __attribute__ ((alias ("set_cursor")));
+
+static inline
+int destroy_cursor(uint32_t cursor)
+{
+ int ret;
+ __asm__ __volatile__(
+ "int $0x40"
+ :"=a"(ret)
+ :"a"(37), "b"(6), "c"(cursor)
+ :"memory");
+ return ret;
+};
+static inline int DestroyCursor(uint32_t cursor) __attribute__ ((alias ("destroy_cursor")));
+
+static inline void get_proc_info(char *info)
+{
+ __asm__ __volatile__(
+ "int $0x40"
+ :
+ :"a"(9), "b"(info), "c"(-1));
+};
+static inline void GetProcInfo(char *info) __attribute__ ((alias ("get_proc_info")));
+
+static inline
+void* user_realloc(void *mem, size_t size)
+{
+ void *val;
+ __asm__ __volatile__(
+ "int $0x40"
+ :"=a"(val)
+ :"a"(68),"b"(20),"c"(size),"d"(mem)
+ :"memory");
+
+ return val;
+};
+static inline void* UserRealloc(void *mem, size_t size) __attribute__ ((alias ("user_realloc")));
+
+/*--------------------------------------------------------------------------*/
+/* Added by ashmew2 when experimenting with newlib and how the binary will be created finally using i586-kos32-* builders */
+
+/* struct dll_proc_entry */
+/* { */
+/* char *proc_name; */
+/* void *proc_address; */
+/* }; */
+
+/* typedef struct dll_proc_entry* dll_proc_table; */
+
+/* static inline dll_proc_table dll_load(char *path) */
+/* { */
+/* void *dll_table; */
+/* __asm__ __volatile__( */
+/* "int $0x40" */
+/* :"=a"(dll_table) */
+/* :"a"(68), "b"(19), "c"(path)); */
+
+/* return (dll_proc_table) dll_table; */
+/* }; */
+/* static inline dll_proc_table LoadDLL(char *path) __attribute__ ((alias ("dll_load"))); */
+
+/* void *dll_find_proc(dll_proc_table table, char *proc_name) */
+/* { */
+/* int i; */
+
+/* if(table == NULL) */
+/* return NULL; */
+
+/* for(i = 0; table[i].proc_name && strcmp(proc_name, table[i].proc_name); i++); */
+
+/* if(table[i].proc_name) */
+/* return table[i].proc_address; */
+/* else */
+/* return NULL; */
+/* } */
+
+/* static inline void * DLLFindProc(dll_proc_table table, char *proc_name) __attribute__ ((alias ("dll_find_proc"))); */
+
+/* static inline void board_write_byte(const char ch){ */
+/* __asm__ __volatile__( */
+/* "int $0x40" */
+/* : */
+/* :"a"(63), "b"(1), "c"(ch)); */
+/* } */
+
+/* void board_write_str(const char* str){ */
+/* while(*str) */
+/* board_write_byte(*str++); */
+/* } */
+
+/*--------------------------------------------------------------------------*/
+
+void *get_resource(void *data, uint32_t id);
+
+struct blit_call
+{
+ int dstx;
+ int dsty;
+ int w;
+ int h;
+
+ int srcx;
+ int srcy;
+ int srcw;
+ int srch;
+
+ void *bitmap;
+ int stride;
+};
+
+static inline void Blit(void *bitmap, int dst_x, int dst_y,
+ int src_x, int src_y, int w, int h,
+ int src_w, int src_h, int stride)
+{
+ volatile struct blit_call bc;
+
+ bc.dstx = dst_x;
+ bc.dsty = dst_y;
+ bc.w = w;
+ bc.h = h;
+ bc.srcx = src_x;
+ bc.srcy = src_y;
+ bc.srcw = src_w;
+ bc.srch = src_h;
+ bc.stride = stride;
+ bc.bitmap = bitmap;
+
+ __asm__ __volatile__(
+ "int $0x40"
+ ::"a"(73),"b"(0),"c"(&bc.dstx));
+};
+
+void* load_library(const char *name);
+
+void* get_proc_address(void *handle, const char *proc_name);
+
+void enumerate_libraries(int (*callback)(void *handle, const char* name,
+ uint32_t base, uint32_t size, void *user_data),
+ void *user_data);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
+
+
+
+
+
diff --git a/frontends/kolibrios/loadboxlib.asm b/frontends/kolibrios/loadboxlib.asm
new file mode 100644
index 0000000..faeadb0
--- a/dev/null
+++ b/frontends/kolibrios/loadboxlib.asm
@@ -0,0 +1,135 @@
+format coff
+use32 ; Tell compiler to use 32 bit instructions
+
+section '.init' code ; Keep this line before includes or GCC messes up call addresses
+
+include 'proc32.inc'
+include 'macros.inc'
+purge section,mov,add,sub
+
+include 'box_lib.mac'
+include 'txtbut.inc'
+include 'dll.inc'
+
+public init_boxlib as '_init_boxlib_asm'
+public editbox_key as '_editbox_key@4'
+
+;;; Returns 0 on success. -1 on failure.
+
+proc init_boxlib
+
+ mcall 68,11
+
+ stdcall dll.Load, @IMPORT
+ test eax, eax
+ jnz error
+
+ mov eax, 0
+ ret
+
+error:
+ mov eax, -1
+ ret
+endp
+
+;; Wrapper to handle edit_box_key function for editboxes.
+;; Call this baby from C (refer kolibri_editbox.h for details)
+editbox_key:
+ mov [oldebp], ebp ;Save ebp because GCC is crazy for it otherwise.
+ pop ebp ;Save return address in ebp. Stack top is param now.
+ mcall 2
+ call [edit_box_key] ; The pointer we passed should be on the stack already.
+ push ebp ;push the return address back to stack
+ mov ebp, [oldebp]
+ ret
+
+oldebp dd ?
+
+@IMPORT:
+library lib_boxlib, 'box_lib.obj'
+
+import lib_boxlib, \
+ edit_box_draw, 'edit_box' , \
+ edit_box_key, 'edit_box_key' , \
+ edit_box_mouse, 'edit_box_mouse', \
+ edit_box_set_text, 'edit_box_set_text' , \
+ init_checkbox2, 'init_checkbox2' , \
+ check_box_draw2, 'check_box_draw2' , \
+ check_box_mouse2, 'check_box_mouse2' , \
+ option_box_draw, 'option_box_draw' , \
+ option_box_mouse, 'option_box_mouse' , \
+ scroll_bar_vertical_draw, 'scrollbar_ver_draw' , \
+ scroll_bar_vertical_mouse, 'scrollbar_ver_mouse' , \
+ scroll_bar_horizontal_draw, 'scrollbar_hor_draw' , \
+ scroll_bar_horizontal_mouse, 'scrollbar_hor_mouse' , \
+ dinamic_button_draw, 'dbutton_draw' , \
+ dinamic_button_mouse, 'dbutton_mouse' , \
+ menu_bar_draw, 'menu_bar_draw' , \
+ menu_bar_mouse, 'menu_bar_mouse' , \
+ menu_bar_activate, 'menu_bar_activate' , \
+ fb_draw_panel, 'filebrowser_draw' , \
+ fb_mouse, 'filebrowser_mouse' , \
+ fb_key, 'filebrowser_key' , \
+ tl_data_init, 'tl_data_init' , \
+ tl_data_clear, 'tl_data_clear' , \
+ tl_info_clear, 'tl_info_clear' , \
+ tl_key, 'tl_key' , \
+ tl_mouse, 'tl_mouse' , \
+ tl_draw, 'tl_draw' , \
+ tl_info_undo, 'tl_info_undo' , \
+ tl_info_redo, 'tl_info_redo' , \
+ tl_node_add, 'tl_node_add' , \
+ tl_node_set_data, 'tl_node_set_data' , \
+ tl_node_get_data, 'tl_node_get_data' , \
+ tl_node_delete, 'tl_node_delete' , \
+ tl_cur_beg, 'tl_cur_beg' , \
+ tl_cur_next, 'tl_cur_next' , \
+ tl_cur_perv, 'tl_cur_perv' , \
+ tl_node_close_open, 'tl_node_close_open' , \
+ tl_node_lev_inc, 'tl_node_lev_inc' , \
+ tl_node_lev_dec, 'tl_node_lev_dec' , \
+ tl_node_move_up, 'tl_node_move_up' , \
+ tl_node_move_down, 'tl_node_move_down' , \
+ tl_node_poi_get_info, 'tl_node_poi_get_info' , \
+ tl_node_poi_get_next_info, 'tl_node_poi_get_next_info' , \
+ tl_node_poi_get_data, 'tl_node_poi_get_data' , \
+ tl_save_mem, 'tl_save_mem' , \
+ tl_load_mem, 'tl_load_mem' , \
+ tl_get_mem_size, 'tl_get_mem_size' , \
+ path_show_prepare, 'pathshow_prepare' , \
+ path_show_draw, 'pathshow_draw' , \
+ ted_but_sumb_upper, 'ted_but_sumb_upper' , \
+ ted_but_sumb_lover, 'ted_but_sumb_lover' , \
+ ted_but_convert_by_table, 'ted_but_convert_by_table' , \
+ ted_can_save, 'ted_can_save' , \
+ ted_clear, 'ted_clear' , \
+ ted_delete, 'ted_delete' , \
+ ted_draw, 'ted_draw' , \
+ ted_init, 'ted_init' , \
+ ted_init_scroll_bars, 'ted_init_scroll_bars' , \
+ ted_init_syntax_file, 'ted_init_syntax_file' , \
+ ted_is_select, 'ted_is_select' , \
+ ted_key, 'ted_key' , \
+ ted_mouse, 'ted_mouse' , \
+ ted_open_file, 'ted_open_file' , \
+ ted_save_file, 'ted_save_file' , \
+ ted_text_add, 'ted_text_add' , \
+ ted_but_select_word, 'ted_but_select_word' , \
+ ted_but_cut, 'ted_but_cut' , \
+ ted_but_copy, 'ted_but_copy' , \
+ ted_but_paste, 'ted_but_paste' , \
+ ted_but_undo, 'ted_but_undo' , \
+ ted_but_redo, 'ted_but_redo' , \
+ ted_but_reverse, 'ted_but_reverse' , \
+ ted_but_find_next, 'ted_but_find_next' , \
+ ted_text_colored, 'ted_text_colored' , \
+ frame_draw, 'frame_draw' , \
+ progressbar_draw,'progressbar_draw' , \
+ progressbar_progress, 'progressbar_progress'
+
+public edit_box_draw as '_edit_box_draw'
+public edit_box_key as '_edit_box_key'
+public edit_box_mouse as '_edit_box_mouse'
+
+public check_box_draw2 as '_check_box_draw2'
+public check_box_mouse2 as '_check_box_mouse2'
diff --git a/frontends/kolibrios/loadboxlib.obj b/frontends/kolibrios/loadboxlib.obj
new file mode 100644
index 0000000..8746f7f
--- a/dev/null
+++ b/frontends/kolibrios/loadboxlib.obj
Binary files differ
diff --git a/frontends/kolibrios/loadhttp.asm b/frontends/kolibrios/loadhttp.asm
new file mode 100644
index 0000000..0a38c22
--- a/dev/null
+++ b/frontends/kolibrios/loadhttp.asm
@@ -0,0 +1,64 @@
+format coff
+use32 ; Tell compiler to use 32 bit instructions
+
+section '.flat' code ; Keep this line before includes or GCC messes up call addresses
+
+include 'struct.inc'
+include 'proc32.inc'
+include 'macros.inc'
+purge section,mov,add,sub
+
+include 'network.inc'
+include 'http.inc'
+include 'dll.inc'
+
+virtual at 0
+ http_msg http_msg
+end virtual
+
+public init_network as '_init_network_asm'
+
+;;; Returns 0 on success. -1 on failure.
+
+proc init_network
+
+ mcall 68,11
+
+ stdcall dll.Load, @IMPORT
+ test eax, eax
+ jnz error
+
+ mov eax, 0
+ ret
+
+error:
+ mov eax, -1
+ ret
+endp
+
+@IMPORT:
+
+library lib_http, 'http.obj'
+
+import lib_http, \
+ HTTP_get , 'get' , \
+ HTTP_head , 'head' , \
+ HTTP_post , 'post' , \
+ HTTP_find_header_field , 'find_header_field' , \
+ HTTP_send , 'send' , \
+ HTTP_receive , 'receive' , \
+ HTTP_disconnect , 'disconnect' , \
+ HTTP_free , 'free' , \
+ HTTP_escape , 'escape' , \
+ HTTP_unescape , 'unescape'
+
+public HTTP_get as '_http_get_asm'
+public HTTP_head as '_http_head_asm'
+public HTTP_post as '_http_post_asm'
+public HTTP_find_header_field as '_http_find_header_field_asm'
+public HTTP_send as '_http_send_asm'
+public HTTP_receive as '_http_receive_asm'
+public HTTP_disconnect as '_http_disconnect_asm'
+public HTTP_free as '_http_free_asm'
+public HTTP_escape as '_http_escape_asm'
+public HTTP_unescape as '_http_unescape_asm'
diff --git a/frontends/kolibrios/loadhttp.obj b/frontends/kolibrios/loadhttp.obj
new file mode 100644
index 0000000..8e38835
--- a/dev/null
+++ b/frontends/kolibrios/loadhttp.obj
Binary files differ
diff --git a/frontends/kolibrios/main.c b/frontends/kolibrios/main.c
new file mode 100644
index 0000000..818e5b0
--- a/dev/null
+++ b/frontends/kolibrios/main.c
@@ -0,0 +1,314 @@
+#include <stdbool.h>
+#include <sys/types.h>
+
+#include "kolibrios/kolibri_debug.h"
+#include "kolibrios/kolibri_gui.h"
+
+#include "utils/errors.h"
+
+#include "utils/messages.h"
+#include "utils/filepath.h"
+#include "utils/nsoption.h"
+#include "utils/nsurl.h"
+
+#include "netsurf/window.h"
+#include "netsurf/misc.h"
+#include "netsurf/netsurf.h"
+#include "netsurf/bitmap.h"
+#include "netsurf/plot_style.h"
+
+#include "utils/file.h"
+#include "netsurf/utf8.h"
+#include "netsurf/search.h"
+#include "content/backing_store.h"
+
+#include "kolibrios/kolibri_http.h"
+#include <libnsfb.h>
+#include <libnsfb_plot.h>
+#include <libnsfb_event.h>
+
+#include "utils/utils.h"
+#include "utils/nsoption.h"
+#include "utils/filepath.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "desktop/textinput.h"
+#include "desktop/browser_history.h"
+
+#include "kolibrios/fb/gui.h"
+#include "kolibrios/fb/fbtk.h"
+#include "kolibrios/fb/framebuffer.h"
+#include "kolibrios/fb/schedule.h"
+#include "kolibrios/fb/findfile.h"
+#include "kolibrios/fb/image_data.h"
+#include "kolibrios/fb/font.h"
+#include "kolibrios/fb/clipboard.h"
+#include "kolibrios/fb/fetch.h"
+#include "kolibrios/fb/bitmap.h"
+
+/**************************************************
+Make life easier with these path specifiers here.
+***************************************************/
+/* #define KOLIBRI_FONTFILE "/usbhd0/1/kolibrios/res/sans.ttf" */
+/* #define KOLIBRI_RESPATH "/usbhd0/1/kolibrios/res/" */
+/* #define FILE_KOLIBRI_RESPATH "file:///usbhd0/1/kolibrios/res/" */
+/************************************************/
+
+char **respaths; /** resource search path vector */
+
+extern struct gui_browser_table framebuffer_browser_table;
+extern struct gui_window_table framebuffer_window_table ;
+extern struct gui_clipboard_table *framebuffer_clipboard_table ;
+extern struct gui_fetch_table *framebuffer_fetch_table ;
+extern struct gui_utf8_table *framebuffer_utf8_table ;
+extern struct gui_bitmap_table *framebuffer_bitmap_table ;
+
+extern const char *fename;
+extern int febpp;
+extern int fewidth;
+extern int feheight;
+extern const char *feurl;
+extern bool nslog_stream_configure(FILE *fptr);
+extern struct fbtk_bitmap pointer_image;
+extern fbtk_widget_t *fbtk;
+
+static void die(const char *error)
+{
+ debug_board_write_str(error);
+ debug_board_write_str('\n');
+ exit(1);
+}
+
+/* Inspired from monkey, but without the GTK bloat */
+static char **nskolibri_init_resource(const char *resource_path)
+{
+ char **langv = {"de", "en_US", "en", "C"};
+ char **pathv; /* resource path string vector */
+ char **respath; /* resource paths vector */
+
+ pathv = filepath_path_to_strvec(resource_path);
+ respath = filepath_generate(pathv, langv);
+ filepath_free_strvec(pathv);
+
+ return respath;
+}
+
+static nserror set_defaults(struct nsoption_s *defaults)
+{
+ /* Set defaults for absent option strings */
+ nsoption_setnull_charp(cookie_file, *respaths);
+ nsoption_setnull_charp(cookie_jar, *respaths);
+ //TODO: This creates an nsoptions error in macro expansion...
+
+ return NSERROR_OK;
+}
+
+/**
+ * Main entry point from Kolibri OS.
+ */
+extern struct http_msg;
+
+static struct gui_misc_table framebuffer_misc_table = {
+ .schedule = framebuffer_schedule,
+ .warning = fb_warn_user,
+
+ .quit = gui_quit,
+};
+
+int
+main(int argc, char** argv)
+{
+ struct browser_window *bw;
+ char *options;
+ char *messages;
+ nsurl *url;
+ nserror ret;
+ nsfb_t *nsfb;
+
+ struct netsurf_table kolibrios_table = {
+ .misc = &kolibrios_misc_table,
+ .window = &kolibrios_window_table,
+ .clipboard = kolibrios_clipboard_table,
+ .fetch = kolibrios_fetch_table,
+ .utf8 = kolibrios_utf8_table,
+ .bitmap = kolibrios_bitmap_table,
+ .layout = kolibrios_layout_table,
+ };
+
+ /* Initialize HTTP Library */
+ ret = kolibri_http_init();
+ if (ret == 0)
+ debug_board_write_str("Netsurf: KolibriOS HTTP Library Initialized.\n");
+ else {
+ debug_board_write_str("Netsurf: HTTP Library initialization failed..\n");
+ return ret;
+ }
+
+ /* Initialize BoxLib Library for GUI textboxes, etc */
+ ret = kolibri_gui_init();
+ if (ret == 0)
+ debug_board_write_str("Netsurf: KolibriOS BOXLIB Library Initialized.\n");
+ else {
+ debug_board_write_str("Netsurf: BOXLIB Library initialization failed..\n");
+ return ret;
+ }
+
+ /* End of KolibriOS specific libraries initialization phase */
+ debug_board_write_str("Netsurf: Trying to register nskolibri_table.\n");
+
+ ret = netsurf_register(&kolibrios_table);
+ if (ret != NSERROR_OK) {
+ die("NetSurf operation table failed registration");
+ }
+
+ /* Drop the last slash if caller provided it. */
+
+ char current_dir[100];
+ int i = 0;
+
+ for(i = strlen(argv[0]); i>=0; i--)
+ {
+ if(argv[0][i]=='/') {
+ strncpy(current_dir, argv[0], i+1);
+ i++;
+ current_dir[i++] = 'r';
+ current_dir[i++] = 'e';
+ current_dir[i++] = 's';
+ current_dir[i++] = '\0';
+ break;
+ }
+ }
+
+
+ respaths = (char **) malloc(sizeof(char **));
+ *respaths = malloc(i);
+ strcpy(*respaths, current_dir);
+
+ debug_board_write_str("\nCWD: ");
+ debug_board_write_str(*respaths);
+ debug_board_write_str("\n");
+
+ /* __asm__ __volatile__("int3"); */
+
+ /* initialise logging. Not fatal if it fails but not much we
+ * can do about it either.
+ */
+ nslog_init(nslog_stream_configure, &argc, argv);
+
+ /* user options setup */
+ ret = nsoption_init(set_defaults, &nsoptions, &nsoptions_default);
+ if (ret != NSERROR_OK) {
+ die("Options failed to initialise");
+ }
+ options = filepath_find(respaths, "Choices");
+ nsoption_read(options, nsoptions);
+ free(options);
+ nsoption_commandline(&argc, argv, nsoptions);
+
+ /* message init */
+ messages = filepath_find(respaths, "Messages");
+ ret = messages_add_from_file(messages);
+ free(messages);
+ if (ret != NSERROR_OK) {
+ debug_board_write_str("Message translations failed to load\n");
+ }
+
+ /* common initialisation */
+ ret = netsurf_init(NULL);
+ if (ret != NSERROR_OK) {
+ die("NetSurf failed to initialise");
+ }
+
+ /* Override, since we have no support for non-core SELECT menu */
+ nsoption_set_bool(core_select_menu, true);
+ /* Do we really need to parse command line in KolibriOS?
+ Most users will use the GUI to trigger NS .
+ TODO: Look at this later.
+ */
+
+ /* if (process_cmdline(argc,argv) != true) */
+ /* die("unable to process command line.\n"); */
+
+ /* Move the initialization stuff from process_cmdline() to here */
+ /* fename = "sdl"; */
+
+ extern nsfb_surface_rtns_t kolibri_rtns;
+ _nsfb_register_surface(NSFB_SURFACE_KOLIBRI, &kolibri_rtns, "kolibri");
+
+ extern nsfb_surface_rtns_t ram_rtns;
+ _nsfb_register_surface(NSFB_SURFACE_RAM, &ram_rtns, "ram");
+
+ /* fewidth = nsoption_int(window_width); */
+ /* if (fewidth <= 0) { */
+ /* fewidth = 800; */
+ /* } */
+
+ /* feheight = nsoption_int(window_height); */
+ /* if (feheight <= 0) { */
+ /* feheight = 600; */
+ /* } */
+
+ fename = "kolibri";
+ febpp = 32;
+ fewidth = 800;
+ feheight = 600;
+
+ // feurl = "board.kolibrios.org/ucp.php?i=pm&mode=compose";
+ feurl = "ashmew2.me";
+ /* feurl = "kolibrios.org"; */
+ /* feurl = "file://usbhd0/1/kolibrios/res/welcome.html"; */
+ nsfb = framebuffer_initialise(fename, fewidth, feheight, febpp);
+ if (nsfb == NULL)
+ die("Unable to initialise framebuffer");
+
+ framebuffer_set_cursor(&pointer_image);
+
+ if (fb_font_init() == false)
+ die("Unable to initialise the font system");
+
+ fbtk = fbtk_init(nsfb);
+
+ fbtk_enable_oskb(fbtk);
+
+ urldb_load_cookies(nsoption_charp(cookie_file));
+
+ /* create an initial browser window */
+
+ debug_board_write_str("calling browser_window_create\n");
+
+ ret = nsurl_create(feurl, &url);
+ if (ret == NSERROR_OK) {
+ ret = browser_window_create(BW_CREATE_HISTORY,
+ url,
+ NULL,
+ NULL,
+ &bw);
+ nsurl_unref(url);
+ }
+
+ if (ret != NSERROR_OK) {
+ warn_user(messages_get_errorcode(ret), 0);
+ } else {
+ debug_board_write_str("calling framebuffer run\n");
+
+ framebuffer_run();
+
+ debug_board_write_str("framebuffer run returned. \n");
+
+ debug_board_write_str("Killing browser window.\n");
+ browser_window_destroy(bw);
+ }
+
+ debug_board_write_str("Calling netsurf_exit()\n");
+ netsurf_exit();
+
+ if (fb_font_finalise() == false)
+ LOG("Font finalisation failed.");
+
+ /* finalise options */
+ nsoption_finalise(nsoptions, nsoptions_default);
+
+ free(*respaths);
+ free(respaths);
+ return 0;
+}
diff --git a/frontends/kolibrios/options.h b/frontends/kolibrios/options.h
new file mode 100644
index 0000000..eee6f4b
--- a/dev/null
+++ b/frontends/kolibrios/options.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2012 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _NETSURF_FRAMEBUFFER_OPTIONS_H_
+#define _NETSURF_FRAMEBUFFER_OPTIONS_H_
+
+/* currently nothing here */
+
+#endif
+
+/***** surface options *****/
+
+NSOPTION_INTEGER(fb_depth, 32)
+NSOPTION_INTEGER(fb_refresh, 70)
+NSOPTION_STRING(fb_device, NULL)
+NSOPTION_STRING(fb_input_devpath, NULL)
+NSOPTION_STRING(fb_input_glob, NULL)
+
+/***** toolkit options *****/
+
+/** toolkit furniture size */
+NSOPTION_INTEGER(fb_furniture_size, 18)
+/** toolbar furniture size */
+NSOPTION_INTEGER(fb_toolbar_size, 30)
+/** toolbar layout */
+NSOPTION_STRING(fb_toolbar_layout, NULL)
+/** enable on screen keyboard */
+NSOPTION_BOOL(fb_osk, false)
+
+/***** font options *****/
+
+/** render all fonts monochrome */
+NSOPTION_BOOL(fb_font_monochrome, false)
+/** size of font glyph cache in kilobytes. */
+NSOPTION_INTEGER(fb_font_cachesize, 2048)
+
+/* Font face paths. These are treated as absolute paths if they start
+ * with a / otherwise the compile time resource path is searched.
+ */
+NSOPTION_STRING(fb_face_sans_serif, NULL)
+NSOPTION_STRING(fb_face_sans_serif_bold, NULL)
+NSOPTION_STRING(fb_face_sans_serif_italic, NULL)
+NSOPTION_STRING(fb_face_sans_serif_italic_bold, NULL)
+NSOPTION_STRING(fb_face_serif, NULL)
+NSOPTION_STRING(fb_face_serif_bold, NULL)
+NSOPTION_STRING(fb_face_monospace, NULL)
+NSOPTION_STRING(fb_face_monospace_bold, NULL)
+NSOPTION_STRING(fb_face_cursive, NULL)
+NSOPTION_STRING(fb_face_fantasy, NULL)
+
+/*
+ * Local Variables:
+ * c-basic-offset:8
+ * End:
+ */
diff --git a/frontends/kolibrios/res/Messages b/frontends/kolibrios/res/Messages
new file mode 120000
index 0000000..72c9eff
--- a/dev/null
+++ b/frontends/kolibrios/res/Messages
@@ -0,0 +1 @@
+../../../!NetSurf/Resources/en/Messages \ No newline at end of file
diff --git a/frontends/kolibrios/res/adblock.css b/frontends/kolibrios/res/adblock.css
new file mode 120000
index 0000000..ff24856
--- a/dev/null
+++ b/frontends/kolibrios/res/adblock.css
@@ -0,0 +1 @@
+../../../!NetSurf/Resources/AdBlock,f79 \ No newline at end of file
diff --git a/frontends/kolibrios/res/credits.html b/frontends/kolibrios/res/credits.html
new file mode 120000
index 0000000..1ba1739
--- a/dev/null
+++ b/frontends/kolibrios/res/credits.html
@@ -0,0 +1 @@
+../../../!NetSurf/Resources/en/credits.html,faf \ No newline at end of file
diff --git a/frontends/kolibrios/res/default.css b/frontends/kolibrios/res/default.css
new file mode 120000
index 0000000..a8579eb
--- a/dev/null
+++ b/frontends/kolibrios/res/default.css
@@ -0,0 +1 @@
+../../../!NetSurf/Resources/CSS,f79 \ No newline at end of file
diff --git a/frontends/kolibrios/res/favicon.png b/frontends/kolibrios/res/favicon.png
new file mode 120000
index 0000000..5a8b343
--- a/dev/null
+++ b/frontends/kolibrios/res/favicon.png
@@ -0,0 +1 @@
+../../../resources/favicon.png \ No newline at end of file
diff --git a/frontends/kolibrios/res/fonts/glyph_data b/frontends/kolibrios/res/fonts/glyph_data
new file mode 100644
index 0000000..e027566
--- a/dev/null
+++ b/frontends/kolibrios/res/fonts/glyph_data
@@ -0,0 +1,9508 @@
+* Licensed under the MIT License,
+* http://www.opensource.org/licenses/mit-license.php
+*
+* Copyright Tim Tyler
+* Copyright Michael Drake <tlsa@netsurf-browser.org>
+*
+* This font is based on the "Default" font with Zap 1.47 [TEST], which
+* was created for Zap by Tim Tyler. It was converted to a plain text
+* format and many glyphs added for use in the NetSurf project.
+*
+* Plain text font data:
+* http://git.netsurf-browser.org/art.git/plain/fonts/netsurf/glyph_data
+*
+* Zap: http://zap.tartarus.org/
+* NetSurf: http://www.netsurf-browser.org/
+*
+* Thanks to Tim Tyler for the original font and his permission to use it.
+* Thanks to James Aylett for helping track down Tim.
+* Thanks to Christian Ludlam for helping with Zap font info.
+*
+* Please contact Michael Drake if you want to contribute gylphs to
+* this font.
+
+-----------------------------------------------------
+ Regular Italic Bold Bold &
+ Italic
+-----------------------------------------------------
+U+0000 - NULL <CONTROL>
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ #######. .####### #######. .#######
+ ........ ........ ........ ........
+ ###.###. .###.### ###.###. .###.###
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ ###.###. .###.### ###.###. .###.###
+ ........ ........ ........ ........
+ ###.###. ###.###. ###.###. ###.###.
+ #.#.#.#. #.#.#.#. #.#.#.#. #.#.#.#.
+ #.#.#.#. #.#.#.#. #.#.#.#. #.#.#.#.
+ #.#.#.#. #.#.#.#. #.#.#.#. #.#.#.#.
+ ###.###. ###.###. ###.###. ###.###.
+ ........ ........ ........ ........
+ #######. #######. #######. #######.
+-----------------------------------------------------
+U+0001 - START OF HEADING <CONTROL>
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ #######. .####### #######. .#######
+ ........ ........ ........ ........
+ ###.###. .###.### ###.###. .###.###
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ ###.###. .###.### ###.###. .###.###
+ ........ ........ ........ ........
+ ###..#.. ###..#.. ###..#.. ###..#..
+ #.#.##.. #.#.##.. #.#.##.. #.#.##..
+ #.#..#.. #.#..#.. #.#..#.. #.#..#..
+ #.#..#.. #.#..#.. #.#..#.. #.#..#..
+ ###.###. ###.###. ###.###. ###.###.
+ ........ ........ ........ ........
+ #######. #######. #######. #######.
+-----------------------------------------------------
+U+0002 - START OF TEXT <CONTROL>
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ #######. .####### #######. .#######
+ ........ ........ ........ ........
+ ###.###. .###.### ###.###. .###.###
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ ###.###. .###.### ###.###. .###.###
+ ........ ........ ........ ........
+ ###.##.. ###.##.. ###.##.. ###.##..
+ #.#...#. #.#...#. #.#...#. #.#...#.
+ #.#..#.. #.#..#.. #.#..#.. #.#..#..
+ #.#.#... #.#.#... #.#.#... #.#.#...
+ ###.###. ###.###. ###.###. ###.###.
+ ........ ........ ........ ........
+ #######. #######. #######. #######.
+-----------------------------------------------------
+U+0003 - END OF TEXT <CONTROL>
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ #######. .####### #######. .#######
+ ........ ........ ........ ........
+ ###.###. .###.### ###.###. .###.###
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ ###.###. .###.### ###.###. .###.###
+ ........ ........ ........ ........
+ ###.##.. ###.##.. ###.##.. ###.##..
+ #.#...#. #.#...#. #.#...#. #.#...#.
+ #.#.##.. #.#.##.. #.#.##.. #.#.##..
+ #.#...#. #.#...#. #.#...#. #.#...#.
+ ###.##.. ###.##.. ###.##.. ###.##..
+ ........ ........ ........ ........
+ #######. #######. #######. #######.
+-----------------------------------------------------
+U+0004 - END OF TRANSMISSION <CONTROL>
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ #######. .####### #######. .#######
+ ........ ........ ........ ........
+ ###.###. .###.### ###.###. .###.###
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ ###.###. .###.### ###.###. .###.###
+ ........ ........ ........ ........
+ ###.#.#. ###.#.#. ###.#.#. ###.#.#.
+ #.#.#.#. #.#.#.#. #.#.#.#. #.#.#.#.
+ #.#.###. #.#.###. #.#.###. #.#.###.
+ #.#...#. #.#...#. #.#...#. #.#...#.
+ ###...#. ###...#. ###...#. ###...#.
+ ........ ........ ........ ........
+ #######. #######. #######. #######.
+-----------------------------------------------------
+U+0005 - ENQUIRY <CONTROL>
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ #######. .####### #######. .#######
+ ........ ........ ........ ........
+ ###.###. .###.### ###.###. .###.###
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ ###.###. .###.### ###.###. .###.###
+ ........ ........ ........ ........
+ ###.###. ###.###. ###.###. ###.###.
+ #.#.#... #.#.#... #.#.#... #.#.#...
+ #.#.###. #.#.###. #.#.###. #.#.###.
+ #.#...#. #.#...#. #.#...#. #.#...#.
+ ###.###. ###.###. ###.###. ###.###.
+ ........ ........ ........ ........
+ #######. #######. #######. #######.
+-----------------------------------------------------
+U+0006 - ACKNOWLEDGE <CONTROL>
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ #######. .####### #######. .#######
+ ........ ........ ........ ........
+ ###.###. .###.### ###.###. .###.###
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ ###.###. .###.### ###.###. .###.###
+ ........ ........ ........ ........
+ ###..##. ###..##. ###..##. ###..##.
+ #.#.#... #.#.#... #.#.#... #.#.#...
+ #.#.###. #.#.###. #.#.###. #.#.###.
+ #.#.#.#. #.#.#.#. #.#.#.#. #.#.#.#.
+ ###.###. ###.###. ###.###. ###.###.
+ ........ ........ ........ ........
+ #######. #######. #######. #######.
+-----------------------------------------------------
+U+0007 - BELL <CONTROL>
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ #######. .####### #######. .#######
+ ........ ........ ........ ........
+ ###.###. .###.### ###.###. .###.###
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ ###.###. .###.### ###.###. .###.###
+ ........ ........ ........ ........
+ ###.###. ###.###. ###.###. ###.###.
+ #.#...#. #.#...#. #.#...#. #.#...#.
+ #.#..#.. #.#..#.. #.#..#.. #.#..#..
+ #.#..#.. #.#..#.. #.#..#.. #.#..#..
+ ###..#.. ###..#.. ###..#.. ###..#..
+ ........ ........ ........ ........
+ #######. #######. #######. #######.
+-----------------------------------------------------
+U+0008 - BACKSPACE <CONTROL>
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ #######. .####### #######. .#######
+ ........ ........ ........ ........
+ ###.###. .###.### ###.###. .###.###
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ ###.###. .###.### ###.###. .###.###
+ ........ ........ ........ ........
+ ###.###. ###.###. ###.###. ###.###.
+ #.#.#.#. #.#.#.#. #.#.#.#. #.#.#.#.
+ #.#.###. #.#.###. #.#.###. #.#.###.
+ #.#.#.#. #.#.#.#. #.#.#.#. #.#.#.#.
+ ###.###. ###.###. ###.###. ###.###.
+ ........ ........ ........ ........
+ #######. #######. #######. #######.
+-----------------------------------------------------
+U+0009 - CHARACTER TABULATION <CONTROL>
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ #######. .####### #######. .#######
+ ........ ........ ........ ........
+ ###.###. .###.### ###.###. .###.###
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ ###.###. .###.### ###.###. .###.###
+ ........ ........ ........ ........
+ ###.###. ###.###. ###.###. ###.###.
+ #.#.#.#. #.#.#.#. #.#.#.#. #.#.#.#.
+ #.#.###. #.#.###. #.#.###. #.#.###.
+ #.#...#. #.#...#. #.#...#. #.#...#.
+ ###...#. ###...#. ###...#. ###...#.
+ ........ ........ ........ ........
+ #######. #######. #######. #######.
+-----------------------------------------------------
+U+000A - LINE FEED (LF) <CONTROL>
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ #######. .####### #######. .#######
+ ........ ........ ........ ........
+ ###.###. .###.### ###.###. .###.###
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ ###.###. .###.### ###.###. .###.###
+ ........ ........ ........ ........
+ ###..#.. ###..#.. ###..#.. ###..#..
+ #.#.#.#. #.#.#.#. #.#.#.#. #.#.#.#.
+ #.#.###. #.#.###. #.#.###. #.#.###.
+ #.#.#.#. #.#.#.#. #.#.#.#. #.#.#.#.
+ ###.#.#. ###.#.#. ###.#.#. ###.#.#.
+ ........ ........ ........ ........
+ #######. #######. #######. #######.
+-----------------------------------------------------
+U+000B - LINE TABULATION <CONTROL>
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ #######. .####### #######. .#######
+ ........ ........ ........ ........
+ ###.###. .###.### ###.###. .###.###
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ ###.###. .###.### ###.###. .###.###
+ ........ ........ ........ ........
+ ###.##.. ###.##.. ###.##.. ###.##..
+ #.#.#.#. #.#.#.#. #.#.#.#. #.#.#.#.
+ #.#.##.. #.#.##.. #.#.##.. #.#.##..
+ #.#.#.#. #.#.#.#. #.#.#.#. #.#.#.#.
+ ###.##.. ###.##.. ###.##.. ###.##..
+ ........ ........ ........ ........
+ #######. #######. #######. #######.
+-----------------------------------------------------
+U+000C - FORM FEED (FF) <CONTROL>
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ #######. .####### #######. .#######
+ ........ ........ ........ ........
+ ###.###. .###.### ###.###. .###.###
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ ###.###. .###.### ###.###. .###.###
+ ........ ........ ........ ........
+ ###..#.. ###..#.. ###..#.. ###..#..
+ #.#.#.#. #.#.#.#. #.#.#.#. #.#.#.#.
+ #.#.#... #.#.#... #.#.#... #.#.#...
+ #.#.#.#. #.#.#.#. #.#.#.#. #.#.#.#.
+ ###..#.. ###..#.. ###..#.. ###..#..
+ ........ ........ ........ ........
+ #######. #######. #######. #######.
+-----------------------------------------------------
+U+000D - CARRIAGE RETURN (CR) <CONTROL>
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ #######. .####### #######. .#######
+ ........ ........ ........ ........
+ ###.###. .###.### ###.###. .###.###
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ ###.###. .###.### ###.###. .###.###
+ ........ ........ ........ ........
+ ###.##.. ###.##.. ###.##.. ###.##..
+ #.#.#.#. #.#.#.#. #.#.#.#. #.#.#.#.
+ #.#.#.#. #.#.#.#. #.#.#.#. #.#.#.#.
+ #.#.#.#. #.#.#.#. #.#.#.#. #.#.#.#.
+ ###.##.. ###.##.. ###.##.. ###.##..
+ ........ ........ ........ ........
+ #######. #######. #######. #######.
+-----------------------------------------------------
+U+000E - SHIFT OUT <CONTROL>
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ #######. .####### #######. .#######
+ ........ ........ ........ ........
+ ###.###. .###.### ###.###. .###.###
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ ###.###. .###.### ###.###. .###.###
+ ........ ........ ........ ........
+ ###.###. ###.###. ###.###. ###.###.
+ #.#.#... #.#.#... #.#.#... #.#.#...
+ #.#.##.. #.#.##.. #.#.##.. #.#.##..
+ #.#.#... #.#.#... #.#.#... #.#.#...
+ ###.###. ###.###. ###.###. ###.###.
+ ........ ........ ........ ........
+ #######. #######. #######. #######.
+-----------------------------------------------------
+U+000F - SHIFT IN <CONTROL>
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ #######. .####### #######. .#######
+ ........ ........ ........ ........
+ ###.###. .###.### ###.###. .###.###
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ ###.###. .###.### ###.###. .###.###
+ ........ ........ ........ ........
+ ###.###. ###.###. ###.###. ###.###.
+ #.#.#... #.#.#... #.#.#... #.#.#...
+ #.#.##.. #.#.##.. #.#.##.. #.#.##..
+ #.#.#... #.#.#... #.#.#... #.#.#...
+ ###.#... ###.#... ###.#... ###.#...
+ ........ ........ ........ ........
+ #######. #######. #######. #######.
+-----------------------------------------------------
+U+0010 - DATA LINK ESCAPE <CONTROL>
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ #######. .####### #######. .#######
+ ........ ........ ........ ........
+ ###.###. .###.### ###.###. .###.###
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ ###.###. .###.### ###.###. .###.###
+ ........ ........ ........ ........
+ .#..###. .#..###. .#..###. .#..###.
+ ##..#.#. ##..#.#. ##..#.#. ##..#.#.
+ .#..#.#. .#..#.#. .#..#.#. .#..#.#.
+ .#..#.#. .#..#.#. .#..#.#. .#..#.#.
+ ###.###. ###.###. ###.###. ###.###.
+ ........ ........ ........ ........
+ #######. #######. #######. #######.
+-----------------------------------------------------
+U+0011 - DEVICE CONTROL ONE <CONTROL>
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ #######. .####### #######. .#######
+ ........ ........ ........ ........
+ ###.###. .###.### ###.###. .###.###
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ ###.###. .###.### ###.###. .###.###
+ ........ ........ ........ ........
+ .#...#.. .#...#.. .#...#.. .#...#..
+ ##..##.. ##..##.. ##..##.. ##..##..
+ .#...#.. .#...#.. .#...#.. .#...#..
+ .#...#.. .#...#.. .#...#.. .#...#..
+ ###.###. ###.###. ###.###. ###.###.
+ ........ ........ ........ ........
+ #######. #######. #######. #######.
+-----------------------------------------------------
+U+0012 - DEVICE CONTROL TWO <CONTROL>
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ #######. .####### #######. .#######
+ ........ ........ ........ ........
+ ###.###. .###.### ###.###. .###.###
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ ###.###. .###.### ###.###. .###.###
+ ........ ........ ........ ........
+ .#..##.. .#..##.. .#..##.. .#..##..
+ ##....#. ##....#. ##....#. ##....#.
+ .#...#.. .#...#.. .#...#.. .#...#..
+ .#..#... .#..#... .#..#... .#..#...
+ ###.###. ###.###. ###.###. ###.###.
+ ........ ........ ........ ........
+ #######. #######. #######. #######.
+-----------------------------------------------------
+U+0013 - DEVICE CONTROL THREE <CONTROL>
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ #######. .####### #######. .#######
+ ........ ........ ........ ........
+ ###.###. .###.### ###.###. .###.###
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ ###.###. .###.### ###.###. .###.###
+ ........ ........ ........ ........
+ .#..##.. .#..##.. .#..##.. .#..##..
+ ##....#. ##....#. ##....#. ##....#.
+ .#..##.. .#..##.. .#..##.. .#..##..
+ .#....#. .#....#. .#....#. .#....#.
+ ###.##.. ###.##.. ###.##.. ###.##..
+ ........ ........ ........ ........
+ #######. #######. #######. #######.
+-----------------------------------------------------
+U+0014 - DEVICE CONTROL FOUR <CONTROL>
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ #######. .####### #######. .#######
+ ........ ........ ........ ........
+ ###.###. .###.### ###.###. .###.###
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ ###.###. .###.### ###.###. .###.###
+ ........ ........ ........ ........
+ .#..#.#. .#..#.#. .#..#.#. .#..#.#.
+ ##..#.#. ##..#.#. ##..#.#. ##..#.#.
+ .#..###. .#..###. .#..###. .#..###.
+ .#....#. .#....#. .#....#. .#....#.
+ ###...#. ###...#. ###...#. ###...#.
+ ........ ........ ........ ........
+ #######. #######. #######. #######.
+-----------------------------------------------------
+U+0015 - NEGATIVE ACKNOWLEDGE <CONTROL>
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ #######. .####### #######. .#######
+ ........ ........ ........ ........
+ ###.###. .###.### ###.###. .###.###
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ ###.###. .###.### ###.###. .###.###
+ ........ ........ ........ ........
+ .#..###. .#..###. .#..###. .#..###.
+ ##..#... ##..#... ##..#... ##..#...
+ .#..###. .#..###. .#..###. .#..###.
+ .#....#. .#....#. .#....#. .#....#.
+ ###.###. ###.###. ###.###. ###.###.
+ ........ ........ ........ ........
+ #######. #######. #######. #######.
+-----------------------------------------------------
+U+0016 - SYNCHRONOUS IDLE <CONTROL>
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ #######. .####### #######. .#######
+ ........ ........ ........ ........
+ ###.###. .###.### ###.###. .###.###
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ ###.###. .###.### ###.###. .###.###
+ ........ ........ ........ ........
+ .#...##. .#...##. .#...##. .#...##.
+ ##..#... ##..#... ##..#... ##..#...
+ .#..###. .#..###. .#..###. .#..###.
+ .#..#.#. .#..#.#. .#..#.#. .#..#.#.
+ ###.###. ###.###. ###.###. ###.###.
+ ........ ........ ........ ........
+ #######. #######. #######. #######.
+-----------------------------------------------------
+U+0017 - END OF TRANSMISSION BLOCK <CONTROL>
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ #######. .####### #######. .#######
+ ........ ........ ........ ........
+ ###.###. .###.### ###.###. .###.###
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ ###.###. .###.### ###.###. .###.###
+ ........ ........ ........ ........
+ .#..###. .#..###. .#..###. .#..###.
+ ##....#. ##....#. ##....#. ##....#.
+ .#...#.. .#...#.. .#...#.. .#...#..
+ .#...#.. .#...#.. .#...#.. .#...#..
+ ###..#.. ###..#.. ###..#.. ###..#..
+ ........ ........ ........ ........
+ #######. #######. #######. #######.
+-----------------------------------------------------
+U+0018 - CANCEL <CONTROL>
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ #######. .####### #######. .#######
+ ........ ........ ........ ........
+ ###.###. .###.### ###.###. .###.###
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ ###.###. .###.### ###.###. .###.###
+ ........ ........ ........ ........
+ .#..###. .#..###. .#..###. .#..###.
+ ##..#.#. ##..#.#. ##..#.#. ##..#.#.
+ .#..###. .#..###. .#..###. .#..###.
+ .#..#.#. .#..#.#. .#..#.#. .#..#.#.
+ ###.###. ###.###. ###.###. ###.###.
+ ........ ........ ........ ........
+ #######. #######. #######. #######.
+-----------------------------------------------------
+U+0019 - END OF MEDIUM <CONTROL>
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ #######. .####### #######. .#######
+ ........ ........ ........ ........
+ ###.###. .###.### ###.###. .###.###
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ ###.###. .###.### ###.###. .###.###
+ ........ ........ ........ ........
+ .#..###. .#..###. .#..###. .#..###.
+ ##..#.#. ##..#.#. ##..#.#. ##..#.#.
+ .#..###. .#..###. .#..###. .#..###.
+ .#....#. .#....#. .#....#. .#....#.
+ ###...#. ###...#. ###...#. ###...#.
+ ........ ........ ........ ........
+ #######. #######. #######. #######.
+-----------------------------------------------------
+U+001A - SUBSTITUTE <CONTROL>
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ #######. .####### #######. .#######
+ ........ ........ ........ ........
+ ###.###. .###.### ###.###. .###.###
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ ###.###. .###.### ###.###. .###.###
+ ........ ........ ........ ........
+ .#...#.. .#...#.. .#...#.. .#...#..
+ ##..#.#. ##..#.#. ##..#.#. ##..#.#.
+ .#..###. .#..###. .#..###. .#..###.
+ .#..#.#. .#..#.#. .#..#.#. .#..#.#.
+ ###.#.#. ###.#.#. ###.#.#. ###.#.#.
+ ........ ........ ........ ........
+ #######. #######. #######. #######.
+-----------------------------------------------------
+U+001B - ESCAPE <CONTROL>
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ #######. .####### #######. .#######
+ ........ ........ ........ ........
+ ###.###. .###.### ###.###. .###.###
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ ###.###. .###.### ###.###. .###.###
+ ........ ........ ........ ........
+ .#..##.. .#..##.. .#..##.. .#..##..
+ ##..#.#. ##..#.#. ##..#.#. ##..#.#.
+ .#..##.. .#..##.. .#..##.. .#..##..
+ .#..#.#. .#..#.#. .#..#.#. .#..#.#.
+ ###.##.. ###.##.. ###.##.. ###.##..
+ ........ ........ ........ ........
+ #######. #######. #######. #######.
+-----------------------------------------------------
+U+001C - INFORMATION SEPARATOR FOUR <CONTROL>
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ #######. .####### #######. .#######
+ ........ ........ ........ ........
+ ###.###. .###.### ###.###. .###.###
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ ###.###. .###.### ###.###. .###.###
+ ........ ........ ........ ........
+ .#...#.. .#...#.. .#...#.. .#...#..
+ ##..#.#. ##..#.#. ##..#.#. ##..#.#.
+ .#..#... .#..#... .#..#... .#..#...
+ .#..#.#. .#..#.#. .#..#.#. .#..#.#.
+ ###..#.. ###..#.. ###..#.. ###..#..
+ ........ ........ ........ ........
+ #######. #######. #######. #######.
+-----------------------------------------------------
+U+001D - INFORMATION SEPARATOR THREE <CONTROL>
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ #######. .####### #######. .#######
+ ........ ........ ........ ........
+ ###.###. .###.### ###.###. .###.###
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ ###.###. .###.### ###.###. .###.###
+ ........ ........ ........ ........
+ .#..##.. .#..##.. .#..##.. .#..##..
+ ##..#.#. ##..#.#. ##..#.#. ##..#.#.
+ .#..#.#. .#..#.#. .#..#.#. .#..#.#.
+ .#..#.#. .#..#.#. .#..#.#. .#..#.#.
+ ###.##.. ###.##.. ###.##.. ###.##..
+ ........ ........ ........ ........
+ #######. #######. #######. #######.
+-----------------------------------------------------
+U+001E - INFORMATION SEPARATOR TWO <CONTROL>
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ #######. .####### #######. .#######
+ ........ ........ ........ ........
+ ###.###. .###.### ###.###. .###.###
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ ###.###. .###.### ###.###. .###.###
+ ........ ........ ........ ........
+ .#..###. .#..###. .#..###. .#..###.
+ ##..#... ##..#... ##..#... ##..#...
+ .#..##.. .#..##.. .#..##.. .#..##..
+ .#..#... .#..#... .#..#... .#..#...
+ ###.###. ###.###. ###.###. ###.###.
+ ........ ........ ........ ........
+ #######. #######. #######. #######.
+-----------------------------------------------------
+U+001F - INFORMATION SEPARATOR ONE <CONTROL>
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ #######. .####### #######. .#######
+ ........ ........ ........ ........
+ ###.###. .###.### ###.###. .###.###
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ ###.###. .###.### ###.###. .###.###
+ ........ ........ ........ ........
+ .#..###. .#..###. .#..###. .#..###.
+ ##..#... ##..#... ##..#... ##..#...
+ .#..##.. .#..##.. .#..##.. .#..##..
+ .#..#... .#..#... .#..#... .#..#...
+ ###.#... ###.#... ###.#... ###.#...
+ ........ ........ ........ ........
+ #######. #######. #######. #######.
+-----------------------------------------------------
+U+0020 - SPACE
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0021 - EXCLAMATION MARK
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ...##... .....##. ...###.. ....###.
+ ...##... .....##. ...###.. ....###.
+ ...##... .....##. ...###.. ....###.
+ ...##... .....##. ...###.. ....###.
+ ...##... ....##.. ...###.. ...###..
+ ...##... ....##.. ...###.. ...###..
+ ...##... ....##.. ...###.. ...###..
+ ...##... ....##.. ...###.. ...###..
+ ...##... ...##... ........ ........
+ ........ ........ ...###.. ..###...
+ ...##... ...##... ...###.. ..###...
+ ...##... ...##... ...###.. ..###...
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0022 - QUOTATION MARK
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ .##.##.. ...##.## ###.###. .###.###
+ .##.##.. ...##.## ###.###. .###.###
+ .##.##.. ..##.##. ###.###. .###.###
+ .##.##.. ..##.##. ###.###. .###.###
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0023 - NUMBER SIGN
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ .##.##.. ...##.## .##.##.. ..##.##.
+ .##.##.. ...##.## .##.##.. ..##.##.
+ .##.##.. ...##.## #######. .#######
+ #######. .####### #######. .#######
+ #######. .####### #######. .#######
+ .##.##.. ..##.##. .##.##.. ..##.##.
+ .##.##.. ..##.##. .##.##.. .##.##..
+ #######. ######## #######. #######.
+ #######. ######## #######. #######.
+ .##.##.. .##.##.. #######. #######.
+ .##.##.. .##.##.. .##.##.. .##.##..
+ .##.##.. .##.##.. .##.##.. .##.##..
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0024 - DOLLAR SIGN
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ...#.... .....#.. ...#.... ....#...
+ .#####.. ..#####. .#####.. ..#####.
+ #######. .####### #######. .#######
+ ##.#.##. .##.#.## ####.##. .####.##
+ ##.#.... .##.#... ####.... .####...
+ ####.... .####... #####... .#####..
+ .#####.. ..####.. .#####.. .#####..
+ ...####. ...####. ..#####. ..#####.
+ ...#.##. ...#.##. ...####. ...####.
+ ##.#.##. ##.#.##. ##.####. ##.####.
+ #######. #######. #######. #######.
+ .#####.. .#####.. .#####.. .#####..
+ ...#.... ..#..... ...#.... ...#....
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0025 - PERCENT SIGN
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ###..... .###....
+ ##...##. ##...##. ###..##. .###..##
+ ##..###. ##..###. ###.###. .###.###
+ ...###.. ...###.. ...###.. ....###.
+ ..###... ..###... ..###... ..####..
+ .###.... .###.... .###.... .###....
+ ###..##. ###..##. ###.###. ###.###.
+ ##...##. ##...##. ##..###. ##..###.
+ ........ ........ ....###. ....###.
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0026 - AMPERSAND
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ .###.... ...###.. .###.... ...###..
+ #####... ..#####. #####... ..#####.
+ ##.##... ..##.##. #####... .######.
+ ##.##... ..##.##. #####... .#####..
+ #####... ..####.. #####... .#####..
+ .###..#. ..###..# .###.##. ..###.##
+ #######. .####### #######. #######.
+ ##.####. .##.###. #######. #######.
+ ##..##.. ##..##.. ###.##.. ###.##..
+ ##..##.. ##..##.. ###.###. ###.###.
+ #######. #######. #######. #######.
+ .####.#. .####.#. .###.##. .###.#..
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0027 - APOSTROPHE
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ...##... .....##. ..###... ...###..
+ ...##... .....##. ..###... ...###..
+ ...##... ....##.. ..###... ...###..
+ ...##... ....##.. ..###... ...###..
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0028 - LEFT PARENTHESIS
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ .....##. .....##. .....##. ......##
+ ....###. ....###. ....##.. .....##.
+ ...###.. ...###.. ...###.. ....###.
+ ...##... ..###... ..###... ...###..
+ ..###... ..##.... ..###... ...###..
+ ..##.... .##..... .###.... ..###...
+ ..##.... .##..... .###.... ..###...
+ ..##.... ##...... .###.... .###....
+ ..##.... ##...... .###.... .###....
+ ..###... ##...... .###.... .###....
+ ...##... ##...... ..###... ..###...
+ ...###.. ##...... ..###... ..###...
+ ....###. ###..... ...###.. ...###..
+ .....##. .###.... ....##.. ....##..
+ ........ ..##.... .....##. .....##.
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0029 - RIGHT PARENTHESIS
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ .##..... ...##... .##..... .##.....
+ .###.... ...###.. ..##.... ..##....
+ ..###... ....###. ..###... ..###...
+ ...##... .....##. ...###.. ...###..
+ ...###.. .....##. ...###.. ...###..
+ ....##.. .....##. ....###. ....###.
+ ....##.. .....##. ....###. ....###.
+ ....##.. .....##. ....###. ....###.
+ ....##.. ....##.. ....###. ...###..
+ ...###.. ....##.. ....###. ...###..
+ ...##... ...##... ...###.. ..###...
+ ..###... ..###... ...###.. ..###...
+ .###.... .###.... ..###... .###....
+ .##..... ###..... ..##.... .##.....
+ ........ ##...... .##..... ##......
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+002A - ASTERISK
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ...#.... ....#...
+ .##.##.. ..##.##. .#.#.#.. ..#.#.#.
+ .##.##.. ..##.##. #######. .#######
+ ..###... ...###.. .#####.. ..#####.
+ #######. .####### ..###... ...##...
+ #######. #######. .#####.. .#####..
+ ..###... ..###... #######. #######.
+ .##.##.. .##.##.. .#.#.#.. .#.#.#..
+ .##.##.. .##.##.. ...#.... ...#....
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+002B - PLUS SIGN
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ...##... ........ ........ ........
+ ...##... ...##... ..###... ...###..
+ .######. ...##... ..###... ...###..
+ .######. .######. #######. .######.
+ ...##... ######.. #######. .######.
+ ...##... ..##.... ..###... ..###...
+ ........ ..##.... ..###... ..###...
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+002C - COMMA
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ...##... ...##... ..###... ..###...
+ ..###... ..###... .####... .####...
+ ..##.... .###.... .###.... .###....
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+002D - HYPHEN-MINUS
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ .######. .######. ........ ........
+ .######. ######.. #######. #######.
+ ........ ........ #######. #######.
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+002E - FULL STOP
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ...##... ...##... ..###... ..###...
+ ...##... ...##... ..###... ..###...
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+002F - SOLIDUS
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ .....##. .....##. ....###. .....###
+ ....###. ....###. ...####. ....####
+ ...###.. ...###.. ..####.. ..####..
+ ..###... ..###... .####... .####...
+ .###.... .###.... ####.... ####....
+ ###..... ###..... ###..... ###.....
+ ##...... ##...... ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0030 - DIGIT ZERO
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ .#####.. ...####. ..###... ...###..
+ #######. ..###### .#####.. ..#####.
+ ##...##. ..##..## ###.###. .###.###
+ ##..###. ..##..## ###.###. .###.###
+ ##..###. .##..### ###.###. .###.###
+ ##.#.##. .##.###. ###.###. .###.###
+ ##.#.##. .###.##. ###.###. ###.###.
+ ###..##. ###..##. ###.###. ###.###.
+ ###..##. ##..##.. ###.###. ###.###.
+ ##...##. ##..##.. ###.###. ###.###.
+ #######. ######.. .#####.. .#####..
+ .#####.. .####... ..###... ..###...
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0031 - DIGIT ONE
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ...##... .....##. ...##... ....##..
+ ..###... ....###. ..###... ...###..
+ .####... ...####. .####... ..####..
+ .####... ..####.. .####... ..####..
+ ...##... ....##.. ..###... ...###..
+ ...##... ....##.. ..###... ...###..
+ ...##... ...##... ..###... ..###...
+ ...##... ...##... ..###... ..###...
+ ...##... ...##... ..###... ..###...
+ ...##... ..##.... ..###... ..###...
+ ...##... ..##.... ..###... ..###...
+ ...##... ..##.... ..###... ..###...
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0032 - DIGIT TWO
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ .#####.. ...####. .#####.. ..#####.
+ #######. ..###### #######. .#######
+ ##...##. ..##..## ###.###. .###.###
+ .....##. ......## ....###. .....###
+ .....##. .....### ....###. .....###
+ ..#####. ...####. .######. ..#####.
+ .#####.. .#####.. ######.. .#####..
+ ###..... .##..... ###..... ###.....
+ ##...... ##...... ###..... ###.....
+ ##...... ##...... ###..... ###.....
+ #######. ######.. #######. #######.
+ #######. ######.. #######. #######.
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0033 - DIGIT THREE
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ .#####.. ...####. .#####.. ..#####.
+ #######. ..###### #######. .#######
+ ##...##. ..##..## ###.###. .###.###
+ .....##. ......## ....###. .....###
+ .....##. .....##. ....###. .....###
+ ..####.. ...####. ..####.. ...####.
+ ..####.. ...####. ..####.. ..####..
+ .....##. .....##. ....###. ....###.
+ .....##. .....##. ....###. ....###.
+ ##...##. ##..##.. ###.###. ###.###.
+ #######. ######.. #######. #######.
+ .#####.. .####... .#####.. .#####..
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0034 - DIGIT FOUR
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ .....#.. .......# .....#.. ......#.
+ ....##.. ......## ....##.. .....##.
+ ...###.. .....### ...###.. ....###.
+ ..####.. ....#### ..####.. ...####.
+ .#####.. ...####. .#####.. ..#####.
+ ###.##.. ..##.##. .##.##.. .###.##.
+ #######. .####### ###.##.. ###.##..
+ #######. .####### #######. #######.
+ ....##.. ....##.. #######. #######.
+ ....##.. ....##.. ...###.. ...###..
+ ....##.. ...##... ...###.. ...###..
+ ....##.. ...##... ...###.. ...###..
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0035 - DIGIT FIVE
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ #######. ...##### #######. .#######
+ #######. ...##### #######. .#######
+ ##...... ..##.... ###..... .###....
+ ##...... ..##.... ###..... .###....
+ ##...... .#####.. ######.. .#####..
+ ######.. .######. #######. .######.
+ #######. .....##. ....###. ....###.
+ .....##. .....##. ....###. ....###.
+ .....##. .....##. ....###. ....###.
+ ##...##. ##..###. ###.###. ###.###.
+ #######. ######.. #######. #######.
+ .#####.. .####... .#####.. .#####..
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0036 - DIGIT SIX
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ..####.. ....#### .#####.. ..#####.
+ .#####.. ...##### ######.. .######.
+ ###..... ..###... ###..... .###....
+ ##...... ..##.... ###..... .###....
+ ##...... .##..... ######.. .#####..
+ ######.. .#####.. #######. .######.
+ #######. .######. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ #######. #######. #######. #######.
+ .#####.. .#####.. .#####.. .#####..
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0037 - DIGIT SEVEN
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ #######. ..###### #######. .#######
+ #######. .####### #######. .#######
+ ##...##. .##...## ....###. .....###
+ ....###. ......## ....###. .....###
+ ....##.. .....##. ...###.. ....###.
+ ...###.. .....##. ...###.. ....###.
+ ...##... ....##.. ...###.. ...###..
+ ..###... ....##.. ..###... ..###...
+ ..##.... ...##... ..###... ..###...
+ ..##.... ...##... ..###... ..###...
+ ..##.... ..##.... ..###... ..###...
+ ..##.... ..##.... ..###... ..###...
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0038 - DIGIT EIGHT
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ .#####.. ...####. .#####.. ..#####.
+ #######. ..###### #######. .#######
+ ##...##. ..##..## ###.###. .###.###
+ ##...##. ..##..## ###.###. .###.###
+ ##...##. ..##..## #######. .#######
+ .#####.. ...####. .#####.. ..#####.
+ .#####.. .#####.. #######. .######.
+ ##...##. .##..##. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ #######. #######. #######. #######.
+ .#####.. .#####.. .#####.. .#####..
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0039 - DIGIT NINE
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ .#####.. ...####. .#####.. ..#####.
+ #######. ..###### #######. .#######
+ ##...##. ..##..## ###.###. .###.###
+ ##...##. .##...## ###.###. .###.###
+ ##...##. .##...## ###.###. .###.###
+ #######. .######. #######. .#######
+ .######. ..#####. .######. ..#####.
+ .....##. .....##. ....###. ....###.
+ .....##. ....##.. ....###. ....###.
+ ....###. ...###.. ....###. ....###.
+ .#####.. #####... .#####.. .#####..
+ .####... ####.... .####... .####...
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+003A - COLON
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ...##... ....##.. ..###... ...###..
+ ...##... ....##.. ..###... ...###..
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ...##... ........ ........ ........
+ ...##... ...##... ..###... ..###...
+ ........ ...##... ..###... ..###...
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+003B - SEMICOLON
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ...##... ....##.. ..###... ...###..
+ ...##... ....##.. ..###... ...###..
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ...##... ........ ...##... ...##...
+ ...##... ...##... ..###... ..###...
+ ..###... ..###... ..###... ..###...
+ ..##.... ..##.... ..##.... ..##....
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+003C - LESS-THAN SIGN
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ .....##. .....##. ........ ........
+ ....###. ....###. .....##. ......##
+ ...###.. ...###.. ....###. .....###
+ ..###... ..###... ...###.. ....###.
+ .###.... .###.... ..###... ...###..
+ .###.... .###.... .###.... .###....
+ ..###... .###.... .###.... .###....
+ ...###.. ..###... ..###... ..###...
+ ....###. ...###.. ...###.. ...###..
+ .....##. ....##.. ....###. ....###.
+ ........ ........ .....##. .....##.
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+003D - EQUALS SIGN
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ .######. ..#####. ........ ........
+ .######. .#####.. #######. .#######
+ ........ ........ #######. .#######
+ ........ ........ ........ ........
+ .######. .#####.. ........ ........
+ .######. #####... #######. #######.
+ ........ ........ #######. #######.
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+003E - GREATER-THAN SIGN
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ .##..... ...##... ........ ........
+ .###.... ...##... .##..... ..##....
+ ..###... ....##.. .###.... ..###...
+ ...###.. ....##.. ..###... ...###..
+ ....###. .....##. ...###.. ....###.
+ ....###. ....###. ....###. ....###.
+ ...###.. ...###.. ....###. ....###.
+ ..###... ..###... ...###.. ...###..
+ .###.... .###.... ..###... ..###...
+ .##..... .##..... .###.... .###....
+ ........ ........ .##..... .##.....
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+003F - QUESTION MARK
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ .#####.. ...####. .#####.. ..#####.
+ #######. ..###### #######. .#######
+ ##...##. ..##..## ###.###. .###.###
+ ##...##. ..##..## ....###. .....###
+ .....##. ......## ....###. .....###
+ ...####. .....### ..#####. ...####.
+ ..####.. ....###. .#####.. .#####..
+ ..##.... ...###.. .###.... .###....
+ ..##.... ...##... ........ ........
+ ........ ........ .###.... .###....
+ ..##.... ..##.... .###.... .###....
+ ..##.... ..##.... ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0040 - COMMERCIAL AT
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ .#####.. ...####. .#####.. ..#####.
+ #######. ..###### #######. .#######
+ ##...##. ..##..## ###.###. .###.###
+ ##..###. .##...## ###.###. .###.###
+ ##.####. .##.#### ###.###. .###.###
+ ##.#.##. .##.#.## #######. .#######
+ ##.#.##. .##.#.## #######. #######.
+ ##.####. ##..#### ###.##.. ###.##..
+ ##..##.. ##..###. ###..... ###.....
+ ##...... ##...... ###..... ###.....
+ ######.. ######.. ######.. ######..
+ .#####.. .#####.. .#####.. .#####..
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0041 - LATIN CAPITAL LETTER A
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ .#####.. ...####. .#####.. ..#####.
+ #######. ..###### #######. .#######
+ ##...##. ..##..## ###.###. .###.###
+ ##...##. ..##..## ###.###. .###.###
+ ##...##. .##..##. ###.###. .###.###
+ #######. .######. ###.###. .###.##.
+ #######. .######. #######. #######.
+ ##...##. .##..##. #######. #######.
+ ##...##. ##..##.. ###.###. ###.###.
+ ##...##. ##..##.. ###.###. ###.###.
+ ##...##. ##..##.. ###.###. ###.###.
+ ##...##. ##..##.. ###.###. ###.###.
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0042 - LATIN CAPITAL LETTER B
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ######.. ..#####. ######.. .######.
+ #######. ..###### #######. .#######
+ ##...##. ..##..## ###.###. .###.###
+ ##...##. .##...## ###.###. .###.###
+ ##...##. .##...## ###.###. .###.###
+ ######.. .######. ######.. .######.
+ ######.. .#####.. ######.. ######..
+ ##...##. .##..##. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ #######. #######. #######. #######.
+ ######.. ######.. ######.. ######..
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0043 - LATIN CAPITAL LETTER C
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ .#####.. ...####. .#####.. ..#####.
+ #######. ..###### #######. .#######
+ ##...##. ..##..## ###.###. .###.###
+ ##...... ..##.... ###.###. .###.###
+ ##...... .##..... ###..... .###....
+ ##...... .##..... ###..... .###....
+ ##...... .##..... ###..... ###.....
+ ##...... .##..... ###..... ###.....
+ ##...... ##...... ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ #######. #######. #######. #######.
+ .#####.. .#####.. .#####.. .#####..
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0044 - LATIN CAPITAL LETTER D
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ #####... ..#####. #####... .#####..
+ ######.. ..###### ######.. .######.
+ ##..###. ..##..## ###.###. .###.###
+ ##...##. .##...## ###.###. .###.###
+ ##...##. .##...## ###.###. .###.###
+ ##...##. .##...## ###.###. .###.##.
+ ##...##. .##...## ###.###. ###.###.
+ ##...##. ##....## ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ##..###. ##..###. ###.###. ###.###.
+ ######.. ######.. ######.. ######..
+ #####... #####... #####... #####...
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0045 - LATIN CAPITAL LETTER E
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ #######. ..###### #######. .#######
+ #######. ..###### #######. .#######
+ ##...... ..##.... ###..... .###....
+ ##...... ..##.... ###..... .###....
+ ##...... .##..... ###..... .###....
+ #####... .#####.. #####... .#####..
+ #####... .#####.. #####... #####...
+ ##...... .##..... ###..... ###.....
+ ##...... ##...... ###..... ###.....
+ ##...... ##...... ###..... ###.....
+ #######. #######. #######. #######.
+ #######. #######. #######. #######.
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0046 - LATIN CAPITAL LETTER F
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ #######. ..###### #######. .#######
+ #######. ..###### #######. .#######
+ ##...... ..##.... ###..... .###....
+ ##...... ..##.... ###..... .###....
+ ##...... .##..... ###..... .###....
+ #####... .#####.. #####... .#####..
+ #####... .#####.. #####... #####...
+ ##...... .##..... ###..... ###.....
+ ##...... ##...... ###..... ###.....
+ ##...... ##...... ###..... ###.....
+ ##...... ##...... ###..... ###.....
+ ##...... ##...... ###..... ###.....
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0047 - LATIN CAPITAL LETTER G
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ .#####.. ...####. .#####.. ..#####.
+ #######. ..###### #######. .#######
+ ##...##. ..##..## ###.###. .###.###
+ ##...... ..##.... ###.###. .###.###
+ ##...... .##..... ###..... .###....
+ ##.####. .##..... ###..... .###....
+ ##.####. .##.###. #######. #######.
+ ##...##. .##.###. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ##...##. ##..###. ###.###. ###.###.
+ #######. ######.. #######. #######.
+ .#####.. .####... .#####.. .#####..
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0048 - LATIN CAPITAL LETTER H
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ##...##. ..##..## ###.###. .###.###
+ ##...##. ..##..## ###.###. .###.###
+ ##...##. ..##..## ###.###. .###.###
+ ##...##. .##...## ###.###. .###.###
+ ##...##. .##..##. ###.###. .###.###
+ #######. .######. #######. .######.
+ #######. .######. #######. #######.
+ ##...##. ##...##. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ##...##. ##..##.. ###.###. ###.###.
+ ##...##. ##..##.. ###.###. ###.###.
+ ##...##. ##..##.. ###.###. ###.###.
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0049 - LATIN CAPITAL LETTER I
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ .######. ..###### #######. .#######
+ .######. ..###### #######. .#######
+ ...##... ....##.. ..###... ...###..
+ ...##... ....##.. ..###... ...###..
+ ...##... ...##... ..###... ...###..
+ ...##... ...##... ..###... ...###..
+ ...##... ...##... ..###... ..###...
+ ...##... ...##... ..###... ..###...
+ ...##... ..##.... ..###... ..###...
+ ...##... ..##.... ..###... ..###...
+ .######. ######.. #######. #######.
+ .######. ######.. #######. #######.
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+004A - LATIN CAPITAL LETTER J
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ....##.. ......## ....###. .....###
+ ....##.. ......## ....###. .....###
+ ....##.. ......## ....###. .....###
+ ....##.. ......## ....###. .....###
+ ....##.. .....##. ....###. .....###
+ ....##.. .....##. ....###. .....##.
+ ....##.. .....##. ....###. ....###.
+ ....##.. .....##. ....###. ....###.
+ ....##.. ....##.. ###.###. ###.###.
+ ##..##.. ##..##.. ###.###. ###.###.
+ ######.. ######.. #######. #######.
+ .####... .####... .#####.. .#####..
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+004B - LATIN CAPITAL LETTER K
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ##...... ..##.... ###..... .###....
+ ##...##. ..##.... ###..##. .###....
+ ##..###. ..##..## ###.###. .###..#.
+ ##.###.. ..##.##. #######. .###.###
+ #####... .#####.. ######.. .#######
+ ####.... .####... #####... .######.
+ ###..... .###.... ####.... #####...
+ ####.... .####... #####... #####...
+ #####... #####... ######.. ######..
+ ##.###.. ##.###.. #######. #######.
+ ##..###. ##..###. ###.###. ###.###.
+ ##...##. ##...##. ###..##. ###..##.
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+004C - LATIN CAPITAL LETTER L
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ##...... ..##.... ###..... .###....
+ ##...... ..##.... ###..... .###....
+ ##...... ..##.... ###..... .###....
+ ##...... ..##.... ###..... .###....
+ ##...... .##..... ###..... .###....
+ ##...... .##..... ###..... .###....
+ ##...... .##..... ###..... ###.....
+ ##...... .##..... ###..... ###.....
+ ##...... ##...... ###..... ###.....
+ ##...... ##...... ###..... ###.....
+ #######. #######. #######. #######.
+ #######. #######. #######. #######.
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+004D - LATIN CAPITAL LETTER M
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ##...##. ..##..## ##...##. .##...##
+ ##...##. ..##..## ###.###. .###.###
+ ###.###. ..###### #######. .#######
+ #######. ..###### #######. .#######
+ #######. .####### #######. .#######
+ #######. .##.#.## #######. .######.
+ ##.#.##. .##..##. ###.###. ###.###.
+ ##.#.##. .##..##. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ##...##. ##..##.. ###.###. ###.###.
+ ##...##. ##..##.. ###.###. ###.###.
+ ##...##. ##..##.. ###.###. ###.###.
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+004E - LATIN CAPITAL LETTER N
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ##...##. ..##..## ##..###. .##..###
+ ##...##. ..##..## ###.###. .###.###
+ ###..##. ..###.## ###.###. .###.###
+ ###..##. ..###.## #######. .#######
+ ####.##. .####.## #######. .#######
+ ####.##. .######. #######. .######.
+ ##.####. .##.###. #######. #######.
+ ##.####. .##.###. #######. #######.
+ ##..###. ##..###. #######. #######.
+ ##..###. ##..##.. ###.###. ###.###.
+ ##...##. ##..##.. ###.###. ###.###.
+ ##...##. ##..##.. ###..##. ###..##.
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+004F - LATIN CAPITAL LETTER O
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ .#####.. ...####. .#####.. ..#####.
+ #######. ..###### #######. .#######
+ ##...##. ..##..## ###.###. .###.###
+ ##...##. ..##..## ###.###. .###.###
+ ##...##. .##...## ###.###. .###.###
+ ##...##. .##..##. ###.###. .###.##.
+ ##...##. .##..##. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ##...##. ##..##.. ###.###. ###.###.
+ ##...##. ##..##.. ###.###. ###.###.
+ #######. ######.. #######. #######.
+ .#####.. .####... .#####.. .#####..
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0050 - LATIN CAPITAL LETTER P
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ######.. ..#####. ######.. .######.
+ #######. ..###### #######. .#######
+ ##...##. ..##..## ###.###. .###.###
+ ##...##. ..##..## ###.###. .###.###
+ ##...##. .##..### ###.###. .###.###
+ #######. .######. ###.###. .###.###
+ ######.. .#####.. #######. #######.
+ ##...... .##..... ######.. ######..
+ ##...... ##...... ###..... ###.....
+ ##...... ##...... ###..... ###.....
+ ##...... ##...... ###..... ###.....
+ ##...... ##...... ###..... ###.....
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0051 - LATIN CAPITAL LETTER Q
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ .#####.. ...####. .#####.. ..#####.
+ #######. ..###### #######. .#######
+ ##...##. ..##..## ###.###. .###.###
+ ##...##. ..##..## ###.###. .###.###
+ ##...##. .##...## ###.###. .###.###
+ ##...##. .##..##. ###.###. .###.##.
+ ##...##. .##..##. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ##.#.##. ####.##. #######. #######.
+ ##.####. ##.###.. #######. #######.
+ #######. #####... #######. #######.
+ .#####.. .#####.. .######. .######.
+ .....##. ....##.. .....##. .....##.
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0052 - LATIN CAPITAL LETTER R
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ######.. ..#####. ######.. .######.
+ #######. ..###### #######. .#######
+ ##...##. ..##..## ###.###. .###.###
+ ##...##. ..##..## ###.###. .###.###
+ ##...##. .##...## ###.###. .###.###
+ ######.. .######. #######. .######.
+ ######.. .#####.. ######.. ######..
+ ##...##. .##.###. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ##...##. ##..##.. ###.###. ###.###.
+ ##...##. ##..##.. ###.###. ###.###.
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0053 - LATIN CAPITAL LETTER S
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ .#####.. ...####. .#####.. ..#####.
+ #######. ..###### #######. .#######
+ ##...##. ..##..## ###.###. .###.###
+ ##...... .##..... ###..... .###....
+ ##...... .##..... ###..... .###....
+ ######.. .#####.. ######.. .#####..
+ .######. ..#####. .######. ..#####.
+ .....##. .....##. ....###. ....###.
+ .....##. .....##. ....###. ....###.
+ ##...##. ##..###. ###.###. ###.###.
+ #######. ######.. #######. #######.
+ .#####.. .####... .#####.. .#####..
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0054 - LATIN CAPITAL LETTER T
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ .######. .####### #######. .#######
+ .######. .####### #######. .#######
+ ...##... ...##... ..###... ...###..
+ ...##... ...##... ..###... ...###..
+ ...##... ..##.... ..###... ...###..
+ ...##... ..##.... ..###... ...###..
+ ...##... ..##.... ..###... ..###...
+ ...##... ..##.... ..###... ..###...
+ ...##... .##..... ..###... ..###...
+ ...##... .##..... ..###... ..###...
+ ...##... .##..... ..###... ..###...
+ ...##... .##..... ..###... ..###...
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0055 - LATIN CAPITAL LETTER U
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ##...##. ..##..## ###.###. .###.###
+ ##...##. ..##..## ###.###. .###.###
+ ##...##. ..##..## ###.###. .###.###
+ ##...##. ..##..## ###.###. .###.###
+ ##...##. .##...## ###.###. .###.###
+ ##...##. .##..##. ###.###. .###.##.
+ ##...##. .##..##. ###.###. ###.###.
+ ##...##. .##..##. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ##...##. ##..##.. ###.###. ###.###.
+ #######. ######.. #######. #######.
+ .#####.. .#####.. .#####.. .#####..
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0056 - LATIN CAPITAL LETTER V
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ##...##. ..##..## ###.###. .###.###
+ ##...##. ..##..## ###.###. .###.###
+ ##...##. ..##..## ###.###. .###.###
+ ##...##. ..##..## ###.###. .###.###
+ ##...##. .##...## ###.###. .###.###
+ ##...##. .##...## ###.###. .###.##.
+ ###.###. .##..##. ###.###. ###.###.
+ .##.##.. .##..##. .##.##.. .##.##..
+ .#####.. .##.##.. .#####.. .#####..
+ ..###... ..###... ..###... ..###...
+ ..###... ..###... ..###... ..###...
+ ...#.... ...#.... ...#.... ...#....
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0057 - LATIN CAPITAL LETTER W
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ##...##. ..##..## ###.###. .###.###
+ ##...##. ..##..## ###.###. .###.###
+ ##...##. ..##..## ###.###. .###.###
+ ##...##. ..##..## ###.###. .###.###
+ ##...##. .##...## ###.###. .###.###
+ ##...##. .##...## ###.###. .###.##.
+ ##.#.##. .##.#.## ###.###. ###.###.
+ ##.#.##. .##.#.## #######. #######.
+ #######. #######. #######. #######.
+ #######. #######. #######. #######.
+ ###.###. ###.###. ###.###. ###.###.
+ .#...#.. .#...#.. .#...#.. .#...#..
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0058 - LATIN CAPITAL LETTER X
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ##...##. .##...## ###.###. .###.###
+ ##...##. .##...## ###.###. .###.###
+ ##...##. .##...## ###.###. .###.###
+ ###.###. .###.### ###.###. .###.###
+ .#####.. ..#####. .#####.. ..#####.
+ ..###... ...###.. ..###... ...###..
+ ..###... ..###... ..###... ..###...
+ .#####.. .#####.. .#####.. .#####..
+ ###.###. ###.###. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0059 - LATIN CAPITAL LETTER Y
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ##...##. .##..##. ###.###. .###.###
+ ##...##. .##..##. ###.###. .###.###
+ ##...##. .##..##. ###.###. .###.###
+ ##...##. .##..##. ###.###. .###.###
+ ###.###. ..####.. ###.###. .###.###
+ .#####.. ..####.. .#####.. ..#####.
+ ..###... ...##... ..###... ..###...
+ ...##... ...##... ..###... ..###...
+ ...##... ..##.... ..###... ..###...
+ ...##... ..##.... ..###... ..###...
+ ...##... .##..... ..###... ..###...
+ ...##... .##..... ..###... ..###...
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+005A - LATIN CAPITAL LETTER Z
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ #######. .####### #######. .#######
+ #######. .####### #######. .#######
+ ....###. ......## ....###. .....###
+ ....##.. .....### ....###. .....###
+ ...###.. ....###. ...###.. ....###.
+ ...##... ....##.. ..###... ...###..
+ ..###... ...##... ..###... ..###...
+ ..##.... ..###... .###.... .###....
+ .###.... .###.... ###..... ###.....
+ .##..... ###..... ###..... ###.....
+ #######. #######. #######. #######.
+ #######. #######. #######. #######.
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+005B - LEFT SQUARE BRACKET
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ..#####. ....#### ..#####. ...#####
+ ..#####. ....#### ..#####. ...#####
+ ..##.... ....##.. ..###... ...###..
+ ..##.... ....##.. ..###... ...###..
+ ..##.... ...##... ..###... ...###..
+ ..##.... ...##... ..###... ...###..
+ ..##.... ...##... ..###... ..###...
+ ..##.... ...##... ..###... ..###...
+ ..##.... ..##.... ..###... ..###...
+ ..##.... ..##.... ..###... ..###...
+ ..#####. ..#####. ..#####. ..#####.
+ ..#####. ..#####. ..#####. ..#####.
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+005C - REVERSE SOLIDUS
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ .#...... ..#.....
+ ##...... ##...... ###..... .###....
+ ###..... ###..... ####.... .####...
+ .###.... .###.... .####... ..###...
+ ..###... ..###... ..####.. ...###..
+ ...###.. ...###.. ...####. ...####.
+ ....###. ....###. ....###. ....###.
+ .....##. .....##. .....#.. .....#..
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+005D - RIGHT SQUARE BRACKET
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ .#####.. ...##### ######.. .######.
+ .#####.. ...##### ######.. .######.
+ ....##.. ......## ...###.. ....###.
+ ....##.. ......## ...###.. ....###.
+ ....##.. .....##. ...###.. ....###.
+ ....##.. .....##. ...###.. ....###.
+ ....##.. .....##. ...###.. ...###..
+ ....##.. .....##. ...###.. ...###..
+ ....##.. ....##.. ...###.. ...###..
+ ....##.. ....##.. ...###.. ...###..
+ .#####.. .#####.. ######.. ######..
+ .#####.. .#####.. ######.. ######..
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+005E - CIRCUMFLEX ACCENT
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ...#.... .....#.. ...#.... ....#...
+ ..###... ....###. ..###... ...###..
+ .#####.. ...##### .#####.. ..#####.
+ ###.###. ..###.## ###.###. .###.###
+ ##...##. .##...## ##...##. .##...##
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+005F - LOW LINE
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ######## #######. ######## ########
+ ######## #######. ######## ########
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0060 - GRAVE ACCENT
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ..##.... ........ ........ ........
+ ..##.... ....##.. ..##.... ...##...
+ ...##... ....###. ..###... ...###..
+ ....#... ....##.. ...##... ....##..
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0061 - LATIN SMALL LETTER A
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ .#####.. ..####.. .#####.. ..####..
+ .######. ..#####. .######. ..#####.
+ .....##. .....##. ....###. ....###.
+ .######. .######. .######. ..#####.
+ #######. ######.. #######. .######.
+ ##...##. ##..##.. ###.###. ###.###.
+ #######. ######.. #######. #######.
+ .######. .#####.. .######. .#####..
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0062 - LATIN SMALL LETTER B
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ##...... ...##... ###..... ..###...
+ ##...... ...##... ###..... ..###...
+ ##...... ..##.... ###..... ..###...
+ ##...... ..##.... ###..... .###....
+ ######.. ..#####. ######.. .#####..
+ #######. .####### #######. .######.
+ ##...##. .##...## ###.###. .##.###.
+ ##...##. .##...## ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ #######. #######. #######. ######..
+ ######.. ######.. ######.. #####...
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0063 - LATIN SMALL LETTER C
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ .#####.. ..####.. .#####.. ..####..
+ #######. .######. #######. .######.
+ ##...##. .##..##. ###.###. ###.###.
+ ##...... ##...... ###..... ###.....
+ ##...... ##...... ###..... ###.....
+ ##...##. ##..##.. ###.###. ###.###.
+ #######. ######.. #######. #######.
+ .#####.. .####... .#####.. .#####..
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0064 - LATIN SMALL LETTER D
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ .....##. ......## ....###. .....###
+ .....##. ......## ....###. .....###
+ .....##. ......## ....###. .....###
+ .....##. .....##. ....###. .....###
+ .######. ..#####. .######. ..######
+ #######. .######. #######. .######.
+ ##...##. .##..##. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ##...##. ##..##.. ###.###. ###.###.
+ ##...##. ##..##.. ###.###. ###.###.
+ #######. ######.. #######. #######.
+ .######. .#####.. .######. .#####..
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0065 - LATIN SMALL LETTER E
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ .#####.. ..####.. .#####.. ..####..
+ #######. .######. #######. .######.
+ ##...##. .##..##. ###.###. ###.###.
+ #######. #######. #######. #######.
+ #######. ######.. #######. ######..
+ ##...... ##...... ###..... ###.....
+ #######. ######.. #######. ######..
+ .######. .#####.. .######. .#####..
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0066 - LATIN SMALL LETTER F
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ...####. .....### ..#####. ...#####
+ ..#####. ....#### .######. ..######
+ ..##.... ....##.. .###.... ..###...
+ ..##.... ...##... .###.... ..###...
+ ..##.... .######. .###.... .###....
+ .####... .######. #####... .#####..
+ .####... ..##.... #####... .#####..
+ ..##.... ..##.... .###.... .###....
+ ..##.... ..##.... .###.... ###.....
+ ..##.... .##..... .###.... ###.....
+ ..##.... .##..... .###.... ###.....
+ ..##.... .##..... .###.... ###.....
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0067 - LATIN SMALL LETTER G
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ .######. ..###### .######. ..#####.
+ #######. .####### #######. .######.
+ ##...##. .##...## ###.###. ###.###.
+ ##...##. .##...## ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ #######. #######. #######. #######.
+ .######. .######. .######. .#####..
+ .....##. ....##.. ....###. ...###..
+ .######. ######.. .######. ######..
+ .#####.. #####... .#####.. #####...
+-----------------------------------------------------
+U+0068 - LATIN SMALL LETTER H
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ##...... ..##.... ###..... .###....
+ ##...... ..##.... ###..... .###....
+ ##...... ..##.... ###..... .###....
+ ##.###.. .##.###. ######.. .#####..
+ #######. .####### #######. .######.
+ ###..##. .###..## ###.###. ###.###.
+ ##...##. .##...## ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0069 - LATIN SMALL LETTER I
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ...##... .....##. ..###... ....###.
+ ...##... .....##. ..###... ....###.
+ ........ ........ ........ ........
+ ..###... ...###.. .####... ...####.
+ ..###... ..####.. .####... ..#####.
+ ...##... ....##.. ..###... ...###..
+ ...##... ....##.. ..###... ...###..
+ ...##... ...##... ..###... ..###...
+ ...##... ...##... ..###... ..###...
+ ..####.. .#####.. .#####.. .#####..
+ ..####.. .#####.. .#####.. .#####..
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+006A - LATIN SMALL LETTER J
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ....##.. ......## ...###.. ....###.
+ ....##.. ......## ...###.. ....###.
+ ........ ........ ........ ........
+ ...###.. ....###. ..####.. ...####.
+ ...###.. ...####. ..####.. ..#####.
+ ....##.. .....##. ...###.. ....###.
+ ....##.. .....##. ...###.. ...###..
+ ....##.. ....##.. ...###.. ...###..
+ ....##.. ....##.. ...###.. ...###..
+ ....##.. ....##.. ...###.. ...###..
+ ....##.. ....##.. ...###.. ..###...
+ ....##.. ...##... ...###.. ..###...
+ .#####.. #####... .#####.. #####...
+ .####... ####.... .####... ####....
+-----------------------------------------------------
+U+006B - LATIN SMALL LETTER K
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ##...... ..##.... ###..... ..###...
+ ##...... ..##.... ###..... ..###...
+ ##...... ..##.... ###..... ..###...
+ ##...... ..##..## ###..##. ..###.#.
+ ##...##. .##..### ###.###. .#######
+ ##..###. .##.###. #######. .######.
+ ##.###.. .#####.. ######.. .#####..
+ #####... .#####.. #####... .###....
+ #####... ##.###.. ######.. #####...
+ ##.###.. ##..###. #######. ######..
+ ##..###. ##...##. ###.###. ###.###.
+ ##...##. ##...##. ###..##. ###.###.
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+006C - LATIN SMALL LETTER L
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ..###... ....###. .####... ..####..
+ ..###... ....###. .####... ..####..
+ ...##... .....##. ..###... ...###..
+ ...##... .....##. ..###... ...###..
+ ...##... ....##.. ..###... ..###...
+ ...##... ....##.. ..###... ..###...
+ ...##... ....##.. ..###... ..###...
+ ...##... ....##.. ..###... ..###...
+ ...##... ...##... ..###... .###....
+ ...##... ...##... ..###... .###....
+ ...##... ...##... ..###... .###....
+ ...##... ...##... ..###... .###....
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+006D - LATIN SMALL LETTER M
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ###.##.. .###.##. ###.##.. .###.#..
+ #######. .####### #######. .######.
+ #######. .####### #######. #######.
+ ##.#.##. .##.#.## #######. #######.
+ ##.#.##. ##.#.##. #######. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+006E - LATIN SMALL LETTER N
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ##.###.. .##.##.. ######.. .#####..
+ #######. .######. #######. .######.
+ ###..##. .###.##. ###.###. ###.###.
+ ##...##. .##..##. ###.###. ###.###.
+ ##...##. ##..##.. ###.###. ###.###.
+ ##...##. ##..##.. ###.###. ###.###.
+ ##...##. ##..##.. ###.###. ###.###.
+ ##...##. ##..##.. ###.###. ###.###.
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+006F - LATIN SMALL LETTER O
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ .#####.. ..####.. .#####.. ..####..
+ #######. .######. #######. .######.
+ ##...##. .##..##. ###.###. ###.###.
+ ##...##. .##..##. ###.###. ###.###.
+ ##...##. ##..##.. ###.###. ###.###.
+ ##...##. ##..##.. ###.###. ###.###.
+ #######. ######.. #######. ######..
+ .#####.. .####... .#####.. .####...
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0070 - LATIN SMALL LETTER P
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ######.. ..#####. ######.. .#####..
+ #######. ..###### #######. .######.
+ ##...##. ..##..## ###.###. ###.###.
+ ##...##. .##...## ###.###. ###.###.
+ ##...##. .##..##. ###.###. ###.###.
+ ##...##. .##..##. ###.###. ###.###.
+ #######. #######. #######. ######..
+ ######.. ######.. ######.. #####...
+ ##...... ##...... ###..... ###.....
+ ##...... ##...... ###..... ###.....
+ ##...... ##...... ###..... ###.....
+-----------------------------------------------------
+U+0071 - LATIN SMALL LETTER Q
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ .######. ..###### .######. ..#####.
+ #######. .####### #######. .######.
+ ##...##. .##...## ###.###. ###.###.
+ ##...##. .##...## ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ #######. #######. #######. ######..
+ .######. .#####.. .######. .#####..
+ .....##. ....##.. ....###. ...###..
+ .....### ....###. ....#### ...####.
+ .....### ....###. ....#### ...####.
+-----------------------------------------------------
+U+0072 - LATIN SMALL LETTER R
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ##.####. .##.#### ##.####. .###.##.
+ #######. .####### #######. .######.
+ ###..... .###.... ###..... .###....
+ ##...... .##..... ###..... .###....
+ ##...... ##...... ###..... ###.....
+ ##...... ##...... ###..... ###.....
+ ##...... ##...... ###..... ###.....
+ ##...... ##...... ###..... ###.....
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0073 - LATIN SMALL LETTER S
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ .######. ..###### .######. ...#####
+ #######. .####### #######. ..#####.
+ ##...... .##..... ###..... .###....
+ ######.. .#####.. ######.. .#####..
+ .#####.. ..#####. .######. ..#####.
+ .....##. .....##. ....###. ....###.
+ #######. #######. #######. .#####..
+ ######.. ######.. ######.. #####...
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0074 - LATIN SMALL LETTER T
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ...#.... .....##. ...#.... ..###...
+ ..##.... .....##. ..##.... ..###...
+ ..##.... ....##.. .###.... ..###...
+ ..##.... ....##.. .###.... .###....
+ .#####.. ..###### ######.. .#####..
+ ######.. ..###### ######.. .#####..
+ ..##.... ...##... .###.... .###....
+ ..##.... ...##... .###.... ###.....
+ ..##.... ..##.... .###.... ###.....
+ ..##.... ..##.... .###.... ###.....
+ ..#####. ..#####. .######. ######..
+ ...####. ...###.. ..#####. .#####..
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0075 - LATIN SMALL LETTER U
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ##...##. ..##..## ###.###. .###.###
+ ##...##. ..##..## ###.###. .###.##.
+ ##...##. .##..##. ###.###. ###.###.
+ ##...##. .##..##. ###.###. ###.###.
+ ##...##. .##..##. ###.###. ###.###.
+ ##..###. ##..##.. ###.###. ###.###.
+ #######. #######. #######. #######.
+ .###.##. .###.##. .######. .######.
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0076 - LATIN SMALL LETTER V
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ##...##. .##..##. ###.###. .###.###
+ ##...##. .##..##. ###.###. .###.##.
+ ##...##. .##..##. ###.###. ###.###.
+ ##...##. ##..##.. ###.###. ###.###.
+ ###.###. ##..##.. ###.###. ###.###.
+ .#####.. #####... .#####.. .#####..
+ ..###... .###.... ..###... ..###...
+ ...#.... ..#..... ...#.... ...#....
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0077 - LATIN SMALL LETTER W
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ##...##. .##...## ###.###. .###.###
+ ##...##. .##...## ###.###. .###.##.
+ ##...##. .##...## ###.###. ###.###.
+ ##.#.##. .##.#.## #######. #######.
+ ##.#.##. ##.####. #######. #######.
+ #######. #######. #######. #######.
+ #######. #######. ###.###. ###.###.
+ .##.##.. .##.##.. .#...#.. .#...#..
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0078 - LATIN SMALL LETTER X
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ##...##. .##...## ###.###. .###.###
+ ##...##. .##...## ###.###. .###.##.
+ ###.###. .###.### ###.###. .######.
+ .#####.. ..#####. .#####.. ..###...
+ .#####.. .#####.. .#####.. .#####..
+ ###.###. ###.###. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+0079 - LATIN SMALL LETTER Y
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ##...##. .##...## ###.###. .###.###
+ ##...##. .##...## ###.###. .###.##.
+ ##...##. .##...## ###.###. ###.###.
+ ##...##. .##...## ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ##...##. ##...##. #######. #######.
+ #######. #######. .######. .######.
+ .######. .######. ....###. ...###..
+ .....##. ....##.. ....###. ...###..
+ #######. ######.. #######. ######..
+ ######.. #####... ######.. #####...
+-----------------------------------------------------
+U+007A - LATIN SMALL LETTER Z
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ #######. .####### #######. .#######
+ #######. .####### #######. .######.
+ ....###. .....### ...####. ...####.
+ ..####.. ...####. ..####.. ..####..
+ .####... .####... .####... .####...
+ ###..... ###..... ####.... ####....
+ #######. #######. #######. #######.
+ #######. #######. #######. #######.
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+007B - LEFT CURLY BRACKET
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ....###. .....### ...####. ....####
+ ...####. ....###. ..#####. ...#####
+ ...##... ....##.. ..###... ...###..
+ ...##... ....##.. ..###... ...###..
+ ...##... ...##... ..###... ...###..
+ .###.... .###.... ####.... .####...
+ .###.... .###.... ####.... ####....
+ ...##... ...##... ..###... ..###...
+ ...##... ...##... ..###... ..###...
+ ...##... ..##.... ..###... ..###...
+ ...####. ..###... ..#####. ..#####.
+ ....###. ...###.. ...####. ...####.
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+007C - VERTICAL LINE
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ...##... .....##. ..###... ...###..
+ ...##... .....##. ..###... ...###..
+ ...##... .....##. ..###... ...###..
+ ...##... .....##. ..###... ...###..
+ ...##... ....##.. ..###... ...###..
+ ...##... ....##.. ..###... ...###..
+ ...##... ....##.. ..###... ...###..
+ ...##... ....##.. ..###... ..###...
+ ...##... ...##... ..###... ..###...
+ ...##... ...##... ..###... ..###...
+ ...##... ...##... ..###... ..###...
+ ...##... ...##... ..###... ..###...
+ ...##... ..##.... ..###... ..###...
+ ...##... ..##.... ..###... ..###...
+ ...##... ..##.... ..###... ..###...
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+007D - RIGHT CURLY BRACKET
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ .###.... ..###... ####.... .####...
+ .####... ...###.. #####... .#####..
+ ...##... ....##.. ..###... ...###..
+ ...##... ...##... ..###... ...###..
+ ...##... ...##... ..###... ...###..
+ ....###. ....###. ...####. ....####
+ ....###. ....###. ...####. ...####.
+ ...##... ...##... ..###... ..###...
+ ...##... ..##.... ..###... ..###...
+ ...##... ..##.... ..###... ..###...
+ .####... .###.... #####... #####...
+ .###.... ###..... ####.... ####....
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+007E - TILDE
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ .###.##. ...###.# .##..##. ..##..##
+ #######. ..###### #######. .#######
+ ##.###.. ..##.### #######. .#######
+ ........ ........ ##..##.. .##..##.
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+007F - DELETE <CONTROL>
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ #######. .####### #######. .#######
+ ........ ........ ........ ........
+ ###.###. .###.### ###.###. .###.###
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ #.#.#.#. .#.#.#.# #.#.#.#. .#.#.#.#
+ ###.###. .###.### ###.###. .###.###
+ ........ ........ ........ ........
+ ###.###. ###.###. ###.###. ###.###.
+ ..#.#... ..#.#... ..#.#... ..#.#...
+ .#..##.. .#..##.. .#..##.. .#..##..
+ .#..#... .#..#... .#..#... .#..#...
+ .#..#... .#..#... .#..#... .#..#...
+ ........ ........ ........ ........
+ #######. #######. #######. #######.
+-----------------------------------------------------
+U+00A0 - NO-BREAK SPACE
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00A1 - INVERTED EXCLAMATION MARK
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ...##... ....##.. ..###... ...###..
+ ...##... ....##.. ..###... ...###..
+ ........ ........ ........ ........
+ ...##... ....##.. ..###... ..###...
+ ...##... ...##... ..###... ..###...
+ ...##... ...##... ..###... ..###...
+ ...##... ...##... ..###... ..###...
+ ...##... ...##... ..###... ..###...
+ ...##... ..##.... ..###... ..###...
+ ...##... ..##.... ..###... ..###...
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00A2 - CENT SIGN
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ...#.... .....#.. ...#.... ....#...
+ ...#.... .....#.. ...#.... ....#...
+ .#####.. ..#####. .#####.. ..#####.
+ #######. .####### #######. .#######
+ ##.#.##. .##.#.## ##.#.##. ##.#.##.
+ ##.#.... .##.#... ##.#.... ##.#....
+ ##.#.... ##.#.... ##.#.... ##.#....
+ ##.#.##. ##.#.##. ##.#.##. ##.#.##.
+ #######. #######. #######. #######.
+ .#####.. .#####.. .#####.. .#####..
+ ...#.... ..#..... ...#.... ...#....
+ ...#.... ..#..... ...#.... ...#....
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00A3 - POUND SIGN
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ..####.. ....#### ..####.. ...####.
+ .######. ...##### .######. ..######
+ .##..##. ...##..# .###.##. ..###.##
+ .##..... ...##... .###.... ..###...
+ .##..... ..##.... ######.. .######.
+ #####... .#####.. ######.. .######.
+ #####... .#####.. ######.. ######..
+ .##..... ..##.... .###.... .###....
+ .##..... .##..... .###.##. .###.##.
+ ###..##. ###..##. #######. #######.
+ #######. #######. #######. #######.
+ ##.###.. ##.###.. ##.###.. ##.###..
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00A4 - CURRENCY SIGN
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ .##..##. ...##..# ###.###. .###.###
+ .##..##. ..##..## ###.###. .###.###
+ ..####.. ...####. .#####.. ..#####.
+ .######. ..###### #######. #######.
+ .##..##. ..##..## #######. #######.
+ .##..##. .##..##. #######. #######.
+ .######. .######. #######. #######.
+ ..####.. ..####.. .#####.. .#####..
+ .##..##. .##..##. ###.###. ###.###.
+ .##..##. ##..##.. ###.###. ###.###.
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00A5 - YEN SIGN
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ .##..##. ...##..# ###.###. .###.###
+ .##..##. ...##..# ###.###. .###.###
+ .##..##. ...##..# ###.###. .###.###
+ ..####.. ...####. .#####.. ..#####.
+ ...##... ....##.. ..###... ...###..
+ .######. ..###### #######. #######.
+ ...##... ....##.. ..###... ..###...
+ .######. .######. #######. #######.
+ ...##... ...##... ..###... ..###...
+ ...##... ...##... ..###... ..###...
+ ...##... ...##... ..###... ..###...
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00A6 - BROKEN BAR
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ...##... .....##. ..###... ...###..
+ ...##... .....##. ..###... ...###..
+ ...##... ....##.. ..###... ...###..
+ ...##... ....##.. ..###... ...###..
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ...##... ...##... ..###... ..###...
+ ...##... ...##... ..###... ..###...
+ ...##... ..##.... ..###... ..###...
+ ...##... ..##.... ..###... ..###...
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00A7 - SECTION SIGN
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ..####.. .....### ..####.. ...####.
+ .#####.. ....###. .#####.. ..#####.
+ .##..... ...##... .#####.. ..#####.
+ .##..... ...##... .###.... ..###...
+ ..####.. ..####.. ..####.. ...####.
+ .######. .######. .######. ..######
+ .##..##. .##..##. .##..##. .##..##.
+ .######. .######. .######. .######.
+ ..####.. ..####.. ..####.. ..####..
+ .....##. ...##... ....###. ....###.
+ .....##. ...##... ..#####. ..#####.
+ ..#####. .###.... ..#####. ..#####.
+ ..####.. ###..... ..####.. ..####..
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00A8 - DIAERESIS
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ###.###. .###.###
+ .##..##. ..##..## ###.###. .###.###
+ .##..##. .##..##. ###.###. .###.###
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00A9 - COPYRIGHT SIGN
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ..####.. ....###. ..####.. ...####.
+ .######. ...##### .######. ..######
+ ##....## ..#....# ##....## .##....#
+ #..##..# ..#....# #..##..# .#..##.#
+ #.####.# .#..##.# #.####.# .#.###.#
+ #.#..#.# .#.#...# #.#..#.# .#.#...#
+ #.#....# .#.#...# #.#....# #.#....#
+ #.#..#.# #..#...# #.#..#.# #.#..#.#
+ #.####.# #.#....# #.####.# #.####.#
+ #..##..# #..##.#. #..##..# #..##..#
+ ##....## #.....#. ##....## ##....##
+ .######. .#####.. .######. .######.
+ ..####.. ..###... ..####.. ..####..
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00AA - FEMININE ORDINAL INDICATOR
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ .###.... ...###.. .####... ..####..
+ ....#... ......#. ....##.. .....##.
+ .####... ...####. .#####.. ..#####.
+ #...#... ..#...#. ##..##.. .##..##.
+ .####... ..####.. .#####.. ..#####.
+ ........ ........ ........ ........
+ #####... .#####.. ######.. ######..
+ #####... .#####.. ######.. ######..
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00AB - LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ..##.##. ...##.## ..#####. ..#####.
+ .##.##.. ..##.##. .#####.. .#####..
+ ##.##... ##.##... #####... #####...
+ ##.##... ##.##... #####... #####...
+ .##.##.. .##.##.. .#####.. .#####..
+ ..##.##. ..##.##. ..#####. ..#####.
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00AC - NOT SIGN
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ .######. ...####. .######. ..######
+ .######. ..#####. .######. ..######
+ .....##. .....##. .######. ..######
+ ......#. ....##.. .....##. ......##
+ ........ ........ ......#. .......#
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00AD - SOFT HYPHEN
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ .######. ..###### .######. .######.
+ ........ ........ .######. .######.
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00AE - REGISTERED SIGN
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ..####.. ....###. ..####.. ...####.
+ .######. ...##### .######. ..######
+ ##....## ..#....# ##....## .##....#
+ #.###..# .#..#..# #.###..# .#.##..#
+ #.####.# .#.#.#.# #.####.# .#.###.#
+ #.#..#.# .#.#.#.# #.#..#.# .#.#.#.#
+ #.###..# .#.##..# #.###..# #.###..#
+ #.###..# #..##..# #.###..# #.###..#
+ #.#..#.# #.#..#.# #.#..#.# #.#..#.#
+ #.#..#.# #.#..#.# #.#..#.# #.#..#.#
+ ##....## #.....#. ##....## ##....##
+ .######. .######. .######. .######.
+ ..####.. .####... ..####.. ..####..
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00AF - MACRON
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ .######. ...##### #######. .#######
+ ........ ........ #######. .#######
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00B0 - DEGREE SIGN
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ .####... ...####. .####... ..####..
+ ######.. ..###### ######.. .######.
+ ##..##.. ..##..## ##..##.. .##..##.
+ ######.. ..###### ######.. .######.
+ .####... ..####.. .####... ..####..
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00B1 - PLUS-MINUS SIGN
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ..###... ...###..
+ ...##... .....##. ..###... ...###..
+ ...##... .....##. #######. .#######
+ .######. ..###### #######. .#######
+ .######. ..###### #######. .#######
+ ...##... ....##.. ..###... ..###...
+ ...##... ....##.. ..###... ..###...
+ ........ ........ ........ ........
+ .######. .######. #######. #######.
+ .######. .######. #######. #######.
+ ........ ........ #######. #######.
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00B2 - SUPERSCRIPT TWO
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ####.... ..####.. ####.... .####...
+ #####... ..#####. #####... .#####..
+ ...##... .....##. ...##... ....##..
+ .####... ..####.. .####... ..####..
+ ####.... .####... ####.... .####...
+ ##...... .##..... ##...... ##......
+ #####... .#####.. #####... #####...
+ #####... .#####.. #####... #####...
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00B3 - SUPERSCRIPT THREE
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ####.... ..####.. ####.... .####...
+ #####... ..#####. #####... .#####..
+ ...##... .....##. ...##... ....##..
+ ..##.... ...##... ..##.... ...##...
+ ...##... ....##.. ...##... ....##..
+ #####... .#####.. #####... #####...
+ ####.... .####... ####.... ####....
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00B4 - ACUTE ACCENT
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ...##... .....##. ..###... ...###..
+ ..##.... ....##.. .###.... ..###...
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00B5 - MICRO SIGN
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ .##..##. ..##..## ###.###. .###.###
+ .##..##. ..##..## ###.###. ###.###.
+ .##..##. ..##..## ###.###. ###.###.
+ .##..##. .##..##. ###.###. ###.###.
+ .##..##. .##..##. ###.###. ###.###.
+ .######. .######. #######. #######.
+ .#####.. .#####.. ######.. ######..
+ .##..... ##...... ###..... ###.....
+ .##..... ##...... ###..... ###.....
+ ##...... #....... ##...... ##......
+-----------------------------------------------------
+U+00B6 - PILCROW SIGN
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ .####### ..###### .####### ..######
+ ##.##.## .##.#### ##.##.## .##.##.#
+ ##.##.## ##.##.## ##.##.## .##.##.#
+ ##.##.## ##.##.## ##.##.## .##.##.#
+ .####.## .####.## .####.## .####.#.
+ ...##.## ...##.## ...##.## ..##.##.
+ ...##.## ..##.##. ...##.## ..##.##.
+ ...##.## ..##.##. ...##.## ..##.##.
+ ...##.## ..##.##. ...##.## ..##.##.
+ ...##.## ..##.##. ...##.## ..##.##.
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00B7 - MIDDLE DOT
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ..###... ...###..
+ ...##... ....##.. ..###... ..###...
+ ...##... ....##.. ..###... ..###...
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00B8 - CEDILLA
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ...##... ...##... ...##... ...##...
+ ...###.. ...###.. ...###.. ...###..
+ ....##.. ....##.. ....##.. ....##..
+ ...###.. ...###.. ...###.. ...###..
+ ...##... ..##.... ...##... ...##...
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00B9 - SUPERSCRIPT ONE
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ .##..... ...##... .##..... ..##....
+ ###..... ..###... ###..... .###....
+ .##..... ...##... .##..... ..##....
+ .##..... ..##.... .##..... ..##....
+ .##..... ..##.... .##..... ..##....
+ ####.... .####... ####.... ####....
+ ####.... .####... ####.... ####....
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00BA - MASCULINE ORDINAL INDICATOR
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ .###.... ....##.. .###.... ..###...
+ #####... ...####. #####... .#####..
+ #...#... ..#...#. #...#... .#...#..
+ #####... ..####.. #####... .#####..
+ .###.... ...##... .###.... ..###...
+ ........ ........ ........ ........
+ #####... ..####.. #####... #####...
+ #####... .####... #####... #####...
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00BB - RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ##.##... .##.##.. ##.##... ##.##...
+ .##.##.. ..##.##. .##.##.. .##.##..
+ ..##.##. ..##.##. ..##.##. ..##.##.
+ ..##.##. ..##.##. ..##.##. ..##.##.
+ .##.##.. .##.##.. .##.##.. .##.##..
+ ##.##... ##.##... ##.##... ##.##...
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00BC - VULGAR FRACTION ONE QUARTER
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ .#...... ...#.... .##..... ..##....
+ ##...... ..##.... ###..... .###....
+ .#....#. ...#.... .##...#. ..##...#
+ .#...##. ..#...## .##..##. ..##..##
+ ###.##.. .###.##. #######. .#######
+ ...##... ....##.. ...###.. ...###..
+ ..##.... ...##... ..###... ..###...
+ .##..#.. .##..#.. .###.##. .###.##.
+ ##..##.. ##..##.. ###.###. ###.###.
+ #..#.#.. #..#.#.. ##.#.##. ##.#.##.
+ ..#####. ..#####. ..#####. ..#####.
+ .....#.. ....#... ..#####. ..#####.
+ .....#.. ....#... .....##. .....##.
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00BD - VULGAR FRACTION ONE HALF
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ .#...... ...#.... .##..... ..##....
+ ##...... ..##.... ###..... .###....
+ .#....#. ...#.... .##...#. ..##...#
+ .#...##. ..#...## .##..##. ..##..##
+ ###.##.. .###.##. #######. .#######
+ ...##... ....##.. ...###.. ...###..
+ ..##.... ...##... ..###... ..###...
+ .##..... .##..... .###.... .###....
+ ##.###.. ##.###.. ######.. ######..
+ #.....#. #.....#. ##...##. ##...##.
+ ....##.. ...###.. ....##.. ....##..
+ ...#.... ..#..... ...##... ...##...
+ ...####. ..####.. ...####. ...####.
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00BE - VULGAR FRACTION THREE QUARTERS
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ###..... ..###... ###..... .###....
+ ...#.... .....#.. ..##.... ...##...
+ .##...#. ...##... .##...#. ..##...#
+ ...#.##. ....#.## ..##.##. ...##.##
+ ###.##.. .###.##. ###.###. .###.###
+ ...##... ....##.. ...###.. ...###..
+ ..##.... ...##... ..###.#. ..###.#.
+ .##..#.. .##..#.. .###.##. .###.##.
+ ##..##.. ##..##.. ###.###. ###.###.
+ #..#.##. #..#.##. ##.#.##. ##.#.##.
+ ..#####. ..#####. ..#####. ..#####.
+ .....#.. ....#... ..#####. ..#####.
+ .....#.. ....#... .....##. .....##.
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00BF - INVERTED QUESTION MARK
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ...###.. ....###.
+ ...##... .....##. ...###.. ....###.
+ ...##... .....##. ...###.. ....###.
+ ........ ........ ........ ........
+ ...##... ....##.. ...###.. ....###.
+ ...##... ....##.. ...###.. ...###..
+ .####... ..####.. .#####.. .#####..
+ ####.... .###.... #####... #####...
+ ##...... ##...... ###..... ###.....
+ ##...##. ##...##. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ #######. ######.. #######. #######.
+ .#####.. .####... .#####.. .#####..
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00C0 - LATIN CAPITAL LETTER A WITH GRAVE
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ .##..... ...##... ###..... .###....
+ ..##.... ....##.. .###.... ..###...
+ ........ ........ ........ ........
+ ...#.... .....#.. ...#.... ....#...
+ ..###... ...###.. ..###... ...###..
+ .##.##.. ..##.##. .#####.. ..#####.
+ ##...##. .##...## ###.###. ###.###.
+ #######. .####### #######. #######.
+ #######. #######. #######. #######.
+ ##...##. ##...##. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00C1 - LATIN CAPITAL LETTER A WITH ACUTE
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ....##.. ......## ....###. .....###
+ ...##... .....##. ...###.. ....###.
+ ........ ........ ........ ........
+ ...#.... .....#.. ...#.... ....#...
+ ..###... ...###.. ..###... ...###..
+ .##.##.. ..##.##. .#####.. ..#####.
+ ##...##. .##...## ###.###. ###.###.
+ #######. .####### #######. #######.
+ #######. #######. #######. #######.
+ ##...##. ##...##. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00C2 - LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ..###... ....###. ..###... ...###..
+ .##.##.. ...##.## .##.##.. ..##.##.
+ .#...#.. ...#...# ##...##. .##...##
+ ...#.... .....#.. ...#.... ....#...
+ ..###... ...###.. ..###... ...###..
+ .##.##.. ..##.##. .#####.. ..#####.
+ ##...##. .##...## ###.###. ###.###.
+ #######. .####### #######. #######.
+ #######. #######. #######. #######.
+ ##...##. ##...##. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00C3 - LATIN CAPITAL LETTER A WITH TILDE
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ .###.##. ...###.# .###.##. ..###.##
+ ##.###.. ..##.### ##.###.. .##.###.
+ ........ ........ ........ ........
+ ...#.... .....#.. ...#.... ....#...
+ ..###... ...###.. ..###... ...###..
+ .##.##.. ..##.##. .#####.. ..#####.
+ ##...##. .##...## ###.###. ###.###.
+ #######. .####### #######. #######.
+ #######. #######. #######. #######.
+ ##...##. ##...##. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00C4 - LATIN CAPITAL LETTER A WITH DIAERESIS
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ .##.##.. ........ ........ ........
+ .##.##.. ...##.## ###.###. .###.###
+ ........ ...##.## ###.###. .###.###
+ ...#.... .....#.. ...#.... ....#...
+ ..###... ....###. ..###... ...###..
+ .##.##.. ..##.##. .#####.. ..#####.
+ ##...##. .##...## ###.###. .###.##.
+ #######. .####### #######. #######.
+ #######. .####### #######. #######.
+ ##...##. ##...##. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00C5 - LATIN CAPITAL LETTER A WITH RING ABOVE
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ..###... ....###. ..###... ...###..
+ .#...#.. ...#...# .##.##.. ..##.##.
+ ..###... ....###. ..###... ...###..
+ ..###... ....###. ..###... ...###..
+ .##.##.. ..##.##. .#####.. ..#####.
+ ##...##. .##...## ###.###. .###.##.
+ #######. .####### #######. #######.
+ #######. .####### #######. #######.
+ ##...##. ##...##. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00C6 - LATIN CAPITAL LETTER AE
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ...##### .....### ...##### ....####
+ ..###### ....#### ..###### ...#####
+ .#####.. ...##### .####### ..######
+ ###.##.. ..###.## #######. .#######
+ ##..##.. .##..##. ###.###. .###.###
+ #######. .####### ######## .#######
+ #######. .####### ######## ########
+ ##..##.. .##..##. #######. #######.
+ ##..##.. ##..##.. ###.###. ###.###.
+ ##..##.. ##..##.. ###.#### ###.####
+ ##..#### ##..#### ###.#### ###.####
+ ##..#### ##..#### ###.#### ###.####
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00C7 - LATIN CAPITAL LETTER C WITH CEDILLA
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ .#####.. ...####. .#####.. ..#####.
+ #######. ..###### #######. .#######
+ ##...##. ..##..## ###.###. .###.###
+ ##...... ..##.... ###..... .###....
+ ##...... .##..... ###..... .###....
+ ##...... .##..... ###..... .###....
+ ##...... .##..... ###..... ###.....
+ ##...... .##..... ###..... ###.....
+ ##...... ##...... ###..... ###.....
+ ##...##. ##...##. ###.###. ###.###.
+ #######. #######. #######. #######.
+ .#####.. .#####.. .#####.. .#####..
+ ....###. ...###.. ....###. ....###.
+ .##..##. ##..##.. .##.###. .##.###.
+ ..####.. .####... .#####.. .#####..
+-----------------------------------------------------
+U+00C8 - LATIN CAPITAL LETTER E WITH GRAVE
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ..##.... ....##.. .###.... ..###...
+ ...##... .....##. ..###... ...###..
+ ........ ........ ........ ........
+ #######. ..###### #######. .#######
+ #######. .####### #######. .#######
+ ##...... .##..... ###..... .###....
+ ####.... .####... ###..... ###.....
+ ####.... .####... #####... #####...
+ ##...... ##...... ###..... ###.....
+ ##...... ##...... ###..... ###.....
+ #######. #######. #######. #######.
+ #######. #######. #######. #######.
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00C9 - LATIN CAPITAL LETTER E WITH ACUTE
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ....##.. ......## ...###.. ....###.
+ ...##... .....##. ..###... ...###..
+ ........ ........ ........ ........
+ #######. ..###### #######. .#######
+ #######. .####### #######. .#######
+ ##...... .##..... ###..... .###....
+ ####.... .####... ###..... ###.....
+ ####.... .####... #####... #####...
+ ##...... ##...... ###..... ###.....
+ ##...... ##...... ###..... ###.....
+ #######. #######. #######. #######.
+ #######. #######. #######. #######.
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00CA - LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ..###... ....###. .#####.. ..#####.
+ .##.##.. ...##.## ###.###. .###.###
+ ........ ........ ........ ........
+ #######. ..###### #######. .#######
+ #######. .####### #######. .#######
+ ##...... .##..... ###..... .###....
+ ####.... .####... ###..... ###.....
+ ####.... .####... #####... #####...
+ ##...... ##...... ###..... ###.....
+ ##...... ##...... ###..... ###.....
+ #######. #######. #######. #######.
+ #######. #######. #######. #######.
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00CB - LATIN CAPITAL LETTER E WITH DIAERESIS
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ .##.##.. ...##.## ###.###. .###.###
+ .##.##.. ...##.## ###.###. .###.###
+ ........ ........ ........ ........
+ #######. ..###### #######. .#######
+ #######. ..###### #######. .#######
+ ##...... .##..... ###..... .###....
+ ##...... .##..... ###..... .###....
+ ####.... .####... #####... #####...
+ ####.... .####... #####... #####...
+ ##...... ##...... ###..... ###.....
+ ##...... ##...... ###..... ###.....
+ #######. #######. #######. #######.
+ #######. #######. #######. #######.
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00CC - LATIN CAPITAL LETTER I WITH GRAVE
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ..##.... ....##.. .###.... ..###...
+ ...##... .....##. ..###... ...###..
+ ........ ........ ........ ........
+ ...##... ...##### ..###... ...###..
+ ...##... ...##### ..###... ...###..
+ ...##... ....##.. ..###... ...###..
+ ...##... ....##.. ..###... ..###...
+ ...##... ....##.. ..###... ..###...
+ ...##... ...##... ..###... ..###...
+ ...##... ...##... ..###... ..###...
+ ...##... .#####.. ..###... ..###...
+ ...##... .#####.. ..###... ..###...
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00CD - LATIN CAPITAL LETTER I WITH ACUTE
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ....##.. ......## ...###.. ....###.
+ ...##... .....##. ..###... ...###..
+ ........ ........ ........ ........
+ ...##... ...##### ..###... ...###..
+ ...##... ...##### ..###... ...###..
+ ...##... ....##.. ..###... ...###..
+ ...##... ....##.. ..###... ..###...
+ ...##... ....##.. ..###... ..###...
+ ...##... ...##... ..###... ..###...
+ ...##... ...##... ..###... ..###...
+ ...##... .#####.. ..###... ..###...
+ ...##... .#####.. ..###... ..###...
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00CE - LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ...##... .....##. ..###... ...###..
+ ..#..#.. ....#..# .##.##.. ..##.##.
+ ...##... ...##### ..###... ...###..
+ ...##... ...##### ..###... ...###..
+ ...##... ....##.. ..###... ...###..
+ ...##... ....##.. ..###... ...###..
+ ...##... ....##.. ..###... ..###...
+ ...##... ....##.. ..###... ..###...
+ ...##... ...##... ..###... ..###...
+ ...##... ...##... ..###... ..###...
+ ...##... .#####.. ..###... ..###...
+ ...##... .#####.. ..###... ..###...
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00CF - LATIN CAPITAL LETTER I WITH DIAERESIS
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ .##..##. ...##.## ###.###. .###.###
+ .##..##. ...##.## ###.###. .###.###
+ ........ ........ ........ ........
+ ...##... ...##### ..###... ...###..
+ ...##... ...##### ..###... ...###..
+ ...##... ....##.. ..###... ...###..
+ ...##... ....##.. ..###... ..###...
+ ...##... ....##.. ..###... ..###...
+ ...##... ...##... ..###... ..###...
+ ...##... ...##... ..###... ..###...
+ ...##... .#####.. ..###... ..###...
+ ...##... .#####.. ..###... ..###...
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00D0 - LATIN CAPITAL LETTER ETH
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ .####... ...####. #####... .#####..
+ .#####.. ...##### ######.. .######.
+ .##.###. ...##.## ###.###. .###.###
+ .##..##. ..##..## ###.###. .###.###
+ .##..##. ..##..## ###.###. .###.##.
+ ####.##. .####.## #######. #######.
+ .##..##. ..##..## ###.###. ###.###.
+ .##..##. .##..##. ###.###. ###.###.
+ .##.###. .##.###. ###.###. ###.###.
+ .#####.. .#####.. ######.. ######..
+ .####... .####... #####... #####...
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00D1 - LATIN CAPITAL LETTER N WITH TILDE
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ .###.##. ...###.# .###.##. ..###.##
+ ##.###.. ..##.### ##.###.. .##.###.
+ ........ ........ ........ ........
+ ##...##. ..##...# ###.###. .###.###
+ ##...##. .##...## ###.###. .###.###
+ ###..##. .###..## ###.###. .###.##.
+ ####.##. .####.## ####.##. ####.##.
+ #######. .####### #######. #######.
+ ##.####. ##.####. ##.####. ##.####.
+ ##..###. ##..###. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00D2 - LATIN CAPITAL LETTER O WITH GRAVE
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ..##.... ....##.. .###.... ..###...
+ ...##... .....##. ..###... ...###..
+ ........ ........ ........ ........
+ .#####.. ..#####. .#####.. ..#####.
+ #######. .####### #######. .#######
+ ##...##. .##...## ###.###. .###.##.
+ ##...##. .##...## ###.###. ###.###.
+ ##...##. .##...## ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ #######. #######. #######. #######.
+ .#####.. .#####.. .#####.. .#####..
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00D3 - LATIN CAPITAL LETTER O WITH ACUTE
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ....##.. ......## ...###.. ....###.
+ ...##... .....##. ..###... ...###..
+ ........ ........ ........ ........
+ .#####.. ..#####. .#####.. ..#####.
+ #######. .####### #######. .#######
+ ##...##. .##...## ###.###. .###.##.
+ ##...##. .##...## ###.###. ###.###.
+ ##...##. .##...## ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ #######. #######. #######. #######.
+ .#####.. .#####.. .#####.. .#####..
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00D4 - LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ..###... ....###. .#####.. ..#####.
+ .##.##.. ...##.## ###.###. .###.###
+ ........ ........ ........ ........
+ .#####.. ..#####. .#####.. ..#####.
+ #######. .####### #######. .#######
+ ##...##. .##...## ###.###. .###.##.
+ ##...##. .##...## ###.###. ###.###.
+ ##...##. .##...## ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ ##...##. ##...##. ###.###. ###.###.
+ #######. #######. #######. #######.
+ .#####.. .#####.. .#####.. .#####..
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+00D5 - LATIN CAPITAL LETTER O WITH TILDE
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ .###.##. ...###.# .###.##. ..###.##
+ ##.###.. ..##.### ##.###..