summaryrefslogtreecommitdiff
path: root/beos
diff options
context:
space:
mode:
Diffstat (limited to 'beos')
-rw-r--r--beos/beos_bitmap.cpp425
-rw-r--r--beos/beos_bitmap.h34
-rw-r--r--beos/beos_fetch_rsrc.cpp371
-rw-r--r--beos/beos_fetch_rsrc.h29
-rw-r--r--beos/beos_filetype.cpp317
-rw-r--r--beos/beos_filetype.h21
-rw-r--r--beos/beos_font.cpp556
-rw-r--r--beos/beos_font.h30
-rw-r--r--beos/beos_gui.cpp1018
-rw-r--r--beos/beos_gui.h57
-rw-r--r--beos/beos_history.cpp181
-rw-r--r--beos/beos_history.h35
-rw-r--r--beos/beos_login.cpp192
-rw-r--r--beos/beos_options.cpp273
-rw-r--r--beos/beos_options.h33
-rw-r--r--beos/beos_plotters.cpp753
-rw-r--r--beos/beos_plotters.h57
-rw-r--r--beos/beos_res.rdef350
-rw-r--r--beos/beos_res.rsrcbin0 -> 11584 bytes
-rw-r--r--beos/beos_scaffolding.cpp1607
-rw-r--r--beos/beos_scaffolding.h71
-rw-r--r--beos/beos_schedule.cpp209
-rw-r--r--beos/beos_schedule.h26
-rw-r--r--beos/beos_throbber.cpp144
-rw-r--r--beos/beos_throbber.h35
-rw-r--r--beos/beos_thumbnail.cpp133
-rw-r--r--beos/beos_treeview.cpp130
-rw-r--r--beos/beos_window.cpp1570
-rw-r--r--beos/beos_window.h64
-rw-r--r--beos/options.h37
l---------beos/res/adblock.css1
-rw-r--r--beos/res/beosdefault.css21
l---------beos/res/ca-bundle.txt1
l---------beos/res/default.css1
l---------beos/res/messages1
-rw-r--r--beos/res/netsurf.xpm317
-rw-r--r--beos/res/throbber.gifbin0 -> 5175 bytes
37 files changed, 9100 insertions, 0 deletions
diff --git a/beos/beos_bitmap.cpp b/beos/beos_bitmap.cpp
new file mode 100644
index 000000000..6f950394f
--- /dev/null
+++ b/beos/beos_bitmap.cpp
@@ -0,0 +1,425 @@
+/*
+ * Copyright 2004 James Bursa <bursa@users.sourceforge.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/>.
+ */
+
+/** \file
+ * Generic bitmap handling (BeOS implementation).
+ *
+ * This implements the interface given by desktop/bitmap.h using BBitmap.
+ */
+
+#include <stdbool.h>
+#include <assert.h>
+#include <string.h>
+#include <Bitmap.h>
+#include <GraphicsDefs.h>
+extern "C" {
+#include "content/content.h"
+#include "image/bitmap.h"
+#include "utils/log.h"
+}
+#include "beos/beos_bitmap.h"
+#include "beos/beos_scaffolding.h"
+
+struct bitmap {
+ BBitmap *primary;
+ BBitmap *shadow; // in NetSurf's ABGR order
+ BBitmap *pretile_x;
+ BBitmap *pretile_y;
+ BBitmap *pretile_xy;
+ bool opaque;
+};
+
+#define MIN_PRETILE_WIDTH 256
+#define MIN_PRETILE_HEIGHT 256
+
+#warning TODO: check rgba order
+#warning TODO: add correct locking (not strictly required)
+
+
+/** Convert to BeOS RGBA32_LITTLE (strictly BGRA) from NetSurf's favoured ABGR format.
+ * Copies the converted data elsewhere. Operation is rotate left 8 bits.
+ *
+ * \param pixels Array of 32-bit values, in the form of ABGR. This will
+ * be overwritten with new data in the form of BGRA.
+ * \param width Width of the bitmap
+ * \param height Height of the bitmap
+ * \param rowstride Number of bytes to skip after each row (this
+ * implementation requires this to be a multiple of 4.)
+ */
+#if 0
+static inline void nsbeos_abgr_to_bgra(void *src, void *dst, int width, int height,
+ size_t rowstride)
+{
+ u_int32_t *from = (u_int32_t *)src;
+ u_int32_t *to = (u_int32_t *)dst;
+
+ rowstride >>= 2;
+
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ u_int32_t e = from[x];
+ to[x] = (e >> 24) | (e << 8);
+ }
+ from += rowstride;
+ to += rowstride;
+ }
+}
+#endif
+static inline void nsbeos_rgba_to_bgra(void *src, void *dst, int width, int height,
+ size_t rowstride)
+{
+ struct abgr { uint8 a, b, g, r; };
+ struct rgba { uint8 r, g, b ,a; };
+ struct bgra { uint8 b, g, r, a; };
+ struct rgba *from = (struct rgba *)src;
+ struct bgra *to = (struct bgra *)dst;
+
+ rowstride >>= 2;
+
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ to[x].b = from[x].b;
+ to[x].g = from[x].g;
+ to[x].r = from[x].r;
+ to[x].a = from[x].a;
+ if (from[x].a == 0)
+ *(rgb_color *)&to[x] = B_TRANSPARENT_32_BIT;
+ }
+ from += rowstride;
+ to += rowstride;
+ }
+}
+
+
+/**
+ * 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
+ */
+
+struct bitmap *bitmap_create(int width, int height, unsigned int state)
+{
+ struct bitmap *bmp = (struct bitmap *)malloc(sizeof(struct bitmap));
+ if (bmp == NULL)
+ return NULL;
+
+ BRect frame(0, 0, width - 1, height - 1);
+ //XXX: bytes per row ?
+ bmp->primary = new BBitmap(frame, 0, B_RGBA32);
+ bmp->shadow = new BBitmap(frame, 0, B_RGBA32);
+
+ bmp->pretile_x = bmp->pretile_y = bmp->pretile_xy = NULL;
+
+ bmp->opaque = false;
+
+#if 0 /* GTK */
+ bmp->primary = gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, 8,
+ width, height);
+
+ /* fill the pixbuf in with 100% transparent black, as the memory
+ * won't have been cleared.
+ */
+ gdk_pixbuf_fill(bmp->primary, 0);
+ bmp->pretile_x = bmp->pretile_y = bmp->pretile_xy = NULL;
+#endif
+ return bmp;
+}
+
+
+/**
+ * Sets whether a bitmap should be plotted opaque
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ * \param opaque whether the bitmap should be plotted opaque
+ */
+void bitmap_set_opaque(struct bitmap *bitmap, bool opaque)
+{
+ assert(bitmap);
+/* todo: set bitmap as opaque */
+ bitmap->opaque = true;
+}
+
+
+/**
+ * Tests whether a bitmap has an opaque alpha channel
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ * \return whether the bitmap is opaque
+ */
+bool bitmap_test_opaque(struct bitmap *bitmap)
+{
+ assert(bitmap);
+/* todo: test if bitmap as opaque */
+ return bitmap->opaque;
+}
+
+
+/**
+ * Gets whether a bitmap should be plotted opaque
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ */
+bool bitmap_get_opaque(struct bitmap *bitmap)
+{
+ assert(bitmap);
+/* todo: get whether bitmap is opaque */
+ return bitmap->opaque;
+}
+
+
+/**
+ * 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().
+ */
+
+char *bitmap_get_buffer(struct bitmap *bitmap)
+{
+ assert(bitmap);
+ return (char *)(bitmap->shadow->Bits());
+}
+
+
+/**
+ * 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
+ */
+
+size_t bitmap_get_rowstride(struct bitmap *bitmap)
+{
+ assert(bitmap);
+ return (bitmap->primary->BytesPerRow());
+}
+
+
+static void
+nsbeos_bitmap_free_pretiles(struct bitmap *bitmap)
+{
+#define FREE_TILE(XY) if (bitmap->pretile_##XY) delete (bitmap->pretile_##XY); bitmap->pretile_##XY = NULL
+ FREE_TILE(x);
+ FREE_TILE(y);
+ FREE_TILE(xy);
+#undef FREE_TILE
+}
+
+/**
+ * Free a bitmap.
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ */
+
+void bitmap_destroy(struct bitmap *bitmap)
+{
+ assert(bitmap);
+ nsbeos_bitmap_free_pretiles(bitmap);
+ delete bitmap->primary;
+ delete bitmap->shadow;
+ free(bitmap);
+}
+
+
+/**
+ * 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 modify the behaviour of the save
+ * \return true on success, false on error and error reported
+ */
+
+bool bitmap_save(struct bitmap *bitmap, const char *path, unsigned flags)
+{
+#warning WRITEME
+#if 0 /* GTK */
+ GError *err = NULL;
+
+ gdk_pixbuf_save(bitmap->primary, path, "png", &err, NULL);
+
+ if (err == NULL)
+ /* TODO: report an error here */
+ return false;
+
+#endif
+ return true;
+}
+
+
+/**
+ * The bitmap image has changed, so flush any persistant cache.
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ */
+void bitmap_modified(struct bitmap *bitmap) {
+ // convert the shadow (ABGR) to into the primary bitmap
+ nsbeos_rgba_to_bgra(bitmap->shadow->Bits(), bitmap->primary->Bits(),
+ bitmap->primary->Bounds().Width() + 1,
+ bitmap->primary->Bounds().Height() + 1,
+ bitmap->primary->BytesPerRow());
+ nsbeos_bitmap_free_pretiles(bitmap);
+}
+
+
+/**
+ * The bitmap image can be suspended.
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ * \param private_word a private word to be returned later
+ * \param suspend the function to be called upon suspension
+ * \param resume the function to be called when resuming
+ */
+void bitmap_set_suspendable(struct bitmap *bitmap, void *private_word,
+ void (*invalidate)(struct bitmap *bitmap, void *private_word)) {
+}
+
+static BBitmap *
+nsbeos_bitmap_generate_pretile(BBitmap *primary, int repeat_x, int repeat_y)
+{
+ int width = primary->Bounds().Width() + 1;
+ int height = primary->Bounds().Height() + 1;
+ size_t primary_stride = primary->BytesPerRow();
+ BRect frame(0, 0, width * repeat_x - 1, height * repeat_y - 1);
+ BBitmap *result = new BBitmap(frame, 0, B_RGBA32);
+
+ char *target_buffer = (char *)result->Bits();
+ int x,y,row;
+ /* This algorithm won't work if the strides are not multiples */
+ assert((size_t)(result->BytesPerRow()) ==
+ (primary_stride * repeat_x));
+
+ if (repeat_x == 1 && repeat_y == 1) {
+ delete result;
+ // just return a copy
+ return new BBitmap(primary);
+ }
+
+ for (y = 0; y < repeat_y; ++y) {
+ char *primary_buffer = (char *)primary->Bits();
+ for (row = 0; row < height; ++row) {
+ for (x = 0; x < repeat_x; ++x) {
+ memcpy(target_buffer,
+ primary_buffer, primary_stride);
+ target_buffer += primary_stride;
+ }
+ primary_buffer += primary_stride;
+ }
+ }
+ return result;
+
+#if 0 /* GTK */
+ BBitmap *result = gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, 8,
+ width * repeat_x, height * repeat_y);
+ char *target_buffer = (char *)gdk_pixbuf_get_pixels(result);
+ int x,y,row;
+ /* This algorithm won't work if the strides are not multiples */
+ assert((size_t)gdk_pixbuf_get_rowstride(result) ==
+ (primary_stride * repeat_x));
+
+ if (repeat_x == 1 && repeat_y == 1) {
+ g_object_ref(primary);
+ g_object_unref(result);
+ return primary;
+ }
+
+ for (y = 0; y < repeat_y; ++y) {
+ char *primary_buffer = (char *)gdk_pixbuf_get_pixels(primary);
+ for (row = 0; row < height; ++row) {
+ for (x = 0; x < repeat_x; ++x) {
+ memcpy(target_buffer,
+ primary_buffer, primary_stride);
+ target_buffer += primary_stride;
+ }
+ primary_buffer += primary_stride;
+ }
+ }
+ return result;
+#endif
+}
+
+/**
+ * The primary image associated with this bitmap object.
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ */
+BBitmap *
+nsbeos_bitmap_get_primary(struct bitmap* bitmap)
+{
+ return bitmap->primary;
+}
+
+/**
+ * The X-pretiled image associated with this bitmap object.
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ */
+BBitmap *
+nsbeos_bitmap_get_pretile_x(struct bitmap* bitmap)
+{
+ if (!bitmap->pretile_x) {
+ int width = bitmap->primary->Bounds().Width() + 1;
+ int xmult = (MIN_PRETILE_WIDTH + width - 1)/width;
+ LOG(("Pretiling %p for X*%d", bitmap, xmult));
+ bitmap->pretile_x = nsbeos_bitmap_generate_pretile(bitmap->primary, xmult, 1);
+ }
+ return bitmap->pretile_x;
+
+}
+
+/**
+ * The Y-pretiled image associated with this bitmap object.
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ */
+BBitmap *
+nsbeos_bitmap_get_pretile_y(struct bitmap* bitmap)
+{
+ if (!bitmap->pretile_y) {
+ int height = bitmap->primary->Bounds().Height() + 1;
+ int ymult = (MIN_PRETILE_HEIGHT + height - 1)/height;
+ LOG(("Pretiling %p for Y*%d", bitmap, ymult));
+ bitmap->pretile_y = nsbeos_bitmap_generate_pretile(bitmap->primary, 1, ymult);
+ }
+ return bitmap->pretile_y;
+}
+
+/**
+ * The XY-pretiled image associated with this bitmap object.
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ */
+BBitmap *
+nsbeos_bitmap_get_pretile_xy(struct bitmap* bitmap)
+{
+ if (!bitmap->pretile_xy) {
+ int width = bitmap->primary->Bounds().Width() + 1;
+ int height = bitmap->primary->Bounds().Height() + 1;
+ int xmult = (MIN_PRETILE_WIDTH + width - 1)/width;
+ int ymult = (MIN_PRETILE_HEIGHT + height - 1)/height;
+ LOG(("Pretiling %p for X*%d Y*%d", bitmap, xmult, ymult));
+ bitmap->pretile_xy = nsbeos_bitmap_generate_pretile(bitmap->primary, xmult, ymult);
+ }
+ return bitmap->pretile_xy;
+}
diff --git a/beos/beos_bitmap.h b/beos/beos_bitmap.h
new file mode 100644
index 000000000..cecff4713
--- /dev/null
+++ b/beos/beos_bitmap.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2006 Daniel Silverstone <dsilvers@digital-scurf.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 NS_BEOS_BITMAP_H
+#define NS_BEOS_BITMAP_H
+
+#include <Bitmap.h>
+extern "C" {
+#include "image/bitmap.h"
+}
+
+BBitmap *nsbeos_bitmap_get_primary(struct bitmap*);
+BBitmap *nsbeos_bitmap_get_pretile_x(struct bitmap*);
+BBitmap *nsbeos_bitmap_get_pretile_y(struct bitmap*);
+BBitmap *nsbeos_bitmap_get_pretile_xy(struct bitmap*);
+
+
+
+#endif /* NS_BEOS_BITMAP_H */
diff --git a/beos/beos_fetch_rsrc.cpp b/beos/beos_fetch_rsrc.cpp
new file mode 100644
index 000000000..579953e0d
--- /dev/null
+++ b/beos/beos_fetch_rsrc.cpp
@@ -0,0 +1,371 @@
+/*
+ * Copyright 2008 Rob Kendrick <rjek@netsurf-browser.org>
+ *
+ * This file is part of NetSurf.
+ *
+ * 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/>.
+ */
+
+/* rsrc: URL handling. */
+#warning XXX: WRITEME
+
+#define _GNU_SOURCE
+
+#include <assert.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <string.h>
+#include <strings.h>
+#include <time.h>
+#include <sys/select.h>
+#include <sys/stat.h>
+#include <sys/utsname.h>
+#include <curl/curl.h> /* for URL unescaping functions */
+extern "C" {
+#include "utils/config.h"
+#include "content/fetch.h"
+#include "content/urldb.h"
+#include "desktop/netsurf.h"
+#include "desktop/options.h"
+#include "render/form.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/url.h"
+#include "utils/utils.h"
+#include "utils/ring.h"
+#include "utils/base64.h"
+}
+#include "beos/beos_fetch_rsrc.h"
+
+#include <image.h>
+#include <Resources.h>
+
+struct fetch_rsrc_context {
+ struct fetch *parent_fetch;
+ char *name;
+ char *url;
+ char *mimetype;
+ char *data;
+ size_t datalen;
+
+ bool aborted;
+ bool locked;
+
+ struct fetch_rsrc_context *r_next, *r_prev;
+};
+
+static struct fetch_rsrc_context *ring = NULL;
+
+static BResources *gAppResources = NULL;
+
+static bool fetch_rsrc_initialise(const char *scheme)
+{
+ LOG(("fetch_rsrc_initialise called for %s", scheme));
+ return true;
+}
+
+static void fetch_rsrc_finalise(const char *scheme)
+{
+ LOG(("fetch_rsrc_finalise called for %s", scheme));
+}
+
+static void *fetch_rsrc_setup(struct fetch *parent_fetch, const char *url,
+ bool only_2xx, const char *post_urlenc,
+ struct form_successful_control *post_multipart,
+ const char **headers)
+{
+ struct fetch_rsrc_context *ctx;
+ ctx = (struct fetch_rsrc_context *)calloc(1, sizeof(*ctx));
+
+ if (ctx == NULL)
+ return NULL;
+
+ ctx->parent_fetch = parent_fetch;
+ ctx->url = strdup(url);
+
+ if (ctx->url == NULL) {
+ free(ctx);
+ return NULL;
+ }
+
+ RING_INSERT(ring, ctx);
+
+ return ctx;
+}
+
+static bool fetch_rsrc_start(void *ctx)
+{
+ return true;
+}
+
+static void fetch_rsrc_free(void *ctx)
+{
+ struct fetch_rsrc_context *c = (struct fetch_rsrc_context *)ctx;
+
+ free(c->name);
+ free(c->url);
+ free(c->data);
+ free(c->mimetype);
+ RING_REMOVE(ring, c);
+ free(ctx);
+}
+
+static void fetch_rsrc_abort(void *ctx)
+{
+ struct fetch_rsrc_context *c = (struct fetch_rsrc_context *)ctx;
+
+ /* To avoid the poll loop having to deal with the fetch context
+ * disappearing from under it, we simply flag the abort here.
+ * The poll loop itself will perform the appropriate cleanup.
+ */
+ c->aborted = true;
+}
+
+static void fetch_rsrc_send_callback(fetch_msg msg,
+ struct fetch_rsrc_context *c, const void *data,
+ unsigned long size)
+{
+ c->locked = true;
+ fetch_send_callback(msg, c->parent_fetch, data, size);
+ c->locked = false;
+}
+
+static bool fetch_rsrc_process(struct fetch_rsrc_context *c)
+{
+ char *params;
+ char *at = NULL;
+ char *slash;
+ char *comma = NULL;
+ char *unescaped;
+ uint32 type = 'data'; // default for embeded files
+ int32 id = 0;
+
+ /* format of a rsrc: URL is:
+ * rsrc:[TYPE][@NUM]/name[,mime]
+ */
+
+ LOG(("*** Processing %s", c->url));
+
+ if (strlen(c->url) < 6) {
+ /* 6 is the minimum possible length (rsrc:/) */
+ fetch_rsrc_send_callback(FETCH_ERROR, c,
+ "Malformed rsrc: URL", 0);
+ return false;
+ }
+
+ /* skip the rsrc: part */
+ params = c->url + sizeof("rsrc:") - 1;
+
+ /* find the slash */
+ if ( (slash = strchr(params, '/')) == NULL) {
+ fetch_rsrc_send_callback(FETCH_ERROR, c,
+ "Malformed rsrc: URL", 0);
+ return false;
+ }
+ comma = strchr(slash, ',');
+ c->name = strdup(slash + 1);
+
+ if (!comma) {
+ /* there is no mimetype here, assume text/plain */
+ c->mimetype = strdup("text/plain;charset=US-ASCII");
+ } else {
+ /* make a copy of everything after the comma */
+ c->mimetype = strdup(comma + 1);
+ c->name[strlen(c->name) - strlen(comma)] = '\0';
+ }
+
+ if (c->mimetype == NULL) {
+ fetch_rsrc_send_callback(FETCH_ERROR, c,
+ "Unable to allocate memory for mimetype in rsrc: URL",
+ 0);
+ return false;
+ }
+
+ if (params[0] != '/') {
+ uint8 c1, c2, c3, c4;
+ if (sscanf(params, "%c%c%c%c", &c1, &c2, &c3, &c4) > 3) {
+ type = c1 << 24 | c2 << 16 | c3 << 8 | c4;
+ printf("type:%4.4s\n", &type);
+ }
+ }
+
+ fprintf(stderr, "fetch_rsrc: 0x%08lx, %ld, '%s'\n", type, id, c->name);
+
+ bool found;
+ if (id)
+ found = gAppResources->HasResource(type, id);
+ else
+ found = gAppResources->HasResource(type, c->name);
+ if (!found) {
+ fetch_rsrc_send_callback(FETCH_ERROR, c,
+ "Cannot locate rsrc: URL",
+ 0);
+ return false;
+ }
+
+ size_t len;
+ const void *data;
+ if (id)
+ data = gAppResources->LoadResource(type, id, &len);
+ else
+ data = gAppResources->LoadResource(type, c->name, &len);
+
+ if (!data) {
+ fetch_rsrc_send_callback(FETCH_ERROR, c,
+ "Cannot load rsrc: URL",
+ 0);
+ return false;
+ }
+
+ c->datalen = len;
+ c->data = (char *)malloc(c->datalen);
+ if (c->data == NULL) {
+ fetch_rsrc_send_callback(FETCH_ERROR, c,
+ "Unable to allocate memory for rsrc: URL", 0);
+ return false;
+ }
+ memcpy(c->data, data, c->datalen);
+
+ return true;
+}
+
+static void fetch_rsrc_poll(const char *scheme)
+{
+ struct fetch_rsrc_context *c, *next;
+ struct cache_data cachedata;
+
+ if (ring == NULL) return;
+
+ cachedata.req_time = time(NULL);
+ cachedata.res_time = time(NULL);
+ cachedata.date = 0;
+ cachedata.expires = 0;
+ cachedata.age = INVALID_AGE;
+ cachedata.max_age = 0;
+ cachedata.no_cache = true;
+ cachedata.etag = NULL;
+ cachedata.last_modified = 0;
+
+ /* Iterate over ring, processing each pending fetch */
+ c = ring;
+ do {
+ /* Take a copy of the next pointer as we may destroy
+ * the ring item we're currently processing */
+ next = c->r_next;
+
+ /* Ignore fetches that have been flagged as locked.
+ * This allows safe re-entrant calls to this function.
+ * Re-entrancy can occur if, as a result of a callback,
+ * the interested party causes fetch_poll() to be called
+ * again.
+ */
+ if (c->locked == true) {
+ continue;
+ }
+
+ /* Only process non-aborted fetches */
+ if (!c->aborted && fetch_rsrc_process(c) == true) {
+ fetch_set_http_code(c->parent_fetch, 200);
+ LOG(("setting rsrc: MIME type to %s, length to %zd",
+ c->mimetype, c->datalen));
+ /* Any callback can result in the fetch being aborted.
+ * Therefore, we _must_ check for this after _every_
+ * call to fetch_rsrc_send_callback().
+ */
+ fetch_rsrc_send_callback(FETCH_TYPE,
+ c, c->mimetype, c->datalen);
+ if (!c->aborted) {
+ fetch_rsrc_send_callback(FETCH_DATA,
+ c, c->data, c->datalen);
+ }
+ if (!c->aborted) {
+ fetch_rsrc_send_callback(FETCH_FINISHED,
+ c, &cachedata, 0);
+ }
+ } else {
+ LOG(("Processing of %s failed!", c->url));
+
+ /* Ensure that we're unlocked here. If we aren't,
+ * then fetch_rsrc_process() is broken.
+ */
+ assert(c->locked == false);
+ }
+
+ fetch_remove_from_queues(c->parent_fetch);
+ fetch_free(c->parent_fetch);
+
+ /* Advance to next ring entry, exiting if we've reached
+ * the start of the ring or the ring has become empty
+ */
+ } while ( (c = next) != ring && ring != NULL);
+}
+
+/* BAppFileInfo is supposed to find the app's resources for us,
+ * but this won't work if we ever want to be used as a replicant.
+ * This trick should work regardless,
+ */
+static int find_app_resources()
+{
+ image_info info;
+ const char *path = NULL;
+ int32 cookie = 0;
+ while (get_next_image_info(0, &cookie, &info) == B_OK) {
+//fprintf(stderr, "%p <> %p, %p\n", (char *)&find_app_resources, (char *)info.text, (char *)info.text + info.text_size);
+ if (((char *)&find_app_resources >= (char *)info.text)
+ && ((char *)&find_app_resources < (char *)info.text + info.text_size)) {
+//fprintf(stderr, "match\n");
+ path = info.name;
+ break;
+ }
+ }
+ if (path == NULL)
+ return B_ERROR;
+
+//fprintf(stderr, "loading resources from '%s'\n", path);
+
+ BFile file(path, B_READ_ONLY);
+ if (file.InitCheck() < 0)
+ return file.InitCheck();
+ gAppResources = new BResources;
+ status_t err;
+ err = gAppResources->SetTo(&file);
+ if (err >= B_OK)
+ return B_OK;
+ delete gAppResources;
+ gAppResources = NULL;
+ return err;
+}
+
+void fetch_rsrc_register(void)
+{
+ int err;
+ err = find_app_resources();
+ if (err < B_OK) {
+ warn_user("Resources", strerror(err));
+ return;
+ }
+ fetch_add_fetcher("rsrc",
+ fetch_rsrc_initialise,
+ fetch_rsrc_setup,
+ fetch_rsrc_start,
+ fetch_rsrc_abort,
+ fetch_rsrc_free,
+ fetch_rsrc_poll,
+ fetch_rsrc_finalise);
+}
+
+void fetch_rsrc_unregister(void)
+{
+ delete gAppResources;
+ gAppResources = NULL;
+}
diff --git a/beos/beos_fetch_rsrc.h b/beos/beos_fetch_rsrc.h
new file mode 100644
index 000000000..529a1efeb
--- /dev/null
+++ b/beos/beos_fetch_rsrc.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2008 Rob Kendrick <rjek@netsurf-browser.org>
+ *
+ * This file is part of NetSurf.
+ *
+ * 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
+ * rsrc: URL method handler
+ */
+
+#ifndef NETSURF_BEOS_FETCH_DATA_H
+#define NETSURF_BEOS_FETCH_DATA_H
+
+void fetch_rsrc_register(void);
+void fetch_rsrc_unregister(void);
+
+#endif
diff --git a/beos/beos_filetype.cpp b/beos/beos_filetype.cpp
new file mode 100644
index 000000000..a1211eab3
--- /dev/null
+++ b/beos/beos_filetype.cpp
@@ -0,0 +1,317 @@
+/*
+ * Copyright 2007 Rob Kendrick <rjek@netsurf-browser.org>
+ * Copyright 2007 Vincent Sanders <vince@debian.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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <Mime.h>
+#include <NodeInfo.h>
+#include <String.h>
+
+extern "C" {
+#include "content/fetch.h"
+#include "utils/log.h"
+#include "utils/hashtable.h"
+#include "utils/utils.h"
+}
+
+#include "beos/beos_filetype.h"
+
+#warning REMOVEME
+static struct hash_table *mime_hash = NULL;
+
+void beos_fetch_filetype_init(const char *mimefile)
+{
+ BMessage mimes;
+ status_t err;
+
+ err = BMimeType::GetInstalledTypes(&mimes);
+ if (err < B_OK) {
+ warn_user("Mime", strerror(err));
+ return;
+ }
+
+ mime_hash = hash_create(117);
+
+ // just in case
+ hash_add(mime_hash, "css", "text/css");
+ hash_add(mime_hash, "htm", "text/html");
+ hash_add(mime_hash, "html", "text/html");
+ hash_add(mime_hash, "jpg", "image/jpeg");
+ hash_add(mime_hash, "jpeg", "image/jpeg");
+ hash_add(mime_hash, "gif", "image/gif");
+ hash_add(mime_hash, "png", "image/png");
+ hash_add(mime_hash, "jng", "image/jng");
+
+
+ BString type;
+ int i, j;
+ //mimes.PrintToStream();
+ for (i = 0; mimes.FindString("types", i, &type) >= B_OK; i++) {
+ BMimeType mime(type.String());
+ if (!mime.IsValid())
+ continue;
+ BMessage extensions;
+ if (mime.GetFileExtensions(&extensions) < B_OK)
+ continue;
+ BString ext;
+ for (j = 0; extensions.FindString("extentions", i, &ext) >= B_OK; i++) {
+ hash_add(mime_hash, ext.String(), type.String());
+ }
+ }
+
+#warning WRITEME
+#if 0
+ struct stat statbuf;
+ FILE *fh = NULL;
+
+ /* first, check to see if /etc/mime.types in preference */
+
+ if ((stat("/etc/mime.types", &statbuf) == 0) &&
+ S_ISREG(statbuf.st_mode)) {
+ mimefile = "/etc/mime.types";
+
+ }
+
+ fh = fopen(mimefile, "r");
+
+ /* Some OSes (mentioning no Solarises) have a worthlessly tiny
+ * /etc/mime.types that don't include essential things, so we
+ * pre-seed our hash with the essentials. These will get
+ * over-ridden if they are mentioned in the mime.types file.
+ */
+
+ hash_add(mime_hash, "css", "text/css");
+ hash_add(mime_hash, "htm", "text/html");
+ hash_add(mime_hash, "html", "text/html");
+ hash_add(mime_hash, "jpg", "image/jpeg");
+ hash_add(mime_hash, "jpeg", "image/jpeg");
+ hash_add(mime_hash, "gif", "image/gif");
+ hash_add(mime_hash, "png", "image/png");
+ hash_add(mime_hash, "jng", "image/jng");
+
+ if (fh == NULL) {
+ LOG(("Unable to open a mime.types file, so using a minimal one for you."));
+ return;
+ }
+
+ while (!feof(fh)) {
+ char line[256], *ptr, *type, *ext;
+ fgets(line, 256, fh);
+ if (!feof(fh) && line[0] != '#') {
+ ptr = line;
+
+ /* search for the first non-whitespace character */
+ while (isspace(*ptr))
+ ptr++;
+
+ /* is this line empty other than leading whitespace? */
+ if (*ptr == '\n' || *ptr == '\0')
+ continue;
+
+ type = ptr;
+
+ /* search for the first non-whitespace char or NUL or
+ * NL */
+ while (*ptr && (!isspace(*ptr)) && *ptr != '\n')
+ ptr++;
+
+ if (*ptr == '\0' || *ptr == '\n') {
+ /* this mimetype has no extensions - read next
+ * line.
+ */
+ continue;
+ }
+
+ *ptr++ = '\0';
+
+ /* search for the first non-whitespace character which
+ * will be the first filename extenion */
+ while (isspace(*ptr))
+ ptr++;
+
+ while(true) {
+ ext = ptr;
+
+ /* search for the first whitespace char or
+ * NUL or NL which is the end of the ext.
+ */
+ while (*ptr && (!isspace(*ptr)) &&
+ *ptr != '\n')
+ ptr++;
+
+ if (*ptr == '\0' || *ptr == '\n') {
+ /* special case for last extension on
+ * the line
+ */
+ *ptr = '\0';
+ hash_add(mime_hash, ext, type);
+ break;
+ }
+
+ *ptr++ = '\0';
+ hash_add(mime_hash, ext, type);
+
+ /* search for the first non-whitespace char or
+ * NUL or NL, to find start of next ext.
+ */
+ while (*ptr && (isspace(*ptr)) && *ptr != '\n')
+ ptr++;
+ }
+ }
+ }
+
+ fclose(fh);
+#endif
+}
+
+void beos_fetch_filetype_fin(void)
+{
+ hash_destroy(mime_hash);
+}
+
+const char *fetch_filetype(const char *unix_path)
+{
+ struct stat statbuf;
+ status_t err;
+
+ stat(unix_path, &statbuf);
+ if (S_ISDIR(statbuf.st_mode))
+ return "application/x-netsurf-directory";
+
+ if (strchr(unix_path, '.') == NULL) {
+ /* no extension anywhere! */
+ return "text/plain";
+ }
+
+ // force some types
+ const char *ext;
+ ext = strrchr(unix_path, '.');
+ if (!strcmp(ext, ".css"))
+ return "text/css";
+ if (!strcmp(ext, ".html"))
+ return "text/html";
+ if (!strcmp(ext, ".htm"))
+ return "text/html";
+
+ BNode node(unix_path);
+ if (node.InitCheck() < B_OK) {
+ warn_user("Mime", strerror(err));
+ return "text/plain";
+ }
+
+ BNodeInfo info(&node);
+ if (info.InitCheck() < B_OK) {
+ warn_user("Mime", strerror(err));
+ return "text/plain";
+ }
+
+ // NOT THREADSAFE
+ static char type[B_MIME_TYPE_LENGTH];
+ if (info.GetType(type) < B_OK) {
+ // it might not have been sniffed yet...
+ update_mime_info(unix_path, false, true, false);
+ // try again
+ if (info.GetType(type) < B_OK) {
+ warn_user("Mime", strerror(err));
+ return "text/plain";
+ }
+ }
+
+ return type;
+
+#warning WRITEME
+#if 0
+ struct stat statbuf;
+ char *ext;
+ const char *ptr;
+ char *lowerchar;
+ const char *type;
+
+ stat(unix_path, &statbuf);
+ if (S_ISDIR(statbuf.st_mode))
+ return "application/x-netsurf-directory";
+
+ if (strchr(unix_path, '.') == NULL) {
+ /* no extension anywhere! */
+ return "text/plain";
+ }
+
+ ptr = unix_path + strlen(unix_path);
+ while (*ptr != '.' && *ptr != '/')
+ ptr--;
+
+ if (*ptr != '.')
+ return "text/plain";
+
+ ext = strdup(ptr + 1); /* skip the . */
+
+ /* the hash table only contains lower-case versions - make sure this
+ * copy is lower case too.
+ */
+ lowerchar = ext;
+ while(*lowerchar) {
+ *lowerchar = tolower(*lowerchar);
+ lowerchar++;
+ }
+
+ type = hash_get(mime_hash, ext);
+ free(ext);
+
+ return type != NULL ? type : "text/plain";
+#endif
+ return NULL;
+}
+
+char *fetch_mimetype(const char *unix_path)
+{
+ return strdup(fetch_filetype(unix_path));
+}
+
+#ifdef TEST_RIG
+
+int main(int argc, char *argv[])
+{
+ unsigned int c1, *c2;
+ const char *key;
+
+ beos_fetch_filetype_init("./mime.types");
+
+ c1 = 0; c2 = 0;
+
+ while ( (key = hash_iterate(mime_hash, &c1, &c2)) != NULL) {
+ printf("%s ", key);
+ }
+
+ printf("\n");
+
+ if (argc > 1) {
+ printf("%s maps to %s\n", argv[1], fetch_filetype(argv[1]));
+ }
+
+ beos_fetch_filetype_fin();
+}
+
+#endif
diff --git a/beos/beos_filetype.h b/beos/beos_filetype.h
new file mode 100644
index 000000000..d07ed698a
--- /dev/null
+++ b/beos/beos_filetype.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2007 Rob Kendrick <rjek@netsurf-browser.org>
+ * Copyright 2007 Vincent Sanders <vince@debian.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/>.
+ */
+
+void beos_fetch_filetype_init(const char *mimefile);
+void beos_fetch_filetype_fin(void);
diff --git a/beos/beos_font.cpp b/beos/beos_font.cpp
new file mode 100644
index 000000000..89c6736fb
--- /dev/null
+++ b/beos/beos_font.cpp
@@ -0,0 +1,556 @@
+/*
+ * Copyright 2005 James Bursa <bursa@users.sourceforge.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/>.
+ */
+
+/** \file
+ * Font handling (BeOS implementation).
+ * TODO: check for correctness, the code is taken from the GTK one.
+ * maybe use the current view instead of constructing a new BFont each time ?
+ */
+
+
+#include <stdbool.h>
+#include <assert.h>
+#include <stdio.h>
+#include <Font.h>
+#include <String.h>
+#include <View.h>
+extern "C" {
+#include "css/css.h"
+#include "render/font.h"
+#include "utils/utils.h"
+#include "utils/log.h"
+#include "desktop/options.h"
+}
+
+#include "beos/beos_gui.h"
+#include "beos/beos_font.h"
+#include "beos/beos_plotters.h"
+
+static void nsfont_style_to_font(BFont &font,
+ const struct css_style *style);
+
+/**
+ * Measure the width of a string.
+ *
+ * \param style css_style for this text, with style->font_size.size ==
+ * CSS_FONT_SIZE_LENGTH
+ * \param string UTF-8 string to measure
+ * \param length length of string
+ * \param width updated to width of string[0..length)
+ * \return true on success, false on error and error reported
+ */
+
+bool nsfont_width(const struct css_style *style,
+ const char *string, size_t length,
+ int *width)
+{
+ //fprintf(stderr, "%s(, '%s', %d, )\n", __FUNCTION__, string, length);
+ BFont font;
+#if 0 /* GTK */
+ PangoContext *context;
+ PangoLayout *layout;
+#endif
+
+ if (length == 0) {
+ *width = 0;
+ return true;
+ }
+
+ nsfont_style_to_font(font, style);
+ *width = (int)font.StringWidth(string, length);
+ return true;
+#if 0 /* GTK */
+ context = gdk_pango_context_get();
+ layout = pango_layout_new(context);
+ pango_layout_set_font_description(layout, desc);
+ pango_layout_set_text(layout, string, length);
+
+ pango_layout_get_pixel_size(layout, width, 0);
+
+ g_object_unref(layout);
+ g_object_unref(context);
+ pango_font_description_free(desc);
+#endif
+ return true;
+}
+
+
+static int utf8_char_len(const char *c)
+{
+ uint8 *p = (uint8 *)c;
+ uint8 m = 0xE0;
+ uint8 v = 0xC0;
+ int i;
+ if (!*p)
+ return 0;
+ if ((*p & 0x80) == 0)
+ return 1;
+ if ((*p & 0xC0) == 0x80)
+ return 1; // actually one of the remaining bytes...
+ for (i = 2; i < 5; i++) {
+ if ((*p & m) == v)
+ return i;
+ v = (v >> 1) | 0x80;
+ m = (m >> 1) | 0x80;
+ }
+ return i;
+}
+
+/**
+ * Find the position in a string where an x coordinate falls.
+ *
+ * \param style css_style for this text, with style->font_size.size ==
+ * CSS_FONT_SIZE_LENGTH
+ * \param string UTF-8 string to measure
+ * \param length length of string
+ * \param x x coordinate to search for
+ * \param char_offset updated to offset in string of actual_x, [0..length]
+ * \param actual_x updated to x coordinate of character closest to x
+ * \return true on success, false on error and error reported
+ */
+
+bool nsfont_position_in_string(const struct css_style *style,
+ const char *string, size_t length,
+ int x, size_t *char_offset, int *actual_x)
+{
+ //LOG(("(, '%s', %d, %d, , )", string, length, x));
+ //fprintf(stderr, "%s(, '%s', %d, %d, , )\n", __FUNCTION__, string, length, x);
+ int index;
+ BFont font;
+#if 0 /* GTK */
+ PangoFontDescription *desc;
+ PangoContext *context;
+ PangoLayout *layout;
+ PangoRectangle pos;
+#endif
+
+ nsfont_style_to_font(font, style);
+ BString str(string);
+ int32 len = str.CountChars();
+ float escapements[len];
+ float esc = 0.0;
+ float current = 0.0;
+ int i;
+ index = 0;
+ font.GetEscapements(string, len, escapements);
+ // slow but it should work
+ for (i = 0; string[index] && i < len; i++) {
+ if (x < current)
+ break;
+ esc += escapements[i];
+ current = font.Size() * esc;
+ index += utf8_char_len(&string[index]);
+ }
+ *actual_x = (int)current;
+ *char_offset = i; //index;
+#if 0 /* GTK */
+ context = gdk_pango_context_get();
+ layout = pango_layout_new(context);
+ pango_layout_set_font_description(layout, desc);
+ pango_layout_set_text(layout, string, length);
+
+ pango_layout_xy_to_index(layout, x * PANGO_SCALE, 0, &index, 0);
+ if (pango_layout_xy_to_index(layout, x * PANGO_SCALE,
+ 0, &index, 0) == 0)
+ index = length;
+
+ pango_layout_index_to_pos(layout, index, &pos);
+
+ g_object_unref(layout);
+ g_object_unref(context);
+ pango_font_description_free(desc);
+
+ *char_offset = index;
+ *actual_x = PANGO_PIXELS(pos.x);
+#endif
+
+ return true;
+}
+
+
+/**
+ * Find where to split a string to make it fit a width.
+ *
+ * \param style css_style for this text, with style->font_size.size ==
+ * CSS_FONT_SIZE_LENGTH
+ * \param string UTF-8 string to measure
+ * \param length length of string
+ * \param x width available
+ * \param char_offset updated to offset in string of actual_x, [0..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 == 0 ||
+ * string[char_offset] == ' ' ||
+ * char_offset == length]
+ */
+
+bool nsfont_split(const struct css_style *style,
+ const char *string, size_t length,
+ int x, size_t *char_offset, int *actual_x)
+{
+ //fprintf(stderr, "%s(, '%s', %d, %d, , )\n", __FUNCTION__, string, length, x);
+ //LOG(("(, '%s', %d, %d, , )", string, length, x));
+ int index = 0;
+ BFont font;
+#if 0 /* GTK */
+ PangoFontDescription *desc;
+ PangoContext *context;
+ PangoLayout *layout;
+ PangoLayoutLine *line;
+ PangoLayoutIter *iter;
+ PangoRectangle rect;
+#endif
+
+ nsfont_style_to_font(font, style);
+ BString str(string);
+ int32 len = str.CountChars();
+ float escapements[len];
+ float esc = 0.0;
+ float current = 0.0;
+ float last_x = 0.0;
+ int i;
+ int last_space = 0;
+ font.GetEscapements(string, len, escapements);
+ // slow but it should work
+ for (i = 0; string[index] && i < len; i++) {
+ if (string[index] == ' ') {
+ last_x = current;
+ last_space = index;
+ }
+ if (x < current) {
+ *actual_x = (int)last_x;
+ *char_offset = last_space;
+ return true;
+ }
+ esc += escapements[i];
+ current = font.Size() * esc;
+ index += utf8_char_len(&string[index]);
+ }
+ *actual_x = MIN(*actual_x, (int)current);
+ *char_offset = index;
+ return true;
+
+#if 0 /* GTK */
+ context = gdk_pango_context_get();
+ layout = pango_layout_new(context);
+ pango_layout_set_font_description(layout, desc);
+ pango_layout_set_text(layout, string, length);
+
+ pango_layout_set_width(layout, x * PANGO_SCALE);
+ pango_layout_set_wrap(layout, PANGO_WRAP_WORD);
+ line = pango_layout_get_line(layout, 1);
+ if (line)
+ index = line->start_index - 1;
+
+ iter = pango_layout_get_iter(layout);
+ pango_layout_iter_get_line_extents(iter, NULL, &rect);
+ pango_layout_iter_free(iter);
+
+ g_object_unref(layout);
+ g_object_unref(context);
+ pango_font_description_free(desc);
+
+ *char_offset = index;
+ *actual_x = PANGO_PIXELS(rect.width);
+#endif
+
+ return true;
+}
+
+
+/**
+ * Render a string.
+ *
+ * \param style css_style for this text, with style->font_size.size ==
+ * CSS_FONT_SIZE_LENGTH
+ * \param string UTF-8 string to measure
+ * \param length length of string
+ * \param x x coordinate
+ * \param y y coordinate
+ * \param c colour for text
+ * \return true on success, false on error and error reported
+ */
+
+bool nsfont_paint(const struct css_style *style,
+ const char *string, size_t length,
+ int x, int y, colour bg, colour c)
+{
+ //fprintf(stderr, "%s(, '%s', %d, %d, %d, )\n", __FUNCTION__, string, length, x, y);
+ //CALLED();
+ BFont font;
+ rgb_color oldbg;
+ rgb_color background;
+ rgb_color foreground;
+ BView *view;
+ float size;
+
+ if (length == 0)
+ return true;
+
+ nsfont_style_to_font(font, style);
+ background = nsbeos_rgb_colour(bg);
+ foreground = nsbeos_rgb_colour(c);
+
+ view = nsbeos_current_gc/*_lock*/();
+ if (view == NULL) {
+ warn_user("No GC", 0);
+ return false;
+ }
+
+ oldbg = view->LowColor();
+ drawing_mode oldmode = view->DrawingMode();
+#if 0
+ if (oldbg != background)
+ view->SetLowColor(background);
+#endif
+ view->SetLowColor(B_TRANSPARENT_32_BIT);
+
+ //view->SetScale() XXX
+
+//printf("nsfont_paint: Size: %f\n", font.Size());
+ size = (float)(font.Size() * nsbeos_plot_get_scale());
+#warning XXX use scale
+
+ view->SetFont(&font);
+ view->SetHighColor(foreground);
+ view->SetDrawingMode(B_OP_OVER);
+
+ BString line(string, length);
+
+ BPoint where(x, y + 1);
+ view->DrawString(line.String(), where);
+
+ view->SetDrawingMode(oldmode);
+ if (oldbg != background)
+ view->SetLowColor(oldbg);
+
+ //nsbeos_current_gc_unlock();
+
+#if 0 /* GTK */
+ size = (float)((double)pango_font_description_get_size(desc) * nsgtk_plot_get_scale());
+ if (pango_font_description_get_size_is_absolute(desc))
+ pango_font_description_set_absolute_size(desc, size);
+ else
+ pango_font_description_set_size(desc, size);
+
+ PangoFontDescription *desc;
+ PangoLayout *layout;
+ gint size;
+#ifdef CAIRO_VERSION
+ int width, height;
+#else
+ PangoLayoutLine *line;
+ PangoContext *context;
+ GdkColor colour = { 0,
+ ((c & 0xff) << 8) | (c & 0xff),
+ (c & 0xff00) | (c & 0xff00 >> 8),
+ ((c & 0xff0000) >> 8) | (c & 0xff0000 >> 16) };
+#endif
+
+ if (length == 0)
+ return true;
+
+ desc = nsfont_style_to_font(font, style);
+ size = (gint)((double)pango_font_description_get_size(desc) * nsgtk_plot_get_scale());
+ if (pango_font_description_get_size_is_absolute(desc))
+ pango_font_description_set_absolute_size(desc, size);
+ else
+ pango_font_description_set_size(desc, size);
+
+#ifdef CAIRO_VERSION
+ layout = pango_cairo_create_layout(current_cr);
+#else
+ context = gdk_pango_context_get();
+ layout = pango_layout_new(context);
+#endif
+
+ pango_layout_set_font_description(layout, desc);
+ pango_layout_set_text(layout, string, length);
+
+#ifdef CAIRO_VERSION
+ pango_layout_get_pixel_size(layout, &width, &height);
+ cairo_move_to(current_cr, x, y - height);
+ nsgtk_set_colour(c);
+ pango_cairo_show_layout(current_cr, layout);
+#else
+ line = pango_layout_get_line(layout, 0);
+ gdk_draw_layout_line_with_colors(current_drawable, current_gc,
+ x, y, line, &colour, 0);
+
+ g_object_unref(context);
+#endif
+ g_object_unref(layout);
+ pango_font_description_free(desc);
+#endif
+
+ return true;
+}
+
+
+/**
+ * Convert a css_style to a PangoFontDescription.
+ *
+ * \param style css_style for this text, with style->font_size.size ==
+ * CSS_FONT_SIZE_LENGTH
+ * \return a new Pango font description
+ */
+
+static void nsfont_style_to_font(BFont &font,
+ const struct css_style *style)
+{
+ float size;
+ uint16 face = 0;
+ const char *family;
+// PangoFontDescription *desc;
+// PangoWeight weight = PANGO_WEIGHT_NORMAL;
+// PangoStyle styl = PANGO_STYLE_NORMAL;
+
+ assert(style->font_size.size == CSS_FONT_SIZE_LENGTH);
+
+ switch (style->font_family) {
+ case CSS_FONT_FAMILY_SERIF:
+ family = option_font_serif;
+ break;
+ case CSS_FONT_FAMILY_MONOSPACE:
+ family = option_font_mono;
+ break;
+ case CSS_FONT_FAMILY_CURSIVE:
+ family = option_font_cursive;
+ break;
+ case CSS_FONT_FAMILY_FANTASY:
+ family = option_font_fantasy;
+ break;
+ case CSS_FONT_FAMILY_SANS_SERIF:
+ default:
+ family = option_font_sans;
+ break;
+ }
+
+
+ switch (style->font_style) {
+ case CSS_FONT_STYLE_ITALIC:
+ face = B_ITALIC_FACE;
+ break;
+ case CSS_FONT_STYLE_OBLIQUE:
+ face = B_ITALIC_FACE;
+ // XXX: no OBLIQUE flag ??
+ // maybe find "Oblique" style
+ // or use SetShear() ?
+ break;
+ default:
+ break;
+ }
+
+ switch (style->font_weight) {
+ case CSS_FONT_WEIGHT_NORMAL:
+ break;
+ case CSS_FONT_WEIGHT_BOLD:
+ case CSS_FONT_WEIGHT_600:
+ case CSS_FONT_WEIGHT_700:
+#ifndef __HAIKU__XXX
+ case CSS_FONT_WEIGHT_800:
+ case CSS_FONT_WEIGHT_900:
+#endif
+ face |= B_BOLD_FACE; break;
+#ifdef __HAIKU__XXX
+ case CSS_FONT_WEIGHT_BOLDER:
+ case CSS_FONT_WEIGHT_800:
+ case CSS_FONT_WEIGHT_900:
+ face |= B_HEAVY_FACE; break;
+ case CSS_FONT_WEIGHT_100:
+ case CSS_FONT_WEIGHT_200:
+ case CSS_FONT_WEIGHT_300:
+ case CSS_FONT_WEIGHT_LIGHTER:
+ face |= B_LIGHT_FACE; break;
+#endif
+/*
+ case CSS_FONT_WEIGHT_100: weight = 100; break;
+ case CSS_FONT_WEIGHT_200: weight = 200; break;
+ case CSS_FONT_WEIGHT_300: weight = 300; break;
+ case CSS_FONT_WEIGHT_400: weight = 400; break;
+ case CSS_FONT_WEIGHT_500: weight = 500; break;
+ case CSS_FONT_WEIGHT_600: weight = 600; break;
+ case CSS_FONT_WEIGHT_700: weight = 700; break;
+ case CSS_FONT_WEIGHT_800: weight = 800; break;
+ case CSS_FONT_WEIGHT_900: weight = 900; break;
+*/
+ default: break;
+ }
+
+ if (!face)
+ face = B_REGULAR_FACE;
+
+//fprintf(stderr, "nsfont_style_to_font: %d, %d, %d -> '%s' %04x\n", style->font_family, style->font_style, style->font_weight, family, face);
+
+ if (family)
+ font.SetFamilyAndFace((const font_family)family, face);
+ else {
+ //XXX not used
+ font = be_plain_font;
+ font.SetFace(face);
+ }
+
+#if 0
+ *font_size = css_len2px(&style->font_size.value.length, style) *
+ 72.0 / 90.0 * 16.;
+ if (*font_size < option_font_min_size * 1.6)
+ *font_size = option_font_min_size * 1.6;
+ if (1600 < *font_size)
+ *font_size = 1600;
+#endif
+
+#if 0 /* GTK */
+ if (style->font_size.value.length.unit == CSS_UNIT_PX)
+ size = style->font_size.value.length.value;
+ else
+ size = css_len2pt(&style->font_size.value.length, style);
+ //XXX ?
+ if (style->font_size.value.length.unit == CSS_UNIT_PX)
+ font.SetSize(size);
+ else
+ font.SetSize(font.Size() + size);
+#endif
+
+//fprintf(stderr, "nsfont_style_to_font: value %f unit %d\n", style->font_size.value.length.value, style->font_size.value.length.unit);
+ if (style->font_size.value.length.unit == CSS_UNIT_PT)
+ size = style->font_size.value.length.value;
+ else
+ size = css_len2pt(&style->font_size.value.length, style);
+ // * 72.0 / 90.0;
+
+ //XXX: pango stuff ?
+ if (size < abs(option_font_min_size / 10))
+ size = option_font_min_size / 10;
+
+//fprintf(stderr, "nsfont_style_to_font: %f %d\n", size, style->font_size.value.length.unit);
+
+ font.SetSize(size);
+
+
+#if 0 /* GTK */
+ switch (style->font_variant) {
+ case CSS_FONT_VARIANT_SMALL_CAPS:
+ pango_font_description_set_variant(desc, PANGO_VARIANT_SMALL_CAPS);
+ break;
+ case CSS_FONT_VARIANT_NORMAL:
+ default:
+ pango_font_description_set_variant(desc, PANGO_VARIANT_NORMAL);
+ }
+#endif
+}
diff --git a/beos/beos_font.h b/beos/beos_font.h
new file mode 100644
index 000000000..06b8edaff
--- /dev/null
+++ b/beos/beos_font.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2005 James Bursa <bursa@users.sourceforge.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/>.
+ */
+
+/** \file
+ * Font handling (GTK interface).
+ */
+
+#include <stdbool.h>
+
+
+struct css_style;
+
+bool nsfont_paint(const struct css_style *style,
+ const char *string, size_t length,
+ int x, int y, colour bg, colour c);
diff --git a/beos/beos_gui.cpp b/beos/beos_gui.cpp
new file mode 100644
index 000000000..601bdb5b6
--- /dev/null
+++ b/beos/beos_gui.cpp
@@ -0,0 +1,1018 @@
+/*
+ * Copyright 2005 James Bursa <bursa@users.sourceforge.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/>.
+ */
+
+#define _GNU_SOURCE /* for strndup */
+#include <assert.h>
+#include <ctype.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <limits.h>
+#include <sys/select.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <curl/curl.h>
+
+#include <Alert.h>
+#include <Application.h>
+#include <Mime.h>
+#include <Roster.h>
+#include <String.h>
+
+extern "C" {
+#include "content/content.h"
+#include "content/fetch.h"
+#include "content/fetchers/fetch_curl.h"
+#include "content/urldb.h"
+#include "desktop/401login.h"
+#include "desktop/browser.h"
+#include "desktop/cookies.h"
+#include "desktop/gui.h"
+#include "desktop/netsurf.h"
+#include "desktop/options.h"
+
+#include "render/box.h"
+#include "render/form.h"
+#include "render/html.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/url.h"
+#include "utils/utf8.h"
+#include "utils/utils.h"
+}
+
+#include "beos/beos_gui.h"
+
+#include "beos/beos_options.h"
+//#include "beos/beos_completion.h"
+#include "beos/beos_window.h"
+#include "beos/options.h"
+#include "beos/beos_throbber.h"
+#include "beos/beos_history.h"
+#include "beos/beos_filetype.h"
+//#include "beos/beos_download.h"
+#include "beos/beos_schedule.h"
+#include "beos/beos_fetch_rsrc.h"
+
+
+/* Where to search for shared resources. Must have trailing / */
+#define RESPATH "/boot/apps/netsurf/res/"
+//TODO: use resources
+
+bool gui_in_multitask = false;
+
+char *default_stylesheet_url;
+char *adblock_stylesheet_url;
+char *options_file_location;
+char *glade_file_location;
+
+struct gui_window *search_current_window = 0;
+
+BWindow *wndAbout;
+BWindow *wndWarning;
+//GladeXML *gladeWindows;
+BWindow *wndTooltip;
+//beosLabel *labelTooltip;
+BFilePanel *wndOpenFile;
+
+//static beosWidget *select_menu;
+static struct browser_window *select_menu_bw;
+static struct form_control *select_menu_control;
+
+static thread_id sBAppThreadID;
+
+static int sEventPipe[2];
+
+#if 0 /* GTK */
+static void nsbeos_create_ssl_verify_window(struct browser_window *bw,
+ struct content *c, const struct ssl_cert_info *certs,
+ unsigned long num);
+static void nsbeos_ssl_accept(BButton *w, gpointer data);
+static void nsbeos_ssl_reject(BButton *w, gpointer data);
+static void nsbeos_select_menu_clicked(BCheckMenuItem *checkmenuitem,
+ gpointer user_data);
+#endif
+
+// #pragma mark - class NSBrowserFrameView
+
+
+NSBrowserApplication::NSBrowserApplication()
+ : BApplication("application/x-vnd.NetSurf")
+{
+}
+
+
+NSBrowserApplication::~NSBrowserApplication()
+{
+}
+
+
+void
+NSBrowserApplication::MessageReceived(BMessage *message)
+{
+ switch (message->what) {
+ case B_REFS_RECEIVED:
+ // messages for top-level
+ // we'll just send them to the first window
+ case 'back':
+ case 'forw':
+ case 'stop':
+ case 'relo':
+ case 'home':
+ case 'urlc':
+ case 'urle':
+ case 'menu':
+ //DetachCurrentMessage();
+ //nsbeos_pipe_message(message, this, fGuiWindow);
+ break;
+ default:
+ BApplication::MessageReceived(message);
+ }
+}
+
+
+void
+NSBrowserApplication::RefsReceived(BMessage *message)
+{
+ DetachCurrentMessage();
+ NSBrowserWindow *win = nsbeos_find_last_window();
+ if (!win)
+ return;
+ win->Unlock();
+ nsbeos_pipe_message_top(message, win, win->Scaffolding());
+}
+
+
+bool
+NSBrowserApplication::QuitRequested()
+{
+ // let it notice it
+ nsbeos_pipe_message(new BMessage(B_QUIT_REQUESTED), NULL, NULL);
+ // we'll let the main thread Quit() ourselves when it's done.
+ return false;
+}
+
+
+// #pragma mark - implementation
+
+
+// XXX doesn't work
+static char *generate_default_css()
+{
+ BString text;
+ rgb_color colBg = { 255, 255, 255, 255 };
+ rgb_color colFg = { 0, 0, 0, 255 };
+ rgb_color colControlBg = { 255, 255, 255, 255 };
+ rgb_color colControlFg = { 0, 0, 0, 255 };
+ const char *url = "file://beosdefault.css";
+
+ text << "/*\n";
+ text << " * This file is part of NetSurf, http://netsurf-browser.org/\n";
+ text << " */\n";
+ text << "\n";
+ text << "/* Load base stylesheet. */\n";
+ text << "\n";
+ text << "@import \"default.css\";\n";
+ text << "\n";
+ text << "/* Apply BeOS specific rules. */\n";
+ text << "\n";
+ text << "\n";
+ text << "\n";
+ text << "\n";
+
+ text << "input { font-size: 95%; border: medium inset #ddd; }\n";
+ text << "input[type=button], input[type=reset], input[type=submit], button {\n";
+ text << " background-color: #ddd; border: medium outset #ddd; }\n";
+ text << "input[type=checkbox], input[type=radio] { font-size: 105%; }\n";
+ text << "input[type=file] { background-color: #ddd; border: medium inset #ddd; }\n";
+ text << "\n";
+ text << "select { background-color: #ddd; border: medium inset #ddd; font-size: 95%; }\n";
+ text << "select:after { border-left:4px ridge #ddd; }\n";
+ text << "\n";
+ text << "textarea { font-size: 95%; border: medium inset #ddd; }\n";
+
+ struct content *c;
+ c = content_create(url);
+ if (c == NULL)
+ return NULL;
+
+ const char *params[] = { 0 };
+ if (!content_set_type(c, CONTENT_CSS, "text/css", params))
+ return NULL;
+
+ if (!content_process_data(c, text.String(), text.Length()))
+ return NULL;
+
+ content_set_done(c);
+
+ return strdup(url);
+}
+
+/**
+ * Locate a shared resource file by searching known places in order.
+ *
+ * \param buf buffer to write to. must be at least PATH_MAX chars
+ * \param filename file to look for
+ * \param def default to return if file not found
+ * \return buf
+ *
+ * Search order is: ~/.netsurf/, $NETSURFRES/ (where NETSURFRES is an
+ * environment variable), and finally the path specified by the #define
+ * at the top of this file.
+ */
+
+static char *find_resource(char *buf, const char *filename, const char *def)
+{
+ CALLED();
+ char *cdir = getenv("HOME");
+ char t[PATH_MAX];
+
+ if (cdir != NULL) {
+ strcpy(t, cdir);
+ strcat(t, "/.netsurf/");
+ strcat(t, filename);
+ realpath(t, buf);
+ if (access(buf, R_OK) == 0)
+ return buf;
+ }
+
+ cdir = getenv("NETSURFRES");
+
+ if (cdir != NULL) {
+ realpath(cdir, buf);
+ strcat(buf, "/");
+ strcat(buf, filename);
+ if (access(buf, R_OK) == 0)
+ return buf;
+ }
+
+ strcpy(t, RESPATH);
+ strcat(t, filename);
+ realpath(t, buf);
+ if (access(buf, R_OK) == 0)
+ return buf;
+
+ if (def[0] == '~') {
+ snprintf(t, PATH_MAX, "%s%s", getenv("HOME"), def + 1);
+ realpath(t, buf);
+ } else {
+ realpath(def, buf);
+ }
+
+ return buf;
+}
+
+/**
+ * Check that ~/.netsurf/ exists, and if it doesn't, create it.
+ */
+static void check_homedir(void)
+{
+ CALLED();
+//TODO: use find_directory();
+ char *hdir = getenv("HOME");
+ char buf[BUFSIZ];
+
+ if (hdir == NULL) {
+ /* we really can't continue without a home directory. */
+ LOG(("HOME is not set - nowhere to store state!"));
+ die("NetSurf requires HOME to be set in order to run.\n");
+
+ }
+
+ snprintf(buf, BUFSIZ, "%s/.netsurf", hdir);
+ if (access(buf, F_OK) != 0) {
+ LOG(("You don't have a ~/.netsurf - creating one for you."));
+ if (mkdir(buf, 0777) == -1) {
+ LOG(("Unable to create %s", buf));
+ die("NetSurf requires ~/.netsurf to exist, but it cannot be created.\n");
+ }
+ }
+}
+
+static int32 bapp_thread(void *arg)
+{
+ be_app->Lock();
+ be_app->Run();
+ return 0;
+}
+
+void gui_init(int argc, char** argv)
+{
+ char buf[PATH_MAX];
+ CALLED();
+
+ if (pipe(sEventPipe) < 0)
+ return;
+
+ new NSBrowserApplication;
+ sBAppThreadID = spawn_thread(bapp_thread, "BApplication(NetSurf)", B_NORMAL_PRIORITY, (void *)find_thread(NULL));
+ if (sBAppThreadID < B_OK)
+ return; /* #### handle errors */
+ if (resume_thread(sBAppThreadID) < B_OK)
+ return;
+
+ fetch_rsrc_register();
+
+ check_homedir();
+
+ //nsbeos_completion_init();
+
+ find_resource(buf, "throbber.gif", "./beos/res/throbber.gif");
+ nsbeos_throbber_initialise(buf);
+ if (nsbeos_throbber == NULL)
+ die("Unable to load throbber image.\n");
+
+ find_resource(buf, "Choices", "~/.netsurf/Choices");
+ LOG(("Using '%s' as Preferences file", buf));
+ options_file_location = strdup(buf);
+ options_read(buf);
+
+
+ /* check what the font settings are, setting them to a default font
+ * if they're not set - stops Pango whinging
+ */
+#define SETFONTDEFAULT(x,y) (x) = ((x) != NULL) ? (x) : strdup((y))
+ //XXX: use be_plain_font & friends, when we can check if font is serif or not.
+/*
+ font_family family;
+ font_style style;
+ be_plain_font->GetFamilyAndStyle(&family, &style);
+ SETFONTDEFAULT(option_font_sans, family);
+ SETFONTDEFAULT(option_font_serif, family);
+ SETFONTDEFAULT(option_font_mono, family);
+ SETFONTDEFAULT(option_font_cursive, family);
+ SETFONTDEFAULT(option_font_fantasy, family);
+*/
+#ifdef __HAIKU__
+ SETFONTDEFAULT(option_font_sans, "DejaVu Sans");
+ SETFONTDEFAULT(option_font_serif, "DejaVu Serif");
+ SETFONTDEFAULT(option_font_mono, "DejaVu Mono");
+ SETFONTDEFAULT(option_font_cursive, "DejaVu Sans");
+ SETFONTDEFAULT(option_font_fantasy, "DejaVu Sans");
+#else
+ SETFONTDEFAULT(option_font_sans, "Bitstream Vera Sans");
+ SETFONTDEFAULT(option_font_serif, "Bitstream Vera Serif");
+ SETFONTDEFAULT(option_font_mono, "Bitstream Vera Sans Mono");
+ SETFONTDEFAULT(option_font_cursive, "Bitstream Vera Serif");
+ SETFONTDEFAULT(option_font_fantasy, "Bitstream Vera Serif");
+#if 0
+ SETFONTDEFAULT(option_font_sans, "Swis721 BT");
+ SETFONTDEFAULT(option_font_serif, "Dutch801 Rm BT");
+ //SETFONTDEFAULT(option_font_mono, "Monospac821 BT");
+ SETFONTDEFAULT(option_font_mono, "Courier10 BT");
+ SETFONTDEFAULT(option_font_cursive, "Swis721 BT");
+ SETFONTDEFAULT(option_font_fantasy, "Swis721 BT");
+#endif
+#endif
+
+ nsbeos_options_init();
+
+ if (!option_cookie_file) {
+ find_resource(buf, "Cookies", "~/.netsurf/Cookies");
+ LOG(("Using '%s' as Cookies file", buf));
+ option_cookie_file = strdup(buf);
+ }
+ if (!option_cookie_jar) {
+ find_resource(buf, "Cookies", "~/.netsurf/Cookies");
+ LOG(("Using '%s' as Cookie Jar file", buf));
+ option_cookie_jar = strdup(buf);
+ }
+ if (!option_cookie_file || !option_cookie_jar)
+ die("Failed initialising cookie options");
+
+ if (!option_url_file) {
+ find_resource(buf, "URLs", "~/.netsurf/URLs");
+ LOG(("Using '%s' as URL file", buf));
+ option_url_file = strdup(buf);
+ }
+
+ if (!option_ca_path) {
+ find_resource(buf, "certs", "/etc/ssl/certs");
+ LOG(("Using '%s' as certificate path", buf));
+ option_ca_path = strdup(buf);
+ }
+
+ find_resource(buf, "messages", "./beos/res/messages");
+ LOG(("Using '%s' as Messages file", buf));
+ messages_load(buf);
+
+ find_resource(buf, "mime.types", "/etc/mime.types");
+ beos_fetch_filetype_init(buf);
+
+ /* set up stylesheet urls */
+ find_resource(buf, "beosdefault.css", "./beos/res/beosdefault.css");
+ default_stylesheet_url = path_to_url(buf);
+ //default_stylesheet_url = generate_default_css();
+ LOG(("Using '%s' as Default CSS URL", default_stylesheet_url));
+
+ find_resource(buf, "adblock.css", "./beos/res/adblock.css");
+ adblock_stylesheet_url = path_to_url(buf);
+ LOG(("Using '%s' as AdBlock CSS URL", adblock_stylesheet_url));
+
+ urldb_load(option_url_file);
+ urldb_load_cookies(option_cookie_file);
+
+ //nsbeos_history_init();
+ //nsbeos_download_initialise();
+
+ be_app->Unlock();
+
+#if 0 /* GTK */
+ PangoFontDescription *fontdesc;
+
+ gtk_init(&argc, &argv);
+
+ check_homedir();
+
+ find_resource(buf, "netsurf.glade", "./beos/res/netsurf.glade");
+ LOG(("Using '%s' as Glade template file", buf));
+ glade_file_location = strdup(buf);
+
+ glade_init();
+ gladeWindows = glade_xml_new(glade_file_location, NULL, NULL);
+ if (gladeWindows == NULL)
+ die("Unable to load Glade window definitions.\n");
+ glade_xml_signal_autoconnect(gladeWindows);
+
+ find_resource(buf, "netsurf.xpm", "./beos/res/netsurf.xpm");
+ beos_window_set_default_icon_from_file(buf, NULL);
+
+ wndTooltip = beos_WINDOW(glade_xml_get_widget(gladeWindows, "wndTooltip"));
+ labelTooltip = beos_LABEL(glade_xml_get_widget(gladeWindows, "tooltip"));
+
+ nsbeos_completion_init();
+
+ find_resource(buf, "throbber.gif", "./beos/res/throbber.gif");
+ nsbeos_throbber_initialise(buf);
+ if (nsbeos_throbber == NULL)
+ die("Unable to load throbber image.\n");
+
+ find_resource(buf, "Choices", "~/.netsurf/Choices");
+ LOG(("Using '%s' as Preferences file", buf));
+ options_file_location = strdup(buf);
+ options_read(buf);
+
+ /* check what the font settings are, setting them to a default font
+ * if they're not set - stops Pango whinging
+ */
+#define SETFONTDEFAULT(x,y) (x) = ((x) != NULL) ? (x) : strdup((y))
+ SETFONTDEFAULT(option_font_sans, "Sans");
+ SETFONTDEFAULT(option_font_serif, "Serif");
+ SETFONTDEFAULT(option_font_mono, "Monospace");
+ SETFONTDEFAULT(option_font_cursive, "Serif");
+ SETFONTDEFAULT(option_font_fantasy, "Serif");
+
+ nsbeos_options_init();
+
+ if (!option_cookie_file) {
+ find_resource(buf, "Cookies", "~/.netsurf/Cookies");
+ LOG(("Using '%s' as Cookies file", buf));
+ option_cookie_file = strdup(buf);
+ }
+ if (!option_cookie_jar) {
+ find_resource(buf, "Cookies", "~/.netsurf/Cookies");
+ LOG(("Using '%s' as Cookie Jar file", buf));
+ option_cookie_jar = strdup(buf);
+ }
+ if (!option_cookie_file || !option_cookie_jar)
+ die("Failed initialising cookie options");
+
+ if (!option_url_file) {
+ find_resource(buf, "URLs", "~/.netsurf/URLs");
+ LOG(("Using '%s' as URL file", buf));
+ option_url_file = strdup(buf);
+ }
+
+ if (!option_ca_path) {
+ find_resource(buf, "certs", "/etc/ssl/certs");
+ LOG(("Using '%s' as certificate path", buf));
+ option_ca_path = strdup(buf);
+ }
+
+ find_resource(buf, "messages", "./beos/res/messages");
+ LOG(("Using '%s' as Messages file", buf));
+ messages_load(buf);
+
+ find_resource(buf, "mime.types", "/etc/mime.types");
+ beos_fetch_filetype_init(buf);
+
+ /* set up stylesheet urls */
+ find_resource(buf, "beosdefault.css", "./beos/res/beosdefault.css");
+ default_stylesheet_url = path_to_url(buf);
+ LOG(("Using '%s' as Default CSS URL", default_stylesheet_url));
+
+ find_resource(buf, "adblock.css", "./beos/res/adblock.css");
+ adblock_stylesheet_url = path_to_url(buf);
+ LOG(("Using '%s' as AdBlock CSS URL", adblock_stylesheet_url));
+
+ urldb_load(option_url_file);
+ urldb_load_cookies(option_cookie_file);
+
+ wndAbout = beos_WINDOW(glade_xml_get_widget(gladeWindows, "wndAbout"));
+ beos_label_set_text(beos_LABEL(
+ glade_xml_get_widget(gladeWindows, "labelVersion")),
+ netsurf_version);
+ beos_image_set_from_file(beos_IMAGE(
+ glade_xml_get_widget(gladeWindows, "imageLogo")),
+ find_resource(buf, "netsurf-logo.png", "netsurf-logo.png"));
+ fontdesc = pango_font_description_from_string("Monospace 8");
+ beos_widget_modify_font(beos_WIDGET(
+ glade_xml_get_widget(gladeWindows, "textviewGPL")), fontdesc);
+
+ wndWarning = beos_WINDOW(glade_xml_get_widget(gladeWindows, "wndWarning"));
+ wndOpenFile = beos_DIALOG(glade_xml_get_widget(gladeWindows, "wndOpenFile"));
+
+ nsbeos_history_init();
+ nsbeos_download_initialise();
+#endif
+}
+
+
+void gui_init2(int argc, char** argv)
+{
+ CALLED();
+ const char *addr = "http://netsurf-browser.org/welcome/";
+
+ if (option_homepage_url != NULL && option_homepage_url[0] != '\0')
+ addr = option_homepage_url;
+
+ if (argc > 1) addr = argv[1];
+ browser_window_create(addr, 0, 0, true);
+}
+
+
+void nsbeos_pipe_message(BMessage *message, BView *_this, struct gui_window *gui)
+{
+ if (message == NULL) {
+ fprintf(stderr, "%s(NULL)!\n", __FUNCTION__);
+ return;
+ }
+ if (_this)
+ message->AddPointer("View", _this);
+ if (gui)
+ message->AddPointer("gui_window", gui);
+ int len = write(sEventPipe[1], &message, sizeof(void *));
+ //LOG(("nsbeos_pipe_message: %d written", len));
+ printf("nsbeos_pipe_message: %d written\n", len);
+}
+
+
+void nsbeos_pipe_message_top(BMessage *message, BWindow *_this, struct beos_scaffolding *scaffold)
+{
+ if (message == NULL) {
+ fprintf(stderr, "%s(NULL)!\n", __FUNCTION__);
+ return;
+ }
+ if (_this)
+ message->AddPointer("Window", _this);
+ if (scaffold)
+ message->AddPointer("scaffolding", scaffold);
+ int len = write(sEventPipe[1], &message, sizeof(void *));
+ //LOG(("nsbeos_pipe_message: %d written", len));
+ printf("nsbeos_pipe_message: %d written\n", len);
+}
+
+
+void gui_poll(bool active)
+{
+ CALLED();
+ CURLMcode code;
+
+ fd_set read_fd_set, write_fd_set, exc_fd_set;
+ int max_fd = 0;
+ struct timeval timeout;
+ unsigned int fd_count = 0;
+ bool block = true;
+
+ if (browser_reformat_pending)
+ block = false;
+
+ if (active) {
+ fetch_poll();
+ FD_ZERO(&read_fd_set);
+ FD_ZERO(&write_fd_set);
+ FD_ZERO(&exc_fd_set);
+ code = curl_multi_fdset(fetch_curl_multi,
+ &read_fd_set,
+ &write_fd_set,
+ &exc_fd_set,
+ &max_fd);
+ assert(code == CURLM_OK);
+ }
+
+ // our own event pipe
+ FD_SET(sEventPipe[0], &read_fd_set);
+ max_fd = MAX(max_fd, sEventPipe[0] + 1);
+
+
+ bigtime_t next_schedule = earliest_callback_timeout - system_time();
+ timeout.tv_sec = (long)(next_schedule / 1000000LL);
+ timeout.tv_usec = (long)(next_schedule % 1000000LL);
+ LOG(("gui_poll: select(%d, ..., %Ldus", max_fd, next_schedule));
+
+ fd_count = select(max_fd, &read_fd_set, &write_fd_set, &exc_fd_set,
+ /*block?NULL:*/(
+ earliest_callback_timeout == B_INFINITE_TIMEOUT) ? NULL : &timeout);
+
+ if (max_fd > 0 && FD_ISSET(sEventPipe[0], &read_fd_set)) {
+ BMessage *message;
+ int len = read(sEventPipe[0], &message, sizeof(void *));
+ LOG(("gui_poll: BMessage ? %d read", len));
+ if (len == sizeof(void *))
+ nsbeos_dispatch_event(message);
+ }
+
+
+/*
+ for (unsigned int i = 0; fd_count && i < max_fd; i++) {
+ g_main_context_remove_poll(0, fd_list[i]);
+ free(fd_list[i]);
+ fd_count--;
+ }
+*/
+
+#if 0 /* GTK */
+ CURLMcode code;
+ fd_set read_fd_set, write_fd_set, exc_fd_set;
+ int max_fd;
+ GPollFD *fd_list[1000];
+ unsigned int fd_count = 0;
+ bool block = true;
+
+ if (browser_reformat_pending)
+ block = false;
+
+ if (active) {
+ fetch_poll();
+ FD_ZERO(&read_fd_set);
+ FD_ZERO(&write_fd_set);
+ FD_ZERO(&exc_fd_set);
+ code = curl_multi_fdset(fetch_curl_multi,
+ &read_fd_set,
+ &write_fd_set,
+ &exc_fd_set,
+ &max_fd);
+ assert(code == CURLM_OK);
+ for (int i = 0; i <= max_fd; i++) {
+ if (FD_ISSET(i, &read_fd_set)) {
+ GPollFD *fd = malloc(sizeof *fd);
+ fd->fd = i;
+ fd->events = G_IO_IN | G_IO_HUP | G_IO_ERR;
+ g_main_context_add_poll(0, fd, 0);
+ fd_list[fd_count++] = fd;
+ }
+ if (FD_ISSET(i, &write_fd_set)) {
+ GPollFD *fd = malloc(sizeof *fd);
+ fd->fd = i;
+ fd->events = G_IO_OUT | G_IO_ERR;
+ g_main_context_add_poll(0, fd, 0);
+ fd_list[fd_count++] = fd;
+ }
+ if (FD_ISSET(i, &exc_fd_set)) {
+ GPollFD *fd = malloc(sizeof *fd);
+ fd->fd = i;
+ fd->events = G_IO_ERR;
+ g_main_context_add_poll(0, fd, 0);
+ fd_list[fd_count++] = fd;
+ }
+ }
+ }
+
+ beos_main_iteration_do(block);
+
+ for (unsigned int i = 0; i != fd_count; i++) {
+ g_main_context_remove_poll(0, fd_list[i]);
+ free(fd_list[i]);
+ }
+#endif
+
+ schedule_run();
+
+ if (browser_reformat_pending)
+ nsbeos_window_process_reformats();
+}
+
+
+void gui_multitask(void)
+{
+ gui_in_multitask = true;
+#if 0 /* GTK */
+ while (beos_events_pending())
+ beos_main_iteration();
+#endif
+ gui_in_multitask = false;
+}
+
+
+void gui_quit(void)
+{
+ CALLED();
+ urldb_save_cookies(option_cookie_jar);
+ urldb_save(option_url_file);
+ free(default_stylesheet_url);
+ free(adblock_stylesheet_url);
+ free(option_cookie_file);
+ free(option_cookie_jar);
+ beos_fetch_filetype_fin();
+ fetch_rsrc_unregister();
+}
+
+
+
+struct gui_download_window *gui_download_window_create(const char *url,
+ const char *mime_type, struct fetch *fetch,
+ unsigned int total_size)
+{
+ return 0;
+}
+
+
+void gui_download_window_data(struct gui_download_window *dw, const char *data,
+ unsigned int size)
+{
+}
+
+
+void gui_download_window_error(struct gui_download_window *dw,
+ const char *error_msg)
+{
+}
+
+
+void gui_download_window_done(struct gui_download_window *dw)
+{
+}
+
+#if 0 /* GTK */
+static void nsbeos_select_menu_clicked(BCheckMenuItem *checkmenuitem,
+ gpointer user_data)
+{
+ browser_window_form_select(select_menu_bw, select_menu_control,
+ (intptr_t)user_data);
+}
+#endif
+
+void gui_create_form_select_menu(struct browser_window *bw,
+ struct form_control *control)
+{
+ CALLED();
+#if 0 /* GTK */
+
+ intptr_t i;
+ struct form_option *option;
+
+ beosWidget *menu_item;
+
+ /* control->data.select.multiple is true if multiple selections
+ * are allowable. We ignore this, as the core handles it for us.
+ * Yay. \o/
+ */
+
+ if (select_menu != NULL)
+ beos_widget_destroy(select_menu);
+
+ select_menu = beos_menu_new();
+ select_menu_bw = bw;
+ select_menu_control = control;
+
+ for (i = 0, option = control->data.select.items; option;
+ i++, option = option->next) {
+ menu_item = beos_check_menu_item_new_with_label(option->text);
+ if (option->selected)
+ beos_check_menu_item_set_active(
+ beos_CHECK_MENU_ITEM(menu_item), TRUE);
+
+ g_signal_connect(menu_item, "toggled",
+ G_CALLBACK(nsbeos_select_menu_clicked), (gpointer)i);
+
+ beos_menu_shell_append(beos_MENU_SHELL(select_menu), menu_item);
+ }
+
+ beos_widget_show_all(select_menu);
+
+ beos_menu_popup(beos_MENU(select_menu), NULL, NULL, NULL,
+ NULL /* data */, 0, beos_get_current_event_time());
+
+#endif
+}
+
+void gui_window_save_as_link(struct gui_window *g, struct content *c)
+{
+}
+
+/**
+ * Broadcast an URL that we can't handle.
+ */
+
+void gui_launch_url(const char *url)
+{
+ status_t status;
+ // try to open it as an URI
+ BString mimeType = "application/x-vnd.Be.URL.";
+ BString arg(url);
+ mimeType.Append(arg, arg.FindFirst(":"));
+
+ // the protocol should be alphanum
+ // we just check if it's registered
+ // if not there is likely no supporting app anyway
+ if (!BMimeType::IsValid(mimeType.String()))
+ return;
+ char *args[2] = { (char *)url, NULL };
+ status = be_roster->Launch(mimeType.String(), 1, args);
+ if (status < B_OK)
+ warn_user("Cannot launch url", strerror(status));
+}
+
+
+bool gui_search_term_highlighted(struct gui_window *g,
+ unsigned start_offset, unsigned end_offset,
+ unsigned *start_idx, unsigned *end_idx)
+{
+ return false;
+}
+
+
+/**
+ * Display a warning for a serious problem (eg memory exhaustion).
+ *
+ * \param warning message key for warning message
+ * \param detail additional message, or 0
+ */
+
+void warn_user(const char *warning, const char *detail)
+{
+ LOG(("warn_user: %s (%s)", warning, detail));
+ BAlert *alert;
+ BString text(warning);
+ if (detail)
+ text << ":\n" << detail;
+#if 0
+ alert = new BAlert("NetSurf Warning", text.String(), "Ok", NULL, NULL,
+ B_WIDTH_AS_USUAL, B_WARNING_ALERT);
+ alert->Go();
+#else
+ alert = new BAlert("NetSurf Warning", text.String(), "Debug", "Ok", NULL,
+ B_WIDTH_AS_USUAL, B_WARNING_ALERT);
+ if (alert->Go() < 1)
+ debugger("warn_user");
+#endif
+}
+
+void die(const char * const error)
+{
+ fprintf(stderr, "%s", error);
+ BAlert *alert;
+ BString text("Cannot continue:\n");
+ text << error;
+#if 0
+ alert = new BAlert("NetSurf Error", text.String(), "Ok", NULL, NULL,
+ B_WIDTH_AS_USUAL, B_STOP_ALERT);
+ alert->Go();
+#else
+ alert = new BAlert("NetSurf Error", text.String(), "Debug", "Ok", NULL,
+ B_WIDTH_AS_USUAL, B_STOP_ALERT);
+ if (alert->Go() < 1)
+ debugger("die");
+#endif
+ exit(EXIT_FAILURE);
+}
+
+
+void hotlist_visited(struct content *content)
+{
+}
+
+void gui_cert_verify(struct browser_window *bw, struct content *c,
+ const struct ssl_cert_info *certs, unsigned long num)
+{
+ CALLED();
+#if 0 /* GTK */
+ nsbeos_create_ssl_verify_window(bw, c, certs, num);
+#endif
+}
+
+static void nsbeos_create_ssl_verify_window(struct browser_window *bw,
+ struct content *c, const struct ssl_cert_info *certs,
+ unsigned long num)
+{
+ CALLED();
+#if 0 /* GTK */
+ GladeXML *x = glade_xml_new(glade_file_location, NULL, NULL);
+ beosWindow *wnd = beos_WINDOW(glade_xml_get_widget(x, "wndSSLProblem"));
+ beosButton *accept, *reject;
+ void **session = calloc(sizeof(void *), 4);
+
+ session[0] = bw;
+ session[1] = strdup(c->url);
+ session[2] = x;
+ session[3] = wnd;
+
+ accept = beos_BUTTON(glade_xml_get_widget(x, "sslaccept"));
+ reject = beos_BUTTON(glade_xml_get_widget(x, "sslreject"));
+
+ g_signal_connect(G_OBJECT(accept), "clicked",
+ G_CALLBACK(nsbeos_ssl_accept), (gpointer)session);
+ g_signal_connect(G_OBJECT(reject), "clicked",
+ G_CALLBACK(nsbeos_ssl_reject), (gpointer)session);
+
+ beos_widget_show(beos_WIDGET(wnd));
+#endif
+}
+
+#if 0 /* GTK */
+static void nsbeos_ssl_accept(beosButton *w, gpointer data)
+{
+ void **session = data;
+ struct browser_window *bw = session[0];
+ char *url = session[1];
+ GladeXML *x = session[2];
+ beosWindow *wnd = session[3];
+
+ urldb_set_cert_permissions(url, true);
+ browser_window_go(bw, url, 0, true);
+
+ beos_widget_destroy(beos_WIDGET(wnd));
+ g_object_unref(G_OBJECT(x));
+ free(url);
+ free(session);
+}
+
+static void nsbeos_ssl_reject(beosButton *w, gpointer data)
+{
+ void **session = data;
+ GladeXML *x = session[2];
+ beosWindow *wnd = session[3];
+
+ beos_widget_destroy(beos_WIDGET(wnd));
+ g_object_unref(G_OBJECT(x));
+ free(session[1]);
+ free(session);
+}
+#endif
+
+utf8_convert_ret utf8_to_local_encoding(const char *string, size_t len,
+ char **result)
+{
+ assert(string && result);
+
+ if (len == 0)
+ len = strlen(string);
+
+ *result = strndup(string, len);
+ if (!(*result))
+ return UTF8_CONVERT_NOMEM;
+
+ return UTF8_CONVERT_OK;
+}
+
+utf8_convert_ret utf8_from_local_encoding(const char *string, size_t len,
+ char **result)
+{
+ assert(string && result);
+
+ if (len == 0)
+ len = strlen(string);
+
+ *result = strndup(string, len);
+ if (!(*result))
+ return UTF8_CONVERT_NOMEM;
+
+ return UTF8_CONVERT_OK;
+}
+
+char *path_to_url(const char *path)
+{
+ char *r = (char *)malloc(strlen(path) + 7 + 1);
+
+ strcpy(r, "file://");
+ strcat(r, path);
+
+ return r;
+}
+
+char *url_to_path(const char *url)
+{
+ return strdup(url + 5);
+}
+
+bool cookies_update(const char *domain, const struct cookie_data *data)
+{
+ return true;
+}
diff --git a/beos/beos_gui.h b/beos/beos_gui.h
new file mode 100644
index 000000000..0e9f1e266
--- /dev/null
+++ b/beos/beos_gui.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2005 James Bursa <bursa@users.sourceforge.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 <Application.h>
+#include <FilePanel.h>
+#include <Window.h>
+
+#define CALLED() fprintf(stderr, "%s()\n", __FUNCTION__);
+
+extern bool gui_in_multitask;
+#if 0 /* GTK */
+//extern GladeXML *gladeWindows;
+//extern char *glade_file_location;
+#endif
+extern char *options_file_location;
+
+class NSBrowserApplication : public BApplication {
+public:
+ NSBrowserApplication();
+virtual ~NSBrowserApplication();
+
+virtual void MessageReceived(BMessage *message);
+virtual void RefsReceived(BMessage *message);
+
+virtual bool QuitRequested();
+};
+
+
+
+extern BWindow *wndAbout;
+
+extern BWindow *wndTooltip;
+#if 0 /* GTK */
+//extern GtkLabel *labelTooltip;
+#endif
+
+extern BFilePanel *wndOpenFile;
+
+void nsbeos_pipe_message(BMessage *message, BView *_this, struct gui_window *gui);
+void nsbeos_pipe_message_top(BMessage *message, BWindow *_this, struct beos_scaffolding *scaffold);
+
diff --git a/beos/beos_history.cpp b/beos/beos_history.cpp
new file mode 100644
index 000000000..07413f3c8
--- /dev/null
+++ b/beos/beos_history.cpp
@@ -0,0 +1,181 @@
+/*
+ * Copyright 2006 Rob Kendrick <rjek@rjek.com>
+ *
+ * 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/>.
+ */
+
+extern "C" {
+#include "utils/log.h"
+#include "content/urldb.h"
+}
+
+#include "beos/beos_history.h"
+#include "beos/beos_gui.h"
+#include "beos/beos_window.h"
+
+#include <View.h>
+#include <Window.h>
+
+
+enum
+{
+ COL_TITLE = 0,
+ COL_ADDRESS,
+ COL_LASTVISIT,
+ COL_TOTALVISITS,
+ COL_THUMBNAIL,
+ COL_NCOLS
+};
+
+BWindow *wndHistory;
+#warning XXX
+#if 0 /* GTK */
+static GtkTreeView *treeview;
+static GtkTreeStore *history_tree;
+static GtkTreeSelection *selection;
+
+static bool nsgtk_history_add_internal(const char *, const struct url_data *);
+static void nsgtk_history_selection_changed(GtkTreeSelection *, gpointer);
+#endif
+
+void nsgtk_history_init(void)
+{
+#warning XXX
+#if 0 /* GTK */
+ GtkCellRenderer *renderer;
+
+ wndHistory = GTK_WINDOW(glade_xml_get_widget(gladeWindows,
+ "wndHistory"));
+ treeview = GTK_TREE_VIEW(glade_xml_get_widget(gladeWindows,
+ "treeHistory"));
+ history_tree = gtk_tree_store_new(COL_NCOLS,
+ G_TYPE_STRING, /* title */
+ G_TYPE_STRING, /* address */
+ G_TYPE_STRING, /* last visit */
+ G_TYPE_INT, /* nr. visits */
+ GDK_TYPE_PIXBUF); /* thumbnail */
+
+ selection = gtk_tree_view_get_selection(treeview);
+ gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);
+ g_signal_connect(G_OBJECT(selection), "changed",
+ G_CALLBACK(nsgtk_history_selection_changed), NULL);
+
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_insert_column_with_attributes(treeview, -1, "Title",
+ renderer,
+ "text",
+ COL_TITLE,
+ NULL);
+
+ gtk_tree_view_set_model(treeview, GTK_TREE_MODEL(history_tree));
+
+#endif
+ nsbeos_history_update();
+}
+
+void nsbeos_history_update(void)
+{
+#warning XXX
+#if 0 /* GTK */
+ gtk_tree_store_clear(history_tree);
+ urldb_iterate_entries(nsgtk_history_add_internal);
+#endif
+}
+
+bool nsbeos_history_add_internal(const char *url, const struct url_data *data)
+{
+#warning XXX
+#if 0 /* GTK */
+ GtkTreeIter iter;
+
+ if (data->visits > 0)
+ {
+ gtk_tree_store_append(history_tree, &iter, NULL);
+ gtk_tree_store_set(history_tree, &iter,
+ COL_TITLE, data->title,
+ COL_ADDRESS, url,
+ COL_LASTVISIT, "Unknown",
+ COL_TOTALVISITS, data->visits,
+ -1);
+ }
+
+#endif
+ return true;
+}
+
+#warning XXX
+#if 0 /* GTK */
+void nsgtk_history_selection_changed(GtkTreeSelection *treesel, gpointer g)
+{
+ GtkTreeIter iter;
+ GtkTreeModel *model = GTK_TREE_MODEL(history_tree);
+ if (gtk_tree_selection_get_selected(treesel, &model, &iter))
+ {
+ gchar *b;
+ gint i;
+ char buf[20];
+
+ gtk_tree_model_get(model, &iter, COL_ADDRESS, &b, -1);
+ gtk_label_set_text(GTK_LABEL(glade_xml_get_widget(gladeWindows,
+ "labelHistoryAddress")), b);
+
+ gtk_tree_model_get(model, &iter, COL_LASTVISIT, &b, -1);
+ gtk_label_set_text(GTK_LABEL(glade_xml_get_widget(gladeWindows,
+ "labelHistoryLastVisit")), b);
+
+ gtk_tree_model_get(model, &iter, COL_TOTALVISITS,
+ &i, -1);
+ snprintf(buf, 20, "%d", i);
+ gtk_label_set_text(GTK_LABEL(glade_xml_get_widget(gladeWindows,
+ "labelHistoryVisits")), buf);
+
+
+
+ }
+ else
+ {
+
+ }
+}
+
+void nsgtk_history_row_activated(GtkTreeView *tv, GtkTreePath *path,
+ GtkTreeViewColumn *column, gpointer g)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+
+ model = gtk_tree_view_get_model(tv);
+ if (gtk_tree_model_get_iter(model, &iter, path))
+ {
+ gchar *b;
+
+ gtk_tree_model_get(model, &iter, COL_ADDRESS, &b, -1);
+
+ browser_window_create((const char *)b, NULL, NULL, true);
+ }
+}
+#endif
+
+void global_history_add(const char *url)
+{
+ const struct url_data *data;
+
+ data = urldb_get_url_data(url);
+ if (!data)
+ return;
+
+ nsbeos_history_add_internal(url, data);
+
+}
diff --git a/beos/beos_history.h b/beos/beos_history.h
new file mode 100644
index 000000000..c11a73873
--- /dev/null
+++ b/beos/beos_history.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2006 Rob Kendrick <rjek@rjek.com>
+ *
+ * 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 __NSBEOS_HISTORY_H__
+#define __NSBEOS_HISTORY_H__
+
+#include <View.h>
+#include <Window.h>
+
+extern BWindow *wndHistory;
+
+void nsbeos_history_init(void);
+void nsbeos_history_update(void);
+#warning XXX
+#if 0 /* GTK */
+void nsbeos_history_row_activated(GtkTreeView *, GtkTreePath *,
+ GtkTreeViewColumn *, gpointer);
+#endif
+
+#endif /* __NSGTK_HISTORY_H__ */
diff --git a/beos/beos_login.cpp b/beos/beos_login.cpp
new file mode 100644
index 000000000..da1433b1c
--- /dev/null
+++ b/beos/beos_login.cpp
@@ -0,0 +1,192 @@
+/*
+ * Copyright 2006 Rob Kendrick <rjek@rjek.com>
+ *
+ * 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 <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <TextControl.h>
+#include <View.h>
+#include <Window.h>
+extern "C" {
+#include "utils/log.h"
+#include "content/content.h"
+#include "content/urldb.h"
+#include "desktop/browser.h"
+#include "desktop/401login.h"
+#include "desktop/gui.h"
+#include "utils/messages.h"
+#include "utils/url.h"
+#include "utils/utils.h"
+}
+#include "beos/beos_gui.h"
+
+struct session_401 {
+ char *url; /**< URL being fetched */
+ char *host; /**< Host for user display */
+ char *realm; /**< Authentication realm */
+ struct browser_window *bw; /**< Browser window handle */
+#warning WRITEME
+#if 0 /* GTK */
+ GladeXML *x; /**< Our glade windows */
+ GtkWindow *wnd; /**< The login window itself */
+ GtkEntry *user; /**< Widget with username */
+ GtkEntry *pass; /**< Widget with password */
+#endif
+};
+
+static void create_login_window(struct browser_window *bw, const char *host,
+ const char *realm, const char *fetchurl);
+static void destroy_login_window(struct session_401 *session);
+#warning WRITEME
+#if 0 /* GTK */
+static void nsgtk_login_next(GtkWidget *w, gpointer data);
+static void nsgtk_login_ok_clicked(GtkButton *w, gpointer data);
+static void nsgtk_login_cancel_clicked(GtkButton *w, gpointer data);
+#endif
+
+void gui_401login_open(struct browser_window *bw, struct content *c,
+ const char *realm)
+{
+ char *host;
+ url_func_result res;
+
+ res = url_host(c->url, &host);
+ assert(res == URL_FUNC_OK);
+
+ create_login_window(bw, host, realm, c->url);
+
+ free(host);
+}
+
+void create_login_window(struct browser_window *bw, const char *host,
+ const char *realm, const char *fetchurl)
+{
+ struct session_401 *session;
+
+#warning WRITEME
+#if 0 /* GTK */
+ /* create a new instance of the login window, and get handles to all
+ * the widgets we're interested in.
+ */
+
+ GladeXML *x = glade_xml_new(glade_file_location, NULL, NULL);
+ GtkWindow *wnd = GTK_WINDOW(glade_xml_get_widget(x, "wndLogin"));
+ GtkLabel *lhost, *lrealm;
+ GtkEntry *euser, *epass;
+ GtkButton *bok, *bcan;
+
+ lhost = GTK_LABEL(glade_xml_get_widget(x, "labelLoginHost"));
+ lrealm = GTK_LABEL(glade_xml_get_widget(x, "labelLoginRealm"));
+ euser = GTK_ENTRY(glade_xml_get_widget(x, "entryLoginUser"));
+ epass = GTK_ENTRY(glade_xml_get_widget(x, "entryLoginPass"));
+ bok = GTK_BUTTON(glade_xml_get_widget(x, "buttonLoginOK"));
+ bcan = GTK_BUTTON(glade_xml_get_widget(x, "buttonLoginCan"));
+
+ /* create and fill in our session structure */
+
+ session = calloc(1, sizeof(struct session_401));
+ session->url = strdup(fetchurl);
+ session->host = strdup(host);
+ session->realm = strdup(realm ? realm : "Secure Area");
+ session->bw = bw;
+ session->x = x;
+ session->wnd = wnd;
+ session->user = euser;
+ session->pass = epass;
+
+ /* fill in our new login window */
+
+ gtk_label_set_text(GTK_LABEL(lhost), host);
+ gtk_label_set_text(lrealm, realm);
+ gtk_entry_set_text(euser, "");
+ gtk_entry_set_text(epass, "");
+
+ /* attach signal handlers to the Login and Cancel buttons in our new
+ * window to call functions in this file to process the login
+ */
+ g_signal_connect(G_OBJECT(bok), "clicked",
+ G_CALLBACK(nsgtk_login_ok_clicked), (gpointer)session);
+ g_signal_connect(G_OBJECT(bcan), "clicked",
+ G_CALLBACK(nsgtk_login_cancel_clicked),
+ (gpointer)session);
+
+ /* attach signal handlers to the entry boxes such that pressing
+ * enter in one progresses the focus onto the next widget.
+ */
+
+ g_signal_connect(G_OBJECT(euser), "activate",
+ G_CALLBACK(nsgtk_login_next), (gpointer)epass);
+ g_signal_connect(G_OBJECT(epass), "activate",
+ G_CALLBACK(nsgtk_login_next), (gpointer)bok);
+
+ /* make sure the username entry box currently has the focus */
+ gtk_widget_grab_focus(GTK_WIDGET(euser));
+
+ /* finally, show the window */
+ gtk_widget_show(GTK_WIDGET(wnd));
+#endif
+}
+
+void destroy_login_window(struct session_401 *session)
+{
+ free(session->url);
+ free(session->host);
+ free(session->realm);
+#warning WRITEME
+#if 0 /* GTK */
+ gtk_widget_destroy(GTK_WIDGET(session->wnd));
+ g_object_unref(G_OBJECT(session->x));
+#endif
+ free(session);
+}
+
+#warning WRITEME
+#if 0 /* GTK */
+void nsgtk_login_next(GtkWidget *w, gpointer data)
+{
+ gtk_widget_grab_focus(GTK_WIDGET(data));
+}
+
+void nsgtk_login_ok_clicked(GtkButton *w, gpointer data)
+{
+ /* close the window and destroy it, having continued the fetch
+ * assoicated with it.
+ */
+
+ struct session_401 *session = (struct session_401 *)data;
+ const gchar *user = gtk_entry_get_text(session->user);
+ const gchar *pass = gtk_entry_get_text(session->pass);
+ char *auth;
+
+ auth = malloc(strlen(user) + strlen(pass) + 2);
+ sprintf(auth, "%s:%s", user, pass);
+ urldb_set_auth_details(session->url, session->realm, auth);
+ free(auth);
+
+ browser_window_go(session->bw, session->url, 0, true);
+
+ destroy_login_window(session);
+}
+
+void nsgtk_login_cancel_clicked(GtkButton *w, gpointer data)
+{
+ /* just close and destroy the window */
+ destroy_login_window((struct session_401 *)data);
+}
+#endif
diff --git a/beos/beos_options.cpp b/beos/beos_options.cpp
new file mode 100644
index 000000000..c56c38a43
--- /dev/null
+++ b/beos/beos_options.cpp
@@ -0,0 +1,273 @@
+/*
+ * Copyright 2006 Rob Kendrick <rjek@rjek.com>
+ *
+ * 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 <stdlib.h>
+#include <string.h>
+extern "C" {
+#include "utils/log.h"
+#include "desktop/options.h"
+}
+#include "beos/options.h"
+#include "beos/beos_gui.h"
+#include "beos/beos_scaffolding.h"
+#include "beos/beos_options.h"
+//#include "beos/beos_window.h"
+#include <View.h>
+#include <Window.h>
+
+BWindow *wndPreferences;
+
+#if 0 /* GTK */
+GtkWindow *wndPreferences;
+
+static GtkWidget *entryHomePageURL,
+ *checkHideAdverts,
+ *checkDisablePopups,
+ *checkDisablePlugins,
+ *spinHistoryAge,
+ *checkHoverURLs,
+ *checkRequestOverwrite,
+ *checkDisplayRecentURLs,
+ *checkSendReferer,
+
+ *comboProxyType,
+ *entryProxyHost,
+ *entryProxyPort,
+ *entryProxyUser,
+ *entryProxyPassword,
+ *spinMaxFetchers,
+ *spinFetchesPerHost,
+ *spinCachedConnections,
+
+ *checkUseCairo,
+ *checkResampleImages,
+ *spinAnimationSpeed,
+ *checkDisableAnimations,
+
+ *fontSansSerif,
+ *fontSerif,
+ *fontMonospace,
+ *fontCursive,
+ *fontFantasy,
+ *comboDefault,
+ *spinDefaultSize,
+ *spinMinimumSize,
+
+ *spinMemoryCacheSize,
+ *spinDiscCacheAge;
+
+#define FIND_WIDGET(x) (x) = glade_xml_get_widget(gladeWindows, #x); if ((x) == NULL) LOG(("Unable to find widget '%s'!", #x))
+#endif
+
+void nsbeos_options_init(void) {
+#if 0 /* GTK */
+ wndPreferences = GTK_WINDOW(glade_xml_get_widget(gladeWindows,
+ "wndPreferences"));
+
+ /* get widget objects */
+ FIND_WIDGET(entryHomePageURL);
+ FIND_WIDGET(checkHideAdverts);
+ FIND_WIDGET(checkDisablePopups);
+ FIND_WIDGET(checkDisablePlugins);
+ FIND_WIDGET(spinHistoryAge);
+ FIND_WIDGET(checkHoverURLs);
+ FIND_WIDGET(checkRequestOverwrite);
+ FIND_WIDGET(checkDisplayRecentURLs);
+ FIND_WIDGET(checkSendReferer);
+
+ FIND_WIDGET(comboProxyType);
+ FIND_WIDGET(entryProxyHost);
+ FIND_WIDGET(entryProxyPort);
+ FIND_WIDGET(entryProxyUser);
+ FIND_WIDGET(entryProxyPassword);
+ FIND_WIDGET(spinMaxFetchers);
+ FIND_WIDGET(spinFetchesPerHost);
+ FIND_WIDGET(spinCachedConnections);
+
+ FIND_WIDGET(checkUseCairo);
+ FIND_WIDGET(checkResampleImages);
+ FIND_WIDGET(spinAnimationSpeed);
+ FIND_WIDGET(checkDisableAnimations);
+
+ FIND_WIDGET(fontSansSerif);
+ FIND_WIDGET(fontSerif);
+ FIND_WIDGET(fontMonospace);
+ FIND_WIDGET(fontCursive);
+ FIND_WIDGET(fontFantasy);
+ FIND_WIDGET(comboDefault);
+ FIND_WIDGET(spinDefaultSize);
+ FIND_WIDGET(spinMinimumSize);
+
+ FIND_WIDGET(spinMemoryCacheSize);
+ FIND_WIDGET(spinDiscCacheAge);
+
+#endif
+ /* set the widgets to reflect the current options */
+ nsbeos_options_load();
+}
+
+#if 0 /* GTK */
+#define SET_ENTRY(x, y) gtk_entry_set_text(GTK_ENTRY((x)), (y))
+#define SET_SPIN(x, y) gtk_spin_button_set_value(GTK_SPIN_BUTTON((x)), (y))
+#define SET_CHECK(x, y) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON((x)), (y))
+#define SET_COMBO(x, y) gtk_combo_box_set_active(GTK_COMBO_BOX((x)), (y))
+#define SET_FONT(x, y) gtk_font_button_set_font_name(GTK_FONT_BUTTON((x)), (y))
+#endif
+
+void nsbeos_options_load(void) {
+#warning WRITEME
+#if 0 /* GTK */
+ char b[20];
+ int proxytype = 0;
+
+ SET_ENTRY(entryHomePageURL,
+ option_homepage_url ? option_homepage_url : "");
+ SET_CHECK(checkHideAdverts, option_block_ads);
+ SET_CHECK(checkDisplayRecentURLs, option_url_suggestion);
+ SET_CHECK(checkSendReferer, option_send_referer);
+
+ switch (option_http_proxy_auth) {
+ case OPTION_HTTP_PROXY_AUTH_NONE:
+ proxytype = 1;
+ break;
+ case OPTION_HTTP_PROXY_AUTH_BASIC:
+ proxytype = 2;
+ break;
+ case OPTION_HTTP_PROXY_AUTH_NTLM:
+ proxytype = 3;
+ break;
+ }
+
+ if (option_http_proxy == false)
+ proxytype = 0;
+
+ SET_COMBO(comboProxyType, proxytype);
+ SET_ENTRY(entryProxyHost,
+ option_http_proxy_host ? option_http_proxy_host : "");
+ snprintf(b, 20, "%d", option_http_proxy_port);
+ SET_ENTRY(entryProxyPort, b);
+ SET_ENTRY(entryProxyUser, option_http_proxy_auth_user ?
+ option_http_proxy_auth_user : "");
+ SET_ENTRY(entryProxyPassword, option_http_proxy_auth_pass ?
+ option_http_proxy_auth_pass : "");
+
+ SET_SPIN(spinMaxFetchers, option_max_fetchers);
+ SET_SPIN(spinFetchesPerHost, option_max_fetchers_per_host);
+ SET_SPIN(spinCachedConnections, option_max_cached_fetch_handles);
+
+ SET_CHECK(checkUseCairo, option_render_cairo);
+ SET_CHECK(checkResampleImages, option_render_resample);
+ SET_SPIN(spinAnimationSpeed, option_minimum_gif_delay / 100);
+ SET_CHECK(checkDisableAnimations, !option_animate_images);
+
+ SET_FONT(fontSansSerif, option_font_sans);
+ SET_FONT(fontSerif, option_font_serif);
+ SET_FONT(fontMonospace, option_font_mono);
+ SET_FONT(fontCursive, option_font_cursive);
+ SET_FONT(fontFantasy, option_font_fantasy);
+ SET_COMBO(comboDefault, option_font_default - 1);
+ SET_SPIN(spinDefaultSize, option_font_size / 10);
+ SET_SPIN(spinMinimumSize, option_font_min_size / 10);
+
+ SET_SPIN(spinMemoryCacheSize, option_memory_cache_size >> 20);
+ SET_SPIN(spinDiscCacheAge, option_disc_cache_age);
+#endif
+}
+
+#if 0 /* GTK */
+#define GET_ENTRY(x, y) if ((y)) free((y)); \
+ (y) = strdup(gtk_entry_get_text(GTK_ENTRY((x))))
+#define GET_CHECK(x, y) (y) = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON((x)))
+#define GET_SPIN(x, y) (y) = gtk_spin_button_get_value(GTK_SPIN_BUTTON((x)))
+#define GET_COMBO(x, y) (y) = gtk_combo_box_get_active(GTK_COMBO_BOX((x)))
+#define GET_FONT(x, y) if ((y)) free((y)); \
+ (y) = strdup(gtk_font_button_get_font_name(GTK_FONT_BUTTON((x))))
+#endif
+
+void nsbeos_options_save(void) {
+#warning WRITEME
+#if 0 /* GTK */
+ char *b = NULL;
+ int i;
+
+ GET_ENTRY(entryHomePageURL, option_homepage_url);
+ GET_CHECK(checkDisplayRecentURLs, option_url_suggestion);
+
+ GET_COMBO(comboProxyType, i);
+ LOG(("proxy type: %d", i));
+ switch (i)
+ {
+ case 0:
+ option_http_proxy = false;
+ option_http_proxy_auth = OPTION_HTTP_PROXY_AUTH_NONE;
+ break;
+ case 1:
+ option_http_proxy = true;
+ option_http_proxy_auth = OPTION_HTTP_PROXY_AUTH_NONE;
+ break;
+ case 2:
+ option_http_proxy = true;
+ option_http_proxy_auth = OPTION_HTTP_PROXY_AUTH_BASIC;
+ break;
+ case 3:
+ option_http_proxy = true;
+ option_http_proxy_auth = OPTION_HTTP_PROXY_AUTH_NTLM;
+ break;
+ default:
+ option_http_proxy = false;
+ option_http_proxy_auth = OPTION_HTTP_PROXY_AUTH_NONE;
+ break;
+ }
+
+ GET_ENTRY(entryProxyHost, option_http_proxy_host);
+ GET_ENTRY(entryProxyPort, b);
+ option_http_proxy_port = atoi(b);
+ free(b);
+ GET_ENTRY(entryProxyUser, option_http_proxy_auth_user);
+ GET_ENTRY(entryProxyPassword, option_http_proxy_auth_pass);
+
+ GET_SPIN(spinMaxFetchers, option_max_fetchers);
+ GET_SPIN(spinFetchesPerHost, option_max_fetchers_per_host);
+ GET_SPIN(spinCachedConnections, option_max_cached_fetch_handles);
+
+ GET_CHECK(checkUseCairo, option_render_cairo);
+ GET_CHECK(checkResampleImages, option_render_resample);
+ GET_SPIN(spinAnimationSpeed, option_minimum_gif_delay);
+ option_minimum_gif_delay *= 100;
+
+ GET_FONT(fontSansSerif, option_font_sans);
+ GET_FONT(fontSerif, option_font_serif);
+ GET_FONT(fontMonospace, option_font_mono);
+ GET_FONT(fontCursive, option_font_cursive);
+ GET_FONT(fontFantasy, option_font_fantasy);
+ GET_COMBO(comboDefault, option_font_default);
+ option_font_default++;
+
+ GET_SPIN(spinDefaultSize, option_font_size);
+ option_font_size *= 10;
+ GET_SPIN(spinMinimumSize, option_font_min_size);
+ option_font_min_size *= 10;
+
+ GET_SPIN(spinMemoryCacheSize, option_memory_cache_size);
+ option_memory_cache_size <<= 20;
+
+ options_write(options_file_location);
+ nsgtk_reflow_all_windows();
+#endif
+}
diff --git a/beos/beos_options.h b/beos/beos_options.h
new file mode 100644
index 000000000..e5605a922
--- /dev/null
+++ b/beos/beos_options.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2006 Rob Kendrick <rjek@rjek.com>
+ *
+ * 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_BEOS_OPTIONS_H
+#define NETSURF_BEOS_OPTIONS_H
+
+#include <Window.h>
+
+#if 0 /* GTK */
+extern GtkWindow *wndPreferences;
+#endif
+extern BWindow *wndPreferences;
+
+void nsbeos_options_init(void); /** Init options and load window */
+void nsbeos_options_load(void); /** Load current options into window */
+void nsbeos_options_save(void); /** Save options from window */
+
+#endif
diff --git a/beos/beos_plotters.cpp b/beos/beos_plotters.cpp
new file mode 100644
index 000000000..0cfee16a0
--- /dev/null
+++ b/beos/beos_plotters.cpp
@@ -0,0 +1,753 @@
+/*
+ * Copyright 2006 Rob Kendrick <rjek@rjek.com>
+ * Copyright 2005 James Bursa <bursa@users.sourceforge.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/>.
+ */
+
+/** \file
+ * Target independent plotting (BeOS/Haiku implementation).
+ */
+
+#include <math.h>
+#include <BeBuild.h>
+#include <Bitmap.h>
+#include <GraphicsDefs.h>
+#include <Region.h>
+#include <View.h>
+extern "C" {
+#include "desktop/plotters.h"
+#include "render/font.h"
+#include "utils/log.h"
+#include "utils/utils.h"
+#include "desktop/options.h"
+}
+#include "beos/beos_font.h"
+#include "beos/beos_gui.h"
+#include "beos/beos_plotters.h"
+//#include "beos/beos_scaffolding.h"
+//#include "beos/options.h"
+#include "beos/beos_bitmap.h"
+
+#warning MAKE ME static
+/*static*/ BView *current_view;
+
+#if 0 /* GTK */
+GtkWidget *current_widget;
+GdkDrawable *current_drawable;
+GdkGC *current_gc;
+#ifdef CAIRO_VERSION
+cairo_t *current_cr;
+#endif
+#endif
+
+static bool nsbeos_plot_clg(colour c);
+static bool nsbeos_plot_rectangle(int x0, int y0, int width, int height,
+ int line_width, colour c, bool dotted, bool dashed);
+static bool nsbeos_plot_line(int x0, int y0, int x1, int y1, int width,
+ colour c, bool dotted, bool dashed);
+static bool nsbeos_plot_polygon(int *p, unsigned int n, colour fill);
+static bool nsbeos_plot_path(float *p, unsigned int n, colour fill, float width,
+ colour c, float *transform);
+static bool nsbeos_plot_fill(int x0, int y0, int x1, int y1, colour c);
+static bool nsbeos_plot_clip(int clip_x0, int clip_y0,
+ int clip_x1, int clip_y1);
+static bool nsbeos_plot_text(int x, int y, const struct css_style *style,
+ const char *text, size_t length, colour bg, colour c);
+static bool nsbeos_plot_disc(int x, int y, int radius, colour c, bool filled);
+static bool nsbeos_plot_arc(int x, int y, int radius, int angle1, int angle2,
+ colour c);
+static bool nsbeos_plot_bitmap(int x, int y, int width, int height,
+ struct bitmap *bitmap, colour bg);
+static bool nsbeos_plot_bitmap_tile(int x, int y, int width, int height,
+ struct bitmap *bitmap, colour bg,
+ bool repeat_x, bool repeat_y);
+
+#if 0 /* GTK */
+static GdkRectangle cliprect;
+#endif
+static float nsbeos_plot_scale = 1.0;
+
+#warning make patterns nicer
+static const pattern kDottedPattern = { 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa };
+static const pattern kDashedPattern = { 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0x33, 0x33 };
+
+static const rgb_color kBlackColor = { 0, 0, 0, 255 };
+
+struct plotter_table plot;
+
+const struct plotter_table nsbeos_plotters = {
+ nsbeos_plot_clg,
+ nsbeos_plot_rectangle,
+ nsbeos_plot_line,
+ nsbeos_plot_polygon,
+ nsbeos_plot_fill,
+ nsbeos_plot_clip,
+ nsbeos_plot_text,
+ nsbeos_plot_disc,
+ nsbeos_plot_arc,
+ nsbeos_plot_bitmap,
+ nsbeos_plot_bitmap_tile,
+ NULL,
+ NULL,
+ NULL,
+ nsbeos_plot_path
+};
+
+
+BView *nsbeos_current_gc(void)
+{
+ return current_view;
+}
+
+BView *nsbeos_current_gc_lock(void)
+{
+ BView *view = current_view;
+ if (view && view->LockLooper())
+ return view;
+ return NULL;
+}
+
+void nsbeos_current_gc_unlock(void)
+{
+ if (current_view)
+ current_view->UnlockLooper();
+}
+
+void nsbeos_current_gc_set(BView *view)
+{
+ // XXX: (un)lock previous ?
+ current_view = view;
+}
+
+
+bool nsbeos_plot_clg(colour c)
+{
+#warning BView::Invalidate() ?
+ return true;
+}
+
+bool nsbeos_plot_rectangle(int x0, int y0, int width, int height,
+ int line_width, colour c, bool dotted, bool dashed)
+{
+ pattern pat = B_SOLID_HIGH;
+ BView *view;
+
+ if (dotted)
+ pat = kDottedPattern;
+ else if (dashed)
+ pat = kDashedPattern;
+
+ view = nsbeos_current_gc/*_lock*/();
+ if (view == NULL) {
+ warn_user("No GC", 0);
+ return false;
+ }
+
+ nsbeos_set_colour(c);
+
+ BRect rect(x0, y0, x0 + width - 1, y0 + height - 1);
+ view->StrokeRect(rect, pat);
+
+ //nsbeos_current_gc_unlock();
+
+#if 0 /* GTK */
+#ifdef CAIRO_VERSION
+ if (option_render_cairo) {
+ if (line_width == 0)
+ line_width = 1;
+
+ cairo_set_line_width(current_cr, line_width);
+ cairo_rectangle(current_cr, x0, y0, width, height);
+ cairo_stroke(current_cr);
+ } else
+#endif
+ gdk_draw_rectangle(current_drawable, current_gc,
+ FALSE, x0, y0, width, height);
+ return true;
+#endif
+}
+
+
+bool nsbeos_plot_line(int x0, int y0, int x1, int y1, int width,
+ colour c, bool dotted, bool dashed)
+{
+ pattern pat = B_SOLID_HIGH;
+ BView *view;
+
+ if (dotted)
+ pat = kDottedPattern;
+ else if (dashed)
+ pat = kDashedPattern;
+
+ view = nsbeos_current_gc/*_lock*/();
+ if (view == NULL) {
+ warn_user("No GC", 0);
+ return false;
+ }
+
+ nsbeos_set_colour(c);
+
+ BPoint start(x0, y0);
+ BPoint end(x1, y1);
+ view->StrokeLine(start, end, pat);
+
+ //nsbeos_current_gc_unlock();
+
+#if 0 /* GTK */
+#ifdef CAIRO_VERSION
+ if (option_render_cairo) {
+ if (width == 0)
+ width = 1;
+
+ cairo_set_line_width(current_cr, width);
+ cairo_move_to(current_cr, x0, y0 - 0.5);
+ cairo_line_to(current_cr, x1, y1 - 0.5);
+ cairo_stroke(current_cr);
+ } else
+#endif
+ gdk_draw_line(current_drawable, current_gc,
+ x0, y0, x1, y1);
+#endif
+ return true;
+}
+
+
+bool nsbeos_plot_polygon(int *p, unsigned int n, colour fill)
+{
+ unsigned int i;
+ BView *view;
+
+ view = nsbeos_current_gc/*_lock*/();
+ if (view == NULL) {
+ warn_user("No GC", 0);
+ return false;
+ }
+
+ rgb_color color = nsbeos_rgb_colour(fill);
+
+ view->BeginLineArray(n);
+
+ for (i = 0; i < n; i++) {
+ BPoint start(p[2 * i], p[2 * i + 1]);
+ BPoint end(p[(2 * i + 2) % n], p[(2 * i + 3) % n]);
+ view->AddLine(start, end, color);
+ }
+
+ view->EndLineArray();
+
+ //nsbeos_current_gc_unlock();
+
+#if 0 /* GTK */
+ nsbeos_set_colour(fill);
+ nsbeos_set_solid();
+#ifdef CAIRO_VERSION
+ if (option_render_cairo) {
+ cairo_set_line_width(current_cr, 0);
+ cairo_move_to(current_cr, p[0], p[1]);
+ for (i = 1; i != n; i++) {
+ cairo_line_to(current_cr, p[i * 2], p[i * 2 + 1]);
+ }
+ cairo_fill(current_cr);
+ cairo_stroke(current_cr);
+ } else
+#endif
+ {
+ GdkPoint q[n];
+ for (i = 0; i != n; i++) {
+ q[i].x = p[i * 2];
+ q[i].y = p[i * 2 + 1];
+ }
+ gdk_draw_polygon(current_drawable, current_gc,
+ TRUE, q, n);
+ }
+#endif
+ return true;
+}
+
+
+bool nsbeos_plot_fill(int x0, int y0, int x1, int y1, colour c)
+{
+ BView *view;
+
+ view = nsbeos_current_gc/*_lock*/();
+ if (view == NULL) {
+ warn_user("No GC", 0);
+ return false;
+ }
+
+ nsbeos_set_colour(c);
+
+ BRect rect(x0, y0, x1, y1);
+ view->FillRect(rect);
+
+ //nsbeos_current_gc_unlock();
+
+#if 0 /* GTK */
+ nsbeos_set_colour(c);
+ nsbeos_set_solid();
+#ifdef CAIRO_VERSION
+ if (option_render_cairo) {
+ cairo_set_line_width(current_cr, 0);
+ cairo_rectangle(current_cr, x0, y0, x1 - x0, y1 - y0);
+ cairo_fill(current_cr);
+ cairo_stroke(current_cr);
+ } else
+#endif
+ gdk_draw_rectangle(current_drawable, current_gc,
+ TRUE, x0, y0, x1 - x0, y1 - y0);
+#endif
+ return true;
+}
+
+
+bool nsbeos_plot_clip(int clip_x0, int clip_y0,
+ int clip_x1, int clip_y1)
+{
+ BView *view;
+ //fprintf(stderr, "%s(%d, %d, %d, %d)\n", __FUNCTION__, clip_x0, clip_y0, clip_x1, clip_y1);
+
+ view = nsbeos_current_gc/*_lock*/();
+ if (view == NULL) {
+ warn_user("No GC", 0);
+ return false;
+ }
+
+ BRect rect(clip_x0, clip_y0, clip_x1, clip_y1);
+ BRegion clip(rect);
+ view->ConstrainClippingRegion(NULL);
+ if (view->Bounds() != rect)
+ view->ConstrainClippingRegion(&clip);
+
+
+ //nsbeos_current_gc_unlock();
+
+#if 0 /* GTK */
+#ifdef CAIRO_VERSION
+ if (option_render_cairo) {
+ cairo_reset_clip(current_cr);
+ cairo_rectangle(current_cr, clip_x0, clip_y0,
+ clip_x1 - clip_x0, clip_y1 - clip_y0);
+ cairo_clip(current_cr);
+ }
+#endif
+ cliprect.x = clip_x0;
+ cliprect.y = clip_y0;
+ cliprect.width = clip_x1 - clip_x0;
+ cliprect.height = clip_y1 - clip_y0;
+ gdk_gc_set_clip_rectangle(current_gc, &cliprect);
+#endif
+ return true;
+}
+
+
+bool nsbeos_plot_text(int x, int y, const struct css_style *style,
+ const char *text, size_t length, colour bg, colour c)
+{
+ return nsfont_paint(style, text, length, x, y, bg, c);
+}
+
+
+bool nsbeos_plot_disc(int x, int y, int radius, colour c, bool filled)
+{
+ BView *view;
+
+ view = nsbeos_current_gc/*_lock*/();
+ if (view == NULL) {
+ warn_user("No GC", 0);
+ return false;
+ }
+
+ nsbeos_set_colour(c);
+
+ BPoint center(x, y);
+ if (filled)
+ view->FillEllipse(center, radius, radius);
+ else
+ view->StrokeEllipse(center, radius, radius);
+
+ //nsbeos_current_gc_unlock();
+
+#if 0 /* GTK */
+ nsbeos_set_colour(c);
+ nsbeos_set_solid();
+#ifdef CAIRO_VERSION
+ if (option_render_cairo) {
+ if (filled)
+ cairo_set_line_width(current_cr, 0);
+ else
+ cairo_set_line_width(current_cr, 1);
+
+ cairo_arc(current_cr, x, y, radius, 0, M_PI * 2);
+
+ if (filled)
+ cairo_fill(current_cr);
+
+ cairo_stroke(current_cr);
+ } else
+#endif
+ gdk_draw_arc(current_drawable, current_gc,
+ filled ? TRUE : FALSE, x - (radius), y - radius,
+ radius * 2, radius * 2,
+ 0,
+ 360 * 64);
+
+#endif
+ return true;
+}
+
+bool nsbeos_plot_arc(int x, int y, int radius, int angle1, int angle2, colour c)
+{
+ BView *view;
+
+ view = nsbeos_current_gc/*_lock*/();
+ if (view == NULL) {
+ warn_user("No GC", 0);
+ return false;
+ }
+
+ nsbeos_set_colour(c);
+
+ BPoint center(x, y);
+ float angle = angle1; // in degree
+ float span = angle2 - angle1; // in degree
+ view->StrokeArc(center, radius, radius, angle, span);
+
+ //nsbeos_current_gc_unlock();
+
+#if 0 /* GTK */
+ nsbeos_set_colour(c);
+ nsbeos_set_solid();
+#ifdef CAIRO_VERSION
+ if (option_render_cairo) {
+ cairo_set_line_width(current_cr, 1);
+ cairo_arc(current_cr, x, y, radius,
+ (angle1 + 90) * (M_PI / 180),
+ (angle2 + 90) * (M_PI / 180));
+ cairo_stroke(current_cr);
+ } else
+#endif
+ gdk_draw_arc(current_drawable, current_gc,
+ FALSE, x - (radius), y - radius,
+ radius * 2, radius * 2,
+ angle1 * 64, angle2 * 64);
+
+#endif
+ return true;
+}
+
+static bool nsbeos_plot_bbitmap(int x, int y, int width, int height,
+ BBitmap *b, colour bg)
+{
+ /* XXX: This currently ignores the background colour supplied.
+ * Does this matter?
+ */
+
+ if (width == 0 || height == 0)
+ return true;
+
+ BView *view;
+
+ view = nsbeos_current_gc/*_lock*/();
+ if (view == NULL) {
+ warn_user("No GC", 0);
+ return false;
+ }
+
+ drawing_mode oldmode = view->DrawingMode();
+ view->SetDrawingMode(B_OP_OVER);
+
+ // XXX DrawBitmap() resamples if rect doesn't match,
+ // but doesn't do any filtering
+ // XXX: use Zeta API if available ?
+
+ BRect rect(x, y, x + width - 1, y + height - 1);
+ rgb_color old = view->LowColor();
+ if (bg != TRANSPARENT) {
+ view->SetLowColor(nsbeos_rgb_colour(bg));
+ view->FillRect(rect, B_SOLID_LOW);
+ }
+ view->DrawBitmap(b, rect);
+ // maybe not needed?
+ view->SetLowColor(old);
+ view->SetDrawingMode(oldmode);
+
+ //nsbeos_current_gc_unlock();
+
+#if 0 /* GTK */
+ /* XXX: This currently ignores the background colour supplied.
+ * Does this matter?
+ */
+
+ if (width == 0 || height == 0)
+ return true;
+
+ if (gdk_pixbuf_get_width(pixbuf) == width &&
+ gdk_pixbuf_get_height(pixbuf) == height) {
+ gdk_draw_pixbuf(current_drawable, current_gc,
+ pixbuf,
+ 0, 0,
+ x, y,
+ width, height,
+ GDK_RGB_DITHER_MAX, 0, 0);
+
+ } else {
+ GdkPixbuf *scaled;
+ scaled = gdk_pixbuf_scale_simple(pixbuf,
+ width, height,
+ option_render_resample ? GDK_INTERP_BILINEAR
+ : GDK_INTERP_NEAREST);
+ if (!scaled)
+ return false;
+
+ gdk_draw_pixbuf(current_drawable, current_gc,
+ scaled,
+ 0, 0,
+ x, y,
+ width, height,
+ GDK_RGB_DITHER_MAX, 0, 0);
+
+ g_object_unref(scaled);
+ }
+
+#endif
+ return true;
+}
+
+bool nsbeos_plot_bitmap(int x, int y, int width, int height,
+ struct bitmap *bitmap, colour bg)
+{
+ BBitmap *b = nsbeos_bitmap_get_primary(bitmap);
+ return nsbeos_plot_bbitmap(x, y, width, height, b, bg);
+#if 0 /* GTK */
+ GdkPixbuf *pixbuf = gtk_bitmap_get_primary(bitmap);
+ return nsbeos_plot_pixbuf(x, y, width, height, pixbuf, bg);
+#endif
+}
+
+bool nsbeos_plot_bitmap_tile(int x, int y, int width, int height,
+ struct bitmap *bitmap, colour bg,
+ bool repeat_x, bool repeat_y)
+{
+ int doneheight = 0, donewidth = 0;
+ BBitmap *primary;
+ BBitmap *pretiled;
+
+ if (!(repeat_x || repeat_y)) {
+ /* Not repeating at all, so just pass it on */
+ return nsbeos_plot_bitmap(x,y,width,height,bitmap,bg);
+ }
+
+ if (repeat_x && !repeat_y)
+ pretiled = nsbeos_bitmap_get_pretile_x(bitmap);
+ if (repeat_x && repeat_y)
+ pretiled = nsbeos_bitmap_get_pretile_xy(bitmap);
+ if (!repeat_x && repeat_y)
+ pretiled = nsbeos_bitmap_get_pretile_y(bitmap);
+ primary = nsbeos_bitmap_get_primary(bitmap);
+ /* use the primary and pretiled widths to scale the w/h provided */
+ width *= pretiled->Bounds().Width() + 1;
+ width /= primary->Bounds().Width() + 1;
+ height *= pretiled->Bounds().Height() + 1;
+ height /= primary->Bounds().Height() + 1;
+
+ BView *view;
+
+ view = nsbeos_current_gc/*_lock*/();
+ if (view == NULL) {
+ warn_user("No GC", 0);
+ return false;
+ }
+
+ // XXX: do we really need to use clipping reg ?
+ // I guess it's faster to not draw clipped out stuff...
+
+ BRect cliprect;
+ BRegion clipreg;
+ view->GetClippingRegion(&clipreg);
+ cliprect = clipreg.Frame();
+
+ //XXX: FIXME
+
+ if (y > cliprect.top)
+ doneheight = ((int)cliprect.top - height) + ((y - (int)cliprect.top) % height);
+ else
+ doneheight = y;
+
+ while (doneheight < ((int)cliprect.bottom)) {
+ if (x > cliprect.left)
+ donewidth = ((int)cliprect.left - width) + ((x - (int)cliprect.left) % width);
+ else
+ donewidth = x;
+ while (donewidth < (cliprect.right)) {
+ nsbeos_plot_bbitmap(donewidth, doneheight,
+ width, height, pretiled, bg);
+ donewidth += width;
+ if (!repeat_x) break;
+ }
+ doneheight += height;
+ if (!repeat_y) break;
+ }
+
+#warning WRITEME
+#if 0 /* GTK */
+ int doneheight = 0, donewidth = 0;
+ GdkPixbuf *primary;
+ GdkPixbuf *pretiled;
+
+ if (!(repeat_x || repeat_y)) {
+ /* Not repeating at all, so just pass it on */
+ return nsbeos_plot_bitmap(x,y,width,height,bitmap,bg);
+ }
+
+ if (repeat_x && !repeat_y)
+ pretiled = gtk_bitmap_get_pretile_x(bitmap);
+ if (repeat_x && repeat_y)
+ pretiled = gtk_bitmap_get_pretile_xy(bitmap);
+ if (!repeat_x && repeat_y)
+ pretiled = gtk_bitmap_get_pretile_y(bitmap);
+ primary = gtk_bitmap_get_primary(bitmap);
+ /* use the primary and pretiled widths to scale the w/h provided */
+ width *= gdk_pixbuf_get_width(pretiled);
+ width /= gdk_pixbuf_get_width(primary);
+ height *= gdk_pixbuf_get_height(pretiled);
+ height /= gdk_pixbuf_get_height(primary);
+
+ if (y > cliprect.y)
+ doneheight = (cliprect.y - height) + ((y - cliprect.y) % height);
+ else
+ doneheight = y;
+
+ while (doneheight < (cliprect.y + cliprect.height)) {
+ if (x > cliprect.x)
+ donewidth = (cliprect.x - width) + ((x - cliprect.x) % width);
+ else
+ donewidth = x;
+ while (donewidth < (cliprect.x + cliprect.width)) {
+ nsbeos_plot_pixbuf(donewidth, doneheight,
+ width, height, pretiled, bg);
+ donewidth += width;
+ if (!repeat_x) break;
+ }
+ doneheight += height;
+ if (!repeat_y) break;
+ }
+
+
+#endif
+ return true;
+}
+
+bool nsbeos_plot_path(float *p, unsigned int n, colour fill, float width,
+ colour c, float *transform)
+{
+#warning WRITEME
+#if 0 /* GTK */
+ /* Only the internal SVG renderer uses this plot call currently,
+ * and the GTK version uses librsvg. Thus, we ignore this complexity,
+ * and just return true obliviously.
+ */
+
+#endif
+ return true;
+}
+
+rgb_color nsbeos_rgb_colour(colour c)
+{
+ rgb_color color;
+ if (c == TRANSPARENT)
+ return B_TRANSPARENT_32_BIT;
+ color.red = c & 0x0000ff;
+ color.green = (c & 0x00ff00) >> 8;
+ color.blue = (c & 0xff0000) >> 16;
+ return color;
+}
+
+void nsbeos_set_colour(colour c)
+{
+ rgb_color color = nsbeos_rgb_colour(c);
+ BView *view = nsbeos_current_gc();
+ view->SetHighColor(color);
+#if 0 /* GTK */
+ int r, g, b;
+ GdkColor colour;
+
+ r = c & 0xff;
+ g = (c & 0xff00) >> 8;
+ b = (c & 0xff0000) >> 16;
+
+ colour.red = r | (r << 8);
+ colour.green = g | (g << 8);
+ colour.blue = b | (b << 8);
+ colour.pixel = (r << 16) | (g << 8) | b;
+
+ gdk_color_alloc(gdk_colormap_get_system(),
+ &colour);
+ gdk_gc_set_foreground(current_gc, &colour);
+#ifdef CAIRO_VERSION
+ if (option_render_cairo)
+ cairo_set_source_rgba(current_cr, r / 255.0,
+ g / 255.0, b / 255.0, 1.0);
+#endif
+#endif
+}
+
+void nsbeos_plot_set_scale(float s)
+{
+ nsbeos_plot_scale = s;
+}
+
+float nsbeos_plot_get_scale(void)
+{
+ return nsbeos_plot_scale;
+}
+
+/** Plot a caret. It is assumed that the plotters have been set up. */
+void nsbeos_plot_caret(int x, int y, int h)
+{
+ BView *view;
+
+ view = nsbeos_current_gc/*_lock*/();
+ if (view == NULL)
+ /* TODO: report an error here */
+ return;
+
+ BPoint start(x, y);
+ BPoint end(x, y + h - 1);
+#if defined(__HAIKU__) || defined(B_BEOS_VERSION_DANO)
+ view->SetHighColor(ui_color(B_DOCUMENT_TEXT_COLOR));
+#else
+ view->SetHighColor(kBlackColor);
+#endif
+ view->StrokeLine(start, end);
+
+ //nsbeos_current_gc_unlock();
+
+#if 0 /* GTK */
+ GdkColor colour;
+
+ colour.red = 0;
+ colour.green = 0;
+ colour.blue = 0;
+ colour.pixel = 0;
+ gdk_color_alloc(gdk_colormap_get_system(),
+ &colour);
+ gdk_gc_set_foreground(current_gc, &colour);
+
+ gdk_draw_line(current_drawable, current_gc,
+ x, y,
+ x, y + h - 1);
+#endif
+}
diff --git a/beos/beos_plotters.h b/beos/beos_plotters.h
new file mode 100644
index 000000000..9530c4b7e
--- /dev/null
+++ b/beos/beos_plotters.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2005 James Bursa <bursa@users.sourceforge.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/>.
+ */
+
+/** \file
+ * Target independent plotting (BeOS interface).
+ */
+
+#ifndef NETSURF_BEOS_PLOTTERS_H
+#define NETSURF_BEOS_PLOTTERS_H 1
+
+extern "C" {
+
+struct plotter_table;
+
+extern const struct plotter_table nsbeos_plotters;
+
+}
+
+#include <View.h>
+
+extern BView *current_view;
+#if 0 /* GTK */
+extern GtkWidget *current_widget;
+extern GdkDrawable *current_drawable;
+extern GdkGC *current_gc;
+#ifdef CAIRO_VERSION
+extern cairo_t *current_cr;
+#endif
+#endif
+
+extern BView *nsbeos_current_gc(void);
+extern BView *nsbeos_current_gc_lock(void);
+extern void nsbeos_current_gc_unlock(void);
+extern void nsbeos_current_gc_set(BView *view);
+
+void nsbeos_plot_set_scale(float s);
+float nsbeos_plot_get_scale(void);
+rgb_color nsbeos_rgb_colour(colour c);
+void nsbeos_set_colour(colour c);
+void nsbeos_plot_caret(int x, int y, int h);
+
+#endif /* NETSURF_GTK_PLOTTERS_H */
diff --git a/beos/beos_res.rdef b/beos/beos_res.rdef
new file mode 100644
index 000000000..641098bb4
--- /dev/null
+++ b/beos/beos_res.rdef
@@ -0,0 +1,350 @@
+/*
+** /boot/home/beos_res.rdef
+**
+** Automatically generated by BResourceParser on
+** Saturday, May 17, 2008 at 23:10:33.
+**
+*/
+
+enum {
+ R_ResBackNavActive = 1042,
+ R_ResBackNavInactive = 1043,
+ R_ResForwNavActive = 1044,
+ R_ResForwNavInactive = 1045,
+ R_ResUpNavActive = 1046,
+ R_ResUpNavInactive = 1047,
+ R_ResBackNavActiveSel = 1048,
+ R_ResForwNavActiveSel = 1049,
+ R_ResUpNavActiveSel = 1050
+};
+
+
+//resource(123, "beosdefault.css") import beos/beosdefault.css;
+//resource(123, "beosdefault.css") #'PNG ' import "beos/res/beosdefault.css";
+//import(123, "beosdefault.css") "beos/beosdefault.css";
+//resource(123, "beos/beosdefault.css") #'PNG ' read("beos/beosdefault.css");
+
+resource(1, "BEOS:APP_FLAGS") (#'APPF') $"01000000";
+
+resource(1, "BEOS:L:STD_ICON") #'ICON' array {
+ $"FFFFFFFFFFFFFFFFFFFFFF0E0A00D600D6000AAF0EFFFFFFFFFFFFFFFFFFFFFF"
+ $"FFFFFFFFFFFFFFFF0E0A000001DED5D5D5DE020000090EFFFFFFFFFFFFFFFFFF"
+ $"FFFFFFFFFFFFFF0B0001B58D6666666C6C6C6C93B50200090EFFFFFFFFFFFFFF"
+ $"FFFFFFFFFF0E0000016D66666666666C6C6C6C6C6C6CB40104AFFFFFFFFFFFFF"
+ $"FFFFFFFF0E0001B503464666666666666C6C6C6C6C6C6C9303000DFFFFFFFFFF"
+ $"FFFFFF0E000267AEB5464666666666666C6C6C6C66666C7292DE000DFFFFFFFF"
+ $"FFFFFF070167464666464646666666666C666C6C1F1F66664092DE000EFFFFFF"
+ $"FFFF0B008E46464646464646666666666C403F1E3F3F3F3F6692930100FFFFFF"
+ $"FFFF00074646668D46464666666666666C663F3F3F3F3F3F6672927E000EFFFF"
+ $"FF0B006D6646670246464666666666666C663F3F3F3F3F3F3F1E6C923D00FFFF"
+ $"FF00D56666668E044646666666666666403F3F3F3F3F3F3F1F6692927E000EFF"
+ $"0E008E666666678E666666666666666C6C661E3F3F3F3F3F1D92929293000BFF"
+ $"0B016C66666666666666666666666C6C6C6C403F3F3F3F3F3F6C929292DE00FF"
+ $"08036C666666666666666666666C6C6C6C6C1E1D403F1E6C666C929292DD00FF"
+ $"00D56C6C66668D06666666666C6C6C6C6C6C6C6C6C1D667292929292927E03FF"
+ $"00D56C6C6C6C8D02666C6C6C6C6C6C6C6C6C6C6C6C6C729292929292927E03FF"
+ $"00D56C6C6C6C6CDE6C6C6C6C6C6C6C6C6C6C6C6C7272729292929292927E03FF"
+ $"00DE6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C7272729292929292925F0103FF"
+ $"09026C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C72727292929292929293010100FF"
+ $"0B008D6C6C6C6C8DD56C6C6C6C6C6C6C6C72727272929292929292927E3D29FF"
+ $"0E00B46C6C6C6C6C01936C6C6C6C6C6C72727292929292927E7E92925F000BFF"
+ $"FF00DE6C6C6C6C6CB5B46C6C6C6C727272729292929292DE297E9292DD020EFF"
+ $"FF0C0002B4726C6C6C6C7272727272727292B4DD7F929293929292920100FFFF"
+ $"FFFF00007F7272B4DDDD927293DDDEB49292DEDDB3929292929292DD000EFFFF"
+ $"FFFFAF00B4727293B47FDEB4937E7E93929292929292929292925F0009FFFFFF"
+ $"FFFFFF0A00B4929292929301939292929292929292929292925F0100FFFFFFFF"
+ $"FFFFFFFF0700B4929292927E9392929292929292929292925F01000EFFFFFFFF"
+ $"FFFFFFFFFF0700DD9292929292929292929292929292927E01000EFFFFFFFFFF"
+ $"FFFFFFFFFFFF0A003D7E9292927E7E9292929292925FDE00000EFFFFFFFFFFFF"
+ $"FFFFFFFFFFFFFF0D00003D7F5F5F017E92925F7EDE000300FFFFFFFFFFFFFFFF"
+ $"FFFFFFFFFFFFFFFFFF0D00030000000001010000000C0EFFFFFFFFFFFFFFFFFF"
+ $"FFFFFFFFFFFFFFFFFFFFFFFF0E0B000A0A0A0D0EFFFFFFFFFFFFFFFFFFFFFFFF"
+};
+
+resource(101, "BEOS:M:STD_ICON") #'MICN' array {
+ $"FFFFFFFF0E0900020205000DFFFFFFFF"
+ $"FFFFFF09038E66666C6C93DD000EFFFF"
+ $"FFFF00B5AE4666666C6C666CB4050EFF"
+ $"FF098E464646666666401D4066B400FF"
+ $"0E05668E664666666C1E3F3F1D6CDDAF"
+ $"098E668E66666666661F3F3F1E729300"
+ $"006C66666666666C6C401E1E40729204"
+ $"026C6CB46C666C6C6C6C6C66929292DE"
+ $"026C6C8D6C6C6C6C6C6C72729292923D"
+ $"006C6C6C8D6C6C6C6C72729292927E04"
+ $"09946C6CB56C6C6C72729292DD935F00"
+ $"0E009492B49293B492B47E929292DE0D"
+ $"FF0A7F92937F939392929292927E00FF"
+ $"FFFF08DD92929292929292927E00FFFF"
+ $"FFFFFF0B017E93DD92927EDE09FFFFFF"
+ $"FFFFFFFF0E0B000500000A0EFFFFFFFF"
+};
+
+resource(1, "BEOS:APP_SIG") (#'MIMS') "application/x-vnd.NetSurf";
+
+resource(1, "BEOS:FILE_TYPES") message {
+ "types" = "text/html",
+ "types" = "image/gif",
+ "types" = "image/jpeg",
+ "types" = "application/x-vnd.Be-bookmark",
+ "types" = "text",
+ "types" = "application/x-vnd.Be-doc_bookmark",
+ "types" = "application/x-vnd.Be.URL.file",
+ "types" = "application/x-vnd.Be.URL.ftp",
+ "types" = "application/x-vnd.Be.URL.http",
+ "types" = "application/x-vnd.Be.URL.https"
+};
+
+resource(R_ResBackNavActive) archive(, 0x00000000) BBitmap {
+ "_frame" = rect { 0.0, 0.0, 18.0, 16.0 },
+ "_cspace" = 4,
+ "_bmflags" = 1,
+ "_rowbytes" = 20,
+ "_data" = array {
+ $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3FFFFFFFFFFFFFFF3B3B18FFFF"
+ $"FFFFFFFFFFFFFF3FFFFFFFFFFFFF3B353B1418FFFFFFFFFFFFFFFF3FFFFFFFFF"
+ $"FF3B35353B1418FFFFFFFFFFFFFFFF3FFFFFFFFF3B3435353B3B3B3B3B3B3B3B"
+ $"18FFFF3FFFFFFF3B34343535363637373737373B1418FF3FFFFF3B3434343535"
+ $"363637373737373B1418FF3FFF3B343434353536363637373737373B1418FF3F"
+ $"FF183B3535353536363637373737373B1418FF3FFFFF183B3536363636373737"
+ $"3737373B1418FF3FFFFFFF183B3636373B3B3B3B3B3B3B3B1418FF3FFFFFFFFF"
+ $"183B37373B141414141414141418FF3FFFFFFFFFFF183B373B14181818181818"
+ $"18FFFF3FFFFFFFFFFFFF183B3B1418FFFFFFFFFFFFFFFF3FFFFFFFFFFFFFFF18"
+ $"141418FFFFFFFFFFFFFFFF3FFFFFFFFFFFFFFFFF1818FFFFFFFFFFFFFFFFFF3F"
+ $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3F"
+ }
+};
+
+resource(R_ResBackNavInactive) archive(, 0x00000000) BBitmap {
+ "_frame" = rect { 0.0, 0.0, 18.0, 16.0 },
+ "_cspace" = 4,
+ "_bmflags" = 1,
+ "_rowbytes" = 20,
+ "_data" = array {
+ $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3FFFFFFFFFFFFFFF0000FFFFFF"
+ $"FFFFFFFFFFFFFF3FFFFFFFFFFFFF001800FFFFFFFFFFFFFFFFFFFF3FFFFFFFFF"
+ $"FF00181800FFFFFFFFFFFFFFFFFFFF3FFFFFFFFF001C18180000000000000000"
+ $"FFFFFF3FFFFFFF001C1C18181515111111111100FFFFFF3FFFFF001C1C1C1818"
+ $"1515111111111100FFFFFF3FFF001C1C1C1818151515111111111100FFFFFF3F"
+ $"FFFF0018181818151515111111111100FFFFFF3FFFFFFF001815151515111111"
+ $"11111100FFFFFF3FFFFFFFFF001515110000000000000000FFFFFF3FFFFFFFFF"
+ $"FF00111100FFFFFFFFFFFFFFFFFFFF3FFFFFFFFFFFFF001100FFFFFFFFFFFFFF"
+ $"FFFFFF3FFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFF3FFFFFFFFFFFFFFFFF"
+ $"FFFFFFFFFFFFFFFFFFFFFF3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3F"
+ $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3F"
+ }
+};
+
+resource(R_ResForwNavActive) archive(, 0x00000000) BBitmap {
+ "_frame" = rect { 0.0, 0.0, 18.0, 16.0 },
+ "_cspace" = 4,
+ "_bmflags" = 1,
+ "_rowbytes" = 20,
+ "_data" = array {
+ $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3FFFFFFFFFFFFFFFFF3B3B18FF"
+ $"FFFFFFFFFFFFFF3FFFFFFFFFFFFFFFFF3B353B18FFFFFFFFFFFFFF3FFFFFFFFF"
+ $"FFFFFFFF3B35363B18FFFFFFFFFFFF3FFF3B3B3B3B3B3B3B3B3536363B18FFFF"
+ $"FFFFFF3FFF3B34343434353535363636373B18FFFFFFFF3FFF3B343434353535"
+ $"3536363637373B18FFFFFF3FFF3B343435353535363636373737373B18FFFF3F"
+ $"FF3B3535353535363636373737373B141418FF3FFF3B35353536363636373737"
+ $"373B141418FFFF3FFF3B3B3B3B3B3B3B3B3737373B141418FFFFFF3FFF181414"
+ $"141414143B37373B141418FFFFFFFF3FFFFF1818181818183B373B141418FFFF"
+ $"FFFFFF3FFFFFFFFFFFFFFFFF3B3B141418FFFFFFFFFFFF3FFFFFFFFFFFFFFFFF"
+ $"18141418FFFFFFFFFFFFFF3FFFFFFFFFFFFFFFFFFF1818FFFFFFFFFFFFFFFF3F"
+ $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3F"
+ }
+};
+
+resource(R_ResForwNavInactive) archive(, 0x00000000) BBitmap {
+ "_frame" = rect { 0.0, 0.0, 18.0, 16.0 },
+ "_cspace" = 4,
+ "_bmflags" = 1,
+ "_rowbytes" = 20,
+ "_data" = array {
+ $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3FFFFFFFFFFFFFFFFF0000FFFF"
+ $"FFFFFFFFFFFFFF3FFFFFFFFFFFFFFFFF001800FFFFFFFFFFFFFFFF3FFFFFFFFF"
+ $"FFFFFFFF00181500FFFFFFFFFFFFFF3FFF000000000000000018151500FFFFFF"
+ $"FFFFFF3FFF001C1C1C1C1818181515151100FFFFFFFFFF3FFF001C1C1C181818"
+ $"18151515111100FFFFFFFF3FFF001C1C181818181515151111111100FFFFFF3F"
+ $"FF0018181818181515151111111100FFFFFFFF3FFF0018181815151515111111"
+ $"1100FFFFFFFFFF3FFF000000000000000011111100FFFFFFFFFFFF3FFFFFFFFF"
+ $"FFFFFFFF00111100FFFFFFFFFFFFFF3FFFFFFFFFFFFFFFFF001100FFFFFFFFFF"
+ $"FFFFFF3FFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFF3FFFFFFFFFFFFFFFFF"
+ $"FFFFFFFFFFFFFFFFFFFFFF3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3F"
+ $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3F"
+ }
+};
+
+resource(R_ResUpNavActive) archive(, 0x00000000) BBitmap {
+ "_frame" = rect { 0.0, 0.0, 17.0, 16.0 },
+ "_cspace" = 4,
+ "_bmflags" = 1,
+ "_rowbytes" = 20,
+ "_data" = array {
+ $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3F3FFFFFFFFFFFFFFFFF00FFFFFF"
+ $"FFFFFFFFFFFF3F3FFFFFFFFFFFFFFF00E50018FFFFFFFFFFFFFF3F3FFFFFFFFF"
+ $"FFFF00E5BDBD0018FFFFFFFFFFFF3F3FFFFFFFFFFF00E5BDBDBDBD0018FFFFFF"
+ $"FFFF3F3FFFFFFFFF00E5BDBDBDBDBDBD0018FFFFFFFF3F3FFFFFFF00E5BDBDBD"
+ $"BDBDBDBDBD0018FFFFFF3F3FFFFF00E5E5E5BDBDBDBDBD9898980018FFFF3F3F"
+ $"FF00000000E5BDBDBDBDBD980000000018FF3F3FFFFF141400E5BDBDBDBDBD98"
+ $"00141418FFFF3F3FFFFFFF1800E5BDBDBDBDBD98001418FFFFFF3F3FFFFFFFFF"
+ $"00E5BDBDBDBDBD98001418FFFFFF3F3FFFFFFFFF00E5989898989898001418FF"
+ $"FFFF3F3FFFFFFFFF0000000000000000001418FFFFFF3F3FFFFFFFFF18141414"
+ $"141414141418FFFFFFFF3F3FFFFFFFFFFF181818181818181818FFFFFFFF3F3F"
+ $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3F3F"
+ }
+};
+
+resource(R_ResUpNavInactive) archive(, 0x00000000) BBitmap {
+ "_frame" = rect { 0.0, 0.0, 17.0, 16.0 },
+ "_cspace" = 4,
+ "_bmflags" = 1,
+ "_rowbytes" = 20,
+ "_data" = array {
+ $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3F3FFFFFFFFFFFFFFFFF00FFFFFF"
+ $"FFFFFFFFFFFF3F3FFFFFFFFFFFFFFF001C00FFFFFFFFFFFFFFFF3F3FFFFFFFFF"
+ $"FFFF001C171700FFFFFFFFFFFFFF3F3FFFFFFFFFFF001C1717171700FFFFFFFF"
+ $"FFFF3F3FFFFFFFFF001C17171717171700FFFFFFFFFF3F3FFFFFFF001C171717"
+ $"171717171700FFFFFFFF3F3FFFFF001C1C1C171717171712121200FFFFFF3F3F"
+ $"FF000000001C17171717171200000000FFFF3F3FFFFFFFFF001C171717171712"
+ $"00FFFFFFFFFF3F3FFFFFFFFF001C17171717171200FFFFFFFFFF3F3FFFFFFFFF"
+ $"001C17171717171200FFFFFFFFFF3F3FFFFFFFFF001C12121212121200FFFFFF"
+ $"FFFF3F3FFFFFFFFF000000000000000000FFFFFFFFFF3F3FFFFFFFFFFFFFFFFF"
+ $"FFFFFFFFFFFFFFFFFFFF3F3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3F3F"
+ $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3F3F"
+ }
+};
+
+resource(R_ResBackNavActiveSel) archive(, 0x00000000) BBitmap {
+ "_frame" = rect { 0.0, 0.0, 18.0, 16.0 },
+ "_cspace" = 4,
+ "_bmflags" = 1,
+ "_rowbytes" = 20,
+ "_data" = array {
+ $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3FFFFFFFFFFFFFFF3B3BFFFFFF"
+ $"FFFFFFFFFFFFFF3FFFFFFFFFFFFF3B353BFFFFFFFFFFFFFFFFFFFF3FFFFFFFFF"
+ $"FF3B35353BFFFFFFFFFFFFFFFFFFFF3FFFFFFFFF3B3435353B3B3B3B3B3B3B3B"
+ $"FFFFFF3FFFFFFF3B34343535363637373737373BFFFFFF3FFFFF3B3434343535"
+ $"363637373737373BFFFFFF3FFF3B343434353536363637373737373BFFFFFF3F"
+ $"FFFF3B3535353536363637373737373BFFFFFF3FFFFFFF3B3536363636373737"
+ $"3737373BFFFFFF3FFFFFFFFF3B3636373B3B3B3B3B3B3B3BFFFFFF3FFFFFFFFF"
+ $"FF3B37373BFFFFFFFFFFFFFFFFFFFF3FFFFFFFFFFFFF3B373BFFFFFFFFFFFFFF"
+ $"FFFFFF3FFFFFFFFFFFFFFF3B3BFFFFFFFFFFFFFFFFFFFF3FFFFFFFFFFFFFFFFF"
+ $"FFFFFFFFFFFFFFFFFFFFFF3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3F"
+ $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3F"
+ }
+};
+
+resource(R_ResForwNavActiveSel) archive(, 0x00000000) BBitmap {
+ "_frame" = rect { 0.0, 0.0, 18.0, 16.0 },
+ "_cspace" = 4,
+ "_bmflags" = 1,
+ "_rowbytes" = 20,
+ "_data" = array {
+ $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3FFFFFFFFFFFFFFFFF3B3BFFFF"
+ $"FFFFFFFFFFFFFF3FFFFFFFFFFFFFFFFF3B353BFFFFFFFFFFFFFFFF3FFFFFFFFF"
+ $"FFFFFFFF3B35363BFFFFFFFFFFFFFF3FFF3B3B3B3B3B3B3B3B3536363BFFFFFF"
+ $"FFFFFF3FFF3B34343434353535363636373BFFFFFFFFFF3FFF3B343434353535"
+ $"3536363637373BFFFFFFFF3FFF3B343435353535363636373737373BFFFFFF3F"
+ $"FF3B3535353535363636373737373BFFFFFFFF3FFF3B35353536363636373737"
+ $"373BFFFFFFFFFF3FFF3B3B3B3B3B3B3B3B3737373BFFFFFFFFFFFF3FFFFFFFFF"
+ $"FFFFFFFF3B37373BFFFFFFFFFFFFFF3FFFFFFFFFFFFFFFFF3B373BFFFFFFFFFF"
+ $"FFFFFF3FFFFFFFFFFFFFFFFF3B3BFFFFFFFFFFFFFFFFFF3FFFFFFFFFFFFFFFFF"
+ $"FFFFFFFFFFFFFFFFFFFFFF3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3F"
+ $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3F"
+ }
+};
+
+resource(R_ResUpNavActiveSel) archive(, 0x00000000) BBitmap {
+ "_frame" = rect { 0.0, 0.0, 17.0, 16.0 },
+ "_cspace" = 4,
+ "_bmflags" = 1,
+ "_rowbytes" = 20,
+ "_data" = array {
+ $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3F3FFFFFFFFFFFFFFFFF00FFFFFF"
+ $"FFFFFFFFFFFF3F3FFFFFFFFFFFFFFF00E500FFFFFFFFFFFFFFFF3F3FFFFFFFFF"
+ $"FFFF00E5BDBD00FFFFFFFFFFFFFF3F3FFFFFFFFFFF00E5BDBDBDBD00FFFFFFFF"
+ $"FFFF3F3FFFFFFFFF00E5BDBDBDBDBDBD00FFFFFFFFFF3F3FFFFFFF00E5BDBDBD"
+ $"BDBDBDBDBD00FFFFFFFF3F3FFFFF00E5E5E5BDBDBDBDBD98989800FFFFFF3F3F"
+ $"FF00000000E5BDBDBDBDBD9800000000FFFF3F3FFFFFFFFF00E5BDBDBDBDBD98"
+ $"00FFFFFFFFFF3F3FFFFFFFFF00E5BDBDBDBDBD9800FFFFFFFFFF3F3FFFFFFFFF"
+ $"00E5BDBDBDBDBD9800FFFFFFFFFF3F3FFFFFFFFF00E598989898989800FFFFFF"
+ $"FFFF3F3FFFFFFFFF000000000000000000FFFFFFFFFF3F3FFFFFFFFFFFFFFFFF"
+ $"FFFFFFFFFFFFFFFFFFFF3F3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3F3F"
+ $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3F3F"
+ }
+};
+
+resource(101, "BEOS:ICON") #'VICN' array {
+ $"6E636966060200060240CCB33B58BF3B58BFC0CCB34E598BCD1673003F6EFFFF"
+ $"93ADFF05FF020106023E5402000000000000BE540248497948816C00B8F5FFFF"
+ $"0097FF05000201060242B568000000000000C2B5684E57E54A4B53002668EEFF"
+ $"B8F5FF032668EE120204B685BFC2B685C434B685BB51BE90B7B7BA1EB7B7C302"
+ $"B7B7C69CBFC2C69CBB51C69CC434BE90C7CEC302C7CEBA1EC7CE0204B685BFC2"
+ $"B685C434B685BB51BE90B7B7BA1EB7B7C302B7B7C69CBFC2C69CBB51C69CC434"
+ $"BE90C7CEC302C7CEBA1EC7CE0204B685BFC2B685C434B685BB51BE90B7B7BA1E"
+ $"B7B7C302B7B7C69CBFC2C69CBB51C69CC434BE90C7CEC302C7CEBA1EC7CE0204"
+ $"B685BFC2B685C434B685BB51BE90B7B7BA1EB7B7C302B7B7C69CBFC2C69CBB51"
+ $"C69CC434BE90C7CEC302C7CEBA1EC7CE0A10C3E8BE78C367BD12C48EBC60C335"
+ $"BBBEC389BA6FC222BAF1C170B9C9C0CEBB22BF80BACFC001BC35BEDABCE7C033"
+ $"BD89BFE0BED8C146BE56C1F8BF7EC29ABE250A10C3E8BE78C367BD12C48EBC60"
+ $"C335BBBEC389BA6FC222BAF1C170B9C9C0CEBB22BF80BACFC001BC35BEDABCE7"
+ $"C033BD89BFE0BED8C146BE56C1F8BF7EC29ABE250A04BAF5B910BA97BA76B9FA"
+ $"BA56BA65B8D10A04BA4CBBE132BD4DB99CBD47B9BCBBC90A0432BEC6BA65C02B"
+ $"B9C8C04AB99CBECC0A04BABDC197BB4DC2DDBAC3C31C32C1BD0A04BBFDC429BC"
+ $"D2C54ABC54C5AEBB79C4750A04BDBAC677BEC8C78BBE31C7D6BD49C6D60A04B7"
+ $"6EC2F6B8A7C37AB882C3FEB774C3AC0A04BA0DC3C5BB85C3DEBB7FC47BB9FAC4"
+ $"550A04BCF7C3E5BE69C3BFBE7CC455BCFEC47B0A04BFD5C387C13BC32FC167C3"
+ $"C5BFF5C41D0A04C2A1C2B8C3EDC221C42BC2A5C2D9C3480A04C51AC159C615C0"
+ $"5DC69FC0B5C57EC1D0120A0101001240D69000000000000040D690C65277C763"
+ $"0301144000000000000000004000000000000000000A0101011240D690000000"
+ $"00000040D690C65277C7630301178403040A0201020240D69000000000000040"
+ $"D690C65277C763030A0301031240D69000000000000040D690C65277C7630301"
+ $"178103040A0101040240D69000000000000040D690C65277C763030A01010512"
+ $"40D69000000000000040D690C65277C7630301178003040A0301060240D69000"
+ $"000000000040D690C65277C763030A0301070240D69000000000000040D690C6"
+ $"5277C763030A0301080240D69000000000000040D690C65277C763030A030109"
+ $"0240D69000000000000040D690C65277C763030A03010A0240D6900000000000"
+ $"0040D690C65277C763030A03010B0240D69000000000000040D690C65277C763"
+ $"030A03010C0240D69000000000000040D690C65277C763030A03010D0240D690"
+ $"00000000000040D690C65277C763030A03010E0240D69000000000000040D690"
+ $"C65277C763030A03010F0240D69000000000000040D690C65277C763030A0301"
+ $"100240D69000000000000040D690C65277C763030A0301110240D69000000000"
+ $"000040D690C65277C76303"
+};
+
+resource(101, "BEOS:D:STD_ICON") (#'iICO') $"4944585A055300";
+
+resource(101, "BEOS:V:STD_ICON") #'zICO' array {
+ $"7A10000078DAED57DD6EDB3618BDEF5310CA4D03C40C7F3E8A6466B7C002AC37"
+ $"2C066CCD03B8B1EC6853A44052B3644FBFF351769C7601D68B41BB5814C03AA2"
+ $"8EA8C3F3FD5059BE7FB86DC47DD50F75D7AE0A2D5521AAF6BADBD4ED6E555C7D"
+ $"FA69110A318CEB76B36EBAB65A158FD550BC7FF76639DCEFC41FF566BC591525"
+ $"15E2A6AA7737E384AFBBA6EB17753B56FD5DD7ACC73C7353B7D5BAFFE5C38FC5"
+ $"BB3762B9C38F58DEADC71B4CFED860DE6DDD341727DB7C14B8391D9B55F131C8"
+ $"6085355299CB0C8D92C10BEDF3AFCE231137277C494AEAC3384569F49E3FE169"
+ $"9A099365E6C4772633F33C195F4EF34FE3F9B513FD28E6CFA3CAB15FB7C3B6EB"
+ $"6F57C5ED7AECEB87B75A928E670A7F135AE08D21B8B385B6D2913FE567CF5FF6"
+ $"A085CD3F60A4EF7EAF0E861CAE17D9F10B92D6C5F26990ADFDADABDB8BCFD57D"
+ $"D5FC9FCCEBD79B7ADD7CE053D58EA2C68A77FB0BE4F1015EB5F538AC8A2F43D5"
+ $"FF7AB7BEAE7E6EAF860A69FAB02AC0BA7ECCA77ECADDC3339FFEA64A49174C56"
+ $"B598A00ED2C4F20C0E292277CA790D49C3D8DD896EBB1DAA31CFCBD78B5C11AB"
+ $"E2E473D83AA4F7F90B54FD0D55A9E80FD4E5F9D70B7D3971BEF4CDDB93A7E59F"
+ $"BE16D15311A97C7C53445A3AEBC26B117D6717262309EB0CD287449A8518278D"
+ $"4F445295C260529BB0923208A36524E638811229CB64BD8C41E828A34DB69486"
+ $"D83A054CB2746C0EE964B5B49E39A01B5912CFA875821F1E9864C03846A0A094"
+ $"44CCB1D92D6F9275321856468E5FE5BCE0C980A3D450869743E551FD7FD8B7D1"
+ $"29BCF9BEBEFD6AF73F25E954D45FBBC68BC6B2E09449C02A5B02CD30C069C604"
+ $"1CA42B858619E9197D5E9921DB89CA8E90C39185DFBA942E66CC30F26D45E919"
+ $"7566891C6E477BBB900CCAB18DE84EC0F6492E3248A70379EE5813C494B23489"
+ $"1B2C9A629441735029705325CBC24088313D23CF2A1281837B68DCCA2794150A"
+ $"8D9C8C09D54668FFA50CC05A9A4C0958C7913EAF4C98640405CE438E64291CFA"
+ $"0970902AF2166493C9658F7DCB43F2913E6FC8D1080D875621FF48EA2828B71E"
+ $"6DB3366E64893981C7C384F7FC79757AE9598ECAD1B591B1A58CF32E1EFCBE23"
+ $"01E7AADAB3E78DB9934AF37B89C3CC9969789730874F0DC721577EAFF7C89E55"
+ $"A4CD5F3F882605DE78BCE668A2E3A09235ED2D06C7E5E847979EF1E7D589E70D"
+ $"37206C8A6C12FACEB4115A2E20BE5BF206E9F3D75EC8F8C09F5527BA0F3666B8"
+ $"A774227C5F46EEE6E8F2FC3D4A025F088025F726C8D7907FA4FF2B3297E7F8C7"
+ $"7F793EDCE3F417BB10DA0B"
+};
+
diff --git a/beos/beos_res.rsrc b/beos/beos_res.rsrc
new file mode 100644
index 000000000..d37e9e6ec
--- /dev/null
+++ b/beos/beos_res.rsrc
Binary files differ
diff --git a/beos/beos_scaffolding.cpp b/beos/beos_scaffolding.cpp
new file mode 100644
index 000000000..7bda4e4d7
--- /dev/null
+++ b/beos/beos_scaffolding.cpp
@@ -0,0 +1,1607 @@
+/*
+ * Copyright 2006 Rob Kendrick <rjek@rjek.com>
+ *
+ * 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 <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <BeBuild.h>
+#include <Button.h>
+#include <MenuBar.h>
+#include <Node.h>
+#include <Path.h>
+#include <PopUpMenu.h>
+#include <Screen.h>
+#include <ScrollView.h>
+#include <String.h>
+#include <StringView.h>
+#include <TextControl.h>
+#include <View.h>
+#include <Window.h>
+#include <fs_attr.h>
+extern "C" {
+#include "content/content.h"
+#include "desktop/browser.h"
+#include "desktop/history_core.h"
+#include "desktop/gui.h"
+#include "desktop/netsurf.h"
+#include "desktop/plotters.h"
+#include "desktop/options.h"
+#include "desktop/textinput.h"
+#include "render/box.h"
+#include "render/font.h"
+#include "render/form.h"
+#include "render/html.h"
+#include "utils/messages.h"
+#include "utils/utils.h"
+#undef NDEBUG
+#include "utils/log.h"
+}
+#include "beos/beos_gui.h"
+#include "beos/beos_plotters.h"
+#include "beos/beos_scaffolding.h"
+#include "beos/beos_options.h"
+//#include "beos/beos_completion.h"
+#include "beos/beos_throbber.h"
+//#include "beos/beos_history.h"
+#include "beos/beos_window.h"
+//#include "beos/beos_schedule.h"
+//#include "beos/beos_download.h"
+
+#define TOOLBAR_HEIGHT 32
+
+struct beos_history_window;
+
+class NSBrowserWindow;
+class NSThrobber;
+
+struct beos_scaffolding {
+ NSBrowserWindow *window; // top-level container object
+
+ // top-level view, contains toolbar & top-level browser view
+ BView *top_view;
+
+ BMenuBar *menu_bar;
+
+ BPopUpMenu *popup_menu;
+
+ BControl *back_button;
+ BControl *forward_button;
+ BControl *stop_button;
+ BControl *reload_button;
+ BControl *home_button;
+
+ BTextControl *url_bar;
+ //BMenuField *url_bar_completion;
+
+ NSThrobber *throbber;
+
+ BStringView *status_bar;
+
+ BScrollView *scroll_view;
+#warning XXX
+#if 0 /* GTK */
+ GtkWindow *window;
+ GtkEntry *url_bar;
+ GtkEntryCompletion *url_bar_completion;
+ GtkLabel *status_bar;
+ GtkToolbar *tool_bar;
+ GtkToolButton *back_button;
+ GtkToolButton *forward_button;
+ GtkToolButton *stop_button;
+ GtkToolButton *reload_button;
+ GtkMenuBar *menu_bar;
+ GtkMenuItem *back_menu;
+ GtkMenuItem *forward_menu;
+ GtkMenuItem *stop_menu;
+ GtkMenuItem *reload_menu;
+ GtkImage *throbber;
+ GtkPaned *status_pane;
+
+ GladeXML *xml;
+
+ GladeXML *popup_xml;
+ GtkMenu *popup_menu;
+
+ struct gtk_history_window *history_window;
+#endif
+
+ int throb_frame;
+ struct gui_window *top_level;
+ int being_destroyed;
+
+ bool fullscreen;
+};
+
+struct beos_history_window {
+ struct beos_scaffolding *g;
+#warning XXX
+#if 0 /* GTK */
+ GtkWindow *window;
+ GtkScrolledWindow *scrolled;
+ GtkDrawingArea *drawing_area;
+#endif
+};
+
+struct menu_events {
+ const char *widget;
+#warning XXX
+#if 0 /* GTK */
+ GCallback handler;
+#endif
+};
+
+
+#warning XXX: UPDATE
+typedef enum {
+
+ /* no/unknown actions */
+ NO_ACTION,
+
+ /* help actions */
+ HELP_OPEN_CONTENTS,
+ HELP_OPEN_GUIDE,
+ HELP_OPEN_INFORMATION,
+ HELP_OPEN_ABOUT,
+ HELP_LAUNCH_INTERACTIVE,
+
+ /* history actions */
+ HISTORY_SHOW_LOCAL,
+ HISTORY_SHOW_GLOBAL,
+
+ /* hotlist actions */
+ HOTLIST_ADD_URL,
+ HOTLIST_SHOW,
+
+ /* cookie actions */
+ COOKIES_SHOW,
+ COOKIES_DELETE,
+
+ /* page actions */
+ BROWSER_PAGE,
+ BROWSER_PAGE_INFO,
+ BROWSER_PRINT,
+ BROWSER_NEW_WINDOW,
+ BROWSER_VIEW_SOURCE,
+
+ /* object actions */
+ BROWSER_OBJECT,
+ BROWSER_OBJECT_INFO,
+ BROWSER_OBJECT_RELOAD,
+
+ /* save actions */
+ BROWSER_OBJECT_SAVE,
+ BROWSER_OBJECT_EXPORT_SPRITE,
+ BROWSER_OBJECT_SAVE_URL_URI,
+ BROWSER_OBJECT_SAVE_URL_URL,
+ BROWSER_OBJECT_SAVE_URL_TEXT,
+ BROWSER_SAVE,
+ BROWSER_SAVE_COMPLETE,
+ BROWSER_EXPORT_DRAW,
+ BROWSER_EXPORT_TEXT,
+ BROWSER_SAVE_URL_URI,
+ BROWSER_SAVE_URL_URL,
+ BROWSER_SAVE_URL_TEXT,
+ HOTLIST_EXPORT,
+ HISTORY_EXPORT,
+
+ /* navigation actions */
+ BROWSER_NAVIGATE_HOME,
+ BROWSER_NAVIGATE_BACK,
+ BROWSER_NAVIGATE_FORWARD,
+ BROWSER_NAVIGATE_UP,
+ BROWSER_NAVIGATE_RELOAD,
+ BROWSER_NAVIGATE_RELOAD_ALL,
+ BROWSER_NAVIGATE_STOP,
+ BROWSER_NAVIGATE_URL,
+
+ /* browser window/display actions */
+ BROWSER_SCALE_VIEW,
+ BROWSER_FIND_TEXT,
+ BROWSER_IMAGES_FOREGROUND,
+ BROWSER_IMAGES_BACKGROUND,
+ BROWSER_BUFFER_ANIMS,
+ BROWSER_BUFFER_ALL,
+ BROWSER_SAVE_VIEW,
+ BROWSER_WINDOW_DEFAULT,
+ BROWSER_WINDOW_STAGGER,
+ BROWSER_WINDOW_COPY,
+ BROWSER_WINDOW_RESET,
+
+ /* tree actions */
+ TREE_NEW_FOLDER,
+ TREE_NEW_LINK,
+ TREE_EXPAND_ALL,
+ TREE_EXPAND_FOLDERS,
+ TREE_EXPAND_LINKS,
+ TREE_COLLAPSE_ALL,
+ TREE_COLLAPSE_FOLDERS,
+ TREE_COLLAPSE_LINKS,
+ TREE_SELECTION,
+ TREE_SELECTION_EDIT,
+ TREE_SELECTION_LAUNCH,
+ TREE_SELECTION_DELETE,
+ TREE_SELECT_ALL,
+ TREE_CLEAR_SELECTION,
+
+ /* toolbar actions */
+ TOOLBAR_BUTTONS,
+ TOOLBAR_ADDRESS_BAR,
+ TOOLBAR_THROBBER,
+ TOOLBAR_EDIT,
+
+ /* misc actions */
+ CHOICES_SHOW,
+ APPLICATION_QUIT,
+} menu_action;
+
+
+static int open_windows = 0; /**< current number of open browsers */
+static struct beos_scaffolding *current_model; /**< current window for model dialogue use */
+#warning XXX
+#if 0 /* GTK */
+static void nsbeos_window_destroy_event(GtkWidget *, gpointer);
+#endif
+
+static void nsbeos_window_update_back_forward(struct beos_scaffolding *);
+static void nsbeos_throb(void *);
+#warning XXX
+#if 0 /* GTK */
+static gboolean nsbeos_window_url_activate_event(beosWidget *, gpointer);
+static gboolean nsbeos_window_url_changed(beosWidget *, GdkEventKey *, gpointer);
+
+static gboolean nsbeos_history_expose_event(beosWidget *, GdkEventExpose *,
+ gpointer);
+static gboolean nsbeos_history_button_press_event(beosWidget *, GdkEventButton *,
+ gpointer);
+
+static void nsbeos_attach_menu_handlers(GladeXML *, gpointer);
+
+gboolean nsbeos_openfile_open(beosWidget *widget, gpointer data);
+
+#define MENUEVENT(x) { #x, G_CALLBACK(nsbeos_on_##x##_activate) }
+#define MENUPROTO(x) static gboolean nsbeos_on_##x##_activate( \
+ beosMenuItem *widget, gpointer g)
+/* prototypes for menu handlers */
+/* file menu */
+MENUPROTO(new_window);
+MENUPROTO(open_location);
+MENUPROTO(open_file);
+MENUPROTO(close_window);
+MENUPROTO(quit);
+
+/* edit menu */
+MENUPROTO(preferences);
+
+/* view menu */
+MENUPROTO(stop);
+MENUPROTO(reload);
+MENUPROTO(zoom_in);
+MENUPROTO(normal_size);
+MENUPROTO(zoom_out);
+MENUPROTO(full_screen);
+MENUPROTO(menu_bar);
+MENUPROTO(tool_bar);
+MENUPROTO(status_bar);
+MENUPROTO(downloads);
+MENUPROTO(save_window_size);
+MENUPROTO(toggle_debug_rendering);
+MENUPROTO(save_box_tree);
+
+/* navigate menu */
+MENUPROTO(back);
+MENUPROTO(forward);
+MENUPROTO(home);
+MENUPROTO(local_history);
+MENUPROTO(global_history);
+
+/* help menu */
+MENUPROTO(about);
+
+/* structure used by nsbeos_attach_menu_handlers to connect menu items to
+ * their handling functions.
+ */
+static struct menu_events menu_events[] = {
+ /* file menu */
+ MENUEVENT(new_window),
+ MENUEVENT(open_location),
+ MENUEVENT(open_file),
+ MENUEVENT(close_window),
+ MENUEVENT(quit),
+
+ /* edit menu */
+ MENUEVENT(preferences),
+
+ /* view menu */
+ MENUEVENT(stop),
+ MENUEVENT(reload),
+ MENUEVENT(zoom_in),
+ MENUEVENT(normal_size),
+ MENUEVENT(zoom_out),
+ MENUEVENT(full_screen),
+ MENUEVENT(menu_bar),
+ MENUEVENT(tool_bar),
+ MENUEVENT(status_bar),
+ MENUEVENT(downloads),
+ MENUEVENT(save_window_size),
+ MENUEVENT(toggle_debug_rendering),
+ MENUEVENT(save_box_tree),
+
+ /* navigate menu */
+ MENUEVENT(back),
+ MENUEVENT(forward),
+ MENUEVENT(home),
+ MENUEVENT(local_history),
+ MENUEVENT(global_history),
+
+ /* help menu */
+ MENUEVENT(about),
+
+ /* sentinel */
+ { NULL, NULL }
+};
+
+void nsbeos_attach_menu_handlers(GladeXML *xml, gpointer g)
+{
+ struct menu_events *event = menu_events;
+
+ while (event->widget != NULL)
+ {
+ beosWidget *w = glade_xml_get_widget(xml, event->widget);
+ g_signal_connect(G_OBJECT(w), "activate", event->handler, g);
+ event++;
+ }
+}
+#endif
+
+// #pragma mark - class NSThrobber
+
+class NSThrobber : public BView {
+public:
+ NSThrobber(BRect frame);
+virtual ~NSThrobber();
+
+virtual void MessageReceived(BMessage *message);
+virtual void Draw(BRect updateRect);
+void SetBitmap(const BBitmap *bitmap);
+
+private:
+ const BBitmap *fBitmap;
+};
+
+NSThrobber::NSThrobber(BRect frame)
+ : BView(frame, "NSThrobber", B_FOLLOW_TOP | B_FOLLOW_RIGHT, B_WILL_DRAW),
+ fBitmap(NULL)
+{
+}
+
+
+NSThrobber::~NSThrobber()
+{
+}
+
+
+void
+NSThrobber::MessageReceived(BMessage *message)
+{
+ BView::MessageReceived(message);
+}
+
+
+void
+NSThrobber::Draw(BRect updateRect)
+{
+ if (!fBitmap)
+ return;
+ DrawBitmap(fBitmap);
+}
+
+
+void
+NSThrobber::SetBitmap(const BBitmap *bitmap)
+{
+ fBitmap = bitmap;
+}
+
+
+
+// #pragma mark - class NSBrowserWindow
+
+
+NSBrowserWindow::NSBrowserWindow(BRect frame, struct beos_scaffolding *scaf)
+ : BWindow(frame, "NetSurf", B_DOCUMENT_WINDOW, 0),
+ fScaffolding(scaf)
+{
+}
+
+
+NSBrowserWindow::~NSBrowserWindow()
+{
+}
+
+
+void
+NSBrowserWindow::MessageReceived(BMessage *message)
+{
+ switch (message->what) {
+ case B_REFS_RECEIVED:
+ DetachCurrentMessage();
+ nsbeos_pipe_message_top(message, this, fScaffolding);
+ break;
+ default:
+ BWindow::MessageReceived(message);
+ }
+}
+
+bool
+NSBrowserWindow::QuitRequested(void)
+{
+ BWindow::QuitRequested();
+ BMessage *message = DetachCurrentMessage();
+ // BApplication::Quit() calls us directly...
+ if (message == NULL)
+ message = new BMessage(B_QUIT_REQUESTED);
+ nsbeos_pipe_message_top(message, this, fScaffolding);
+ return false; // we will Quit() ourselves from the main thread
+}
+
+
+// #pragma mark - implementation
+
+/* event handlers and support functions for them */
+
+static void nsbeos_window_destroy_event(NSBrowserWindow *window, nsbeos_scaffolding *g, BMessage *event)
+{
+ LOG(("Being Destroyed = %d", g->being_destroyed));
+
+ if (--open_windows == 0)
+ netsurf_quit = true;
+
+ window->Lock();
+ window->Quit();
+
+ if (!g->being_destroyed) {
+ g->being_destroyed = 1;
+ nsbeos_window_destroy_browser(g->top_level);
+ }
+}
+
+
+void nsbeos_scaffolding_dispatch_event(nsbeos_scaffolding *scaffold, BMessage *message)
+{
+ int width, height;
+ struct browser_window *bw;
+ bw = nsbeos_get_browser_for_gui(scaffold->top_level);
+ LOG(("nsbeos_scaffolding_dispatch_event() what = 0x%08lx", message->what));
+ switch (message->what) {
+ case B_QUIT_REQUESTED:
+ nsbeos_scaffolding_destroy(scaffold);
+ break;
+ case B_SIMPLE_DATA:
+ {
+ if (!message->HasRef("refs")) {
+ // XXX handle DnD
+ break;
+ }
+ // FALL THROUGH
+ // handle refs
+ }
+ case B_REFS_RECEIVED:
+ {
+ entry_ref ref;
+
+ if (message->FindRef("refs", &ref) < B_OK)
+ break;
+
+ BString url("file://");
+ BPath path(&ref);
+ if (path.InitCheck() < B_OK)
+ break;
+
+ BNode node(path.Path());
+ if (node.InitCheck() < B_OK)
+ break;
+
+ attr_info ai;
+ if (node.GetAttrInfo("META:url", &ai) >= B_OK) {
+ char data[(size_t)ai.size + 1];
+ memset(data, 0, (size_t)ai.size + 1);
+ if (node.ReadAttr("META:url", B_STRING_TYPE, 0LL, data, (size_t)ai.size) < 4)
+ break;
+ url = data;
+ } else
+ url << path.Path();
+ browser_window_go(bw, url.String(), 0, true);
+ break;
+ }
+ case 'back':
+ if (!history_back_available(bw->history))
+ break;
+ history_back(bw, bw->history);
+ nsbeos_window_update_back_forward(scaffold);
+ break;
+ case 'forw':
+ if (!history_back_available(bw->history))
+ break;
+ history_forward(bw, bw->history);
+ nsbeos_window_update_back_forward(scaffold);
+ break;
+ case 'stop':
+ browser_window_stop(bw);
+ break;
+ case 'relo':
+ browser_window_reload(bw, true);
+ break;
+ case 'home':
+ {
+ static const char *addr = "http://netsurf-browser.org/welcome/";
+
+ if (option_homepage_url != NULL && option_homepage_url[0] != '\0')
+ addr = option_homepage_url;
+
+ browser_window_go(bw, addr, 0, true);
+ break;
+ }
+ case 'urle':
+ {
+ BString text;
+ if (!scaffold->url_bar->LockLooper())
+ break;
+ text = scaffold->url_bar->Text();
+ scaffold->scroll_view->Target()->MakeFocus();
+ scaffold->url_bar->UnlockLooper();
+ browser_window_go(bw, text.String(), 0, true);
+ break;
+ }
+ case 'urlc':
+ {
+ BString text;
+ if (!scaffold->url_bar->LockLooper())
+ break;
+ text = scaffold->url_bar->Text();
+ scaffold->url_bar->UnlockLooper();
+ //nsbeos_completion_update(text.String());
+ break;
+ }
+ case 'menu':
+ {
+ menu_action action;
+ if (message->FindInt32("action", (int32 *)&action) < B_OK)
+ break;
+ switch (action) {
+ case NO_ACTION:
+ case HELP_OPEN_CONTENTS:
+ case HELP_OPEN_GUIDE:
+ case HELP_OPEN_INFORMATION:
+ case HELP_OPEN_ABOUT:
+ case HELP_LAUNCH_INTERACTIVE:
+
+ break;
+ }
+#warning XXX
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+void nsbeos_scaffolding_destroy(nsbeos_scaffolding *scaffold)
+{
+ LOG(("Being Destroyed = %d", scaffold->being_destroyed));
+ if (scaffold->being_destroyed) return;
+ scaffold->being_destroyed = 1;
+ nsbeos_window_destroy_event(scaffold->window, scaffold, NULL);
+#warning XXX
+#if 0 /* GTK */
+ /* Our top_level has asked us to die */
+ LOG(("Being Destroyed = %d", scaffold->being_destroyed));
+ if (scaffold->being_destroyed) return;
+ scaffold->being_destroyed = 1;
+ nsbeos_window_destroy_event(0, scaffold);
+#endif
+}
+
+
+void nsbeos_window_update_back_forward(struct beos_scaffolding *g)
+{
+ int width, height;
+ struct browser_window *bw = nsbeos_get_browser_for_gui(g->top_level);
+
+ if (!g->top_view->LockLooper())
+ return;
+
+ g->back_button->SetEnabled(history_back_available(bw->history));
+ g->forward_button->SetEnabled(history_forward_available(bw->history));
+
+ g->top_view->UnlockLooper();
+
+#warning XXX
+#if 0 /* GTK */
+ beos_widget_set_sensitive(beos_WIDGET(g->back_button),
+ history_back_available(bw->history));
+ beos_widget_set_sensitive(beos_WIDGET(g->forward_button),
+ history_forward_available(bw->history));
+
+ beos_widget_set_sensitive(beos_WIDGET(g->back_menu),
+ history_back_available(bw->history));
+ beos_widget_set_sensitive(beos_WIDGET(g->forward_menu),
+ history_forward_available(bw->history));
+
+ /* update the local history window, as well as queuing a redraw
+ * for it.
+ */
+ history_size(bw->history, &width, &height);
+ beos_widget_set_size_request(beos_WIDGET(g->history_window->drawing_area),
+ width, height);
+ beos_widget_queue_draw(beos_WIDGET(g->history_window->drawing_area));
+#endif
+}
+
+void nsbeos_throb(void *p)
+{
+ struct beos_scaffolding *g = (struct beos_scaffolding *)p;
+
+ if (g->throb_frame >= (nsbeos_throbber->nframes - 1))
+ g->throb_frame = 1;
+ else
+ g->throb_frame++;
+
+ if (!g->top_view->LockLooper())
+ return;
+
+#if 0
+ g->throbber->SetViewBitmap(nsbeos_throbber->framedata[g->throb_frame],
+ B_FOLLOW_RIGHT | B_FOLLOW_TOP);
+#endif
+ g->throbber->SetBitmap(nsbeos_throbber->framedata[g->throb_frame]);
+ g->throbber->Invalidate();
+
+ g->top_view->UnlockLooper();
+
+ schedule(10, nsbeos_throb, p);
+
+}
+
+#warning XXX
+#if 0 /* GTK */
+
+gboolean nsbeos_openfile_open(beosWidget *widget, gpointer data)
+{
+ struct browser_window *bw = nsbeos_get_browser_for_gui(
+ current_model->top_level);
+ char *filename = beos_file_chooser_get_filename(
+ beos_FILE_CHOOSER(wndOpenFile));
+ char *url = malloc(strlen(filename) + strlen("file://") + 1);
+
+ sprintf(url, "file://%s", filename);
+
+ browser_window_go(bw, url, 0, true);
+
+ g_free(filename);
+ free(url);
+
+ return TRUE;
+}
+#endif
+
+#warning XXX
+#if 0 /* GTK */
+/* signal handlers for menu entries */
+#define MENUHANDLER(x) gboolean nsbeos_on_##x##_activate(beosMenuItem *widget, \
+ gpointer g)
+
+MENUHANDLER(new_window)
+{
+ struct beos_scaffolding *gw = (struct beos_scaffolding *)g;
+ struct browser_window *bw = nsbeos_get_browser_for_gui(gw->top_level);
+ const char *url = beos_entry_get_text(beos_ENTRY(gw->url_bar));
+
+ browser_window_create(url, bw, NULL, false);
+
+ return TRUE;
+}
+
+MENUHANDLER(open_location)
+{
+ struct beos_scaffolding *gw = (struct beos_scaffolding *)g;
+
+ beos_widget_grab_focus(beos_WIDGET(gw->url_bar));
+
+ return TRUE;
+}
+
+MENUHANDLER(open_file)
+{
+ current_model = (struct beos_scaffolding *)g;
+ beos_dialog_run(wndOpenFile);
+
+ return TRUE;
+}
+
+MENUHANDLER(close_window)
+{
+ struct beos_scaffolding *gw = (struct beos_scaffolding *)g;
+
+ beos_widget_destroy(beos_WIDGET(gw->window));
+
+ return TRUE;
+}
+
+MENUHANDLER(quit)
+{
+ netsurf_quit = true;
+ return TRUE;
+}
+
+MENUHANDLER(preferences)
+{
+ beos_widget_show(beos_WIDGET(wndPreferences));
+
+ return TRUE;
+}
+
+MENUHANDLER(zoom_in)
+{
+ struct beos_scaffolding *gw = (struct beos_scaffolding *)g;
+ struct browser_window *bw = nsbeos_get_browser_for_gui(gw->top_level);
+ float old_scale = nsbeos_get_scale_for_gui(gw->top_level);
+
+ browser_window_set_scale(bw, old_scale + 0.05, true);
+
+ return TRUE;
+}
+
+MENUHANDLER(normal_size)
+{
+ struct beos_scaffolding *gw = (struct beos_scaffolding *)g;
+ struct browser_window *bw = nsbeos_get_browser_for_gui(gw->top_level);
+
+ browser_window_set_scale(bw, 1.0, true);
+
+ return TRUE;
+}
+
+MENUHANDLER(zoom_out)
+{
+ struct beos_scaffolding *gw = (struct beos_scaffolding *)g;
+ struct browser_window *bw = nsbeos_get_browser_for_gui(gw->top_level);
+ float old_scale = nsbeos_get_scale_for_gui(gw->top_level);
+
+ browser_window_set_scale(bw, old_scale - 0.05, true);
+
+ return TRUE;
+}
+
+MENUHANDLER(full_screen)
+{
+ struct beos_scaffolding *gw = (struct beos_scaffolding *)g;
+
+ if (gw->fullscreen) {
+ beos_window_unfullscreen(gw->window);
+ } else {
+ beos_window_fullscreen(gw->window);
+ }
+
+ gw->fullscreen = !gw->fullscreen;
+
+ return TRUE;
+}
+
+MENUHANDLER(menu_bar)
+{
+ struct beos_scaffolding *gw = (struct beos_scaffolding *)g;
+
+ if (beos_check_menu_item_get_active(beos_CHECK_MENU_ITEM(widget))) {
+ beos_widget_show(beos_WIDGET(gw->menu_bar));
+ } else {
+ beos_widget_hide(beos_WIDGET(gw->menu_bar));
+ }
+
+ return TRUE;
+}
+
+MENUHANDLER(tool_bar)
+{
+ struct beos_scaffolding *gw = (struct beos_scaffolding *)g;
+
+ if (beos_check_menu_item_get_active(beos_CHECK_MENU_ITEM(widget))) {
+ beos_widget_show(beos_WIDGET(gw->tool_bar));
+ } else {
+ beos_widget_hide(beos_WIDGET(gw->tool_bar));
+ }
+
+ return TRUE;
+}
+
+MENUHANDLER(status_bar)
+{
+ struct beos_scaffolding *gw = (struct beos_scaffolding *)g;
+
+ if (beos_check_menu_item_get_active(beos_CHECK_MENU_ITEM(widget))) {
+ beos_widget_show(beos_WIDGET(gw->status_bar));
+ } else {
+ beos_widget_hide(beos_WIDGET(gw->status_bar));
+ }
+
+ return TRUE;
+}
+
+MENUHANDLER(downloads)
+{
+ nsbeos_download_show();
+
+ return TRUE;
+}
+
+MENUHANDLER(save_window_size)
+{
+ struct beos_scaffolding *gw = (struct beos_scaffolding *)g;
+
+ option_toolbar_status_width = beos_paned_get_position(gw->status_pane);
+ beos_window_get_position(gw->window, &option_window_x, &option_window_y);
+ beos_window_get_size(gw->window, &option_window_width,
+ &option_window_height);
+
+
+ options_write(options_file_location);
+
+ return TRUE;
+}
+
+MENUHANDLER(toggle_debug_rendering)
+{
+ html_redraw_debug = !html_redraw_debug;
+ nsbeos_reflow_all_windows();
+ return TRUE;
+}
+
+MENUHANDLER(save_box_tree)
+{
+ beosWidget *save_dialog;
+ struct beos_scaffolding *gw = (struct beos_scaffolding *)g;
+
+ save_dialog = beos_file_chooser_dialog_new("Save File", gw->window,
+ beos_FILE_CHOOSER_ACTION_SAVE,
+ beos_STOCK_CANCEL, beos_RESPONSE_CANCEL,
+ beos_STOCK_SAVE, beos_RESPONSE_ACCEPT,
+ NULL);
+
+ beos_file_chooser_set_current_folder(beos_FILE_CHOOSER(save_dialog),
+ getenv("HOME") ? getenv("HOME") : "/");
+
+ beos_file_chooser_set_current_name(beos_FILE_CHOOSER(save_dialog),
+ "boxtree.txt");
+
+ if (beos_dialog_run(beos_DIALOG(save_dialog)) == beos_RESPONSE_ACCEPT) {
+ char *filename = beos_file_chooser_get_filename(
+ beos_FILE_CHOOSER(save_dialog));
+ FILE *fh;
+ LOG(("Saving box tree dump to %s...\n", filename));
+
+ fh = fopen(filename, "w");
+ if (fh == NULL) {
+ warn_user("Error saving box tree dump.",
+ "Unable to open file for writing.");
+ } else {
+ struct browser_window *bw;
+ bw = nsbeos_get_browser_window(gw->top_level);
+
+ if (bw->current_content &&
+ bw->current_content->type ==
+ CONTENT_HTML) {
+ box_dump(fh,
+ bw->current_content->data.html.layout,
+ 0);
+ }
+
+ fclose(fh);
+ }
+
+ g_free(filename);
+ }
+
+ beos_widget_destroy(save_dialog);
+}
+
+MENUHANDLER(stop)
+{
+ return nsbeos_window_stop_button_clicked(beos_WIDGET(widget), g);
+}
+
+MENUHANDLER(reload)
+{
+ return nsbeos_window_reload_button_clicked(beos_WIDGET(widget), g);
+}
+
+MENUHANDLER(back)
+{
+ return nsbeos_window_back_button_clicked(beos_WIDGET(widget), g);
+}
+
+MENUHANDLER(forward)
+{
+ return nsbeos_window_forward_button_clicked(beos_WIDGET(widget), g);
+}
+
+MENUHANDLER(home)
+{
+ return nsbeos_window_home_button_clicked(beos_WIDGET(widget), g);
+}
+
+MENUHANDLER(local_history)
+{
+ struct beos_scaffolding *gw = (struct beos_scaffolding *)g;
+
+ beos_widget_show(beos_WIDGET(gw->history_window->window));
+ gdk_window_raise(beos_WIDGET(gw->history_window->window)->window);
+
+ return TRUE;
+}
+
+MENUHANDLER(global_history)
+{
+ beos_widget_show(beos_WIDGET(wndHistory));
+ gdk_window_raise(beos_WIDGET(wndHistory)->window);
+
+ return TRUE;
+}
+
+MENUHANDLER(about)
+{
+ beos_widget_show(beos_WIDGET(wndAbout));
+ gdk_window_raise(beos_WIDGET(wndAbout)->window);
+ return TRUE;
+}
+
+/* signal handler functions for the local history window */
+gboolean nsbeos_history_expose_event(beosWidget *widget,
+ GdkEventExpose *event, gpointer g)
+{
+ struct beos_history_window *hw = (struct beos_history_window *)g;
+ struct browser_window *bw = nsbeos_get_browser_for_gui(hw->g->top_level);
+
+ current_widget = widget;
+ current_drawable = widget->window;
+ current_gc = gdk_gc_new(current_drawable);
+#ifdef CAIRO_VERSION
+ current_cr = gdk_cairo_create(current_drawable);
+#endif
+ plot = nsbeos_plotters;
+ nsbeos_plot_set_scale(1.0);
+
+ history_redraw(bw->history);
+
+ g_object_unref(current_gc);
+#ifdef CAIRO_VERSION
+ cairo_destroy(current_cr);
+#endif
+ return FALSE;
+}
+
+gboolean nsbeos_history_button_press_event(beosWidget *widget,
+ GdkEventButton *event, gpointer g)
+{
+ struct beos_history_window *hw = (struct beos_history_window *)g;
+ struct browser_window *bw = nsbeos_get_browser_for_gui(hw->g->top_level);
+
+ LOG(("X=%g, Y=%g", event->x, event->y));
+
+ history_click(bw, bw->history,
+ event->x, event->y, false);
+
+ return TRUE;
+}
+
+#define GET_WIDGET(x) glade_xml_get_widget(g->xml, (x))
+
+static gboolean do_scroll_event(beosWidget *widget, GdkEvent *ev,
+ gpointer data)
+{
+ switch (((GdkEventScroll *)ev)->direction)
+ {
+ case GDK_SCROLL_UP:
+ case GDK_SCROLL_DOWN:
+ beos_widget_event(g_object_get_data(
+ G_OBJECT(widget), "vScroll"), ev);
+ break;
+ default:
+ beos_widget_event(g_object_get_data(
+ G_OBJECT(widget), "hScroll"), ev);
+ }
+
+ return TRUE;
+}
+#endif
+
+NSBrowserWindow *nsbeos_find_last_window(void)
+{
+ int32 i;
+ if (!be_app || !be_app->Lock())
+ return NULL;
+ for (i = be_app->CountWindows() - 1; i >= 0; i--) {
+ if (be_app->WindowAt(i) == NULL)
+ continue;
+ NSBrowserWindow *win;
+ win = dynamic_cast<NSBrowserWindow *>(be_app->WindowAt(i));
+ if (win) {
+ win->Lock();
+ be_app->Unlock();
+ return win;
+ }
+ }
+ be_app->Unlock();
+ return NULL;
+}
+
+void nsbeos_attach_toplevel_view(nsbeos_scaffolding *g, BView *view)
+{
+ LOG(("Attaching view to scaffolding %p", g));
+
+ BRect rect(g->top_view->Bounds());
+ rect.top += TOOLBAR_HEIGHT;
+ rect.right -= B_H_SCROLL_BAR_HEIGHT;
+ rect.bottom -= B_H_SCROLL_BAR_HEIGHT;
+
+ view->ResizeTo(rect.Width() /*+ 1*/, rect.Height() /*+ 1*/);
+ view->MoveTo(rect.LeftTop());
+
+
+ g->scroll_view = new BScrollView("NetSurfScrollView", view,
+ B_FOLLOW_ALL, 0, true, true, B_NO_BORDER);
+
+ g->top_view->AddChild(g->scroll_view);
+
+ view->MakeFocus();
+
+ // resize the horiz scrollbar to make room for the status bar and add it.
+
+ BScrollBar *sb = g->scroll_view->ScrollBar(B_HORIZONTAL);
+ rect = sb->Frame();
+ float divider = rect.Width() + 1;
+ //divider /= 2;
+ divider *= 67.0/100; // 67%
+
+ sb->ResizeBy(-divider, 0);
+ sb->MoveBy(divider, 0);
+
+ rect.right = rect.left + divider - 1;
+
+ /*
+ BBox *statusBarBox = new BBox(rect, "StatusBarBox",
+ B_FOLLOW_LEFT_RIGHT | B_FOLLOW_BOTTOM,
+ B_WILL_DRAW | B_FRAME_EVENTS,
+ B_RAISED_BORDER);
+ */
+
+ BString status("NetSurf");
+ status << " " << netsurf_version;
+ g->status_bar = new BStringView(rect, "StatusBar", status.String(),
+ B_FOLLOW_LEFT/*_RIGHT*/ | B_FOLLOW_BOTTOM);
+ g->scroll_view->AddChild(g->status_bar);
+ g->status_bar->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
+ g->status_bar->SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR)) ;
+#if defined(__HAIKU__) || defined(B_DANO_VERSION)
+ g->status_bar->SetHighColor(ui_color(B_PANEL_TEXT_COLOR));
+#endif
+
+
+
+ // set targets to the topmost ns view,
+ // we might not have a window later (replicant ?)
+ g->back_button->SetTarget(view);
+ g->forward_button->SetTarget(view);
+ g->stop_button->SetTarget(view);
+ g->reload_button->SetTarget(view);
+ g->home_button->SetTarget(view);
+
+ g->url_bar->SetTarget(view);
+
+
+ if (g->window)
+ g->window->Show();
+
+#warning XXX
+#if 0 /* GTK */
+ beosWidget *scrollbar;
+
+ /* Insert the viewport into the right part of our table */
+ beosTable *table = beos_TABLE(GET_WIDGET("centreTable"));
+ LOG(("Attaching viewport to scaffolding %p", g));
+ beos_table_attach_defaults(table, beos_WIDGET(vp), 0, 1, 0, 1);
+
+ /* connect our scrollbars to the viewport */
+ scrollbar = GET_WIDGET("coreScrollHorizontal");
+ beos_viewport_set_hadjustment(vp,
+ beos_range_get_adjustment(beos_RANGE(scrollbar)));
+ g_object_set_data(G_OBJECT(vp), "hScroll", scrollbar);
+ scrollbar = GET_WIDGET("coreScrollVertical");
+ beos_viewport_set_vadjustment(vp,
+ beos_range_get_adjustment(beos_RANGE(scrollbar)));
+ g_object_set_data(G_OBJECT(vp), "vScroll", scrollbar);
+ g_signal_connect(G_OBJECT(vp), "scroll_event",
+ G_CALLBACK(do_scroll_event), NULL);
+
+ gdk_window_set_accept_focus (beos_WIDGET(vp)->window, TRUE);
+
+ /* And set the size-request to zero to cause it to get its act together */
+ beos_widget_set_size_request(beos_WIDGET(vp), 0, 0);
+
+#endif
+}
+
+nsbeos_scaffolding *nsbeos_new_scaffolding(struct gui_window *toplevel)
+{
+ struct beos_scaffolding *g = (struct beos_scaffolding *)malloc(sizeof(*g));
+
+ LOG(("Constructing a scaffold of %p for gui_window %p", g, toplevel));
+
+ g->top_level = toplevel;
+
+ open_windows++;
+
+ BRect frame(0, 0, 600-1, 500-1);
+ if (option_window_width > 0) {
+ frame.Set(0, 0, option_window_width - 1, option_window_height - 1);
+ frame.OffsetToSelf(option_window_x, option_window_y);
+ } else {
+ BPoint pos(50, 50);
+ // XXX: use last BApplication::WindowAt()'s dynamic_cast<NSBrowserWindow *> Frame()
+ NSBrowserWindow *win = nsbeos_find_last_window();
+ if (win) {
+ pos = win->Frame().LeftTop();
+ win->Unlock();
+ }
+ pos += BPoint(20, 20);
+ BScreen screen;
+ BRect screenFrame(screen.Frame());
+ if (pos.y + frame.Height() >= screenFrame.Height()) {
+ pos.y = 50;
+ pos.x += 50;
+ }
+ if (pos.x + frame.Width() >= screenFrame.Width()) {
+ pos.x = 50;
+ pos.y = 50;
+ }
+ frame.OffsetToSelf(pos);
+ }
+
+ g->window = new NSBrowserWindow(frame, g);
+
+ g->being_destroyed = 0;
+
+ g->fullscreen = false;
+
+
+ BMessage *message;
+
+ // build popup menu
+ g->popup_menu = new BPopUpMenu("");
+
+
+
+
+ BRect rect;
+ rect = frame.OffsetToCopy(0,0);
+ rect.bottom = rect.top + 20;
+
+ // build menus
+ g->menu_bar = new BMenuBar(rect, "menu_bar");
+ g->window->AddChild(g->menu_bar);
+
+ BMenu *menu;
+
+ menu = new BMenu("File");
+ g->menu_bar->AddItem(menu);
+
+ menu = new BMenu("Edit");
+ g->menu_bar->AddItem(menu);
+
+ menu = new BMenu("View");
+ g->menu_bar->AddItem(menu);
+
+ menu = new BMenu("Navigate");
+ g->menu_bar->AddItem(menu);
+
+ menu = new BMenu("Help");
+ g->menu_bar->AddItem(menu);
+
+ // the base view that receives the toolbar, statusbar and top-level view.
+ rect = frame.OffsetToCopy(0,0);
+ rect.top = g->menu_bar->Bounds().Height() + 1;
+ //rect.top = 20 + 1; // XXX
+ //rect.bottom -= B_H_SCROLL_BAR_HEIGHT;
+
+ g->top_view = new BView(rect, "NetSurfBrowser",
+ B_FOLLOW_ALL_SIDES, 0);
+ g->top_view->SetViewColor(0, 255, 0);
+ g->window->AddChild(g->top_view);
+
+ // toolbar
+ rect = g->top_view->Bounds();
+ rect.bottom = rect.top + TOOLBAR_HEIGHT;
+ BView *toolbar = new BView(rect, "Toolbar",
+ B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP, 0);
+ toolbar->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
+ toolbar->SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR)) ;
+#if defined(__HAIKU__) || defined(B_DANO_VERSION)
+ toolbar->SetHighColor(ui_color(B_PANEL_TEXT_COLOR));
+#endif
+ g->top_view->AddChild(toolbar);
+
+ // buttons
+#warning use BPictureButton
+ rect = toolbar->Bounds();
+ rect.right = TOOLBAR_HEIGHT;
+ rect.InsetBySelf(5, 5);
+
+ message = new BMessage('back');
+ message->AddPointer("scaffolding", g);
+
+ g->back_button = new BButton(rect, "back_button", "<", message);
+ toolbar->AddChild(g->back_button);
+
+ rect.OffsetBySelf(TOOLBAR_HEIGHT, 0);
+ message = new BMessage('forw');
+ message->AddPointer("scaffolding", g);
+ g->forward_button = new BButton(rect, "forward_button", ">", message);
+ toolbar->AddChild(g->forward_button);
+
+ rect.OffsetBySelf(TOOLBAR_HEIGHT, 0);
+ message = new BMessage('stop');
+ message->AddPointer("scaffolding", g);
+ g->stop_button = new BButton(rect, "stop_button", "S", message);
+ toolbar->AddChild(g->stop_button);
+
+ rect.OffsetBySelf(TOOLBAR_HEIGHT, 0);
+ message = new BMessage('relo');
+ message->AddPointer("scaffolding", g);
+ g->reload_button = new BButton(rect, "reload_button", "R", message);
+ toolbar->AddChild(g->reload_button);
+
+ rect.OffsetBySelf(TOOLBAR_HEIGHT, 0);
+ message = new BMessage('home');
+ message->AddPointer("scaffolding", g);
+ g->home_button = new BButton(rect, "home_button", "H", message);
+ toolbar->AddChild(g->home_button);
+
+
+ // url bar
+ rect = toolbar->Bounds();
+ rect.left += TOOLBAR_HEIGHT * 5;
+ rect.right -= TOOLBAR_HEIGHT * 1;
+ rect.InsetBySelf(5, 5);
+ message = new BMessage('urle');
+ message->AddPointer("scaffolding", g);
+ g->url_bar = new BTextControl(rect, "url_bar", "url", "", message,
+ B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP);
+ g->url_bar->SetDivider(g->url_bar->StringWidth("url "));
+ toolbar->AddChild(g->url_bar);
+
+
+ // throbber
+ rect.Set(0, 0, 24, 24);
+ rect.OffsetTo(toolbar->Bounds().right - 24 - (TOOLBAR_HEIGHT - 24) / 2,
+ (TOOLBAR_HEIGHT - 24) / 2);
+ g->throbber = new NSThrobber(rect);
+ toolbar->AddChild(g->throbber);
+ g->throbber->SetViewColor(toolbar->ViewColor());
+ g->throbber->SetLowColor(toolbar->ViewColor());
+ g->throbber->SetDrawingMode(B_OP_OVER);
+ /* set up the throbber. */
+ g->throbber->SetBitmap(nsbeos_throbber->framedata[0]);
+ g->throb_frame = 0;
+
+
+ // the status bar at the bottom
+ // will be constructed when adding the top view.
+
+#warning XXX
+#if 0 /* GTK */
+ /* load the window template from the glade xml file, and extract
+ * widget references from it for later use.
+ */
+ g->xml = glade_xml_new(glade_file_location, "wndBrowser", NULL);
+ glade_xml_signal_autoconnect(g->xml);
+ g->window = beos_WINDOW(GET_WIDGET("wndBrowser"));
+ g->url_bar = beos_ENTRY(GET_WIDGET("URLBar"));
+ g->menu_bar = beos_MENU_BAR(GET_WIDGET("menubar"));
+ g->status_bar = beos_LABEL(GET_WIDGET("statusBar"));
+ g->tool_bar = beos_TOOLBAR(GET_WIDGET("toolbar"));
+ g->back_button = beos_TOOL_BUTTON(GET_WIDGET("toolBack"));
+ g->forward_button = beos_TOOL_BUTTON(GET_WIDGET("toolForward"));
+ g->stop_button = beos_TOOL_BUTTON(GET_WIDGET("toolStop"));
+ g->reload_button = beos_TOOL_BUTTON(GET_WIDGET("toolReload"));
+ g->back_menu = beos_MENU_ITEM(GET_WIDGET("back"));
+ g->forward_menu = beos_MENU_ITEM(GET_WIDGET("forward"));
+ g->stop_menu = beos_MENU_ITEM(GET_WIDGET("stop"));
+ g->reload_menu = beos_MENU_ITEM(GET_WIDGET("reload"));
+ g->throbber = beos_IMAGE(GET_WIDGET("throbber"));
+ g->status_pane = beos_PANED(GET_WIDGET("hpaned1"));
+
+ /* set this window's size and position to what's in the options, or
+ * or some sensible default if they're not set yet.
+ */
+ if (option_window_width > 0) {
+ beos_window_move(g->window, option_window_x, option_window_y);
+ beos_window_resize(g->window, option_window_width,
+ option_window_height);
+ } else {
+ beos_window_set_default_size(g->window, 600, 600);
+ }
+
+ /* set the size of the hpane with status bar and h scrollbar */
+ beos_paned_set_position(g->status_pane, option_toolbar_status_width);
+
+ /* set the URL entry box to expand, as we can't do this from within
+ * glade because of the way it emulates toolbars.
+ */
+ beos_tool_item_set_expand(beos_TOOL_ITEM(GET_WIDGET("toolURLBar")), TRUE);
+
+ /* disable toolbar buttons that make no sense initially. */
+ beos_widget_set_sensitive(beos_WIDGET(g->back_button), FALSE);
+ beos_widget_set_sensitive(beos_WIDGET(g->forward_button), FALSE);
+ beos_widget_set_sensitive(beos_WIDGET(g->stop_button), FALSE);
+
+ /* create the local history window to be assoicated with this browser */
+ g->history_window = malloc(sizeof(struct beos_history_window));
+ g->history_window->g = g;
+ g->history_window->window = beos_WINDOW(
+ beos_window_new(beos_WINDOW_TOPLEVEL));
+ beos_window_set_transient_for(g->history_window->window, g->window);
+ beos_window_set_default_size(g->history_window->window, 400, 400);
+ beos_window_set_title(g->history_window->window, "NetSurf History");
+ beos_window_set_type_hint(g->history_window->window,
+ GDK_WINDOW_TYPE_HINT_UTILITY);
+ g->history_window->scrolled = beos_SCROLLED_WINDOW(
+ beos_scrolled_window_new(0, 0));
+ beos_container_add(beos_CONTAINER(g->history_window->window),
+ beos_WIDGET(g->history_window->scrolled));
+
+ beos_widget_show(beos_WIDGET(g->history_window->scrolled));
+ g->history_window->drawing_area = beos_DRAWING_AREA(
+ beos_drawing_area_new());
+
+ beos_widget_set_events(beos_WIDGET(g->history_window->drawing_area),
+ GDK_EXPOSURE_MASK |
+ GDK_POINTER_MOTION_MASK |
+ GDK_BUTTON_PRESS_MASK);
+ beos_widget_modify_bg(beos_WIDGET(g->history_window->drawing_area),
+ beos_STATE_NORMAL,
+ &((GdkColor) { 0, 0xffff, 0xffff, 0xffff } ));
+ beos_scrolled_window_add_with_viewport(g->history_window->scrolled,
+ beos_WIDGET(g->history_window->drawing_area));
+ beos_widget_show(beos_WIDGET(g->history_window->drawing_area));
+
+ /* set up URL bar completion */
+ g->url_bar_completion = beos_entry_completion_new();
+ beos_entry_set_completion(g->url_bar, g->url_bar_completion);
+ beos_entry_completion_set_match_func(g->url_bar_completion,
+ nsbeos_completion_match, NULL, NULL);
+ beos_entry_completion_set_model(g->url_bar_completion,
+ beos_TREE_MODEL(nsbeos_completion_list));
+ beos_entry_completion_set_text_column(g->url_bar_completion, 0);
+ beos_entry_completion_set_minimum_key_length(g->url_bar_completion, 1);
+ beos_entry_completion_set_popup_completion(g->url_bar_completion, TRUE);
+ g_object_set(G_OBJECT(g->url_bar_completion),
+ "popup-set-width", TRUE,
+ "popup-single-match", TRUE,
+ NULL);
+
+ /* set up the throbber. */
+ beos_image_set_from_pixbuf(g->throbber, nsbeos_throbber->framedata[0]);
+ g->throb_frame = 0;
+
+#define CONNECT(obj, sig, callback, ptr) \
+ g_signal_connect(G_OBJECT(obj), (sig), G_CALLBACK(callback), (ptr))
+
+ /* connect history window signals to their handlers */
+ CONNECT(g->history_window->drawing_area, "expose_event",
+ nsbeos_history_expose_event, g->history_window);
+// CONNECT(g->history_window->drawing_area, "motion_notify_event",
+// nsbeos_history_motion_notify_event, g->history_window);
+ CONNECT(g->history_window->drawing_area, "button_press_event",
+ nsbeos_history_button_press_event, g->history_window);
+ CONNECT(g->history_window->window, "delete_event",
+ beos_widget_hide_on_delete, NULL);
+
+ /* connect signals to handlers. */
+ CONNECT(g->window, "destroy", nsbeos_window_destroy_event, g);
+
+ /* toolbar and URL bar signal handlers */
+ CONNECT(g->back_button, "clicked", nsbeos_window_back_button_clicked, g);
+ CONNECT(g->forward_button, "clicked",
+ nsbeos_window_forward_button_clicked, g);
+ CONNECT(g->stop_button, "clicked", nsbeos_window_stop_button_clicked, g);
+ CONNECT(g->reload_button, "clicked",
+ nsbeos_window_reload_button_clicked, g);
+ CONNECT(GET_WIDGET("toolHome"), "clicked",
+ nsbeos_window_home_button_clicked, g);
+ CONNECT(g->url_bar, "activate", nsbeos_window_url_activate_event, g);
+ CONNECT(g->url_bar, "changed", nsbeos_window_url_changed, g);
+
+ /* set up the menu signal handlers */
+ nsbeos_attach_menu_handlers(g->xml, g);
+
+ g->being_destroyed = 0;
+
+ g->fullscreen = false;
+
+ /* create the popup version of the menu */
+ g->popup_xml = glade_xml_new(glade_file_location, "menuPopup", NULL);
+ g->popup_menu = beos_MENU(glade_xml_get_widget(g->popup_xml, "menuPopup"));
+
+#define POPUP_ATTACH(x, y) beos_menu_item_set_submenu( \
+ beos_MENU_ITEM(glade_xml_get_widget(g->popup_xml, x)),\
+ beos_WIDGET(glade_xml_get_widget(g->xml, y)))
+
+ POPUP_ATTACH("menupopup_file", "menumain_file");
+ POPUP_ATTACH("menupopup_edit", "menumain_edit");
+ POPUP_ATTACH("menupopup_view", "menumain_view");
+ POPUP_ATTACH("menupopup_navigate", "menumain_navigate");
+ POPUP_ATTACH("menupopup_help", "menumain_help");
+
+#undef POPUP_ATTACH
+
+ /* finally, show the window. */
+ beos_widget_show(beos_WIDGET(g->window));
+
+#endif
+ return g;
+}
+
+void gui_window_set_title(struct gui_window *_g, const char *title)
+{
+ struct beos_scaffolding *g = nsbeos_get_scaffold(_g);
+ if (g->top_level != _g) return;
+
+ // if we're a replicant, discard
+ if (!g->window)
+ return;
+
+ BString nt(title);
+ if (nt.Length())
+ nt << " - ";
+ nt << "NetSurf";
+
+ if (!g->top_view->LockLooper())
+ return;
+
+ g->window->SetTitle(nt.String());
+
+ g->top_view->UnlockLooper();
+}
+
+void gui_window_set_status(struct gui_window *_g, const char *text)
+{
+ struct beos_scaffolding *g = nsbeos_get_scaffold(_g);
+ assert(g);
+ assert(g->status_bar);
+
+ if (!g->top_view->LockLooper())
+ return;
+
+ if (text == NULL || text[0] == '\0')
+ {
+ BString status("NetSurf");
+ status << " " << netsurf_version;
+ g->status_bar->SetText(status.String());
+ }
+ else
+ {
+ g->status_bar->SetText(text);
+ }
+ g->top_view->UnlockLooper();
+}
+
+void gui_window_set_url(struct gui_window *_g, const char *url)
+{
+ struct beos_scaffolding *g = nsbeos_get_scaffold(_g);
+ if (g->top_level != _g) return;
+ assert(g->status_bar);
+
+ if (!g->top_view->LockLooper())
+ return;
+
+ g->url_bar->SetText(url);
+
+ g->top_view->UnlockLooper();
+#warning XXX
+#if 0 /* GTK */
+ beos_entry_set_text(g->url_bar, url);
+ beos_editable_set_position(beos_EDITABLE(g->url_bar), -1);
+#endif
+}
+
+void gui_window_start_throbber(struct gui_window* _g)
+{
+ struct beos_scaffolding *g = nsbeos_get_scaffold(_g);
+
+ if (!g->top_view->LockLooper())
+ return;
+
+ g->stop_button->SetEnabled(true);
+ g->reload_button->SetEnabled(false);
+
+ g->top_view->UnlockLooper();
+
+ nsbeos_window_update_back_forward(g);
+
+ schedule(10, nsbeos_throb, g);
+
+#warning XXX
+#if 0 /* GTK */
+ beos_widget_set_sensitive(beos_WIDGET(g->stop_button), TRUE);
+ beos_widget_set_sensitive(beos_WIDGET(g->reload_button), FALSE);
+ beos_widget_set_sensitive(beos_WIDGET(g->stop_menu), TRUE);
+ beos_widget_set_sensitive(beos_WIDGET(g->reload_button), FALSE);
+
+ nsbeos_window_update_back_forward(g);
+
+ schedule(10, nsbeos_throb, g);
+#endif
+}
+
+void gui_window_stop_throbber(struct gui_window* _g)
+{
+ struct beos_scaffolding *g = nsbeos_get_scaffold(_g);
+
+ nsbeos_window_update_back_forward(g);
+
+ schedule_remove(nsbeos_throb, g);
+
+ if (!g->top_view->LockLooper())
+ return;
+
+ g->stop_button->SetEnabled(false);
+ g->reload_button->SetEnabled(true);
+
+ g->throbber->SetBitmap(nsbeos_throbber->framedata[0]);
+ g->throbber->Invalidate();
+
+ g->top_view->UnlockLooper();
+
+#warning XXX
+#if 0 /* GTK */
+ beos_widget_set_sensitive(beos_WIDGET(g->stop_button), FALSE);
+ beos_widget_set_sensitive(beos_WIDGET(g->reload_button), TRUE);
+ beos_widget_set_sensitive(beos_WIDGET(g->stop_menu), FALSE);
+ beos_widget_set_sensitive(beos_WIDGET(g->reload_menu), TRUE);
+
+ nsbeos_window_update_back_forward(g);
+
+ schedule_remove(nsbeos_throb, g);
+
+ beos_image_set_from_pixbuf(g->throbber, nsbeos_throbber->framedata[0]);
+#endif
+}
+
+#warning XXX
+#if 0 /* GTK */
+gboolean nsbeos_scaffolding_is_busy(nsbeos_scaffolding *scaffold)
+{
+ /* We are considered "busy" if the stop button is sensitive */
+ return beos_WIDGET_SENSITIVE((beos_WIDGET(scaffold->stop_button)));
+}
+#endif
+
+void nsbeos_scaffolding_popup_menu(nsbeos_scaffolding *g, BPoint where)
+{
+ g->popup_menu->Go(where);
+}
diff --git a/beos/beos_scaffolding.h b/beos/beos_scaffolding.h
new file mode 100644
index 000000000..2fcc7280e
--- /dev/null
+++ b/beos/beos_scaffolding.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2005 James Bursa <bursa@users.sourceforge.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/>.
+ */
+
+#ifndef NETSURF_BEOS_SCAFFOLDING_H
+#define NETSURF_BEOS_SCAFFOLDING_H 1
+
+#include <View.h>
+#include <Window.h>
+extern "C" {
+#include "desktop/gui.h"
+#include "desktop/plotters.h"
+}
+
+typedef struct beos_scaffolding nsbeos_scaffolding;
+
+class NSBrowserWindow : public BWindow {
+public:
+ NSBrowserWindow(BRect frame, struct beos_scaffolding *scaf);
+virtual ~NSBrowserWindow();
+
+virtual void MessageReceived(BMessage *message);
+virtual bool QuitRequested(void);
+
+struct beos_scaffolding *Scaffolding() const { return fScaffolding; };
+
+private:
+ struct beos_scaffolding *fScaffolding;
+};
+
+
+NSBrowserWindow *nsbeos_find_last_window(void);
+
+nsbeos_scaffolding *nsbeos_new_scaffolding(struct gui_window *toplevel);
+
+bool nsbeos_scaffolding_is_busy(nsbeos_scaffolding *scaffold);
+
+void nsbeos_attach_toplevel_view(nsbeos_scaffolding *g, BView *view);
+
+#if 0 /* GTK */
+void nsbeos_attach_toplevel_viewport(nsbeos_scaffolding *g, GtkViewport *vp);
+#endif
+
+void nsbeos_scaffolding_dispatch_event(nsbeos_scaffolding *scaffold, BMessage *message);
+
+void nsbeos_scaffolding_destroy(nsbeos_scaffolding *scaffold);
+
+//void nsbeos_window_destroy_event(NSBrowserWindow *window, nsbeos_scaffolding *g, BMessage *event);
+
+
+void nsbeos_scaffolding_popup_menu(nsbeos_scaffolding *g, BPoint where);
+
+#if 0 /* GTK */
+void nsbeos_scaffolding_popup_menu(nsbeos_scaffolding *g, guint button);
+#endif
+
+#endif /* NETSURF_BEOS_SCAFFOLDING_H */
diff --git a/beos/beos_schedule.cpp b/beos/beos_schedule.cpp
new file mode 100644
index 000000000..b91c26b49
--- /dev/null
+++ b/beos/beos_schedule.cpp
@@ -0,0 +1,209 @@
+/*
+ * Copyright 2006-2007 Daniel Silverstone <dsilvers@digital-scurf.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <OS.h>
+#include <List.h>
+
+extern "C" {
+#include "desktop/browser.h"
+
+#ifdef DEBUG_BEOS_SCHEDULE
+#include "utils/log.h"
+#else
+#define LOG(X)
+#endif
+}
+
+/** Killable callback closure embodiment. */
+typedef struct {
+ void (*callback)(void *); /**< The callback function. */
+ void *context; /**< The context for the callback. */
+ bool callback_killed; /**< Whether or not this was killed. */
+ bool callback_fired; /**< Whether or not this has fired yet. */
+ bigtime_t timeout;
+} _nsbeos_callback_t;
+
+/** List of all callbacks. */
+static BList *callbacks = NULL;
+
+/** earliest deadline. It's used for select() in gui_poll() */
+bigtime_t earliest_callback_timeout = B_INFINITE_TIMEOUT;
+
+#warning XXX
+#if 0 /* GTK */
+/** List of callbacks which have occurred and are pending running. */
+static GList *pending_callbacks = NULL;
+/** List of callbacks which are queued to occur in the future. */
+static GList *queued_callbacks = NULL;
+/** List of callbacks which are about to be run in this ::schedule_run. */
+static GList *this_run = NULL;
+
+static gboolean
+nsbeos_schedule_generic_callback(gpointer data)
+{
+ _nsbeos_callback_t *cb = (_nsbeos_callback_t *)(data);
+ if (cb->callback_killed) {
+ /* This callback instance has been killed. */
+ LOG(("CB at %p already dead.", cb));
+ free(cb);
+ return FALSE;
+ }
+ LOG(("CB for %p(%p) set pending.", cb->callback, cb->context));
+ /* The callback is alive, so move it to pending. */
+ cb->callback_fired = true;
+ queued_callbacks = g_list_remove(queued_callbacks, cb);
+ pending_callbacks = g_list_append(pending_callbacks, cb);
+ return FALSE;
+}
+#endif
+
+static bool
+nsbeos_schedule_kill_callback(void *_target, void *_match)
+{
+ _nsbeos_callback_t *target = (_nsbeos_callback_t *)_target;
+ _nsbeos_callback_t *match = (_nsbeos_callback_t *)_match;
+ if ((target->callback == match->callback) &&
+ (target->context == match->context)) {
+ LOG(("Found match for %p(%p), killing.",
+ target->callback, target->context));
+ target->callback = NULL;
+ target->context = NULL;
+ target->callback_killed = true;
+ }
+ return false;
+}
+
+void
+schedule_remove(void (*callback)(void *p), void *p)
+{
+ LOG(("schedule_remove() for %p(%p)", cb->callback, cb->context));
+ if (callbacks == NULL)
+ return;
+ _nsbeos_callback_t cb_match;
+ cb_match.callback = callback;
+ cb_match.context = p;
+
+
+ callbacks->DoForEach(nsbeos_schedule_kill_callback, &cb_match);
+
+#warning XXX
+#if 0 /* GTK */
+ _nsbeos_callback_t cb_match = {
+ .callback = callback,
+ .context = p,
+ };
+
+ g_list_foreach(queued_callbacks,
+ nsbeos_schedule_kill_callback, &cb_match);
+ g_list_foreach(pending_callbacks,
+ nsbeos_schedule_kill_callback, &cb_match);
+ g_list_foreach(this_run,
+ nsbeos_schedule_kill_callback, &cb_match);
+#endif
+}
+
+void
+schedule(int t, void (*callback)(void *p), void *p)
+{
+ LOG(("schedule(%d, %p, %p)", t, cb->callback, cb->context));
+ if (callbacks == NULL)
+ callbacks = new BList;
+
+ bigtime_t timeout = system_time() + t * 10 * 1000LL;
+ const int msec_timeout = t * 10;
+ _nsbeos_callback_t *cb = (_nsbeos_callback_t *)malloc(sizeof(_nsbeos_callback_t));
+ /* Kill any pending schedule of this kind. */
+ schedule_remove(callback, p);
+ cb->callback = callback;
+ cb->context = p;
+ cb->callback_killed = cb->callback_fired = false;
+ cb->timeout = timeout;
+ if (earliest_callback_timeout > timeout)
+ earliest_callback_timeout = timeout;
+ callbacks->AddItem(cb);
+
+#warning XXX
+#if 0 /* GTK */
+ const int msec_timeout = t * 10;
+ _nsbeos_callback_t *cb = malloc(sizeof(_nsbeos_callback_t));
+ /* Kill any pending schedule of this kind. */
+ schedule_remove(callback, p);
+ cb->callback = callback;
+ cb->context = p;
+ cb->callback_killed = cb->callback_fired = false;
+ /* Prepend is faster right now. */
+ queued_callbacks = g_list_prepend(queued_callbacks, cb);
+ g_timeout_add(msec_timeout, nsbeos_schedule_generic_callback, cb);
+#endif
+}
+
+void
+schedule_run(void)
+{
+ LOG(("schedule_run()"));
+ if (callbacks == NULL)
+ return; /* Nothing to do */
+
+ bigtime_t now = system_time();
+ earliest_callback_timeout = B_INFINITE_TIMEOUT;
+ int32 i;
+
+ LOG(("Checking %ld callbacks to for deadline.", this_run->CountItems()));
+
+ /* Run all the callbacks which made it this far. */
+ for (i = 0; i < callbacks->CountItems(); ) {
+ _nsbeos_callback_t *cb = (_nsbeos_callback_t *)(callbacks->ItemAt(i));
+ if (cb->timeout > now) {
+ // update next deadline
+ if (earliest_callback_timeout > cb->timeout)
+ earliest_callback_timeout = cb->timeout;
+ i++;
+ continue;
+ }
+ LOG(("Running callbacks %p(%p).", cb->callback, cb->context));
+ if (!cb->callback_killed)
+ cb->callback(cb->context);
+ callbacks->RemoveItem(cb);
+ free(cb);
+ }
+
+#warning XXX
+#if 0 /* GTK */
+ /* Capture this run of pending callbacks into the list. */
+ this_run = pending_callbacks;
+
+ if (this_run == NULL)
+ return; /* Nothing to do */
+
+ /* Clear the pending list. */
+ pending_callbacks = NULL;
+
+ LOG(("Captured a run of %d callbacks to fire.", g_list_length(this_run)));
+
+ /* Run all the callbacks which made it this far. */
+ while (this_run != NULL) {
+ _nsbeos_callback_t *cb = (_nsbeos_callback_t *)(this_run->data);
+ this_run = g_list_remove(this_run, this_run->data);
+ if (!cb->callback_killed)
+ cb->callback(cb->context);
+ free(cb);
+ }
+#endif
+}
diff --git a/beos/beos_schedule.h b/beos/beos_schedule.h
new file mode 100644
index 000000000..b7ffd074d
--- /dev/null
+++ b/beos/beos_schedule.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2006 Daniel Silverstone <dsilvers@digital-scurf.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_BEOS_CALLBACK_H
+#define NETSURF_BEOS_CALLBACK_H 1
+
+typedef void (*beos_callback)(void *p);
+
+extern bigtime_t earliest_callback_timeout;
+
+#endif /* NETSURF_BEOS_CALLBACK_H */
diff --git a/beos/beos_throbber.cpp b/beos/beos_throbber.cpp
new file mode 100644
index 000000000..69cc09076
--- /dev/null
+++ b/beos/beos_throbber.cpp
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2006 Rob Kendrick <rjek@rjek.com>
+ *
+ * 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 <stdlib.h>
+extern "C" {
+#include "utils/log.h"
+#include "image/gifread.h"
+}
+#include "beos/beos_throbber.h"
+#include "beos/beos_bitmap.h"
+
+struct nsbeos_throbber *nsbeos_throbber = NULL;
+
+bool nsbeos_throbber_initialise(const char *fn)
+{
+ /* disect the GIF provided by filename in *fn into a series of
+ * BBitmap for use later.
+ */
+ struct gif_animation *gif; /**< structure for gifread.c */
+ struct nsbeos_throbber *throb; /**< structure we generate */
+ int i;
+
+ FILE *fh = fopen(fn, "rb");
+
+ if (fh == NULL) {
+ LOG(("Unable to open throbber image '%s' for reading!", fn));
+ return false;
+ }
+
+ gif = (struct gif_animation *)malloc(sizeof(struct gif_animation));
+ throb = (struct nsbeos_throbber *)malloc(sizeof(struct nsbeos_throbber));
+
+ /* discover the size of the data file. */
+ fseek(fh, 0, SEEK_END);
+ gif->buffer_size = ftell(fh);
+ fseek(fh, 0, SEEK_SET);
+
+ /* allocate a block of sufficient size, and load the data in. */
+ gif->gif_data = (unsigned char *)malloc(gif->buffer_size);
+ fread(gif->gif_data, gif->buffer_size, 1, fh);
+ fclose(fh);
+
+ /* set current position within GIF file to beginning, in order to
+ * signal to gifread that we're brand new.
+ */
+ gif->buffer_position = 0;
+
+ /* initialise the gif_animation structure. */
+ switch (gif_initialise(gif))
+ {
+ case GIF_INSUFFICIENT_FRAME_DATA:
+ case GIF_FRAME_DATA_ERROR:
+ case GIF_INSUFFICIENT_DATA:
+ case GIF_DATA_ERROR:
+ LOG(("GIF image '%s' appears invalid!", fn));
+ free(gif->gif_data);
+ free(gif);
+ free(throb);
+ return false;
+ break;
+ case GIF_INSUFFICIENT_MEMORY:
+ LOG(("Ran out of memory decoding GIF image '%s'!", fn));
+ free(gif->gif_data);
+ free(gif);
+ free(throb);
+ return false;
+ break;
+ }
+
+ throb->nframes = gif->frame_count;
+
+ if (throb->nframes < 2)
+ {
+ /* we need at least two frames - one for idle, one for active */
+ LOG(("Insufficent number of frames in throbber image '%s'!",
+ fn));
+ LOG(("(GIF contains %d frames, where 2 is a minimum.)",
+ throb->nframes));
+ free(gif->gif_data);
+ free(gif);
+ free(throb);
+ return false;
+ }
+
+ throb->framedata = (BBitmap **)malloc(sizeof(BBitmap *)
+ * throb->nframes);
+
+ /* decode each frame in turn, extracting the struct bitmap * for each,
+ * and put that in our array of frames.
+ */
+ for (i = 0; i < throb->nframes; i++)
+ {
+ gif_decode_frame(gif, i);
+ throb->framedata[i] = new BBitmap(
+ nsbeos_bitmap_get_primary(gif->frame_image));
+ }
+
+ gif_finalise(gif);
+ free(gif->gif_data);
+ free(gif);
+
+ /* debug code: save out each frame as a PNG to make sure decoding is
+ * working correctly.
+
+ for (i = 0; i < throb->nframes; i++) {
+ char fname[20];
+ sprintf(fname, "frame%d.png", i);
+ gdk_pixbuf_save(throb->framedata[i], fname, "png", NULL, NULL);
+ }
+ */
+
+ nsbeos_throbber = throb;
+
+ return true;
+}
+
+void nsbeos_throbber_finalise(void)
+{
+ int i;
+
+ for (i = 0; i < nsbeos_throbber->nframes; i++)
+ delete nsbeos_throbber->framedata[i];
+
+ free(nsbeos_throbber->framedata);
+ free(nsbeos_throbber);
+
+ nsbeos_throbber = NULL;
+}
diff --git a/beos/beos_throbber.h b/beos/beos_throbber.h
new file mode 100644
index 000000000..47f8249e6
--- /dev/null
+++ b/beos/beos_throbber.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2006 Rob Kendrick <rjek@rjek.com>
+ *
+ * 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 __BEOS_THROBBER_H__
+#define __BEOS_THROBBER_H__
+
+#include <Bitmap.h>
+
+struct nsbeos_throbber
+{
+ int nframes; /**< Number of frames in the throbber */
+ BBitmap **framedata;
+};
+
+extern struct nsbeos_throbber *nsbeos_throbber;
+
+bool nsbeos_throbber_initialise(const char *fn);
+void nsbeos_throbber_finalise(void);
+
+#endif /* __BEOS_THROBBER_H__ */
diff --git a/beos/beos_thumbnail.cpp b/beos/beos_thumbnail.cpp
new file mode 100644
index 000000000..7860e386e
--- /dev/null
+++ b/beos/beos_thumbnail.cpp
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2006 Rob Kendrick <rjek@rjek.com>
+ *
+ * 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
+ * Page thumbnail creation (implementation).
+ *
+ * Thumbnails are created by setting the current drawing contexts to a BView
+ * attached to the BBitmap we are passed, and plotting the page at a small
+ * scale.
+ */
+
+#include <assert.h>
+#include <Bitmap.h>
+#include <View.h>
+extern "C" {
+#include "content/content.h"
+#include "content/urldb.h"
+#include "desktop/plotters.h"
+#include "desktop/browser.h"
+#include "image/bitmap.h"
+#include "render/font.h"
+#include "utils/log.h"
+}
+#include "beos/beos_scaffolding.h"
+#include "beos/beos_plotters.h"
+#include "beos/beos_bitmap.h"
+
+/**
+ * Create a thumbnail of a page.
+ *
+ * \param content content structure to thumbnail
+ * \param bitmap the bitmap to draw to
+ * \param url the URL the thumnail belongs to, or NULL
+ */
+bool thumbnail_create(struct content *content, struct bitmap *bitmap,
+ const char *url)
+{
+#warning WRITEME
+#if 0 /* GTK */
+ GdkPixbuf *pixbuf;
+ gint width;
+ gint height;
+ gint depth;
+ GdkPixmap *pixmap;
+ GdkPixbuf *big;
+
+ assert(content);
+ assert(bitmap);
+
+ pixbuf = beos_bitmap_get_primary(bitmap);
+ width = gdk_pixbuf_get_width(pixbuf);
+ height = gdk_pixbuf_get_height(pixbuf);
+ depth = (gdk_screen_get_system_visual(gdk_screen_get_default()))->depth;
+
+ LOG(("Trying to create a thumbnail pixmap for a content of %dx%d@%d",
+ content->width, content->width, depth));
+
+ pixmap = gdk_pixmap_new(NULL, content->width, content->width, depth);
+
+ if (pixmap == NULL) {
+ /* the creation failed for some reason: most likely because
+ * we've been asked to create with with at least one dimention
+ * as zero. The RISC OS thumbnail generator returns false
+ * from here when it can't create a bitmap, so we assume it's
+ * safe to do so here too.
+ */
+ return false;
+ }
+
+ gdk_drawable_set_colormap(pixmap, gdk_colormap_get_system());
+
+ /* set the plotting functions up */
+ plot = nsbeos_plotters;
+
+ nsbeos_plot_set_scale(1.0);
+
+ /* set to plot to pixmap */
+ current_drawable = pixmap;
+ current_gc = gdk_gc_new(current_drawable);
+#ifdef CAIRO_VERSION
+ current_cr = gdk_cairo_create(current_drawable);
+#endif
+ plot.fill(0, 0, content->width, content->width, 0xffffffff);
+
+ /* render the content */
+ content_redraw(content, 0, 0, content->width, content->width,
+ 0, 0, content->width, content->width, 1.0, 0xFFFFFF);
+
+ /* resample the large plot down to the size of our thumbnail */
+ big = gdk_pixbuf_get_from_drawable(NULL, pixmap, NULL, 0, 0, 0, 0,
+ content->width, content->width);
+
+ gdk_pixbuf_scale(big, pixbuf, 0, 0, width, height, 0, 0,
+ (double)width / (double)content->width,
+ (double)height / (double)content->width,
+ GDK_INTERP_TILES);
+
+ /* As a debugging aid, try this to dump out a copy of the thumbnail as
+ * a PNG: gdk_pixbuf_save(pixbuf, "thumbnail.png", "png", NULL, NULL);
+ */
+
+ /* register the thumbnail with the URL */
+ if (url)
+ urldb_set_thumbnail(url, bitmap);
+
+ bitmap_modified(bitmap);
+
+ g_object_unref(current_gc);
+#ifdef CAIRO_VERSION
+ cairo_destroy(current_cr);
+#endif
+ g_object_unref(pixmap);
+ g_object_unref(big);
+
+ return true;
+#endif
+ return false;
+}
diff --git a/beos/beos_treeview.cpp b/beos/beos_treeview.cpp
new file mode 100644
index 000000000..965501892
--- /dev/null
+++ b/beos/beos_treeview.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2004 Richard Wilson <not_ginger_matt@users.sourceforge.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/>.
+ */
+
+/** \file
+ * Generic tree handling (implementation).
+ */
+
+
+extern "C" {
+#include "utils/config.h"
+#include "desktop/tree.h"
+}
+
+
+/**
+ * Sets the origin variables to the correct values for a specified tree
+ *
+ * \param tree the tree to set the origin for
+ */
+void tree_initialise_redraw(struct tree *tree) {
+}
+
+
+/**
+ * Informs the current window manager that an area requires updating.
+ *
+ * \param tree the tree that is requesting a redraw
+ * \param x the x co-ordinate of the redraw area
+ * \param y the y co-ordinate of the redraw area
+ * \param width the width of the redraw area
+ * \param height the height of the redraw area
+ */
+void tree_redraw_area(struct tree *tree, int x, int y, int width, int height) {
+}
+
+
+/**
+ * Draws a line.
+ *
+ * \param x the x co-ordinate
+ * \param x the y co-ordinate
+ * \param x the width of the line
+ * \param x the height of the line
+ */
+void tree_draw_line(int x, int y, int width, int height) {
+}
+
+
+/**
+ * Draws an element, including any expansion icons
+ *
+ * \param tree the tree to draw an element for
+ * \param element the element to draw
+ */
+void tree_draw_node_element(struct tree *tree, struct node_element *element) {
+}
+
+
+/**
+ * Draws an elements expansion icon
+ *
+ * \param tree the tree to draw the expansion for
+ * \param element the element to draw the expansion for
+ */
+void tree_draw_node_expansion(struct tree *tree, struct node *node) {
+}
+
+
+/**
+ * Recalculates the dimensions of a node element.
+ *
+ * \param element the element to recalculate
+ */
+void tree_recalculate_node_element(struct node_element *element) {
+}
+
+/**
+ * Sets a node element as having a specific sprite.
+ *
+ * \param node the node to update
+ * \param sprite the sprite to use
+ * \param selected the expanded sprite name to use
+ */
+void tree_set_node_sprite(struct node *node, const char *sprite,
+ const char *expanded) {
+
+}
+
+/**
+ * Sets a node element as having a folder sprite
+ *
+ * \param node the node to update
+ */
+void tree_set_node_sprite_folder(struct node *node) {
+
+}
+
+/**
+ * Updates the node details for a URL node.
+ * The internal node dimensions are not updated.
+ *
+ * \param node the node to update
+ */
+void tree_update_URL_node(struct node *node, const char *url,
+ const struct url_data *data) {
+}
+
+
+/**
+ * Updates the tree owner following a tree resize
+ *
+ * \param tree the tree to update the owner of
+ */
+void tree_resized(struct tree *tree) {
+}
diff --git a/beos/beos_window.cpp b/beos/beos_window.cpp
new file mode 100644
index 000000000..36b01acc5
--- /dev/null
+++ b/beos/beos_window.cpp
@@ -0,0 +1,1570 @@
+/*
+ * Copyright 2006 Daniel Silverstone <dsilvers@digital-scurf.org>
+ * Copyright 2006 Rob Kendrick <rjek@rjek.com>
+ *
+ * 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>
+extern "C" {
+#include "desktop/browser.h"
+#include "desktop/options.h"
+#include "desktop/textinput.h"
+#undef NDEBUG
+#include "utils/log.h"
+#include "utils/utils.h"
+}
+#include "beos/beos_window.h"
+#include "beos/beos_gui.h"
+#include "beos/beos_scaffolding.h"
+#include "beos/beos_plotters.h"
+//#include "beos/beos_schedule.h"
+
+#include <AppDefs.h>
+#include <BeBuild.h>
+#include <Cursor.h>
+#include <InterfaceDefs.h>
+#include <Message.h>
+#include <ScrollBar.h>
+#include <View.h>
+#include <Window.h>
+
+class NSBrowserFrameView;
+
+struct gui_window {
+ /* All gui_window objects have an ultimate scaffold */
+ nsbeos_scaffolding *scaffold;
+ bool toplevel;
+ /* A gui_window is the rendering of a browser_window */
+ struct browser_window *bw;
+
+ /* These are the storage for the rendering */
+ int caretx, carety, careth;
+ gui_pointer_shape current_pointer;
+ int last_x, last_y;
+
+ NSBrowserFrameView *view;
+
+ // some cached events to speed up things
+ // those are the last queued event of their kind,
+ // we can safely drop others and avoid wasting cpu.
+ // number of pending resizes
+ vint32 pending_resizes;
+ // accumulated rects of pending redraws
+ //volatile BMessage *lastRedraw;
+ // UNUSED YET
+ BRect pendingRedraw;
+#if 0 /* GTK */
+ /* Within GTK, a gui_window is a scrolled window
+ * with a viewport inside
+ * with a gtkfixed in that
+ * with a drawing area in that
+ * The scrolled window is optional and only chosen
+ * for frames which need it. Otherwise we just use
+ * a viewport.
+ */
+ GtkScrolledWindow *scrolledwindow;
+ GtkViewport *viewport;
+ GtkFixed *fixed;
+ GtkDrawingArea *drawing_area;
+#endif
+
+ /* Keep gui_windows in a list for cleanup later */
+ struct gui_window *next, *prev;
+};
+
+static const rgb_color kWhiteColor = {255, 255, 255, 255};
+
+static struct gui_window *window_list = 0; /**< first entry in win list*/
+
+static void nsbeos_gui_window_attach_child(struct gui_window *parent,
+ struct gui_window *child);
+/* Methods which apply only to a gui_window */
+static void nsbeos_window_expose_event(BView *view, gui_window *g, BMessage *message);
+static void nsbeos_window_keypress_event(BView *view, gui_window *g, BMessage *event);
+static void nsbeos_window_resize_event(BView *view, gui_window *g, BMessage *event);
+static void nsbeos_window_moved_event(BView *view, gui_window *g, BMessage *event);
+/* Other useful bits */
+static void nsbeos_redraw_caret(struct gui_window *g);
+
+#if 0 /* GTK */
+static GdkCursor *nsbeos_create_menu_cursor(void);
+#endif
+
+// #pragma mark - class NSBrowserFrameView
+
+
+NSBrowserFrameView::NSBrowserFrameView(BRect frame, struct gui_window *gui)
+ : BView(frame, "NSBrowserFrameView", B_FOLLOW_ALL_SIDES,
+ B_WILL_DRAW | B_NAVIGABLE | B_FRAME_EVENTS),
+ fGuiWindow(gui)
+{
+}
+
+
+NSBrowserFrameView::~NSBrowserFrameView()
+{
+}
+
+
+void
+NSBrowserFrameView::MessageReceived(BMessage *message)
+{
+ switch (message->what) {
+ case B_SIMPLE_DATA:
+ case B_REFS_RECEIVED:
+ message->PrintToStream();
+ //case B_MOUSE_WHEEL_CHANGED:
+ // messages for top-level
+ case 'back':
+ case 'forw':
+ case 'stop':
+ case 'relo':
+ case 'home':
+ case 'urlc':
+ case 'urle':
+ case 'menu':
+ Window()->DetachCurrentMessage();
+ nsbeos_pipe_message_top(message, NULL, fGuiWindow->scaffold);
+ break;
+ default:
+ BView::MessageReceived(message);
+ }
+}
+
+
+void
+NSBrowserFrameView::Draw(BRect updateRect)
+{
+ BMessage *message = NULL;
+ //message = Window()->DetachCurrentMessage();
+ // might be called directly...
+ if (message == NULL)
+ message = new BMessage(_UPDATE_);
+ message->AddRect("rect", updateRect);
+ nsbeos_pipe_message(message, this, fGuiWindow);
+}
+
+
+#if 0
+void
+NSBrowserFrameView::FrameMoved(BPoint new_location)
+{
+ BMessage *message = Window()->DetachCurrentMessage();
+ // discard any other pending resize,
+ // so we don't end up processing them all, the last one matters.
+ //atomic_add(&fGuiWindow->pending_resizes, 1);
+ nsbeos_pipe_message(message, this, fGuiWindow);
+ BView::FrameMoved(new_location);
+}
+#endif
+
+void
+NSBrowserFrameView::FrameResized(float new_width, float new_height)
+{
+ BMessage *message = Window()->DetachCurrentMessage();
+ // discard any other pending resize,
+ // so we don't end up processing them all, the last one matters.
+ atomic_add(&fGuiWindow->pending_resizes, 1);
+ nsbeos_pipe_message(message, this, fGuiWindow);
+ BView::FrameResized(new_width, new_height);
+}
+
+
+void
+NSBrowserFrameView::KeyDown(const char *bytes, int32 numBytes)
+{
+ BMessage *message = Window()->DetachCurrentMessage();
+ nsbeos_pipe_message(message, this, fGuiWindow);
+}
+
+
+void
+NSBrowserFrameView::MouseDown(BPoint where)
+{
+ BMessage *message = Window()->DetachCurrentMessage();
+ BPoint screenWhere;
+ if (message->FindPoint("screen_where", &screenWhere) < B_OK) {
+ screenWhere = ConvertToScreen(where);
+ message->AddPoint("screen_where", screenWhere);
+ }
+ nsbeos_pipe_message(message, this, fGuiWindow);
+}
+
+
+void
+NSBrowserFrameView::MouseUp(BPoint where)
+{
+ //BMessage *message = Window()->DetachCurrentMessage();
+ //nsbeos_pipe_message(message, this, fGuiWindow);
+ BView::MouseUp(where);
+}
+
+
+void
+NSBrowserFrameView::MouseMoved(BPoint where, uint32 transit, const BMessage *msg)
+{
+ if (transit != B_INSIDE_VIEW) {
+ BView::MouseMoved(where, transit, msg);
+ return;
+ }
+ BMessage *message = Window()->DetachCurrentMessage();
+ nsbeos_pipe_message(message, this, fGuiWindow);
+}
+
+
+// #pragma mark - gui_window
+
+struct browser_window *nsbeos_get_browser_window(struct gui_window *g)
+{
+ return g->bw;
+}
+
+nsbeos_scaffolding *nsbeos_get_scaffold(struct gui_window *g)
+{
+ return g->scaffold;
+}
+
+struct browser_window *nsbeos_get_browser_for_gui(struct gui_window *g)
+{
+ return g->bw;
+}
+
+float nsbeos_get_scale_for_gui(struct gui_window *g)
+{
+ return g->bw->scale;
+}
+
+/* Create a gui_window */
+struct gui_window *gui_create_browser_window(struct browser_window *bw,
+ struct browser_window *clone)
+{
+ struct gui_window *g; /**< what we're creating to return */
+
+ g = (struct gui_window *)malloc(sizeof(*g));
+ if (!g) {
+ warn_user("NoMemory", 0);
+ return 0;
+ }
+
+ LOG(("Creating gui window %p for browser window %p", g, bw));
+
+ g->bw = bw;
+ g->current_pointer = GUI_POINTER_DEFAULT;
+ if (clone != NULL)
+ bw->scale = clone->scale;
+ else
+ bw->scale = (float) option_scale / 100;
+
+ g->careth = 0;
+ g->pending_resizes = 0;
+
+ /* Attach ourselves to the list (push_top) */
+ if (window_list)
+ window_list->prev = g;
+ g->next = window_list;
+ g->prev = NULL;
+ window_list = g;
+
+ if (bw->parent != NULL) {
+ /* Find our parent's scaffolding */
+ g->scaffold = bw->parent->window->scaffold;
+ } else {
+ /* Now construct and attach a scaffold */
+ g->scaffold = nsbeos_new_scaffolding(g);
+ }
+
+ /* Construct our primary elements */
+ BRect frame(0,0,-1,-1); // will be resized later
+ g->view = new NSBrowserFrameView(frame, g);
+ /* set the default background colour of the drawing area to white. */
+ g->view->SetViewColor(kWhiteColor);
+ g->view->SetHighColor(kWhiteColor);
+
+ if (bw->parent != NULL ) {
+ g->toplevel = false;
+ // XXX handle scrollview later
+ //g->scrollview = new BScrollView(g->view);
+
+ /* Attach ourselves into our parent at the right point */
+ nsbeos_gui_window_attach_child(bw->parent->window, g);
+ } else {
+ g->toplevel = true;
+
+ /* Attach our viewport into the scaffold */
+ nsbeos_attach_toplevel_view(g->scaffold, g->view);
+ }
+
+#warning WRITEME
+#if 0 /* GTK */
+ GtkPolicyType scrollpolicy;
+
+ /* Construct our primary elements */
+ g->fixed = GTK_FIXED(gtk_fixed_new());
+ g->drawing_area = GTK_DRAWING_AREA(gtk_drawing_area_new());
+ gtk_fixed_put(g->fixed, GTK_WIDGET(g->drawing_area), 0, 0);
+ gtk_container_set_border_width(GTK_CONTAINER(g->fixed), 0);
+
+ if (bw->parent != NULL ) {
+ g->scrolledwindow = GTK_SCROLLED_WINDOW(gtk_scrolled_window_new(NULL, NULL));
+ gtk_scrolled_window_add_with_viewport(g->scrolledwindow,
+ GTK_WIDGET(g->fixed));
+ gtk_scrolled_window_set_shadow_type(g->scrolledwindow,
+ GTK_SHADOW_NONE);
+ g->viewport = GTK_VIEWPORT(gtk_bin_get_child(GTK_BIN(g->scrolledwindow)));
+ /* Attach ourselves into our parent at the right point */
+ nsbeos_gui_window_attach_child(bw->parent->window, g);
+ } else {
+ g->scrolledwindow = 0;
+ g->viewport = GTK_VIEWPORT(gtk_viewport_new(NULL, NULL)); /* Need to attach adjustments */
+ gtk_container_add(GTK_CONTAINER(g->viewport), GTK_WIDGET(g->fixed));
+
+ /* Attach our viewport into the scaffold */
+ nsbeos_attach_toplevel_viewport(g->scaffold, g->viewport);
+ }
+
+ gtk_container_set_border_width(GTK_CONTAINER(g->viewport), 0);
+ gtk_viewport_set_shadow_type(g->viewport, GTK_SHADOW_NONE);
+ if (g->scrolledwindow)
+ gtk_widget_show(GTK_WIDGET(g->scrolledwindow));
+ /* And enable visibility from our viewport down */
+ gtk_widget_show(GTK_WIDGET(g->viewport));
+ gtk_widget_show(GTK_WIDGET(g->fixed));
+ gtk_widget_show(GTK_WIDGET(g->drawing_area));
+
+ switch(bw->scrolling) {
+ case SCROLLING_NO:
+ scrollpolicy = GTK_POLICY_NEVER;
+ break;
+ case SCROLLING_YES:
+ scrollpolicy = GTK_POLICY_ALWAYS;
+ break;
+ case SCROLLING_AUTO:
+ default:
+ scrollpolicy = GTK_POLICY_AUTOMATIC;
+ break;
+ };
+
+ switch(bw->browser_window_type) {
+ case BROWSER_WINDOW_FRAMESET:
+ if (g->scrolledwindow)
+ gtk_scrolled_window_set_policy(g->scrolledwindow,
+ GTK_POLICY_NEVER,
+ GTK_POLICY_NEVER);
+ break;
+ case BROWSER_WINDOW_FRAME:
+ if (g->scrolledwindow)
+ gtk_scrolled_window_set_policy(g->scrolledwindow,
+ scrollpolicy,
+ scrollpolicy);
+ break;
+ case BROWSER_WINDOW_NORMAL:
+ if (g->scrolledwindow)
+ gtk_scrolled_window_set_policy(g->scrolledwindow,
+ scrollpolicy,
+ scrollpolicy);
+ break;
+ case BROWSER_WINDOW_IFRAME:
+ if (g->scrolledwindow)
+ gtk_scrolled_window_set_policy(g->scrolledwindow,
+ scrollpolicy,
+ scrollpolicy);
+ break;
+ }
+
+ /* set the events we're interested in receiving from the browser's
+ * drawing area.
+ */
+ gtk_widget_add_events(GTK_WIDGET(g->drawing_area),
+ GDK_EXPOSURE_MASK |
+ GDK_LEAVE_NOTIFY_MASK |
+ GDK_BUTTON_PRESS_MASK |
+ GDK_POINTER_MOTION_MASK |
+ GDK_KEY_PRESS_MASK |
+ GDK_KEY_RELEASE_MASK);
+ GTK_WIDGET_SET_FLAGS(GTK_WIDGET(g->drawing_area), GTK_CAN_FOCUS);
+
+ /* set the default background colour of the drawing area to white. */
+ gtk_widget_modify_bg(GTK_WIDGET(g->drawing_area), GTK_STATE_NORMAL,
+ &((GdkColor) { 0, 0xffff, 0xffff, 0xffff } ));
+
+#define CONNECT(obj, sig, callback, ptr) \
+ g_signal_connect(G_OBJECT(obj), (sig), G_CALLBACK(callback), (ptr))
+ CONNECT(g->drawing_area, "expose_event", nsgtk_window_expose_event, g);
+ CONNECT(g->drawing_area, "motion_notify_event",
+ nsgtk_window_motion_notify_event, g);
+ CONNECT(g->drawing_area, "button_press_event",
+ nsgtk_window_button_press_event, g);
+ CONNECT(g->drawing_area, "key_press_event",
+ nsgtk_window_keypress_event, g);
+ CONNECT(g->viewport, "size_allocate",
+ nsgtk_window_size_allocate_event, g);
+#endif
+
+ return g;
+}
+
+static void nsbeos_gui_window_attach_child(struct gui_window *parent,
+ struct gui_window *child)
+{
+ /* Attach the child gui_window (frame) into the parent.
+ * It will be resized later on.
+ */
+ if (parent->view == NULL || child->view == NULL)
+ return;
+ if (!parent->view->LockLooper())
+ return;
+
+ //if (child->scrollview)
+ // parent->view->AddChild(child->scrollview);
+ //else
+ parent->view->AddChild(child->view);
+
+ // non-top-level views shouldn't resize automatically (?)
+ child->view->SetResizingMode(B_FOLLOW_NONE);
+
+ parent->view->UnlockLooper();
+
+#warning WRITEME
+#if 0 /* GTK */
+ /* Attach the child gui_window (frame) into the parent.
+ * It will be resized later on.
+ */
+ GtkFixed *parent_fixed = parent->fixed;
+ GtkWidget *child_widget = GTK_WIDGET(child->scrolledwindow);
+ gtk_fixed_put(parent_fixed, child_widget, 0, 0);
+#endif
+}
+
+void gui_window_position_frame(struct gui_window *g, int x0, int y0, int x1, int y1)
+{
+ CALLED();
+
+ /* g is a child frame, we need to place it relative to its parent */
+#warning XXX: BScrollView ?
+ BView *view = g->view;
+ BView *parent = g->bw->parent->window->view;
+ assert(view);
+ assert(parent);
+ LOG(("%s: %d,%d %dx%d", g->bw->name, x0, y0, x1-x0+2, y1-y0+2));
+
+ /* if the window has not changed position or size, do not bother
+ * moving/resising it.
+ */
+
+ if (!parent->LockLooper())
+ return;
+
+ LOG((" current: %d,%d %dx%d",
+ view->Frame().left, view->Frame().top,
+ view->Frame().Width() + 1, view->Frame().Height() + 1));
+
+ if (view->Frame().left != x0 || view->Frame().top != y0 ||
+ view->Frame().Width() + 1 != x1 - x0 + 2 ||
+ view->Frame().Height() + 1 != y1 - y0 + 2) {
+ LOG((" frame has moved/resized."));
+ view->MoveTo(x0, y0);
+ view->ResizeTo(x1 - x0 + 2 - 1, y1 - y0 + 2 - 1);
+ }
+
+ parent->UnlockLooper();
+#warning WRITEME
+#if 0 /* GTK */
+ /* g is a child frame, we need to place it relative to its parent */
+ GtkWidget *w = GTK_WIDGET(g->scrolledwindow);
+ GtkFixed *f = g->bw->parent->window->fixed;
+ assert(w);
+ assert(f);
+ LOG(("%s: %d,%d %dx%d", g->bw->name, x0, y0, x1-x0+2, y1-y0+2));
+
+ /* if the window has not changed position or size, do not bother
+ * moving/resising it.
+ */
+
+ LOG((" current: %d,%d %dx%d",
+ w->allocation.x, w->allocation.y,
+ w->allocation.width, w->allocation.height));
+
+ if (w->allocation.x != x0 || w->allocation.y != y0 ||
+ w->allocation.width != x1 - x0 + 2 ||
+ w->allocation.height != y1 - y0 + 2) {
+ LOG((" frame has moved/resized."));
+ gtk_fixed_move(f, w, x0, y0);
+ gtk_widget_set_size_request(w, x1 - x0 + 2, y1 - y0 + 2);
+ }
+#endif
+}
+
+void nsbeos_dispatch_event(BMessage *message)
+{
+ struct gui_window *gui = NULL;
+ NSBrowserFrameView *view = NULL;
+ struct beos_scaffolding *scaffold = NULL;
+ NSBrowserWindow *window = NULL;
+
+ message->PrintToStream();
+ if (message->FindPointer("View", (void **)&view) < B_OK)
+ view = NULL;
+ if (message->FindPointer("gui_window", (void **)&gui) < B_OK)
+ gui = NULL;
+ if (message->FindPointer("Window", (void **)&window) < B_OK)
+ window = NULL;
+ if (message->FindPointer("scaffolding", (void **)&scaffold) < B_OK)
+ scaffold = NULL;
+
+ struct gui_window *z;
+ for (z = window_list; z && gui && z != gui; z = z->next)
+ continue;
+
+ struct gui_window *y;
+ for (y = window_list; y && scaffold && y->scaffold != scaffold; y = y->next)
+ continue;
+
+ if (gui && gui != z) {
+ LOG(("discarding event for destroyed gui_window"));
+ return;
+ }
+ if (scaffold && (!y || scaffold != y->scaffold)) {
+ LOG(("discarding event for destroyed scaffolding"));
+ return;
+ }
+ //#warning XXX VALIDATE gui_window!!!
+
+ // messages for top-level
+ if (scaffold) {
+ LOG(("dispatching to top-level"));
+ nsbeos_scaffolding_dispatch_event(scaffold, message);
+ delete message;
+ return;
+ }
+
+ switch (message->what) {
+ case B_QUIT_REQUESTED:
+ // from the BApplication
+ netsurf_quit = true;
+ break;
+ case _UPDATE_:
+ if (gui && view)
+ nsbeos_window_expose_event(view, gui, message);
+ break;
+ case B_MOUSE_MOVED:
+ {
+ if (gui == NULL)
+ break;
+
+ BPoint where;
+ // where refers to Window coords !?
+ // check be:view_where first
+ if (message->FindPoint("be:view_where", &where) < B_OK) {
+ if (message->FindPoint("where", &where) < B_OK)
+ break;
+ }
+
+ browser_window_mouse_track(gui->bw, (browser_mouse_state)0,
+ (int)(where.x / gui->bw->scale),
+ (int)(where.y / gui->bw->scale));
+
+ gui->last_x = (int)where.x;
+ gui->last_y = (int)where.y;
+ break;
+ }
+ case B_MOUSE_DOWN:
+ {
+ if (gui == NULL)
+ break;
+
+ BPoint where;
+ int32 buttons;
+ BPoint screenWhere;
+ if (message->FindPoint("be:view_where", &where) < B_OK) {
+ if (message->FindPoint("where", &where) < B_OK)
+ break;
+ }
+ if (message->FindInt32("buttons", &buttons) < B_OK)
+ break;
+ if (message->FindPoint("screen_where", &screenWhere) < B_OK)
+ break;
+
+ browser_mouse_state button = BROWSER_MOUSE_CLICK_1;
+
+ if (buttons & B_TERTIARY_MOUSE_BUTTON) /* 3 == middle button on BeOS */
+ button = BROWSER_MOUSE_CLICK_2;
+
+ if (buttons & B_SECONDARY_MOUSE_BUTTON) {
+ /* 2 == right button on BeOS */
+
+ nsbeos_scaffolding_popup_menu(gui->scaffold, screenWhere);
+ break;
+ }
+
+ browser_window_mouse_click(gui->bw, button,
+ (int)(where.x / gui->bw->scale),
+ (int)(where.y / gui->bw->scale));
+
+ if (view && view->LockLooper()) {
+ view->MakeFocus();
+ view->UnlockLooper();
+ }
+ break;
+ }
+ case B_KEY_DOWN:
+ if (gui && view)
+ nsbeos_window_keypress_event(view, gui, message);
+ break;
+ case B_VIEW_RESIZED:
+ if (gui && view)
+ nsbeos_window_resize_event(view, gui, message);
+ break;
+ case B_VIEW_MOVED:
+ if (gui && view)
+ nsbeos_window_moved_event(view, gui, message);
+ break;
+ case B_MOUSE_WHEEL_CHANGED:
+ default:
+ break;
+ }
+ delete message;
+}
+
+void nsbeos_window_expose_event(BView *view, gui_window *g, BMessage *message)
+{
+ BRect updateRect;
+ struct content *c;
+ float scale = g->bw->scale;
+
+ assert(g);
+ assert(g->bw);
+
+ struct gui_window *z;
+ for (z = window_list; z && z != g; z = z->next)
+ continue;
+ assert(z);
+ assert(g->view == view);
+
+ if (message->FindRect("rect", &updateRect) < B_OK)
+ return;
+
+ c = g->bw->current_content;
+ if (c == NULL)
+ return;
+
+ /* HTML rendering handles scale itself */
+ if (c->type == CONTENT_HTML)
+ scale = 1;
+
+ if (!view->LockLooper())
+ return;
+ nsbeos_current_gc_set(view);
+
+ plot = nsbeos_plotters;
+ nsbeos_plot_set_scale(g->bw->scale);
+ content_redraw(c, 0, 0,
+ (view->Bounds().Width() + 1) * scale,
+ (view->Bounds().Height() + 1) * scale,
+ updateRect.left,
+ updateRect.top,
+ updateRect.right,
+ updateRect.bottom,
+ g->bw->scale, 0xFFFFFF);
+
+ if (g->careth != 0)
+ nsbeos_plot_caret(g->caretx, g->carety, g->careth);
+
+ // reset clipping just in case
+ view->ConstrainClippingRegion(NULL);
+ nsbeos_current_gc_set(NULL);
+ view->UnlockLooper();
+}
+
+void nsbeos_window_keypress_event(BView *view, gui_window *g, BMessage *event)
+{
+ const char *bytes;
+ char buff[6];
+ int numbytes = 0;
+ uint32 mods;
+ uint32 key;
+ uint32 raw_char;
+ uint32_t nskey;
+ int i;
+
+ if (event->FindInt32("modifiers", (int32 *)&mods) < B_OK)
+ mods = modifiers();
+ if (event->FindInt32("key", (int32 *)&key) < B_OK)
+ key = 0;
+ if (event->FindInt32("raw_char", (int32 *)&raw_char) < B_OK)
+ raw_char = 0;
+ /* check for byte[] first, because C-space gives bytes="" (and byte[0] = '\0') */
+ for (i = 0; i < 5; i++) {
+ buff[i] = '\0';
+ if (event->FindInt8("byte", i, (int8 *)&buff[i]) < B_OK)
+ break;
+ }
+
+ if (i) {
+ bytes = buff;
+ numbytes = i;
+ } else if (event->FindString("bytes", &bytes) < B_OK)
+ bytes = "";
+
+ if (!numbytes)
+ numbytes = strlen(bytes);
+
+
+ char byte;
+ if (numbytes == 1) {
+ byte = bytes[0];
+ if (mods & B_CONTROL_KEY)
+ byte = (char)raw_char;
+ if (byte >= '!' && byte <= '~')
+ nskey = (uint32_t)byte;
+ else {
+ switch (byte) {
+ case B_BACKSPACE: nskey = KEY_DELETE_LEFT; break;
+ case B_TAB: nskey = KEY_TAB; break;
+ /*case XK_Linefeed: return QKlinefeed;*/
+ case B_ENTER: nskey = (uint32_t)10; break;
+ case B_ESCAPE: nskey = (uint32_t)'\033'; break;
+ case B_SPACE: nskey = (uint32_t)' '; break;
+ case B_DELETE: nskey = KEY_DELETE_RIGHT; break;
+ /*
+ case B_INSERT: nskey = KEYSYM("insert"); break;
+ */
+ case B_HOME: nskey = KEY_LINE_START; break; // XXX ?
+ case B_END: nskey = KEY_LINE_END; break; // XXX ?
+ case B_PAGE_UP: nskey = KEY_PAGE_UP; break;
+ case B_PAGE_DOWN: nskey = KEY_PAGE_DOWN; break;
+ case B_LEFT_ARROW: nskey = KEY_LEFT; break;
+ case B_RIGHT_ARROW: nskey = KEY_RIGHT; break;
+ case B_UP_ARROW: nskey = KEY_UP; break;
+ case B_DOWN_ARROW: nskey = KEY_DOWN; break;
+ /*
+ case B_FUNCTION_KEY:
+ switch (scancode) {
+ case B_F1_KEY: nskey = KEYSYM("f1"); break;
+ case B_F2_KEY: nskey = KEYSYM("f2"); break;
+ case B_F3_KEY: nskey = KEYSYM("f3"); break;
+ case B_F4_KEY: nskey = KEYSYM("f4"); break;
+ case B_F5_KEY: nskey = KEYSYM("f5"); break;
+ case B_F6_KEY: nskey = KEYSYM("f6"); break;
+ case B_F7_KEY: nskey = KEYSYM("f7"); break;
+ case B_F8_KEY: nskey = KEYSYM("f8"); break;
+ case B_F9_KEY: nskey = KEYSYM("f9"); break;
+ case B_F10_KEY: nskey = KEYSYM("f10"); break;
+ case B_F11_KEY: nskey = KEYSYM("f11"); break;
+ case B_F12_KEY: nskey = KEYSYM("f12"); break;
+ case B_PRINT_KEY: nskey = KEYSYM("print"); break;
+ case B_SCROLL_KEY: nskey = KEYSYM("scroll-lock"); break;
+ case B_PAUSE_KEY: nskey = KEYSYM("pause"); break;
+ }
+ */
+ case 0:
+ nskey = (uint32_t)0;
+ default:
+ nskey = (uint32_t)raw_char;
+ /*if (simple_p)
+ nskey = (uint32_t)0;*/
+ break;
+ }
+ }
+ } else {
+ // XXX is raw_char actually UCS ??
+ nskey = (uint32_t)raw_char;
+ // else use convert_from_utf8()
+ }
+
+ if (browser_window_key_press(g->bw, nskey))
+ return;
+
+}
+
+#warning WRITEME
+#if 0 /* GTK */
+gboolean nsbeos_window_keypress_event(GtkWidget *widget, GdkEventKey *event,
+ gpointer data)
+{
+ struct gui_window *g = data;
+ uint32_t nskey = gdkkey_to_nskey(event);
+
+ if (browser_window_key_press(g->bw, nskey))
+ return TRUE;
+
+ if (event->state == 0) {
+ double value;
+ GtkAdjustment *vscroll = gtk_viewport_get_vadjustment(g->viewport);
+
+ GtkAdjustment *hscroll = gtk_viewport_get_hadjustment(g->viewport);
+
+ GtkAdjustment *scroll;
+
+ const GtkAllocation *const alloc =
+ &GTK_WIDGET(g->viewport)->allocation;
+
+ switch (event->keyval) {
+ default:
+ return TRUE;
+
+ case GDK_Home:
+ case GDK_KP_Home:
+ scroll = vscroll;
+ value = scroll->lower;
+ break;
+
+ case GDK_End:
+ case GDK_KP_End:
+ scroll = vscroll;
+ value = scroll->upper - alloc->height;
+ if (value < scroll->lower)
+ value = scroll->lower;
+ break;
+
+ case GDK_Left:
+ case GDK_KP_Left:
+ scroll = hscroll;
+ value = gtk_adjustment_get_value(scroll) -
+ scroll->step_increment;
+ if (value < scroll->lower)
+ value = scroll->lower;
+ break;
+
+ case GDK_Up:
+ case GDK_KP_Up:
+ scroll = vscroll;
+ value = gtk_adjustment_get_value(scroll) -
+ scroll->step_increment;
+ if (value < scroll->lower)
+ value = scroll->lower;
+ break;
+
+ case GDK_Right:
+ case GDK_KP_Right:
+ scroll = hscroll;
+ value = gtk_adjustment_get_value(scroll) +
+ scroll->step_increment;
+ if (value > scroll->upper - alloc->width)
+ value = scroll->upper - alloc->width;
+ break;
+
+ case GDK_Down:
+ case GDK_KP_Down:
+ scroll = vscroll;
+ value = gtk_adjustment_get_value(scroll) +
+ scroll->step_increment;
+ if (value > scroll->upper - alloc->height)
+ value = scroll->upper - alloc->height;
+ break;
+
+ case GDK_Page_Up:
+ case GDK_KP_Page_Up:
+ scroll = vscroll;
+ value = gtk_adjustment_get_value(scroll) -
+ scroll->page_increment;
+ if (value < scroll->lower)
+ value = scroll->lower;
+ break;
+
+ case GDK_Page_Down:
+ case GDK_KP_Page_Down:
+ scroll = vscroll;
+ value = gtk_adjustment_get_value(scroll) +
+ scroll->page_increment;
+ if (value > scroll->upper - alloc->height)
+ value = scroll->upper - alloc->height;
+ break;
+ }
+
+ gtk_adjustment_set_value(scroll, value);
+ }
+
+ return TRUE;
+}
+
+#endif
+
+void nsbeos_window_resize_event(BView *view, gui_window *g, BMessage *event)
+{
+ CALLED();
+ int32 width;
+ int32 height;
+
+ // drop this event if we have at least 2 resize pending
+#if 1
+ if (atomic_add(&g->pending_resizes, -1) > 1)
+ return;
+#endif
+
+ if (event->FindInt32("width", &width) < B_OK)
+ width = -1;
+ if (event->FindInt32("height", &height) < B_OK)
+ height = -1;
+ width++;
+ height++;
+
+
+#if 0
+ struct content *content;
+
+ content = g->bw->current_content;
+
+ /* reformat or change extent if necessary */
+ if ((content) && (g->old_width != width || g->old_height != height)) {
+ /* Ctrl-resize of a top-level window scales the content size */
+#if 0
+ if ((g->old_width > 0) && (g->old_width != width) && (!g->bw->parent) &&
+ (ro_gui_ctrl_pressed()))
+ new_scale = (g->bw->scale * width) / g->old_width;
+#endif
+ g->bw->reformat_pending = true;
+ browser_reformat_pending = true;
+ }
+ if (g->update_extent || g->old_width != width || g->old_height != height) {
+ g->old_width = width;
+ g->old_height = height;
+ g->update_extent = false;
+ gui_window_set_extent(g, width, height);
+ }
+#endif
+ g->bw->reformat_pending = true;
+ browser_reformat_pending = true;
+
+ return;
+}
+
+
+void nsbeos_window_moved_event(BView *view, gui_window *g, BMessage *event)
+{
+ CALLED();
+
+#warning XXX: Invalidate ?
+ if (!view || !view->LockLooper())
+ return;
+ //view->Invalidate(view->Bounds());
+ view->UnlockLooper();
+
+ //g->bw->reformat_pending = true;
+ //browser_reformat_pending = true;
+
+
+ return;
+}
+
+
+void nsbeos_reflow_all_windows(void)
+{
+ for (struct gui_window *g = window_list; g; g = g->next)
+ g->bw->reformat_pending = true;
+
+ browser_reformat_pending = true;
+}
+
+
+/**
+ * Process pending reformats
+ */
+
+void nsbeos_window_process_reformats(void)
+{
+ struct gui_window *g;
+
+ browser_reformat_pending = false;
+ for (g = window_list; g; g = g->next) {
+ NSBrowserFrameView *view = g->view;
+ if (!g->bw->reformat_pending)
+ continue;
+ if (!view || !view->LockLooper())
+ continue;
+ g->bw->reformat_pending = false;
+ BRect bounds = view->Bounds();
+ view->UnlockLooper();
+#warning XXX why - 1 & - 2 !???
+ browser_window_reformat(g->bw,
+ bounds.Width() + 1 - 1 /* - 2*/,
+ bounds.Height() + 1 - 1);
+ }
+
+#warning WRITEME
+#if 0 /* GTK */
+ for (g = window_list; g; g = g->next) {
+ GtkWidget *widget = GTK_WIDGET(g->viewport);
+ if (!g->bw->reformat_pending)
+ continue;
+ g->bw->reformat_pending = false;
+ browser_window_reformat(g->bw,
+ widget->allocation.width - 2,
+ widget->allocation.height);
+ }
+#endif
+}
+
+
+void nsbeos_window_destroy_browser(struct gui_window *g)
+{
+ browser_window_destroy(g->bw);
+}
+
+void gui_window_destroy(struct gui_window *g)
+{
+ if (g->prev)
+ g->prev->next = g->next;
+ else
+ window_list = g->next;
+
+ if (g->next)
+ g->next->prev = g->prev;
+
+
+ LOG(("Destroying gui_window %p", g));
+ assert(g != NULL);
+ assert(g->bw != NULL);
+ LOG((" Scaffolding: %p", g->scaffold));
+ LOG((" Window name: %s", g->bw->name));
+
+ if (g->view == NULL)
+ return;
+ if (!g->view->LockLooper())
+ return;
+
+ BLooper *looper = g->view->Looper();
+ /* If we're a top-level gui_window, destroy our scaffold */
+ if (g->toplevel) {
+ g->view->RemoveSelf();
+ delete g->view;
+ nsbeos_scaffolding_destroy(g->scaffold);
+ } else {
+ g->view->RemoveSelf();
+ delete g->view;
+ looper->Unlock();
+ }
+ //XXX
+ //looper->Unlock();
+
+#warning FIXME
+
+#if 0 /* GTK */
+ /* If we're a top-level gui_window, destroy our scaffold */
+ if (g->scrolledwindow == NULL) {
+ gtk_widget_destroy(GTK_WIDGET(g->viewport));
+ nsgtk_scaffolding_destroy(g->scaffold);
+ } else {
+ gtk_widget_destroy(GTK_WIDGET(g->scrolledwindow));
+ }
+#endif
+
+ free(g);
+
+}
+
+void nsbeos_redraw_caret(struct gui_window *g)
+{
+ if (g->careth == 0)
+ return;
+
+ gui_window_redraw(g, g->caretx, g->carety,
+ g->caretx, g->carety + g->careth);
+}
+
+void gui_window_redraw(struct gui_window *g, int x0, int y0, int x1, int y1)
+{
+ if (g->view == NULL)
+ return;
+ if (!g->view->LockLooper())
+ return;
+
+ nsbeos_current_gc_set(g->view);
+
+//XXX +1 ??
+ g->view->Invalidate(BRect(x0, y0, x1, y1));
+
+ nsbeos_current_gc_set(NULL);
+ g->view->UnlockLooper();
+}
+
+void gui_window_redraw_window(struct gui_window *g)
+{
+ if (g->view == NULL)
+ return;
+ if (!g->view->LockLooper())
+ return;
+
+ nsbeos_current_gc_set(g->view);
+
+ g->view->Invalidate();
+
+ nsbeos_current_gc_set(NULL);
+ g->view->UnlockLooper();
+}
+
+void gui_window_update_box(struct gui_window *g,
+ const union content_msg_data *data)
+{
+ struct content *c = g->bw->current_content;
+
+ if (c == NULL)
+ return;
+
+ if (g->view == NULL)
+ return;
+ if (!g->view->LockLooper())
+ return;
+
+ nsbeos_current_gc_set(g->view);
+
+//XXX +1 ??
+ g->view->Invalidate(BRect(data->redraw.x, data->redraw.y,
+ data->redraw.x + data->redraw.width - 1,
+ data->redraw.y + data->redraw.height - 1));
+
+ nsbeos_current_gc_set(NULL);
+ g->view->UnlockLooper();
+}
+
+bool gui_window_get_scroll(struct gui_window *g, int *sx, int *sy)
+{
+ CALLED();
+ if (g->view == NULL)
+ return false;
+ if (!g->view->LockLooper())
+ return false;
+
+#warning XXX: report to view frame ?
+ if (g->view->ScrollBar(B_HORIZONTAL))
+ *sx = (int)g->view->ScrollBar(B_HORIZONTAL)->Value();
+ if (g->view->ScrollBar(B_VERTICAL))
+ *sy = (int)g->view->ScrollBar(B_VERTICAL)->Value();
+
+ g->view->UnlockLooper();
+#warning WRITEME
+#if 0 /* GTK */
+ GtkAdjustment *vadj = gtk_viewport_get_vadjustment(g->viewport);
+ GtkAdjustment *hadj = gtk_viewport_get_hadjustment(g->viewport);
+
+ assert(vadj);
+ assert(hadj);
+
+ *sy = (int)(gtk_adjustment_get_value(vadj));
+ *sx = (int)(gtk_adjustment_get_value(hadj));
+
+#endif
+ return true;
+}
+
+void gui_window_set_scroll(struct gui_window *g, int sx, int sy)
+{
+ CALLED();
+ if (g->view == NULL)
+ return;
+ if (!g->view->LockLooper())
+ return;
+
+#warning XXX: report to view frame ?
+ if (g->view->ScrollBar(B_HORIZONTAL))
+ g->view->ScrollBar(B_HORIZONTAL)->SetValue(sx);
+ if (g->view->ScrollBar(B_VERTICAL))
+ g->view->ScrollBar(B_VERTICAL)->SetValue(sy);
+
+ g->view->UnlockLooper();
+#warning WRITEME
+#if 0 /* GTK */
+ GtkAdjustment *vadj = gtk_viewport_get_vadjustment(g->viewport);
+ GtkAdjustment *hadj = gtk_viewport_get_hadjustment(g->viewport);
+ gdouble vlower, vpage, vupper, hlower, hpage, hupper, x = (double)sx, y = (double)sy;
+
+ assert(vadj);
+ assert(hadj);
+
+ g_object_get(vadj, "page-size", &vpage, "lower", &vlower, "upper", &vupper, NULL);
+ g_object_get(hadj, "page-size", &hpage, "lower", &hlower, "upper", &hupper, NULL);
+
+ if (x < hlower)
+ x = hlower;
+ if (x > (hupper - hpage))
+ x = hupper - hpage;
+ if (y < vlower)
+ y = vlower;
+ if (y > (vupper - vpage))
+ y = vupper - vpage;
+
+ gtk_adjustment_set_value(vadj, y);
+ gtk_adjustment_set_value(hadj, x);
+#endif
+}
+
+
+/**
+ * Set the scale setting of a window
+ *
+ * \param g gui window
+ * \param scale scale value (1.0 == normal scale)
+ */
+
+void gui_window_set_scale(struct gui_window *g, float scale)
+{
+}
+
+
+void gui_window_update_extent(struct gui_window *g)
+{
+ CALLED();
+ if (!g->bw->current_content)
+ return;
+
+ if (g->view == NULL)
+ return;
+ if (!g->view->LockLooper())
+ return;
+
+ float x_max = g->bw->current_content->width * g->bw->scale /* - 1*/;
+ float y_max = g->bw->current_content->height * g->bw->scale /* - 1*/;
+ float x_prop = g->view->Bounds().Width() / x_max;
+ float y_prop = g->view->Bounds().Height() / y_max;
+ x_max -= g->view->Bounds().Width() + 1;
+ y_max -= g->view->Bounds().Height() + 1;
+printf("x_max = %f y_max = %f x_prop = %f y_prop = %f\n", x_max, y_max, x_prop, y_prop);
+ if (g->view->ScrollBar(B_HORIZONTAL)) {
+ g->view->ScrollBar(B_HORIZONTAL)->SetRange(0, x_max);
+ g->view->ScrollBar(B_HORIZONTAL)->SetProportion(x_prop);
+ g->view->ScrollBar(B_HORIZONTAL)->SetSteps(10, 50);
+ }
+ if (g->view->ScrollBar(B_VERTICAL)) {
+ g->view->ScrollBar(B_VERTICAL)->SetRange(0, y_max);
+ g->view->ScrollBar(B_VERTICAL)->SetProportion(y_prop);
+ g->view->ScrollBar(B_VERTICAL)->SetSteps(10, 50);
+ }
+
+#if 0
+ g->view->ResizeTo(
+ g->bw->current_content->width * g->bw->scale /* - 1*/,
+ g->bw->current_content->height * g->bw->scale /* - 1*/);
+#endif
+
+ g->view->UnlockLooper();
+
+#warning WRITEME
+#if 0 /* GTK */
+ gtk_widget_set_size_request(GTK_WIDGET(g->drawing_area),
+ g->bw->current_content->width * g->bw->scale,
+ g->bw->current_content->height * g->bw->scale);
+
+ gtk_widget_set_size_request(GTK_WIDGET(g->viewport), 0, 0);
+#endif
+}
+
+/* some cursors like those in Firefox */
+// XXX: move to separate file or resource ?
+
+const uint8 kLinkCursorBits[] = {
+ 16, /* cursor size */
+ 1, /* bits per pixel */
+ 2, /* vertical hot spot */
+ 2, /* horizontal hot spot */
+
+ /* data */
+ 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x24, 0x00, 0x24, 0x00, 0x13, 0xe0, 0x12, 0x5c, 0x09, 0x2a,
+ 0x08, 0x01, 0x3c, 0x21, 0x4c, 0x71, 0x42, 0x71, 0x30, 0xf9, 0x0c, 0xf9, 0x02, 0x02, 0x01, 0x00,
+
+ /* mask */
+ 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x1f, 0xe0, 0x1f, 0xfc, 0x0f, 0xfe,
+ 0x0f, 0xff, 0x3f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x3f, 0xff, 0x0f, 0xff, 0x03, 0xfc, 0x01, 0xe0
+};
+
+const uint8 kWatchCursorBits[] = {
+ 16, /* cursor size */
+ 1, /* bits per pixel */
+ 0, /* vertical hot spot */
+ 1, /* horizontal hot spot */
+
+ /* data */
+ 0x70, 0x00, 0x48, 0x00, 0x48, 0x00, 0x27, 0xc0, 0x24, 0xb8, 0x12, 0x54, 0x10, 0x02, 0x78, 0x02,
+ 0x98, 0x02, 0x84, 0x02, 0x60, 0x3a, 0x18, 0x46, 0x04, 0x8a, 0x02, 0x92, 0x01, 0x82, 0x00, 0x45,
+
+ /* mask */
+ 0x70, 0x00, 0x78, 0x00, 0x78, 0x00, 0x3f, 0xc0, 0x3f, 0xf8, 0x1f, 0xfc, 0x1f, 0xfe, 0x7f, 0xfe,
+ 0xff, 0xfe, 0xff, 0xfe, 0x7f, 0xfe, 0x1f, 0xfe, 0x07, 0xfe, 0x03, 0xfe, 0x01, 0xfe, 0x00, 0x7f
+};
+
+const uint8 kWatch2CursorBits[] = {
+ 16, /* cursor size */
+ 1, /* bits per pixel */
+ 0, /* vertical hot spot */
+ 1, /* horizontal hot spot */
+
+ /* data */
+ 0x70, 0x00, 0x48, 0x00, 0x48, 0x00, 0x27, 0xc0, 0x24, 0xb8, 0x12, 0x54, 0x10, 0x02, 0x78, 0x02,
+ 0x98, 0x02, 0x84, 0x02, 0x60, 0x3a, 0x18, 0x46, 0x04, 0xa2, 0x02, 0x92, 0x01, 0xa2, 0x00, 0x45,
+
+ /* mask */
+ 0x70, 0x00, 0x78, 0x00, 0x78, 0x00, 0x3f, 0xc0, 0x3f, 0xf8, 0x1f, 0xfc, 0x1f, 0xfe, 0x7f, 0xfe,
+ 0xff, 0xfe, 0xff, 0xfe, 0x7f, 0xfe, 0x1f, 0xfe, 0x07, 0xfe, 0x03, 0xfe, 0x01, 0xfe, 0x00, 0x7f
+};
+
+
+#if 0 /* GTK */
+static GdkCursor *nsbeos_create_menu_cursor(void)
+{
+ static char menu_cursor_bits[] = {
+ 0x00, 0x00, 0x80, 0x7F, 0x88, 0x40, 0x9E, 0x5E, 0x88, 0x40, 0x80, 0x56,
+ 0x80, 0x40, 0x80, 0x5A, 0x80, 0x40, 0x80, 0x5E, 0x80, 0x40, 0x80, 0x56,
+ 0x80, 0x40, 0x80, 0x7F, 0x00, 0x00, 0x00, 0x00, };
+
+ static char menu_cursor_mask_bits[] = {
+ 0xC0, 0xFF, 0xC8, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xC8, 0xFF,
+ 0xC0, 0xFF, 0xC0, 0xFF, 0xC0, 0xFF, 0xC0, 0xFF, 0xC0, 0xFF, 0xC0, 0xFF,
+ 0xC0, 0xFF, 0xC0, 0xFF, 0xC0, 0xFF, 0x00, 0x00, };
+
+ static GdkCursor *r;
+ static GdkColor fg = { 0, 0, 0, 0 };
+ static GdkColor bg = { 0, 65535, 65535, 65535 };
+
+ GdkPixmap *source, *mask;
+
+ if (r != NULL)
+ return r;
+
+ source = gdk_bitmap_create_from_data(NULL, menu_cursor_bits,
+ 16, 16);
+ mask = gdk_bitmap_create_from_data (NULL, menu_cursor_mask_bits,
+ 16, 16);
+
+ r = gdk_cursor_new_from_pixmap(source, mask, &fg, &bg, 8, 8);
+ gdk_pixmap_unref(source);
+ gdk_pixmap_unref(mask);
+
+ return r;
+}
+#endif
+
+void gui_window_set_pointer(struct gui_window *g, gui_pointer_shape shape)
+{
+ BCursor *cursor = NULL;
+ bool allocated = false;
+
+ if (g->current_pointer == shape)
+ return;
+
+ g->current_pointer = shape;
+
+ switch (shape) {
+ case GUI_POINTER_POINT:
+ cursor = new BCursor(kLinkCursorBits);
+ allocated = true;
+#if 0 // it's ugly anyway
+#ifdef B_ZETA_VERSION
+ cursor = (BCursor *)B_CURSOR_LINK;
+#endif
+#endif
+ break;
+ case GUI_POINTER_CARET:
+ cursor = (BCursor *)B_CURSOR_I_BEAM;
+ break;
+ case GUI_POINTER_WAIT:
+ cursor = new BCursor(kWatchCursorBits);
+ allocated = true;
+ break;
+ case GUI_POINTER_PROGRESS:
+ cursor = new BCursor(kWatch2CursorBits);
+ allocated = true;
+ break;
+#if 0 /* GTK */
+ case GUI_POINTER_UP:
+ cursortype = GDK_TOP_SIDE;
+ break;
+ case GUI_POINTER_DOWN:
+ cursortype = GDK_BOTTOM_SIDE;
+ break;
+ case GUI_POINTER_LEFT:
+ cursortype = GDK_LEFT_SIDE;
+ break;
+ case GUI_POINTER_RIGHT:
+ cursortype = GDK_RIGHT_SIDE;
+ break;
+ case GUI_POINTER_LD:
+ cursortype = GDK_BOTTOM_LEFT_CORNER;
+ break;
+ case GUI_POINTER_RD:
+ cursortype = GDK_BOTTOM_RIGHT_CORNER;
+ break;
+ case GUI_POINTER_LU:
+ cursortype = GDK_TOP_LEFT_CORNER;
+ break;
+ case GUI_POINTER_RU:
+ cursortype = GDK_TOP_RIGHT_CORNER;
+ break;
+ case GUI_POINTER_CROSS:
+ cursortype = GDK_CROSS;
+ break;
+ case GUI_POINTER_MOVE:
+ cursortype = GDK_FLEUR;
+ break;
+ case GUI_POINTER_WAIT:
+ cursortype = GDK_WATCH;
+ break;
+ case GUI_POINTER_HELP:
+ cursortype = GDK_QUESTION_ARROW;
+ break;
+ case GUI_POINTER_MENU:
+ cursor = nsbeos_create_menu_cursor();
+ nullcursor = true;
+ break;
+ case GUI_POINTER_PROGRESS:
+ /* In reality, this needs to be the funky left_ptr_watch
+ * which we can't do easily yet.
+ */
+ cursortype = GDK_WATCH;
+ break;
+ /* The following we're not sure about */
+ case GUI_POINTER_NO_DROP:
+ case GUI_POINTER_NOT_ALLOWED:
+ case GUI_POINTER_DEFAULT:
+#endif
+ default:
+ cursor = (BCursor *)B_CURSOR_SYSTEM_DEFAULT;
+ allocated = false;
+ }
+
+ if (g->view && g->view->LockLooper()) {
+ g->view->SetViewCursor(cursor);
+ g->view->UnlockLooper();
+ }
+
+ if (allocated)
+ delete cursor;
+}
+
+void gui_window_hide_pointer(struct gui_window *g)
+{
+ //XXX no BView::HideCursor... use empty one
+}
+
+void gui_window_place_caret(struct gui_window *g, int x, int y, int height)
+{
+ CALLED();
+ if (g->view == NULL)
+ return;
+ if (!g->view->LockLooper())
+ return;
+
+ nsbeos_redraw_caret(g);
+
+ g->caretx = x;
+ g->carety = y + 1;
+ g->careth = height - 2;
+
+ nsbeos_redraw_caret(g);
+ g->view->MakeFocus();
+
+ g->view->UnlockLooper();
+}
+
+void gui_window_remove_caret(struct gui_window *g)
+{
+ int oh = g->careth;
+
+ if (oh == 0)
+ return;
+
+ g->careth = 0;
+
+ gui_window_redraw(g, g->caretx, g->carety,
+ g->caretx, g->carety + oh);
+}
+
+void gui_window_new_content(struct gui_window *g)
+{
+ if (!g->toplevel)
+ return;
+
+ if (g->view == NULL)
+ return;
+ if (!g->view->LockLooper())
+ return;
+
+ // scroll back to top
+ g->view->ScrollTo(0,0);
+
+ g->view->UnlockLooper();
+}
+
+bool gui_window_scroll_start(struct gui_window *g)
+{
+ return true;
+}
+
+bool gui_window_box_scroll_start(struct gui_window *g,
+ int x0, int y0, int x1, int y1)
+{
+ return true;
+}
+
+void gui_drag_save_object(gui_save_type type, struct content *c,
+ struct gui_window *g)
+{
+
+}
+
+void gui_drag_save_selection(struct selection *s, struct gui_window *g)
+{
+
+}
+
+void gui_start_selection(struct gui_window *g)
+{
+
+}
+
+void gui_paste_from_clipboard(struct gui_window *g, int x, int y)
+{
+
+}
+
+bool gui_empty_clipboard(void)
+{
+ return true;
+}
+
+bool gui_add_to_clipboard(const char *text, size_t length, bool space)
+{
+ return true;
+}
+
+bool gui_commit_clipboard(void)
+{
+ return true;
+}
+
+
+bool gui_copy_to_clipboard(struct selection *s)
+{
+ return true;
+}
+
+
+void gui_window_get_dimensions(struct gui_window *g, int *width, int *height,
+ bool scaled)
+{
+ if (g->view && g->view->LockLooper()) {
+ *width = g->view->Bounds().Width() + 1;
+ *height = g->view->Bounds().Height() + 1;
+ g->view->UnlockLooper();
+ }
+
+ if (scaled) {
+ *width /= g->bw->scale;
+ *height /= g->bw->scale;
+ }
+}
+
+bool gui_window_frame_resize_start(struct gui_window *g)
+{
+ return true;
+}
diff --git a/beos/beos_window.h b/beos/beos_window.h
new file mode 100644
index 000000000..6dd3ecdd7
--- /dev/null
+++ b/beos/beos_window.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2006 Daniel Silverstone <dsilvers@digital-scurf.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_BEOS_WINDOW_H
+#define NETSURF_BEOS_WINDOW_H 1
+
+extern "C" {
+#include "desktop/gui.h"
+#include "desktop/browser.h"
+}
+#include "beos/beos_scaffolding.h"
+
+class NSBrowserFrameView : public BView {
+public:
+ NSBrowserFrameView(BRect frame, struct gui_window *gui);
+virtual ~NSBrowserFrameView();
+
+virtual void MessageReceived(BMessage *message);
+virtual void Draw(BRect updateRect);
+
+//virtual void FrameMoved(BPoint new_location);
+virtual void FrameResized(float new_width, float new_height);
+
+virtual void KeyDown(const char *bytes, int32 numBytes);
+virtual void MouseDown(BPoint where);
+virtual void MouseUp(BPoint where);
+virtual void MouseMoved(BPoint where, uint32 transit, const BMessage *msg);
+
+private:
+ struct gui_window *fGuiWindow;
+};
+
+void nsbeos_dispatch_event(BMessage *message);
+
+
+
+void nsbeos_reflow_all_windows(void);
+void nsbeos_window_process_reformats(void);
+
+nsbeos_scaffolding *nsbeos_get_scaffold(struct gui_window *g);
+struct browser_window *nsbeos_get_browser_for_gui(struct gui_window *g);
+
+float nsbeos_get_scale_for_gui(struct gui_window *g);
+int nsbeos_gui_window_update_targets(struct gui_window *g);
+void nsbeos_window_destroy_browser(struct gui_window *g);
+
+struct browser_window *nsbeos_get_browser_window(struct gui_window *g);
+
+#endif /* NETSURF_BEOS_WINDOW_H */
diff --git a/beos/options.h b/beos/options.h
new file mode 100644
index 000000000..f98d2a467
--- /dev/null
+++ b/beos/options.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2006 Rob Kendrick <rjek@rjek.com>
+ *
+ * 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_BEOS_OPTIONS_H_
+#define _NETSURF_BEOS_OPTIONS_H_
+
+#include "desktop/options.h"
+
+extern bool option_render_cairo;
+extern bool option_render_resample;
+extern char *option_url_file;
+
+#define EXTRA_OPTION_DEFINE \
+bool option_render_cairo = true; \
+bool option_render_resample = false; \
+char *option_url_file = 0;
+
+#define EXTRA_OPTION_TABLE \
+{ "render_cairo", OPTION_BOOL, &option_render_cairo }, \
+{ "render_resample", OPTION_BOOL, &option_render_resample }, \
+{ "url_file", OPTION_STRING, &option_url_file },
+#endif
diff --git a/beos/res/adblock.css b/beos/res/adblock.css
new file mode 120000
index 000000000..e3811f62b
--- /dev/null
+++ b/beos/res/adblock.css
@@ -0,0 +1 @@
+../../!NetSurf/Resources/AdBlock,f79 \ No newline at end of file
diff --git a/beos/res/beosdefault.css b/beos/res/beosdefault.css
new file mode 100644
index 000000000..9021eedd9
--- /dev/null
+++ b/beos/res/beosdefault.css
@@ -0,0 +1,21 @@
+/*
+ * This file is part of NetSurf, http://netsurf-browser.org/
+ */
+
+/* Load base stylesheet. */
+
+@import "default.css";
+
+/* Apply GTK specific rules. */
+
+input { font-size: 95%; border: medium inset #ddd; }
+input[type=button], input[type=reset], input[type=submit], button {
+ background-color: #ddd; border: medium outset #ddd; }
+input[type=checkbox], input[type=radio] { font-size: 105%; }
+input[type=file] { background-color: #ddd; border: medium inset #ddd; }
+
+select { background-color: #ddd; border: medium inset #ddd; font-size: 95%; }
+select:after { border-left:4px ridge #ddd; }
+
+textarea { font-size: 95%; border: medium inset #ddd; }
+
diff --git a/beos/res/ca-bundle.txt b/beos/res/ca-bundle.txt
new file mode 120000
index 000000000..ad2dd6b55
--- /dev/null
+++ b/beos/res/ca-bundle.txt
@@ -0,0 +1 @@
+../../!NetSurf/Resources/ca-bundle \ No newline at end of file
diff --git a/beos/res/default.css b/beos/res/default.css
new file mode 120000
index 000000000..6d2d4da5b
--- /dev/null
+++ b/beos/res/default.css
@@ -0,0 +1 @@
+../../!NetSurf/Resources/CSS,f79 \ No newline at end of file
diff --git a/beos/res/messages b/beos/res/messages
new file mode 120000
index 000000000..f4a4d2bba
--- /dev/null
+++ b/beos/res/messages
@@ -0,0 +1 @@
+../../!NetSurf/Resources/en/Messages \ No newline at end of file
diff --git a/beos/res/netsurf.xpm b/beos/res/netsurf.xpm
new file mode 100644
index 000000000..7061727d6
--- /dev/null
+++ b/beos/res/netsurf.xpm
@@ -0,0 +1,317 @@
+/* XPM */
+static char *netsurf[] = {
+/* columns rows colors chars-per-pixel */
+"132 135 176 2",
+" c black",
+". c #010101",
+"X c #010202",
+"o c #030406",
+"O c #040A0D",
+"+ c #060E14",
+"@ c #08141A",
+"# c #081720",
+"$ c #091B27",
+"% c #0F2430",
+"& c #142E3D",
+"* c #143548",
+"= c #153C53",
+"- c #194662",
+"; c #1E516E",
+": c #1D577A",
+"> c #175B87",
+", c #1A6595",
+"< c #1E6B9C",
+"1 c #26709C",
+"2 c #33789E",
+"3 c #3188BD",
+"4 c #3E89B3",
+"5 c #1F92DD",
+"6 c #0E9CFD",
+"7 c #0E9DFF",
+"8 c #0F9EFF",
+"9 c #1A95E7",
+"0 c #1898ED",
+"q c #1299F4",
+"w c #119BF9",
+"e c #119FFF",
+"r c #14A0FF",
+"t c #15A1FF",
+"y c #17A2FF",
+"u c #18A3FF",
+"i c #1AA3FE",
+"p c #1BA4FE",
+"a c #1CA5FE",
+"s c #1EA5FE",
+"d c #1FA6FE",
+"f c #268AC9",
+"g c #218ED3",
+"h c #20A6FE",
+"j c #21A7FE",
+"k c #23A8FE",
+"l c #24A8FE",
+"z c #25A8FE",
+"x c #26A9FE",
+"c c #27AAFE",
+"v c #28AAFE",
+"b c #2AABFF",
+"n c #2BACFF",
+"m c #2CADFF",
+"M c #2EAEFF",
+"N c #2FAEFF",
+"B c #31AFFE",
+"V c #31AFFF",
+"C c #32B0FF",
+"Z c #34B1FF",
+"A c #35B2FF",
+"S c #36B2FF",
+"D c #37B2FF",
+"F c #3AB2FB",
+"G c #38B3FE",
+"H c #39B3FE",
+"J c #3AB3FC",
+"K c #3BB4FE",
+"L c #3CB5FE",
+"P c #3DB5FE",
+"I c #3EB6FF",
+"U c #3FB7FF",
+"Y c #4182A4",
+"T c #4789AB",
+"R c #43B7FB",
+"E c #40B7FF",
+"W c #44B6FA",
+"Q c #42B8FE",
+"! c #44B9FE",
+"~ c #46BAFF",
+"^ c #47BAFF",
+"/ c #48BBFF",
+"( c #49BCFF",
+") c #4ABCFF",
+"_ c #4CBDFF",
+"` c #4EBEFF",
+"' c #50BFFE",
+"] c #50BFFF",
+"[ c #51BFFF",
+"{ c #5ABFF7",
+"} c #52C0FE",
+"| c #54C1FE",
+" . c #56C2FF",
+".. c #57C3FF",
+"X. c #58C3FE",
+"o. c #58C3FF",
+"O. c #5CC1F8",
+"+. c #5DC4FD",
+"@. c #5CC5FE",
+"#. c #5DC5FE",
+"$. c #5DC6FF",
+"%. c #5EC6FF",
+"&. c #5FC7FF",
+"*. c #61C8FF",
+"=. c #62C8FF",
+"-. c #63C9FF",
+";. c #65CAFF",
+":. c #66CBFF",
+">. c #67CBFF",
+",. c #68CCFF",
+"<. c #69CDFF",
+"1. c #6BCDFF",
+"2. c #6CCEFF",
+"3. c #6DCEFF",
+"4. c #6FCFFF",
+"5. c #70D0FF",
+"6. c #72D1FF",
+"7. c #73D1FF",
+"8. c #74D2FF",
+"9. c #76D3FF",
+"0. c #77D3FF",
+"q. c #78D4FF",
+"w. c #79D5FF",
+"e. c #7AD5FF",
+"r. c #7CD6FF",
+"t. c #7ED7FF",
+"y. c #7FD8FF",
+"u. c #81CBE7",
+"i. c #82CBE7",
+"p. c #83CEEB",
+"a. c #81D4F7",
+"s. c #84D3F4",
+"d. c #80D7FE",
+"f. c #80D8FF",
+"g. c #84DAFF",
+"h. c #85DAFF",
+"j. c #86DBFF",
+"k. c #87DBFF",
+"l. c #89DCFF",
+"z. c #8ADDFF",
+"x. c #8BDEFF",
+"c. c #8DDEFF",
+"v. c #8EDEFF",
+"b. c #8FDFFF",
+"n. c #91E0FF",
+"m. c #92E1FF",
+"M. c #93E2FF",
+"N. c #95E3FF",
+"B. c #97E3FF",
+"V. c #98E4FF",
+"C. c #99E4FE",
+"Z. c #9BE5FE",
+"A. c #9CE6FE",
+"S. c #9EE6FF",
+"D. c #9FE7FF",
+"F. c #A1E8FF",
+"G. c #A3E9FF",
+"H. c #A5EBFF",
+"J. c #A6ECFF",
+"K. c #A8EDFF",
+"L. c #ABEEFF",
+"P. c #ADEFFF",
+"I. c #B0F0FF",
+"U. c #B3F1FF",
+"Y. c #B7F2FF",
+"T. c #C7F3FF",
+"R. c #DCF6FF",
+"E. c #EAF8FF",
+"W. c #F1FAFF",
+"Q. c #F8FCFF",
+"!. c #FCFEFF",
+"~. c #FDFEFF",
+"^. c #FEFEFF",
+"/. c #FEFFFF",
+"(. c gray100",
+"). c None",
+/* pixels */
+").).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).). ).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).). ).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).). ).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).). ).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).). % ).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).). O & ; 2 T O.O.a.r.e.e.e.q.9.9.4.{ { T 2 ; % O ).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).). @ - T r.l.k.k.k.y.t.t.t.t.r.e.e.q.9.8.8.8.8.4.4.1.1.1.{ T ; # ).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).). = Y p.v.x.x.s.v.k.k.k.a.g.t.y.t.r.e.e.q.9.8.8.8.2.4.4.4.4.,.,.;.;.;.O.4 = o ).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).). % 2 u.m.m.v.v.c.x.x.l.k.k.k.k.g.t.y.t.t.r.e.e.q.9.8.8.8.8.4.4.1.1.,.,.;.;.-.-.-.{ 2 & ).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).). O ; u.B.m.m.m.m.m.v.c.c.x.x.x.k.k.k.g.g.g.t.t.r.e.e.q.9.9.8.8.2.2.8.2.1.1.,.,.;.;.-.*.*.$.$.! : + ).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).).).).).).).).).).).).).).). O : p.C.C.B.B.B.m.m.m.m.c.c.c.c.x.k.l.k.k.g.y.g.t.t.r.e.e.q.q.8.9.2.2.4.2.1.1.1.,.;.;.-.-.-.&.$.$.+.O.2 @ ).).).).).).).).).).).).).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).).).).).).).).).).).).). + 2 s.A.A.C.C.C.B.m.N.m.M.m.m.m.c.l.x.x.l.k.k.g.g.t.f.t.r.r.e.q.9.9.8.8.8.8.8.1.2.,.,.,.;.-.-.&.&.&.$.+... .| 2 @ ).).).).).).).).).).).).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).).).).).).).).).).).). = p.F.F.A.A.A.C.C.C.C.N.N.m.m.m.m.v.v.c.x.l.l.g.k.g.t.f.f.t.r.e.e.q.9.8.8.8.2.8.2.2.1.,.,.,.;.-.&.-.&.+.+....... .` 1 O ).).).).).).).).).).).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).).).).).).).).).).). ; A.F.F.A.A.A.A.C.C.C.N.N.N.m.m.m.v.c.x.x.l.k.k.g.g.f.f.t.r.e.e.q.9.q.8.8.8.2.2.2.1.,.,.;.;.-.-.&.&.$.+.$..... .| | W = ).).).).).).).).).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).).).).).).).).). o T F.F.F.A.F.S.A.A.C.C.C.N.M.M.m.m.c.c.c.x.l.k.k.g.g.f.f.f.t.t.e.e.q.9.9.8.5.5.4.1.1.1.;.,.-.-.-.-.$.*.$.+.o. . . .| | ` T # ).).).).).).).).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).).).).).).).). * & p.F.F.F.A.F.F.A.A.A.C.C.N.N.M.M.m.m.c.c.x.x.k.k.k.g.h.f.f.t.r.r.e.q.9.9.8.5.5.4.4.4.1.1.;.,.;.-.-.&.$.$.+. . . . .| | ` ` W ; ).).).).).).).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).).).).).).). 2 A. % J.J.F.J.F.F.S.F.F.A.A.C.C.C.N.M.m.m.c.c.c.x.x.l.k.k.f.t.t.t.t.r.e.q.0.9.9.8.5.4.4.1.1.,.,.;.-.-.&.-.$.$.$.o.+... .| | ` ) ) ) 2 O ).).).).).).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).).).).).). @ u.J.T ; J.J.J.F.J.F.F.F.A.A.D.C.N.C.N.M.M.m.m.m.x.x.x.l.k.k.k.k.f.f.t.r.r.q.0.9.5.5.5.5.4.4.1.,.,.;.;.-.-.&.$.$.+.o. ... .| | ` | [ ) ( 5 $ ).).).).).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).).).).). & p.K.K.: T J.J.J.J.F.G.F.F.F.F.A.A.N.C.C.N.M.m.m.c.c.c.x.x.l.k.g.g.t.t.t.r.r.q.0.0.9.8.5.5.4.3.1.,.,.,.;.-.-.&.h.k.+.$.o. . . .| ` ` ` | ( ( W - ).).).).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).).).). = F.K.P.K.& p.K.J.J.J.J.F.F.F.A.F.D.A.A.C.C.N.M.M.m.m.c.c.x.l.l.k.k.g.g.g.t.r.r.r.e.0.9.9.5.5.4.4.1.1.,.;.,.-.-.,.Q./.8.o.o.o. .[ ` | | ` ) ) ( ( ( ; ).).).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).).). ; J.K.P.P.F. % K.P.K.J.J.J.G.G.G.F.A.D.A.A.C.C.N.N.M.m.m.m.v.x.x.l.k.g.g.t.y.t.t.r.q.0.0.9.7.9.5.4.4.2.1.,.,.;.;.-.F././.T.$.o.o. . .| ) ` ) ) ) ( ( ! ! , ).).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).). : K.K.P.P.P.u. ; P.K.P.K.K.J.J.J.G.F.F.D.D.D.C.C.N.N.M.m.m.c.v.c.x.l.k.k.g.k.y.t.r.r.r.0.0.9.9.5.5.4.4.2.1.,.;.,.;.,.W./././.l.o. . . . .| | ` ) ) ( ( ^ ! Q 1 ).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).). Y K.K.P.P.P.I.Y T P.P.P.K.K.J.J.J.F.G.F.D.D.A.A.N.N.N.N.M.m.m.c.c.c.x.l.k.g.g.y.t.t.t.r.w.q.q.8.7.5.5.4.2.1.,.,.;.;.F././././.E.+. . . .| | ) ` ) ) ) ( / ! ! W 2 ).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).). 2 K.P.P.P.P.P.I.P.u.T ; % i.I.I.P.P.P.K.J.J.J.G.F.D.D.D.A.C.C.N.N.m.m.m.c.c.x.l.l.g.k.g.y.t.t.r.r.w.q.8.8.7.5.5.5.2.1.,.,.;.;.E./././././.P. . . .| | | ) ) ` ( 1.K.0.! E Q 1 ).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).). ; J.K.P.P.P.I.I.U.U.U.U.U.U.U.I.I.P.P.P.K.J.J.J.G.G.D.D.D.A.D.C.C.N.N.m.N.c.c.x.l.l.g.k.g.y.g.t.r.r.r.q.q.8.7.5.5.5.2.2.,.,.;.C./././././././.4.o.o.| | ) | $.C.R././.U.! ! U L > ).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).). * F.J.K.K.P.I.I.U.U.U.U.U.U.U.U.U.I.I.P.K.K.J.J.J.G.G.D.D.D.D.C.N.C.N.m.m.m.c.c.x.x.l.k.k.k.y.t.t.r.r.q.q.8.8.9.5.5.5.2.2.,.,.;.E./././././././.T.o.[ | .v.T./.!././.!.k.! E Q L L - ).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).). & C.J.K.K.P.P.I.I.U.U.U.Y.Y.Y.U.U.U.I.I.P.P.P.K.J.G.J.F.D.D.D.A.C.C.N.N.M.m.m.m.c.x.l.l.k.k.g.y.y.y.r.r.r.M.R.U.C.9.5.5.2.2.1.,.v.!././././././././.k.d.T././././././././.+.! ! E E L G * ).).).).).).).).).).).).).",
+").).).).).).).).).).).).). + p.J.J.K.P.P.P.I.I.U.U.Y.Y.Y.Y.Y.U.U.U.I.P.P.K.K.J.J.J.F.F.D.D.A.D.N.C.N.M.m.m.c.c.x.x.l.z.g.g.y.g.y.r.r.r.L./.!././.R.U.m.2.1.>.R./././././././././././././././././././.W.! ! E E E L L F $ ).).).).).).).).).).).).",
+").).).).).).).).).).).).). T G.J.J.K.K.P.P.I.I.U.U.Y.Y.Y.Y.Y.U.U.I.I.P.P.P.K.J.J.J.G.F.D.D.A.D.C.C.N.M.m.M.c.c.x.x.l.k.k.g.y.t.y.t.r.q.r.!./././././././.R.T././././././././././././././././././././.Y.! ! ! E L L L K g o ).).).).).).).).).).).).",
+").).).).).).).).).).).). ; J.G.J.J.K.K.P.P.I.I.U.U.U.Y.Y.Y.U.U.U.I.I.P.P.P.K.J.G.J.G.F.D.D.D.C.N.C.N.M.m.M.c.c.x.l.l.k.g.g.y.t.y.r.r.r.q.T.!././././././././.!././././././././././././././././././.Q.v.! ! E E E L L K G , ).).).).).).).).).).).",
+").).).).).).).).).).). & A.J.F.J.J.J.J.L.P.P.I.U.U.U.U.U.U.U.U.U.I.I.P.P.P.K.J.J.F.F.F.D.D.A.A.N.C.N.M.m.m.c.c.x.l.l.k.k.h.f.f.f.r.r.r.0.A.^././././././././././././././././././././././././././././.*.! ! E E E L L L G D * ).).).).).).).).).).",
+").).).).).).).).).).). O u.A.F.F.J.J.J.K.K.P.P.I.I.U.U.U.U.U.U.U.I.I.P.P.K.K.J.J.J.F.J.D.D.D.A.A.C.N.N.M.m.m.m.c.x.x.l.k.k.f.f.f.r.r.r.0.0.0.Q./././././././././././././././././././././././././././.W.! ! ! E E L L L P G D B @ ).).).).).).).).).).",
+").).).).).).).).).). Y F.D.F.J.J.J.J.K.L.P.P.P.I.I.I.U.U.U.U.I.I.I.P.P.K.K.J.J.J.G.F.D.D.D.A.C.C.C.N.m.m.m.c.c.x.l.l.k.k.h.f.f.r.r.r.e.0.9.T.^././././././././././././././././././././././././././.T./ ! ! ! E E L L G G D D 1 ).).).).).).).).).",
+").).).).).).).).).). $ N.D.D.F.F.G.J.J.K.K.L.L.P.P.I.I.I.I.I.I.I.I.P.P.P.K.J.J.J.G.G.F.D.D.A.D.C.N.N.M.N.m.m.c.c.x.x.l.k.f.h.f.f.f.r.e.e.e.9.n.^./././././././././././././././././././././././././.Q.K.! ! ! E E L L L G D D B V & ).).).).).).).).).",
+").).).).).).).).). T A.F.D.D.F.F.J.J.J.J.K.L.L.T : T i.J.I.I.P.P.P.K.K.K.J.J.G.G.G.F.D.D.A.C.C.N.N.M.m.m.m.v.v.l.x.k.k.g.g.t.f.f.r.e.e.e.9.9.W./././././././././././././././././././././././././.^.^.R.g.W E E P P P G G D D V g ).).).).).).).).",
+").).).).).).).).). ; C.A.A.D.D.F.F.F.J.J.J.K.K.L.& K.P.P.P.P.K.K.J.J.J.F.G.F.A.D.D.A.C.C.C.N.M.m.m.c.c.x.x.k.k.k.g.f.f.f.r.r.e.0.0.9.8.Y./././././././././././././././././././././././././././././.E.v.W P P G G G D V V N - ).).).).).).).).",
+").).).).).).).). o u.C.C.A.D.D.F.F.F.J.G.J.J.J.K.+ % P.K.K.P.K.K.K.J.J.G.F.F.F.F.D.A.D.C.C.N.M.M.m.m.m.l.x.x.l.k.k.g.f.f.f.r.r.e.9.9.9.8.h./././././././././././././././././././././././././././././././.W.n.^ P G G D D V V b + ).).).).).).).",
+").).).).).).).). ; B.C.C.A.A.D.D.D.F.F.G.J.G.K.A. = K.K.K.K.J.J.K.G.J.G.G.F.F.A.A.A.C.C.N.N.M.m.m.c.v.v.x.l.l.k.k.k.f.f.r.r.r.e.0.9.8.8.B.^./././././././././././././././././././././././././././././././.!.Q.F./ G D V V V N : ).).).).).).).",
+").).).).).).). p.B.N.C.C.D.A.D.D.F.F.G.G.G.J.r. ; J.J.J.J.J.J.J.F.G.G.F.F.S.F.A.C.C.C.N.N.M.m.N.c.x.x.z.z.z.g.g.g.g.t.t.r.r.q.0.0.h.R./././././././././././././././././././././././././././././././././././.Q./.2.A C C V N 0 O ).).).).).).",
+").).).).).).). ; N.N.N.N.C.C.D.D.D.D.F.F.G.G.K.i. 2 J.J.G.J.J.J.G.G.F.F.F.A.A.A.A.C.C.N.N.N.M.m.m.c.c.x.z.z.g.k.g.t.y.y.t.r.r.q.0.Y./././././././././././././././././././././././././././././././././././././.Q.E.&.A C C N N m ; ).).).).).).",
+").).).).).). r.m.B.B.N.C.C.A.A.D.D.D.F.F.G.G.Y X Y J.G.J.J.G.G.G.F.F.S.F.S.A.A.C.C.C.N.M.M.m.M.c.c.x.x.z.k.k.g.g.g.t.t.r.r.q.D.W././././././././././././././././././././././././././././././././././././.^./.G.U A A C C V N m 9 o ).).).).).",
+").).).).).). = n.m.m.m.N.C.C.C.A.A.D.D.A.F.G.G.Y X T G.G.G.F.G.F.F.F.A.F.S.A.A.A.C.C.N.N.M.m.m.c.c.c.x.z.z.k.g.g.g.t.t.t.r.k.R././././././././././././././././././././././././././././././././././././././.T.o.G K A C C V V N m N - ).).).).).",
+").).).).).). X X T n.n.n.n.N.N.C.C.C.A.A.A.F.A.F.A.: u.F.F.F.F.F.A.F.A.A.F.A.A.C.C.N.C.N.M.M.m.m.c.c.x.x.x.k.k.k.g.f.f.t.t.N./.!./././././././././././././././././././././././././././././././././././.Q.W.r.P G G A A D V V V N m b f ).).).).).",
+").).).).). X @ s.n.n.C.n.m.B.N.N.C.C.A.A.Z.F.S.F.; u.F.F.F.F.A.F.F.F.A.A.A.C.C.C.C.N.m.M.m.M.c.c.c.x.l.l.k.k.g.g.f.f.t.r.m.W././././././././././././././././././././././././././././././././././.^.^.G./ L P P G A A D V V N m m b b # ).).).).",
+").).).).). - n.b.M.n.n.m.m.B.m.C.B.C.C.A.A.A.F.= B.A.F.F.A.A.F.A.A.A.C.C.B.C.B.N.M.M.m.m.c.c.c.x.l.l.k.k.g.g.g.f.f.t.r.e.e.J.E././././././././././././././././././././././././././././././././.^.*.E E L L P G A A V V V N m N N b : ).).).).",
+").).).).). e.b.b.s.n.n.m.m.m.B.B.B.C.C.C.C.A.A.* F.F.A.A.A.A.A.A.C.C.B.C.C.m.B.M.M.m.m.c.m.c.x.x.x.l.k.k.g.t.t.f.t.e.e.e.e.9.9.A.R././././././././././././././././././././././././././././././.Q.r.E L L L P G K A A V N N m b b b g ).).).).",
+").).).). % x.l.x.c.c.c.M.m.m.M.M.N.N.C.C.C.C.C.C.D.D.A.A.A.A.A.A.C.A.C.C.C.N.C.N.N.M.M.M.m.m.c.m.l.c.x.x.k.k.k.g.g.g.t.t.t.r.e.e.q.9.8.8.8.m.R./././././././././././././././././././././././././././././.T.Q L L L K K D V V C V N m m b c c % ).).).",
+").).).). 2 l.x.x.x.c.c.c.m.m.m.M.M.N.N.N.C.N.C.N.C.C.C.C.C.C.C.C.C.C.C.C.C.C.N.N.M.m.m.m.m.m.c.v.v.c.l.k.k.k.g.g.y.y.t.t.r.e.e.q.9.9.8.8.4.2.4.l.T././././././././././././././././././././././././././././.) E L J A A D V C V N N m m b c c > ).).).",
+").).).). T k.k.x.x.x.c.c.c.m.m.m.M.M.M.N.N.N.N.C.C.C.C.C.N.C.C.N.C.N.C.N.N.N.M.M.M.m.m.m.c.m.c.c.x.x.l.k.k.k.g.y.g.t.t.r.e.e.e.q.9.8.8.2.8.4.4.1.1.J.!./././././././././././././././././././././././././.!.N.L L L J D A A C V N m m m b c c f ).).).",
+").).).). O a.k.k.l.l.x.x.c.c.c.m.m.m.m.M.N.m.N.N.N.N.N.N.B.B.N.C.N.N.N.N.M.M.M.M.m.m.m.m.c.v.v.l.x.l.l.k.k.g.g.g.y.y.t.t.r.e.e.q.8.8.8.8.8.2.4.1.1.,.T./././././././././././././././././././././././././././.R.L L L A D A C C V N m b b b c c k + ).).",
+").).). * g.k.g.k.l.x.l.x.c.c.c.c.m.m.m.m.m.m.M.M.M.M.M.N.N.N.m.B.M.M.M.M.M.m.m.m.m.c.c.c.x.x.x.x.l.k.k.k.g.g.g.f.t.t.r.r.e.q.9.9.8.8.8.2.4.4.4.1.,.W././././././././././././././././././././././././././././.;.K K A D A V V V N N b m b c c k * ).).",
+").).). 2 k.g.k.k.k.l.l.l.x.x.c.c.m.v.m.m.m.m.m.m.M.M.M.M.M.m.m.m.m.m.m.m.M.m.m.c.m.c.c.c.x.x.x.l.k.k.k.g.k.t.y.t.t.r.r.e.e.q.9.8.8.8.2.8.4.1.1.1.e././././././././././././././././././././././././././././.W.P.K A G D A V V V N m m b c c c k > ).).",
+").).). O.t.g.g.k.k.k.l.l.x.x.x.c.c.v.c.c.m.m.m.m.m.M.M.m.m.m.m.m.m.m.m.m.c.m.c.c.c.c.x.x.l.x.k.k.k.k.g.g.t.f.t.t.t.e.e.e.q.9.9.8.8.4.2.4.4.1.1.;.A.!./././././././././././././././././././.Q././././././././.Q.U K A A A V V V m m m b c c k k g ).).",
+").).). X a.f.t.t.g.g.k.k.k.l.x.l.x.l.v.v.c.c.c.c.m.c.c.M.m.m.m.m.m.c.m.c.c.c.c.c.c.x.x.x.x.l.k.g.k.g.g.g.t.g.t.t.r.r.e.e.q.q.9.8.8.8.4.4.4.1.4.;.1.T././././././././././././././././././././.C.U.W./.W././././.Q.g.K A A V V V N m b b b c c k k k o ).).",
+").).). $ d.f.f.f.f.h.h.k.k.k.k.l.x.z.x.x.x.x.x.c.c.c.c.c.c.c.c.m.c.c.c.c.c.c.x.x.x.x.x.k.l.k.k.k.g.g.g.g.t.y.t.r.e.e.e.q.9.9.8.8.8.8.2.8.1.1.,.,.,.W./././././././././.W.^./././././././.^.T./ ! ! *.C.T./.Q.E.!.T.D A A V V V N b N v v c c k k j $ ).).",
+").). = r.r.f.f.f.f.h.f.k.k.k.k.z.k.z.z.z.x.x.x.x.c.c.c.v.v.v.v.c.c.c.x.x.x.l.x.x.k.k.k.k.k.g.g.k.t.t.y.t.t.r.r.e.q.q.q.9.8.8.8.4.2.8.2.4.1.,.,.9./././././././.E.K.1.8.^./././././././.^.9./ / ! ! ! L Q 8.F.R.R.A A A V V N b N v N v c j k j j * ).",
+").). : r.r.t.t.f.f.f.f.g.g.k.k.k.k.x.k.l.x.x.l.x.x.x.x.x.x.l.x.x.x.x.l.l.x.l.l.z.k.g.k.k.g.g.g.g.t.t.t.r.r.r.r.q.q.9.q.8.8.8.4.2.2.2.2.1.,.,.,.A./././.!.Q.U.w.$. .o. .P./././././././.R./ / ! ! E E E U K K K J D V C C V N b b b v v c j k j d ; ).",
+").). Y e.r.r.t.t.f.f.f.t.g.g.g.k.g.k.k.k.l.l.l.Y ; ; = & s.x.l.l.l.l.l.l.l.k.k.g.k.k.g.g.k.t.t.y.y.t.t.r.r.r.w.q.q.8.8.8.8.8.2.4.8.1.1.,.,.,.;.T././.T.x.&.&.+.+. .o. .+.W././././././.d.! / W ! ! E L U K K A D D C V V V N N b b v c c j k j d , ).",
+").). T e.e.e.e.r.r.t.f.t.g.t.k.g.g.g.k.k.k.k.g.; r.l.l.l.h.k.k.k.k.k.k.k.g.g.g.t.y.y.g.t.t.r.r.r.r.q.q.q.8.8.8.8.4.2.8.4.4.1.,.>.1.;.;.9.A.;.*.&.$.$.$.o.o. . .[ k./././././.E.( / ! ! ! ! L E L L K K A A C C V N N m v v v v j c j d d f ).",
+").). { q.e.e.e.r.r.t.r.t.t.t.g.t.g.g.g.g.g.k.k.; i.h.h.k.k.k.k.k.g.g.g.g.g.g.y.t.g.y.t.t.r.r.w.w.w.q.q.q.8.8.8.4.4.4.4.4.1.1.,.1.>.;.;.*.*.*.*.$.$.+...o. . . . .[ T././././.v./ / ! ! E E E L K K K A A C C V V N m b N v v c z j j d d g ).",
+").). { 9.9.e.e.e.r.r.r.t.t.y.y.y.g.t.t.g.k.g.k.2 T h.h.h.h.f.k.g.g.g.t.t.y.g.t.t.t.t.r.r.r.r.w.q.q.q.8.8.8.8.8.2.4.4.1.1.1.,.,.;.;.;.-.-.*.$.$.+.+.+.o. . . . .[ [ ;./././.Q.) / / ! Q ! L L L U K K A A A C V V m m m v v c c j c j d d 9 ).",
+").). 5.8.9.9.q.e.e.e.r.r.r.t.t.y.y.t.g.t.t.t.t.T Y h.h.f.k.f.f.t.t.y.g.y.y.t.t.t.r.r.r.r.w.q.q.q.8.q.8.8.8.2.2.8.4.4.1.1.,.,.1.;.;.-.-.*.*.*.$.+.+.+.o. . . .[ [ [ [ K.!.!.B./ ! ! ! Q E E E L K A K A A V C V N m m b v c c z j j d d d 0 ).",
+").). 8.8.8.9.8.q.q.q.e.e.r.r.r.r.t.r.f.f.f.f.f.{ ; f.f.f.f.f.f.f.f.t.f.t.t.r.r.r.e.e.e.e.q.q.9.q.8.8.8.8.2.5.5.4.4.1.1.,.,.,.,.-.-.-.-.&.&.$.$.+....... . .| | ) | ) | E.!.[ / / ! Q Q E L L L K A K A A V V V N m b m v c c k k j d d p p ).",
+").). O 8.8.8.8.8.9.9.q.q.e.e.e.e.r.r.r.r.t.t.t.t.u. = f.f.f.t.f.f.t.t.t.t.r.r.r.e.e.e.e.q.q.9.9.8.8.8.8.8.8.8.2.2.1.1.1.,.,.;.;.;.-.-.&.-.&.$.$.$.+. ..... .| | | | ) ) ( ;.-.! ! ! ! Q E L E L L K A A C C V N N m m b b c c c k j d d d i i O ).",
+").). @ 2.4.8.8.8.8.9.9.9.q.q.e.e.e.e.e.r.r.r.r.r.r.O % t.t.t.t.r.r.r.r.r.r.r.e.e.e.e.q.q.9.9.9.8.8.8.8.8.2.2.2.5.2.1.1.,.,.;.,.;.-.-.-.&.&.$.$.$.+...+. . .| ` | ` ` | ) ) ( / / ! ! Q Q E E L L L A K A A C V V N m m m b c c k k j j d p p y + ).",
+").). @ 4.4.4.8.8.8.8.8.8.9.q.q.q.e.e.e.e.e.e.r.r.r.% + r.r.r.r.r.e.r.e.e.e.e.e.q.q.e.9.9.9.8.8.8.8.8.2.8.2.2.8.2.2.1.,.1.;.,.;.-.-.-.&.&.$.$.+.$. ... . . .| | ` ` ) ` ) ) / ( ! ! ! Q E L L L L G K A C C C V V N m b b c c c k k j d d p p i @ ).",
+").). O 4.4.4.2.8.8.8.8.8.8.9.9.9.9.q.q.q.e.e.e.e.e.* r.e.e.e.e.e.e.e.q.q.q.q.9.9.9.9.8.8.9.8.8.8.2.2.8.2.2.2.2.2.,.,.,.;.-.-.-.&.&.&.$.$.+.+..... . . .| | | | ) ) ` ( ( ( ! ! ! W E E E L L P G K A C C V N N m b m b c c k k d d d d p p y O ).",
+").). 4.1.4.8.2.2.8.8.8.8.8.8.8.9.8.9.9.q.q.q.q.e.: Y e.q.e.q.q.e.e.q.q.9.9.9.8.8.8.8.8.8.2.4.2.2.8.2.4.2.2.:.:.,.,.,.;.-.-.-.-.&.&.$.+.+....... . . .| [ ) | [ ) ) ( ( / / ! Q Q E L L L P G G A C C C V N m m b b c c c k k k d d p p y y ).",
+").). O.1.4.4.4.2.8.2.8.8.8.8.8.8.8.8.9.9.9.9.9.9.T O * : Y O.e.9.9.9.9.9.9.9.9.8.8.8.9.8.8.8.4.2.8.2.8.2.2.4.1.:.2.:.:.;.,.-.-.-.-.&.&.&.$.+.+......... .| | | ) | | ) ` ) ( ( ! ! ! Q E L L L P G G G A A C V V N m b m b c c k k k d d d p p p q ).",
+").). { 1.1.1.4.2.8.2.8.2.2.4.8.8.8.8.8.8.8.8.8.9.9.9.9.e.q.q.q.9.9.9.8.8.8.8.8.8.8.8.8.8.8.2.4.4.8.2.2.2.1.1.1.2.:.:.;.-.;.-.-.-.&.&.$.$.$.+...+... ... .| ) [ | ) ) ) ) ( ( ! ! ! ! Q E E P P G G D D C C C V N m m m b c c c k k d d d p p y 9 9 ).",
+").). { ,.,.1.1.2.2.2.2.2.8.2.8.2.8.8.2.9.8.8.8.8.8.8.8.9.9.9.6.9.6.6.9.8.8.8.8.2.8.8.2.4.4.8.2.2.2.2.2.2.,.,.,.,.;.;.;.;.;.;.&.&.&.$.$.$.$...........| | | ` | ) ) ) ) ( ^ ^ ! Q Q Q Q L E L L K A A V V V V V N m b b v c c c j j d d d i p w $ % ).",
+").). T ,.,.,.1.1.2.2.2.4.4.4.8.2.8.2.8.2.8.8.8.8.2.8.8.7.7.6.9.7.7.6.6.8.8.4.4.8.2.2.8.4.4.2.2.2.2.4.1.,.,.,.,.;.;.;.;.-.;.&.&.&.$.$.+.+...........| | ` | ` ` ` ` ( ( ( ( ^ ! ! Q Q L L L L L K A A D V V V V m m m b v c z j j j d d p p y = ).",
+").). Y ,.;.,.,.,.1.1.2.1.1.4.2.4.4.2.8.8.2.2.8.2.2.8.2.7.7.3.3.3.7.3.6.8.2.8.2.4.4.4.2.1.1.4.1.1.1.,.,.,.,.;.;.;.;.&.;.&.&.&.&.&.$.+.+......... .| | | | ` ` ` ) ( ( ( ^ ^ ! ! Q Q Q L L L G G K A V D V V V N N b b b c c j z j j d d p i - ).",
+").). : -.,.;.,.,.,.,.,.1.1.1.1.1.1.4.4.2.8.2.2.8.4.4.4.3.3.3.7.3.3.7.3.2.8.2.2.4.1.1.1.1.1.1.,.,.,.,.,.;.,.;.;.;.;.;.&.-.&.&.$.$.$.+. .......| | | | ` ` | ` ( ` ( ( ( ^ Q Q Q Q U U L L L G G A A A V V V N b b b b c c c c j j d d p p : ).",
+").). = -.;.;.,.,.,.,.,.,.,.,.,.1.1.4.1.2.2.2.2.2.8.2.2.4.4.4.4.7.3.6.3.2.2.2.2.2.1.1.1.,.,.,.,.,.;.,.-.;.;.-.;.;.&.&.&.&.&.$.$.$.+...+... . .| | | ` ` ` ` ` ` ( ( ^ ^ ! ! Q Q Q L U L P P D D D V V V V N m m b b c c z z j j d d d p - ).",
+").).). % -.-.-.;.-.-.,.,.,.,.,.,.,.,.1.1.2.2.2.2.2.2.2.2.2.2.2.1.1.1.3.1.2.1.1.1.1.,.,.,.,.,.,.;.;.,.;.;.-.;.-.&.&.;.&.&.$.$.$.+......... . .| | | ` ` | ` _ _ ( ( ^ ^ ^ ! Q Q Q L U L L P G D D D V V V V N m m m b c c z j c j d d i = ).).",
+").).). o $.&.-.-.-.-.;.;.,.-.,.,.,.,.,.,.,.,.2.:.2.,.:.2.1.1.1.1.,.1.1.,.,.,.,.,.,.,.,.,.,.-.,.,.;.-.-.-.;.&.-.&.&.&.$.$.$.+.+......... . .| | ` ` | ) ` _ _ ( ( ( ^ ^ Q Q Q U U U L K K G G D D V V V V N m m b b c c c z j j d d 0 & O o ).).",
+").).). g -.&.-.-.-.-.-.;.;.-.,.-.,.;.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.;.,.,.-.,.,.;.;.-.-.-.-.-.-.&.&.&.&.$.$.$.$.$....... . . .| | | ` | ) | ) ` ( ( ^ ^ ^ ! Q Q Q U L L K K K G D D B V V V V m m m b b c c k j j d d d - O , ).).",
+").).). 2 $.*.*.*.*.*.;.;.-.-.;.;.;.;.;.,.;.;.,.,.;.,.,.,.,.,.;.;.1.;.;.,.;.;.,.;.;.;.;.;.;.&.;.&.&.&.&.&.&.&.$.$.+.+.$........... .| | | [ [ | ) ) ) ) ) ) / / / ! ! E Q U U U K K K A A A C C V V N N N n N v c c c k c j d d p 0 $ + g , ).).",
+").).). * $.$.$.$.*.*.*.-.&.-.-.-.-.;.;.;.;.;.;.;.;.;.;.,.;.T : # 2 ;.;.;.;.;.;.-.-.-.-.&.;.&.;.&.;.&.&.&.&.$.+.+.+.| ........| .| | | | ) ) [ [ ) ( ( ) ( ! / ! ! E ! U U K K K K K A A A C C V N N m v n v v c c j k j d d p p i g O # 5 e = ).).",
+").).). + $.$.$.$.$.$.*.&.-.-.&.&.;.-.;.;.;.;.&.;.;.;.;.O.O $ -.-.-.-.-.-.-.-.-.&.&.;.&.&.&.&.&.$.$.$.+.$...+...........| | ` ` ` | | ) [ ) ) ) ( ( / ! ! ! Q ! E U L L L K A K A A V C V V N N b N v v v c j k j j d d p i y y < * 0 y e O ).).",
+").).).). T $.$.$.$.$.$.&.&.&.&.&.-.&.&.&.&.&.;.&.;.;.;.-.$ T -.-.-.-.&.&.-.&.-.&.&.&.$.$.$.$.$.+.+........... ...| | | | | ` | ) | ) ) ) ) ( ( / ! ! ! Q Q E L U L L K A K A A A C V V N m b N N v c c c j k j d d d i i y y y y e 8 g ).).).",
+").).).). > o.$.$.+.$.$.$.$.$.$.&.&.&.&.&.;.&.&.;.&.&.&.-.2 - -.&.-.&.&.&.&.&.$.$.$.$.$.$.+.+.+.| ............ .| | ) | ` | ` ) [ ) ) ) ( / ( ! ! ! ! Q Q Q L L L L K K K A A C V C V V N b b b v v c c k k j j d p p i y y y y y e e > ).).).",
+").).).). & o.o.o.o.$.+.+.$.$.$.$.$.$.&.$.&.$.$.&.&.&.&.$.{ o O.&.&.&.$.$.$.$.$.$.+.$.+.+.............| ....| | | | | | | ) | ) ) ) ) ) / ( ! ! ! Q Q Q E L E L L K A J A A A C C V N N b N b b v c z > 5 j d d p d p y y y y e e e 8 & ).).).",
+").).).).). W .o.o. .o...+.$.+.+.+.+.$.$.$.$.$.$.$.&.$.$.$.= 2 &.$.$.$.$.+.$.+.+.$.+.............| ....| | | | ) | | ` ) | ( ) ) ) / ( / ! ! ! Q Q Q L L L L L K K K A A C C C V V N m N b v c c , @ = j d d d i i i y y e y e e 5 ).).).",
+").).).).). : . . .o. ...........$.+.+.$.$.+.$.$.$.+.$.$.$.4 % $.+.+.+.+.$................. . .....| | ` | ` ` | ) ) | ) ` ) ( ( / / ! / ! ! Q Q Q Q L E L L L K A A A A C C V V N m m v v c > + g d d i i i y y y e e e 8 > ).).).).",
+").).).).). # | . . . . . .....+. ......... .$.+.$.+.$.+.+.+.@ 4 ....+...............| ...... .| | | | ` } } ` ) | ) ) ) ) ) / / / / ! ! ! Q Q Q L Q L K K K A K D V C C C V V N m m m 5 ; + * d p i y i i y y e e 8 8 $ ).).).).",
+").).).).).). 4 .| | . . . . .........+. .+............... .: * ..............| ......| | | | | | ` ` } ` ` _ ) ) ) ) ( ( ( / / ! ! ! Q Q Q E L L L L K K A K D D A V C V V N m m 3 = $ 0 p i i y e e e e e 8 g ).).).).).",
+").).).).).). - | | | | | | . . . . . .| .......... . ..... .W o 4 .. . . . . ...| | | | | ` ` ` ` ` } ` ` _ _ ) ) ) ) / / ( ! ! ! ! E W E E L L L L L L K A D A A V C N V N m m b % @ , i p i y y i y e e 8 8 8 - ).).).).).",
+").).).).).). W | ) [ [ | | | | | | . . . . . . . .| ... . .; O : R . . .| | | | | ` | ` | ` | | ` ` ` _ _ _ _ ) ( ( ( / / ! ! ! ! E ! E L E E L L L G A D D D A C C V N N m m b m , $ < d d p i y y y e i e e 8 7 9 O ).).).).).",
+").).).).).).). + 4 ) | | [ [ | | | | | | | | | | | | | | | | | W + : W | .| | | | | | | | ` | | ` ` _ ` ` _ _ _ ( _ ( ( ( ( ! / ! ! ! E ! E E L L L L L L G G G D D V V V V V N m m m b b 0 & < d d d p i y y y y e y e e 8 7 : ).).).).).).",
+").).).).).).). % 2 ( [ ) | ) | ) | | ` | | | | [ | | ` | | .) | | | | ) | ) | | ) ` ` ` ` ` ` ` _ _ _ _ _ _ _ ^ ^ ( / ! ! ! ! Q Q E E E E E L L G P G G G D B 1 3 C V V N m m b m b c c * o - g k d d d p p y y y y e e e 8 8 8 q O ).).).).).).",
+").).).).).).).). + ; 4 | | ) | ` ` ` ) | ) | [ | ) | ` | | [ | ) ) | | | ) | ) | ` ` ` _ _ _ _ _ ( _ ^ _ ^ ^ ^ ^ ! ! ! ! Q Q Q Q E E L L L L P G G G 3 : % * V V N m m m b b b c c 5 0 k k d d d p p i y y y y e e e 8 8 8 > ).).).).).).).",
+").).).).).).).). $ : W ` ` ` | ` ` | | ) ` | ` | ) | ) [ | | ) ) | ) | ) ) _ _ _ _ _ _ _ ( ( ( ^ ^ ^ ^ ^ ! ! ! ! Q Q E E L E L L L P 5 1 ; & o + N N m m m b b c c c k k k k d d d p p i i y i y e e e 8 8 8 w + ).).).).).).).",
+").).).).).).).).). o W ) ) [ ) [ [ ) ) | ) [ ) | [ ) | | ) | [ ) ) ) ) [ ) ) ) ( ( ) ( / / ^ ( ^ ^ ^ ! ^ Q Q Q Q Q Q L L U L K U K , f b N v n v c c c k k k k d d d d i i i y y y e e e e e 8 8 : ).).).).).).).",
+").).).).).).).).). * ( ) ) [ ) ) ) ) [ ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ( ( ) ) ) ( / / / / / ^ ^ ^ Q ! ! Q Q Q G U L L U L L L K K A f > N v N v c c c k k k k d d d p i i y y y y y e e e 8 7 8 5 o ).).).).).).).).",
+").).).).).).).).).). O 1 ( ( ( ( ) ) ) ) ) ) W $ % - ; 1 1 2 f f f W ( ( / / ( / / / ! / 5 f 1 1 > - - % % # : L Q L L K K K K K K V X # - < v b v n v v z z k k d d d d p p i y y y e y e e e 8 7 7 8 * ).).).).).).).).",
+").).).).).).).).).). > : % F / / / / / / / ( ) ) g P / / / ( / / ! / ! ! - - L L L L K J K A A A A % X # = < 5 N N b N b v c c c c j k k d d d p p i i y y i y e e e 8 7 7 7 < ).).).).).).).).).",
+").).).).).).).).).).). O G ! F ! / ! / ! / / ( ( ( ( 3 W / / ! ! ! ! ! ! ! ! ; % L L L K A A A D V A C < > 3 v V N b b N b b v v c c c z j z k d d d p p i y y y e e e e 8 8 7 7 8 q # ).).).).).).).).).).",
+").).).).).).).).).).). & ! ! ! ! ! ! ! ! / ! / ! ! , W ! 2 # 3 ! ! Q Q ! E ; + L G A K K D A D A V C V V V N N b N N b b b v c c c j z j j d d d p p i y y i y e y e e 8 7 7 7 8 - ).).).).).).).).).).",
+").).).).).).).).).).).). : ! Q Q Q ! ! ! ! ! ! ! ! 2 % @ g & @ G ! Q E E E ; % % - F G A A A A A C V V V V V N m N N b N v v c c c j j j j j d d d p p p y y y y e e e e 8 7 7 7 7 , ).).).).).).).).).).).",
+").).).).).).).).).).).).). 3 E Q Q Q Q ! Q Q Q Q Q ! Q Q Q G f 2 1 1 : - - O = E Q L L E 2 : 1 1 f f 9 L J A G G D D A A A C V V V V V N N m m b b b v v c c z z j c j j d j d p p p y y y y e y e e 8 8 7 7 7 g O ).).).).).).).).).).).",
+").).).).).).).).).).).).). + F E L E L Q E E E E ! Q Q Q Q Q Q Q Q Q U Q U 1 1 L L L L L L L K K K K A K K D D A D D V V V V V V N N m m m b m b b b c c c c j j j j d d p p p i y y y e e i e e e 7 7 7 7 w $ ).).).).).).).).).).).).",
+").).).).).).).).).).).).).). & F E E E L L E E L E L U L L Q L L L L L L U U * + G L L L L L K K K D K A A A V D A V V V V V V N N b m m m b b b c c c c k k j j j j j p d i p y y y y y y e e e 7 7 7 7 7 7 - ).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).). * G L L L E L E L L E L U U L Q L L Q U L L L J + * L L K K A A K D D A A A C D V V V V V V V N b N b b m b b b c c c c k k k d j d d p p p i y y y y y e e e e 8 7 7 8 8 8 > ).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).). - L L L L L L L L L L L L K L L L L L L K U K 1 < A K A K A A V D A A C C V V V V V N N N N b b N b b b b c c c k k k k d d d d d d p i i y y y y e y e e 8 7 7 7 8 8 , ).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).). : K K K K L G L P K K K K K K K L L K K K K K = o g D A A A D A A V V V C V V N N N m m m N b N v v v c c c c k k k d k d d d p p i i y i y y y e y e 8 8 7 7 7 7 7 < ).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).). , G G G G G G G K K K D K A K A K D A D A K N @ $ V V D V V V V A V V V V N N m m m b m v N v v v v z c j k k k k d d d d d p p y i y i y e e y e e 8 7 7 7 8 8 f o ).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).). : G D D D G D A A K A D D A K A K D D A A A 3 > D V V V V V V V V N N N m N m m b m b v v v v c c c j j c j j d d d d p p i y y y i e e e e e 8 8 7 7 7 7 7 < o ).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).).). - V D V D D A A A A V D A V D V D V A C A C : + 3 V V V V V V V V N N N b m m b m b b b c v c c z c j j j j j d d d d p i p p y y y y i e y 8 e e 8 8 7 7 7 7 , ).).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).).).). = B D V D A C A A A C A V C C C C C C C C V ; 5 N V N V V N N N b b N N v m b m b v c c c c z c z j j j j d d d d d i p p y y y y i y e e e 8 8 7 7 7 8 8 8 > ).).).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).).).).). & N V V C V V C C V C V C C C V V V V V V V V N N N N N m N b N b b b N b b b c c c c c z j j j c j j d d d d i p p y p y y y y e e e e e 8 7 7 7 7 7 8 - ).).).).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).).).).).). + 3 V V V V V V V V V V V V V N V N N N N N m b N N b m b b b N b v v c c c c c c k k j c j j j j d d d p p i i y y y y y e y e e e 8 8 8 7 7 7 7 9 % ).).).).).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).).).).).).). > N N N N V N N N N N N N N m m m m m m m m b b b m b b b b c c c c k c c k k k k j j j j d d d p p p i i i y y y y e y e e e 8 8 7 7 7 7 7 < + ).).).).).).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).).).).).).).). * 0 N m b N N b m m m m m m N m m b m b b N v b b b c c c c c c c k k k k k d k d d d d p j p p i y y y y i e i e y e e e 8 7 7 7 7 7 7 : ).).).).).).).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).).).).).).).).). O , m b b b N b m m b m b b b b m b b v v v v c c c c c c j k k k k k k d d d d d d d p p p i i y y y e i e e e 8 e 8 8 7 7 7 7 7 f $ ).).).).).).).).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).).).).).).).).).).). % g b b b m b m b b b b b b c c c c c c c c c c k g k k k k k d k d d d d p d i p i i i i y y y i e y e e e 8 8 7 7 7 7 7 q - ).).).).).).).).).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).).).).).).).).).).).). X ; c v b b c c c b c c c c c c c c c k k k d = o f j k k d d d d d d p i i i i i y y y y i e e e e e e e 8 8 8 7 7 7 , + ).).).).).).).).).).).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).).).).).).).).).).).).). O : 0 c c c c c c c c c c k k k k k k 0 & + 5 d d d p d d d p i i y y y y y y e y e e e e e 8 8 7 7 8 8 8 , $ ).).).).).).).).).).).).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).).).).).).).).).).).).).).). O ; 0 c z j j c k k k k k k k k d @ # 9 d d p p i p i y i y y y y y e y y e e e 8 e 7 7 7 8 7 , $ ).).).).).).).).).).).).).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).). o - f j k k k k d d j k d d d : % 0 i p p y y i y y y y y y e y e e e e 8 8 7 7 7 9 > # ).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).). $ > 9 k d d k d d d d d d = % w y p y y y y y e e y e y e e e 8 8 8 7 w < * ).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).). & > g d d d d p d p i & * w y y y y y y e y e e e e 8 8 8 0 < - O ).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).). + = , 5 i p p i 6 % * w y e e e e e 8 e e 8 q < : % ).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).). % = : < f # = y e y g f < , - & @ ).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).). o ).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).). ).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).). ).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).). ).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).). ).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).",
+").).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).)."
+};
diff --git a/beos/res/throbber.gif b/beos/res/throbber.gif
new file mode 100644
index 000000000..f9d0c152d
--- /dev/null
+++ b/beos/res/throbber.gif
Binary files differ