From d21447d096a320a08b3efb2b8768fad0dcdcfd64 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Thu, 5 May 2016 22:28:51 +0100 Subject: move frontends into sub directory --- frontends/beos/Makefile | 102 ++ frontends/beos/Makefile.defaults | 30 + frontends/beos/WindowStack.h | 45 + frontends/beos/about.cpp | 57 + frontends/beos/about.h | 24 + frontends/beos/beos_res.rsrc | Bin 0 -> 11584 bytes frontends/beos/bitmap.cpp | 556 +++++++ frontends/beos/bitmap.h | 33 + frontends/beos/cookies.cpp | 417 ++++++ frontends/beos/cookies.h | 24 + frontends/beos/download.cpp | 264 ++++ frontends/beos/download.h | 19 + frontends/beos/fetch_rsrc.cpp | 396 +++++ frontends/beos/fetch_rsrc.h | 35 + frontends/beos/filetype.cpp | 138 ++ frontends/beos/filetype.h | 21 + frontends/beos/font.cpp | 374 +++++ frontends/beos/font.h | 37 + frontends/beos/gui.cpp | 1109 ++++++++++++++ frontends/beos/gui.h | 88 ++ frontends/beos/gui_options.cpp | 50 + frontends/beos/gui_options.h | 31 + frontends/beos/login.cpp | 196 +++ frontends/beos/options.h | 30 + frontends/beos/plotters.cpp | 659 ++++++++ frontends/beos/plotters.h | 48 + frontends/beos/res.h | 18 + frontends/beos/res.rdef | 242 +++ frontends/beos/res/SearchEngines | 1 + frontends/beos/res/adblock.css | 1 + frontends/beos/res/beosdefault.css | 22 + frontends/beos/res/ca-bundle.txt | 1 + frontends/beos/res/credits.html | 1 + frontends/beos/res/de/welcome.html | 1 + frontends/beos/res/default.css | 1 + frontends/beos/res/en/credits.html | 1 + frontends/beos/res/en/licence.html | 1 + frontends/beos/res/en/maps.html | 1 + frontends/beos/res/en/welcome.html | 1 + frontends/beos/res/favicon.png | 1 + frontends/beos/res/icons | 1 + frontends/beos/res/internal.css | 1 + frontends/beos/res/it/credits.html | 1 + frontends/beos/res/it/licence.html | 1 + frontends/beos/res/it/welcome.html | 1 + frontends/beos/res/ja/welcome.html | 1 + frontends/beos/res/licence.html | 1 + frontends/beos/res/license | 332 ++++ frontends/beos/res/maps.html | 1 + frontends/beos/res/netsurf.png | 1 + frontends/beos/res/quirks.css | 1 + frontends/beos/res/throbber/throbber0.png | Bin 0 -> 521 bytes frontends/beos/res/throbber/throbber1.png | Bin 0 -> 820 bytes frontends/beos/res/throbber/throbber2.png | Bin 0 -> 812 bytes frontends/beos/res/throbber/throbber3.png | Bin 0 -> 826 bytes frontends/beos/res/throbber/throbber4.png | Bin 0 -> 818 bytes frontends/beos/res/throbber/throbber5.png | Bin 0 -> 815 bytes frontends/beos/res/throbber/throbber6.png | Bin 0 -> 839 bytes frontends/beos/res/throbber/throbber7.png | Bin 0 -> 811 bytes frontends/beos/res/throbber/throbber8.png | Bin 0 -> 833 bytes frontends/beos/res/welcome.html | 1 + frontends/beos/scaffolding.cpp | 2332 +++++++++++++++++++++++++++++ frontends/beos/scaffolding.h | 210 +++ frontends/beos/schedule.cpp | 142 ++ frontends/beos/schedule.h | 29 + frontends/beos/search.cpp | 76 + frontends/beos/throbber.cpp | 118 ++ frontends/beos/throbber.h | 36 + frontends/beos/window.cpp | 1382 +++++++++++++++++ frontends/beos/window.h | 83 + 70 files changed, 9827 insertions(+) create mode 100644 frontends/beos/Makefile create mode 100644 frontends/beos/Makefile.defaults create mode 100644 frontends/beos/WindowStack.h create mode 100644 frontends/beos/about.cpp create mode 100644 frontends/beos/about.h create mode 100644 frontends/beos/beos_res.rsrc create mode 100644 frontends/beos/bitmap.cpp create mode 100644 frontends/beos/bitmap.h create mode 100644 frontends/beos/cookies.cpp create mode 100644 frontends/beos/cookies.h create mode 100644 frontends/beos/download.cpp create mode 100644 frontends/beos/download.h create mode 100644 frontends/beos/fetch_rsrc.cpp create mode 100644 frontends/beos/fetch_rsrc.h create mode 100644 frontends/beos/filetype.cpp create mode 100644 frontends/beos/filetype.h create mode 100644 frontends/beos/font.cpp create mode 100644 frontends/beos/font.h create mode 100644 frontends/beos/gui.cpp create mode 100644 frontends/beos/gui.h create mode 100644 frontends/beos/gui_options.cpp create mode 100644 frontends/beos/gui_options.h create mode 100644 frontends/beos/login.cpp create mode 100644 frontends/beos/options.h create mode 100644 frontends/beos/plotters.cpp create mode 100644 frontends/beos/plotters.h create mode 100644 frontends/beos/res.h create mode 100644 frontends/beos/res.rdef create mode 120000 frontends/beos/res/SearchEngines create mode 120000 frontends/beos/res/adblock.css create mode 100644 frontends/beos/res/beosdefault.css create mode 120000 frontends/beos/res/ca-bundle.txt create mode 120000 frontends/beos/res/credits.html create mode 120000 frontends/beos/res/de/welcome.html create mode 120000 frontends/beos/res/default.css create mode 120000 frontends/beos/res/en/credits.html create mode 120000 frontends/beos/res/en/licence.html create mode 120000 frontends/beos/res/en/maps.html create mode 120000 frontends/beos/res/en/welcome.html create mode 120000 frontends/beos/res/favicon.png create mode 120000 frontends/beos/res/icons create mode 120000 frontends/beos/res/internal.css create mode 120000 frontends/beos/res/it/credits.html create mode 120000 frontends/beos/res/it/licence.html create mode 120000 frontends/beos/res/it/welcome.html create mode 120000 frontends/beos/res/ja/welcome.html create mode 120000 frontends/beos/res/licence.html create mode 100644 frontends/beos/res/license create mode 120000 frontends/beos/res/maps.html create mode 120000 frontends/beos/res/netsurf.png create mode 120000 frontends/beos/res/quirks.css create mode 100644 frontends/beos/res/throbber/throbber0.png create mode 100644 frontends/beos/res/throbber/throbber1.png create mode 100644 frontends/beos/res/throbber/throbber2.png create mode 100644 frontends/beos/res/throbber/throbber3.png create mode 100644 frontends/beos/res/throbber/throbber4.png create mode 100644 frontends/beos/res/throbber/throbber5.png create mode 100644 frontends/beos/res/throbber/throbber6.png create mode 100644 frontends/beos/res/throbber/throbber7.png create mode 100644 frontends/beos/res/throbber/throbber8.png create mode 120000 frontends/beos/res/welcome.html create mode 100644 frontends/beos/scaffolding.cpp create mode 100644 frontends/beos/scaffolding.h create mode 100644 frontends/beos/schedule.cpp create mode 100644 frontends/beos/schedule.h create mode 100644 frontends/beos/search.cpp create mode 100644 frontends/beos/throbber.cpp create mode 100644 frontends/beos/throbber.h create mode 100644 frontends/beos/window.cpp create mode 100644 frontends/beos/window.h (limited to 'frontends/beos') diff --git a/frontends/beos/Makefile b/frontends/beos/Makefile new file mode 100644 index 000000000..8a79fc5ec --- /dev/null +++ b/frontends/beos/Makefile @@ -0,0 +1,102 @@ +# ---------------------------------------------------------------------------- +# BeOS target setup +# ---------------------------------------------------------------------------- + +# Linker flags +LDFLAGS += -L/boot/home/config/lib +LDFLAGS += -L/boot/common/lib +LDFLAGS += -lbe -ltranslation -ltracker -lcolumnlistview -lnetwork +ifeq ($(CC_MAJOR),2) + LDFLAGS += -lstdc++.r4 +else + LDFLAGS += -lstdc++ -lsupc++ +endif + +COMMON_WARNFLAGS += -Wno-multichar + +# compiler flags +CFLAGS += -std=c99 -Dnsbeos -D_BSD_SOURCE -D_POSIX_C_SOURCE -Drestrict="" -g +CXXFLAGS += -Dnsbeos -D_BSD_SOURCE -D_POSIX_C_SOURCE -Drestrict="" -g + +BEOS_BERES := beres +BEOS_RC := rc +BEOS_XRES := xres +BEOS_SETVER := setversion +BEOS_MIMESET := mimeset + +VERSION_FULL := $(shell sed -n '/_version.*=.*"/{s/.*"\(.*\)".*/\1/;p;}' desktop/version.c) +VERSION_MAJ := $(shell sed -n '/_major/{s/.* = \([0-9]*\).*/\1/;p;}' desktop/version.c) +VERSION_MIN := $(shell sed -n '/_minor/{s/.* = \([0-9]*\).*/\1/;p;}' desktop/version.c) + +# ---------------------------------------------------------------------------- +# Source file setup +# ---------------------------------------------------------------------------- + +# sources purely for the BeOS build +S_FRONTEND := about.cpp bitmap.cpp cookies.cpp download.cpp \ + fetch_rsrc.cpp filetype.cpp font.cpp gui.cpp login.cpp \ + gui_options.cpp plotters.cpp scaffolding.cpp search.cpp \ + schedule.cpp throbber.cpp window.cpp + +# This is the final source build list +# Note this is deliberately *not* expanded here as common and image +# are not yet available +SOURCES = $(S_COMMON) $(S_IMAGE) $(S_BROWSER) $(S_FRONTEND) +EXETARGET := NetSurf + +# The filter and target for split messages +MESSAGES_FILTER=beos +MESSAGES_TARGET=$(FRONTEND_RESOURCES_DIR) + +# ---------------------------------------------------------------------------- +# Resources +# ---------------------------------------------------------------------------- + +RDEF_BEOS := res.rdef +RDEF_BEOS := $(addprefix $(FRONTEND_SOURCE_DIR)/,$(RDEF_BEOS)) + +RDEF_IMP_BEOS := res_import.rdef +RDEF_IMP_BEOS := $(addprefix $(OBJROOT)/,$(subst /,_,$(RDEF_IMP_BEOS))) + +RDEP_BEOS := \ + adblock.css beosdefault.css default.css internal.css quirks.css \ + netsurf.png favicon.png ca-bundle.txt \ + credits.html licence.html welcome.html maps.html SearchEngines + +RDEP_BEOS := $(addprefix $(FRONTEND_RESOURCES_DIR)/,$(RDEP_BEOS)) \ + $(wildcard $(FRONTEND_RESOURCES_DIR)/icons/*.png) \ + $(wildcard $(FRONTEND_RESOURCES_DIR)/??/*) \ + $(wildcard $(FRONTEND_RESOURCES_DIR)/throbber/throbber*.png) + +RSRC_BEOS = $(addprefix $(OBJROOT)/,$(subst /,_,$(patsubst %.rdef,%.rsrc,$(RDEF_BEOS)))) +RESOURCES = $(RSRC_BEOS) + +$(RDEF_IMP_BEOS): $(RDEP_BEOS) + $(VQ)echo " GEN: $@" + $(Q)n=5000; for f in $^; do echo "resource($$n,\"$${f#beos/res/}\") #'data' import \"$${f#beos/}\";"; n=$$(($$n+1)); done > $@ + +$(RSRC_BEOS): $(RDEF_BEOS) $(RDEF_IMP_BEOS) + $(VQ)echo " RC: $<" + $(Q)$(BEOS_RC) -I beos -o $@ $^ + + +# ---------------------------------------------------------------------------- +# Install target +# ---------------------------------------------------------------------------- + +install-beos: + mkdir -p $(DESTDIR)$(NETSURF_BEOS_BIN) + mkdir -p $(DESTDIR)$(NETSURF_BEOS_RESOURCES) + @copyattr -d $(EXETARGET) $(DESTDIR)$(NETSURF_BEOS_BIN)NetSurf + @cp -vRL $(FRONTEND_RESOURCES_DIR)/adblock.css $(DESTDIR)$(NETSURF_BEOS_RESOURCES) + @cp -vRL $(FRONTEND_RESOURCES_DIR)/ca-bundle.txt $(DESTDIR)$(NETSURF_BEOS_RESOURCES) + @cp -vRL $(FRONTEND_RESOURCES_DIR)/default.css $(DESTDIR)$(NETSURF_BEOS_RESOURCES) + @cp -vRL $(FRONTEND_RESOURCES_DIR)/beosdefault.css $(DESTDIR)$(NETSURF_BEOS_RESOURCES) + @cp -vRL $(FRONTEND_RESOURCES_DIR)/license $(DESTDIR)$(NETSURF_BEOS_RESOURCES) + @cp -vRL $(FRONTEND_RESOURCES_DIR)/SearchEngines $(DESTDIR)$(NETSURF_BEOS_RESOURCES) + +# ---------------------------------------------------------------------------- +# Package target +# ---------------------------------------------------------------------------- + +package-beos: diff --git a/frontends/beos/Makefile.defaults b/frontends/beos/Makefile.defaults new file mode 100644 index 000000000..7616a41a3 --- /dev/null +++ b/frontends/beos/Makefile.defaults @@ -0,0 +1,30 @@ +# ---------------------------------------------------------------------------- +# BeOS-specific options +# ---------------------------------------------------------------------------- + +# Where to install the netsurf binary +NETSURF_BEOS_BIN := /boot/apps/netsurf/ + +# TODO:HAIKU -- not sure if ~/.netsurf applies in beos +# Where to search for NetSurf's resources after looking in ~/.netsurf and +# $NETSURFRES. It must have a trailing / +NETSURF_BEOS_RESOURCES := /boot/apps/netsurf/res/ + +# Enable NetSurf's use of libsvgtiny for displaying SVGs +# Valid options: YES, NO, AUTO +NETSURF_USE_NSSVG := YES + +# Enable NetSurf's use of librosprite for displaying RISC OS Sprites +# Valid options: YES, NO, AUTO +NETSURF_USE_ROSPRITE := AUTO + +# Enable NetSurf's use of libharu for PDF export. +# Valid options: YES, NO +NETSURF_USE_HARU_PDF := NO + +# Force using glibc internal iconv implementation instead of external libiconv +# Valid options: YES, NO +NETSURF_USE_LIBICONV_PLUG := NO + +# Optimisation levels +CFLAGS += -pipe -O2 diff --git a/frontends/beos/WindowStack.h b/frontends/beos/WindowStack.h new file mode 100644 index 000000000..947b14360 --- /dev/null +++ b/frontends/beos/WindowStack.h @@ -0,0 +1,45 @@ +/* + * Copyright 2010, Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef WINDOW_STACK_H +#define WINDOW_STACK_H + + +#include + + +class BWindowStack { +public: + BWindowStack(BWindow* window); + ~BWindowStack(); + + status_t AddWindow(const BWindow* window); + status_t AddWindow(const BMessenger& window); + status_t AddWindowAt(const BWindow* window, + int32 position); + status_t AddWindowAt(const BMessenger& window, + int32 position); + + status_t RemoveWindow(const BWindow* window); + status_t RemoveWindow(const BMessenger& window); + status_t RemoveWindowAt(int32 position, + BMessenger* window = NULL); + + int32 CountWindows(); + + status_t WindowAt(int32 position, + BMessenger& messenger); + bool HasWindow(const BWindow* window); + bool HasWindow(const BMessenger& window); + +private: + status_t _AttachMessenger(const BMessenger& window); + status_t _ReadMessenger(BMessenger& window); + status_t _StartMessage(int32 what); + + BPrivate::PortLink* fLink; +}; + + +#endif diff --git a/frontends/beos/about.cpp b/frontends/beos/about.cpp new file mode 100644 index 000000000..89eb81829 --- /dev/null +++ b/frontends/beos/about.cpp @@ -0,0 +1,57 @@ +/* + * Copyright 2008 François Revol + * + * 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 . + */ + +#define __STDBOOL_H__ 1 +#include +#include +#include +extern "C" { +#include "desktop/version.h" +#include "utils/log.h" +#include "testament.h" +#include "utils/useragent.h" +#include "curl/curlver.h" +#include "desktop/gui_clipboard.h" +} +#include "beos/about.h" +#include "beos/scaffolding.h" +#include "beos/window.h" + +#include +#include +#include +#include + + +/** + * Creates the about alert + */ +void nsbeos_about(struct gui_window *gui) +{ + BString text; + text << "Netsurf : " << user_agent_string() << "\n"; + text << "Version : " << netsurf_version << "\n"; + text << "Build ID : " << WT_REVID << "\n"; + text << "Date : " << WT_COMPILEDATE << "\n"; + text << "cURL : " << LIBCURL_VERSION << "\n"; + + BAboutWindow *alert = new BAboutWindow("About NetSurf", "application/x-vnd.NetSurf"); + alert->AddExtraInfo(text); + alert->Show(); + //TODO: i18n-ize +} diff --git a/frontends/beos/about.h b/frontends/beos/about.h new file mode 100644 index 000000000..f80d33f01 --- /dev/null +++ b/frontends/beos/about.h @@ -0,0 +1,24 @@ +/* + * Copyright 2008 François Revol + * + * 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 . + */ + +#ifndef __BEOS_ABOUT_H__ +#define __BEOS_ABOUT_H__ + +void nsbeos_about(struct gui_window *gui); + +#endif /* __BEOS_ABOUT_H__ */ diff --git a/frontends/beos/beos_res.rsrc b/frontends/beos/beos_res.rsrc new file mode 100644 index 000000000..d37e9e6ec Binary files /dev/null and b/frontends/beos/beos_res.rsrc differ diff --git a/frontends/beos/bitmap.cpp b/frontends/beos/bitmap.cpp new file mode 100644 index 000000000..26b7a3957 --- /dev/null +++ b/frontends/beos/bitmap.cpp @@ -0,0 +1,556 @@ +/* + * Copyright 2008 François Revol + * + * 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 . + */ + +/** + * \file + * BeOS implementation of generic bitmaps. + * + * This implements the interface given by image/bitmap.h using BBitmap. + */ + +#define __STDBOOL_H__ 1 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern "C" { +#include "utils/log.h" +#include "content/content.h" +#include "content/urldb.h" +#include "desktop/plotters.h" +#include "desktop/browser.h" +#include "image/bitmap.h" +} + +#include "beos/bitmap.h" +#include "beos/gui.h" +#include "beos/scaffolding.h" +#include "beos/plotters.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 src Source 32-bit pixels arranged in ABGR order. + * \param dst Output data in BGRA order. + * \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.) + */ +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 + */ +static void *bitmap_create(int width, int height, unsigned int state) +{ + struct bitmap *bmp = (struct bitmap *)malloc(sizeof(struct bitmap)); + if (bmp == NULL) + return NULL; + + int32 flags = 0; + if (state & BITMAP_CLEAR_MEMORY) + flags |= B_BITMAP_CLEAR_TO_WHITE; + + BRect frame(0, 0, width - 1, height - 1); + //XXX: bytes per row ? + bmp->primary = new BBitmap(frame, flags, B_RGBA32); + bmp->shadow = new BBitmap(frame, flags, B_RGBA32); + + bmp->pretile_x = bmp->pretile_y = bmp->pretile_xy = NULL; + + bmp->opaque = (state & BITMAP_OPAQUE) != 0; + + return bmp; +} + + +/** + * Sets whether a bitmap should be plotted opaque + * + * \param vbitmap a bitmap, as returned by bitmap_create() + * \param opaque whether the bitmap should be plotted opaque + */ +static void bitmap_set_opaque(void *vbitmap, bool opaque) +{ + struct bitmap *bitmap = (struct bitmap *)vbitmap; + assert(bitmap); + bitmap->opaque = opaque; +} + + +/** + * Tests whether a bitmap has an opaque alpha channel + * + * \param vbitmap a bitmap, as returned by bitmap_create() + * \return whether the bitmap is opaque + */ +static bool bitmap_test_opaque(void *vbitmap) +{ + struct bitmap *bitmap = (struct bitmap *)vbitmap; + assert(bitmap); + /* todo: test if bitmap is opaque */ + return false; +} + + +/** + * Gets whether a bitmap should be plotted opaque + * + * \param vbitmap a bitmap, as returned by bitmap_create() + */ +static bool bitmap_get_opaque(void *vbitmap) +{ + struct bitmap *bitmap = (struct bitmap *)vbitmap; + assert(bitmap); + return bitmap->opaque; +} + + +/** + * Return a pointer to the pixel data in a bitmap. + * + * \param vbitmap a bitmap, as returned by bitmap_create() + * \return pointer to the pixel buffer + * + * The pixel data is packed as BITMAP_FORMAT, possibly with padding at the end + * of rows. The width of a row in bytes is given by bitmap_get_rowstride(). + */ + +static unsigned char *bitmap_get_buffer(void *vbitmap) +{ + struct bitmap *bitmap = (struct bitmap *)vbitmap; + assert(bitmap); + return (unsigned char *)(bitmap->shadow->Bits()); +} + + +/** + * Find the width of a pixel row in bytes. + * + * \param vbitmap a bitmap, as returned by bitmap_create() + * \return width of a pixel row in the bitmap + */ +static size_t bitmap_get_rowstride(void *vbitmap) +{ + struct bitmap *bitmap = (struct bitmap *)vbitmap; + assert(bitmap); + return (bitmap->primary->BytesPerRow()); +} + + +/** + * Find the bytes per pixels of a bitmap. + * + * \param vbitmap a bitmap, as returned by bitmap_create() + * \return bytes per pixels of the bitmap + */ +static size_t bitmap_get_bpp(void *vbitmap) +{ + struct bitmap *bitmap = (struct bitmap *)vbitmap; + assert(bitmap); + return 4; +} + + +/** + * Free pretiles of a bitmap. + * + * \param bitmap The bitmap to free the pretiles of. + */ +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 vbitmap a bitmap, as returned by bitmap_create() + */ +static void bitmap_destroy(void *vbitmap) +{ + struct bitmap *bitmap = (struct bitmap *)vbitmap; + 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 vbitmap 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 + */ +static bool bitmap_save(void *vbitmap, const char *path, unsigned flags) +{ + struct bitmap *bitmap = (struct bitmap *)vbitmap; + BTranslatorRoster *roster = BTranslatorRoster::Default(); + BBitmapStream stream(bitmap->primary); + BFile file(path, B_WRITE_ONLY | B_CREATE_FILE); + uint32 type = B_PNG_FORMAT; + + if (file.InitCheck() < B_OK) + return false; + + if (roster->Translate(&stream, NULL, NULL, &file, type) < B_OK) + return false; + + return true; +} + + +/** + * The bitmap image has changed, so flush any persistant cache. + * + * \param vbitmap a bitmap, as returned by bitmap_create() + */ +void bitmap_modified(void *vbitmap) +{ + struct bitmap *bitmap = (struct bitmap *)vbitmap; + // 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); +} + + +static int bitmap_get_width(void *vbitmap) +{ + struct bitmap *bitmap = (struct bitmap *)vbitmap; + return bitmap->primary->Bounds().Width() + 1; +} + + +static int bitmap_get_height(void *vbitmap) +{ + struct bitmap *bitmap = (struct bitmap *)vbitmap; + return bitmap->primary->Bounds().Height() + 1; +} + + +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; + +} + + +/** + * 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; +} + + +/** + * Create a thumbnail of a page. + * + * \param bitmap the bitmap to draw to + * \param content content structure to thumbnail + * \return true on success and bitmap updated else false + */ +static nserror bitmap_render(struct bitmap *bitmap, hlcache_handle *content) +{ + BBitmap *thumbnail; + BBitmap *small; + BBitmap *big; + BView *oldView; + BView *view; + BView *thumbView; + float width; + float height; + int big_width; + int big_height; + int depth; + + struct redraw_context ctx; + ctx.interactive = false; + ctx.background_images = true; + ctx.plot = &nsbeos_plotters; + + assert(content); + assert(bitmap); + + thumbnail = nsbeos_bitmap_get_primary(bitmap); + width = thumbnail->Bounds().Width(); + height = thumbnail->Bounds().Height(); + depth = 32; + + big_width = MIN(content_get_width(content), 1024); + big_height = (int)(((big_width * height) + (width / 2)) / width); + + BRect contentRect(0, 0, big_width - 1, big_height - 1); + big = new BBitmap(contentRect, B_BITMAP_ACCEPTS_VIEWS, B_RGB32); + + if (big->InitCheck() < B_OK) { + delete big; + return NSERROR_NOMEM; + } + + small = new BBitmap(thumbnail->Bounds(), + B_BITMAP_ACCEPTS_VIEWS, B_RGB32); + + if (small->InitCheck() < B_OK) { + delete small; + delete big; + return NSERROR_NOMEM; + } + + //XXX: _lock ? + // backup the current gc + oldView = nsbeos_current_gc(); + + view = new BView(contentRect, "thumbnailer", + B_FOLLOW_NONE, B_WILL_DRAW); + big->AddChild(view); + + thumbView = new BView(small->Bounds(), "thumbnail", + B_FOLLOW_NONE, B_WILL_DRAW); + small->AddChild(thumbView); + + view->LockLooper(); + + /* impose our view on the content... */ + nsbeos_current_gc_set(view); + + /* render the content */ + content_scaled_redraw(content, big_width, big_height, &ctx); + + view->Sync(); + view->UnlockLooper(); + + // restore the current gc + nsbeos_current_gc_set(oldView); + + + // now scale it down + //XXX: use Zeta's bilinear scaler ? + //#ifdef B_ZETA_VERSION + // err = ScaleBitmap(*shot, *scaledBmp); + //#else + thumbView->LockLooper(); + thumbView->DrawBitmap(big, big->Bounds(), small->Bounds()); + thumbView->Sync(); + thumbView->UnlockLooper(); + + small->LockBits(); + thumbnail->LockBits(); + + // copy it to the bitmap + memcpy(thumbnail->Bits(), small->Bits(), thumbnail->BitsLength()); + + thumbnail->UnlockBits(); + small->UnlockBits(); + + bitmap_modified(bitmap); + + // cleanup + small->RemoveChild(thumbView); + delete thumbView; + delete small; + big->RemoveChild(view); + delete view; + delete big; + + return NSERROR_OK; +} + + +static struct gui_bitmap_table bitmap_table = { + /*.create =*/ bitmap_create, + /*.destroy =*/ bitmap_destroy, + /*.set_opaque =*/ bitmap_set_opaque, + /*.get_opaque =*/ bitmap_get_opaque, + /*.test_opaque =*/ bitmap_test_opaque, + /*.get_buffer =*/ bitmap_get_buffer, + /*.get_rowstride =*/ bitmap_get_rowstride, + /*.get_width =*/ bitmap_get_width, + /*.get_height =*/ bitmap_get_height, + /*.get_bpp =*/ bitmap_get_bpp, + /*.save =*/ bitmap_save, + /*.modified =*/ bitmap_modified, + /*.render =*/ bitmap_render, +}; + +struct gui_bitmap_table *beos_bitmap_table = &bitmap_table; diff --git a/frontends/beos/bitmap.h b/frontends/beos/bitmap.h new file mode 100644 index 000000000..bcf5f7b8d --- /dev/null +++ b/frontends/beos/bitmap.h @@ -0,0 +1,33 @@ +/* + * Copyright 2008 François Revol + * + * 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 . + */ + +#ifndef NS_BEOS_BITMAP_H +#define NS_BEOS_BITMAP_H + +#include + +extern struct gui_bitmap_table *beos_bitmap_table; + +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*); + +void bitmap_modified(void *vbitmap); + +#endif /* NS_BEOS_BITMAP_H */ diff --git a/frontends/beos/cookies.cpp b/frontends/beos/cookies.cpp new file mode 100644 index 000000000..d1357fffa --- /dev/null +++ b/frontends/beos/cookies.cpp @@ -0,0 +1,417 @@ +/* + * Copyright 2015 Adrián Arroyo Calle + * + * 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 . + */ + +#define __STDBOOL_H__ 1 +#include +#include +#include +extern "C" { +#include "desktop/mouse.h" +#include "utils/log.h" +#include "desktop/cookie_manager.h" +#include "desktop/plotters.h" +#include "desktop/tree.h" +#include "desktop/textinput.h" +#include "content/urldb.h" +} +#include "beos/cookies.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static std::vector cookieJar; + +class CookieWindow : public BWindow { +public: + CookieWindow(BRect frame); + virtual void MessageReceived(BMessage* message); + virtual void Show(); + virtual bool QuitRequested(); + +private: + void _BuildDomainList(); + BStringItem* _AddDomain(BString domain, bool fake); + void _ShowCookiesForDomain(BString domain); + void _DeleteCookies(); + +private: + BOutlineListView* fDomains; + BColumnListView* fCookies; + BStringView* fHeaderView; +}; + +enum { + COOKIE_IMPORT = 'cimp', + COOKIE_EXPORT = 'cexp', + COOKIE_DELETE = 'cdel', + COOKIE_REFRESH = 'rfsh', + + DOMAIN_SELECTED = 'dmsl' +}; + + +class CookieDateColumn: public BDateColumn +{ +public: + CookieDateColumn(const char* title, float width) + : + BDateColumn(title, width, width / 2, width * 2) + { + } + + void DrawField(BField* field, BRect rect, BView* parent) { + BDateField* dateField = (BDateField*)field; + if (dateField->UnixTime() == -1) { + DrawString("Session cookie", parent, rect); + } else { + BDateColumn::DrawField(field, rect, parent); + } + } +}; + + +class CookieRow: public BRow +{ +public: + CookieRow(BColumnListView* list, struct cookie_data& cookie) + : + BRow(), + fCookie(cookie) + { + list->AddRow(this); + SetField(new BStringField(cookie.name), 0); + SetField(new BStringField(cookie.path), 1); + time_t expiration = cookie.expires; + SetField(new BDateField(&expiration), 2); + SetField(new BStringField(cookie.value), 3); + + BString flags; + if (cookie.secure) + flags = "https "; + if (cookie.http_only) + flags = "http "; + + SetField(new BStringField(flags.String()), 4); + } + +public: + struct cookie_data fCookie; +}; + + +class DomainItem: public BStringItem +{ +public: + DomainItem(BString text, bool empty) + : + BStringItem(text), + fEmpty(empty) + { + } + +public: + bool fEmpty; +}; + + +CookieWindow::CookieWindow(BRect frame) + : + BWindow(frame,"Cookie manager", B_TITLED_WINDOW, + B_NORMAL_WINDOW_FEEL, + B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS) +{ + BGroupLayout* root = new BGroupLayout(B_HORIZONTAL, 0.0); + SetLayout(root); + + fDomains = new BOutlineListView("domain list"); + root->AddView(new BScrollView("scroll", fDomains, 0, false, true), 1); + + fHeaderView = new BStringView("label","The cookie jar is empty!"); + fCookies = new BColumnListView("cookie list", B_WILL_DRAW, B_FANCY_BORDER, + false); + + float em = fCookies->StringWidth("M"); + float flagsLength = fCookies->StringWidth("Mhttps hostOnly" B_UTF8_ELLIPSIS); + + fCookies->AddColumn(new BStringColumn("Name", + 20 * em, 10 * em, 50 * em, 0), 0); + fCookies->AddColumn(new BStringColumn("Path", + 10 * em, 10 * em, 50 * em, 0), 1); + fCookies->AddColumn(new CookieDateColumn("Expiration", + fCookies->StringWidth("88/88/8888 88:88:88 AM")), 2); + fCookies->AddColumn(new BStringColumn("Value", + 20 * em, 10 * em, 50 * em, 0), 3); + fCookies->AddColumn(new BStringColumn("Flags", + flagsLength, flagsLength, flagsLength, 0), 4); + + root->AddItem(BGroupLayoutBuilder(B_VERTICAL, B_USE_DEFAULT_SPACING) + .SetInsets(5, 5, 5, 5) + .AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING) + .Add(fHeaderView) + .AddGlue() + .End() + .Add(fCookies) + .AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING) + .SetInsets(5, 5, 5, 5) + .AddGlue() + .Add(new BButton("delete", "Delete", + new BMessage(COOKIE_DELETE))), 3); + + fDomains->SetSelectionMessage(new BMessage(DOMAIN_SELECTED)); +} + + +void +CookieWindow::MessageReceived(BMessage* message) +{ + switch(message->what) { + case DOMAIN_SELECTED: + { + int32 index = message->FindInt32("index"); + BStringItem* item = (BStringItem*)fDomains->ItemAt(index); + if (item != NULL) { + BString domain = item->Text(); + _ShowCookiesForDomain(domain); + } + return; + } + + case COOKIE_REFRESH: + _BuildDomainList(); + return; + + case COOKIE_DELETE: + _DeleteCookies(); + return; + } + BWindow::MessageReceived(message); +} + + +void +CookieWindow::Show() +{ + BWindow::Show(); + if (IsHidden()) + return; + + PostMessage(COOKIE_REFRESH); +} + + +bool +CookieWindow::QuitRequested() +{ + if (!IsHidden()) + Hide(); + cookieJar.clear(); + return false; +} + + +void +CookieWindow::_BuildDomainList() +{ + // Empty the domain list (TODO should we do this when hiding instead?) + for (int i = fDomains->FullListCountItems() - 1; i >= 1; i--) { + delete fDomains->FullListItemAt(i); + } + fDomains->MakeEmpty(); + + // BOutlineListView does not handle parent = NULL in many methods, so let's + // make sure everything always has a parent. + DomainItem* rootItem = new DomainItem("", true); + fDomains->AddItem(rootItem); + + // Populate the domain list - TODO USE STL VECTOR + + + for(std::vector::iterator it = cookieJar.begin(); it != cookieJar.end(); ++it) { + _AddDomain((*it)->domain, false); + } + + int i = 1; + while (i < fDomains->FullListCountItems()) + { + DomainItem* item = (DomainItem*)fDomains->FullListItemAt(i); + // Detach items from the fake root + item->SetOutlineLevel(item->OutlineLevel() - 1); + i++; + } + fDomains->RemoveItem(rootItem); + delete rootItem; + + i = 0; + int firstNotEmpty = i; + // Collapse empty items to keep the list short + while (i < fDomains->FullListCountItems()) + { + DomainItem* item = (DomainItem*)fDomains->FullListItemAt(i); + if (item->fEmpty == true) { + if (fDomains->CountItemsUnder(item, true) == 1) { + // The item has no cookies, and only a single child. We can + // remove it and move its child one level up in the tree. + + int count = fDomains->CountItemsUnder(item, false); + int index = fDomains->FullListIndexOf(item) + 1; + for (int j = 0; j < count; j++) { + BListItem* child = fDomains->FullListItemAt(index + j); + child->SetOutlineLevel(child->OutlineLevel() - 1); + } + + fDomains->RemoveItem(item); + delete item; + + // The moved child is at the same index the removed item was. + // We continue the loop without incrementing i to process it. + continue; + } else { + // The item has no cookies, but has multiple children. Mark it + // as disabled so it is not selectable. + item->SetEnabled(false); + if (i == firstNotEmpty) + firstNotEmpty++; + } + } + + i++; + } + + fDomains->Select(firstNotEmpty); +} + + +BStringItem* +CookieWindow::_AddDomain(BString domain, bool fake) +{ + BStringItem* parent = NULL; + int firstDot = domain.FindFirst('.'); + if (firstDot >= 0) { + BString parentDomain(domain); + parentDomain.Remove(0, firstDot + 1); + parent = _AddDomain(parentDomain, true); + } else { + parent = (BStringItem*)fDomains->FullListItemAt(0); + } + + BListItem* existing; + int i = 0; + // check that we aren't already there + while ((existing = fDomains->ItemUnderAt(parent, true, i++)) != NULL) { + DomainItem* stringItem = (DomainItem*)existing; + if (stringItem->Text() == domain) { + if (fake == false) + stringItem->fEmpty = false; + return stringItem; + } + } + + // Insert the new item, keeping the list alphabetically sorted + BStringItem* domainItem = new DomainItem(domain, fake); + domainItem->SetOutlineLevel(parent->OutlineLevel() + 1); + BStringItem* sibling = NULL; + int siblingCount = fDomains->CountItemsUnder(parent, true); + for (i = 0; i < siblingCount; i++) { + sibling = (BStringItem*)fDomains->ItemUnderAt(parent, true, i); + if (strcmp(sibling->Text(), domainItem->Text()) > 0) { + fDomains->AddItem(domainItem, fDomains->FullListIndexOf(sibling)); + return domainItem; + } + } + + if (sibling) { + // There were siblings, but all smaller than what we try to insert. + // Insert after the last one (and its subitems) + fDomains->AddItem(domainItem, fDomains->FullListIndexOf(sibling) + + fDomains->CountItemsUnder(sibling, false) + 1); + } else { + // There were no siblings, insert right after the parent + fDomains->AddItem(domainItem, fDomains->FullListIndexOf(parent) + 1); + } + + return domainItem; +} + + +void +CookieWindow::_ShowCookiesForDomain(BString domain) +{ + BString label; + label.SetToFormat("Cookies for %s", domain.String()); + fHeaderView->SetText(label); + + // Empty the cookie list + fCookies->Clear(); + + // Populate the domain list + + for(std::vector::iterator it = cookieJar.begin(); it != cookieJar.end(); ++it) { + if((*it)->domain == domain) { + new CookieRow(fCookies,**it); + } + } +} + +static bool nsbeos_cookie_parser(const struct cookie_data* data) +{ + cookieJar.push_back((struct cookie_data*)data); + return true; +} + +void +CookieWindow::_DeleteCookies() +{ + // TODO shall we handle multiple selection here? + CookieRow* row = (CookieRow*)fCookies->CurrentSelection(); + if (row == NULL) { + // TODO see if a domain is selected in the domain list, and delete all + // cookies for that domain + return; + } + + fCookies->RemoveRow(row); + + urldb_delete_cookie(row->fCookie.domain, row->fCookie.path, row->fCookie.name); + cookieJar.clear(); + urldb_iterate_cookies(&nsbeos_cookie_parser); + + delete row; +} + +/** + * Creates the Cookie Manager + */ +void nsbeos_cookies_init(void) +{ + CookieWindow* cookWin=new CookieWindow(BRect(100,100,700,500)); + cookWin->Show(); + cookWin->Activate(); + urldb_iterate_cookies(&nsbeos_cookie_parser); +} diff --git a/frontends/beos/cookies.h b/frontends/beos/cookies.h new file mode 100644 index 000000000..977ccd232 --- /dev/null +++ b/frontends/beos/cookies.h @@ -0,0 +1,24 @@ +/* + * Copyright 2015 Adrián Arroyo Calle + * + * 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 . + */ + +#ifndef __BEOS_COOKIES_H__ +#define __BEOS_COOKIES_H__ + +void nsbeos_cookies_init(); + +#endif /* __BEOS_ABOUT_H__ */ diff --git a/frontends/beos/download.cpp b/frontends/beos/download.cpp new file mode 100644 index 000000000..ea0271e60 --- /dev/null +++ b/frontends/beos/download.cpp @@ -0,0 +1,264 @@ +/* + * Copyright 2012 Adrien Destugues + * + * 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 . + */ + +#define __STDBOOL_H__ 1 +#include +#include +#include + +extern "C" { +#include "desktop/download.h" +#include "desktop/gui_download.h" +#include "utils/utils.h" +#include "utils/string.h" +} +#include "beos/download.h" + +#include +#include +#include +#include +#include +#include + +class NSDownloadWindow: public BWindow +{ + public: + NSDownloadWindow(download_context* ctx); + ~NSDownloadWindow(); + + void MessageReceived(BMessage* message); + + void Progress(int size); + void Failure(const char* error); + void Success(); + private: + download_context* ctx; + BStatusBar* bar; + unsigned long progress; + bool success; +}; + + +struct gui_download_window { + download_context* ctx; + NSDownloadWindow* window; + + BLocker* storageLock; + BDataIO* storage; +}; + + +NSDownloadWindow::NSDownloadWindow(download_context* ctx) + : BWindow(BRect(30, 30, 400, 200), "Downloads", B_TITLED_WINDOW, + B_NOT_RESIZABLE) + , ctx(ctx) + , progress(0) + , success(false) +{ + unsigned long dlsize = download_context_get_total_length(ctx); + char* buffer = human_friendly_bytesize(dlsize); + + // Create the status bar + BRect rect = Bounds(); + rect.InsetBy(3, 3); + bar = new BStatusBar(rect, "progress", + download_context_get_filename(ctx), buffer); + bar->SetMaxValue(dlsize); + + // Create the backgroundview (just so that the area around the progress bar + // is B_PANEL_BACKGROUND_COLOR instead of white) + BView* back = new BView(Bounds(), "back", B_FOLLOW_ALL_SIDES, B_WILL_DRAW); + back->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + + // Add the views to the window + back->AddChild(bar); + AddChild(back); + + // Resize the window to leave a margin around the progress bar + BRect size = bar->Bounds(); + ResizeTo(size.Width() + 6, size.Height() + 6); + Show(); +} + + +NSDownloadWindow::~NSDownloadWindow() +{ + download_context_abort(ctx); + download_context_destroy(ctx); +} + + +void +NSDownloadWindow::MessageReceived(BMessage* message) +{ + switch(message->what) + { + case B_SAVE_REQUESTED: + { + entry_ref directory; + const char* name; + struct gui_download_window* dw; + BFilePanel* source; + + message->FindRef("directory", &directory); + message->FindString("name", &name); + message->FindPointer("dw", (void**)&dw); + + BDirectory dir(&directory); + BFile* storage = new BFile(&dir, name, + B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE); + dw->storageLock->Lock(); + + BMallocIO* tempstore = dynamic_cast(dw->storage); + + storage->Write(tempstore->Buffer(), tempstore->BufferLength()); + delete dw->storage; + + if (success) + delete storage; // File is already finished downloading ! + else + dw->storage = storage; + dw->storageLock->Unlock(); + + message->FindPointer("source", (void**)&source); + delete source; + + break; + } + default: + BWindow::MessageReceived(message); + } +} + + +void +NSDownloadWindow::Progress(int size) +{ + progress += size; + + char* buffer = human_friendly_bytesize(progress); + strcat(buffer, "/"); + + bar->LockLooper(); + bar->Update(size, NULL, buffer); + bar->Invalidate(); + bar->UnlockLooper(); +} + + +void +NSDownloadWindow::Success() +{ + bar->LockLooper(); + bar->SetBarColor(ui_color(B_SUCCESS_COLOR)); + bar->UnlockLooper(); + + success = true; +} + + +void +NSDownloadWindow::Failure(const char* error) +{ + bar->LockLooper(); + bar->Update(0, NULL, error); + bar->SetBarColor(ui_color(B_FAILURE_COLOR)); + bar->UnlockLooper(); +} + + +static struct gui_download_window *gui_download_window_create(download_context *ctx, + struct gui_window *parent) +{ + struct gui_download_window *download = (struct gui_download_window*)malloc(sizeof *download); + if (download == NULL) + return NULL; + + download->storageLock = new BLocker("storage_lock"); + download->storage = new BMallocIO(); + download->ctx = ctx; + + download->window = new NSDownloadWindow(ctx); + + // Also ask the user where to save the file + BMessage* msg = new BMessage(B_SAVE_REQUESTED); + + BFilePanel* panel = new BFilePanel(B_SAVE_PANEL, + new BMessenger(download->window), NULL, 0, false); + + panel->SetSaveText(download_context_get_filename(ctx)); + + msg->AddPointer("source", panel); + msg->AddPointer("dw", download); + panel->SetMessage(msg); + + panel->Show(); + + return download; +} + + +static nserror gui_download_window_data(struct gui_download_window *dw, + const char *data, unsigned int size) +{ + dw->window->Progress(size); + + dw->storageLock->Lock(); + dw->storage->Write(data, size); + dw->storageLock->Unlock(); + + return NSERROR_OK; +} + + +static void gui_download_window_error(struct gui_download_window *dw, + const char *error_msg) +{ + dw->window->Failure(error_msg); + + delete dw->storageLock; + delete dw->storage; +} + + +static void gui_download_window_done(struct gui_download_window *dw) +{ + dw->window->Success(); + + dw->storageLock->Lock(); + + // Only delete if the storage is already a file. Else, we must wait for the + // user to select something in the BFilePanel! + BFile* file = dynamic_cast(dw->storage); + delete file; + if (file) + delete dw->storageLock; + else + dw->storageLock->Unlock(); +} + +static struct gui_download_table download_table = { + gui_download_window_create, + gui_download_window_data, + gui_download_window_error, + gui_download_window_done, +}; + +struct gui_download_table *beos_download_table = &download_table; + diff --git a/frontends/beos/download.h b/frontends/beos/download.h new file mode 100644 index 000000000..0ce387efc --- /dev/null +++ b/frontends/beos/download.h @@ -0,0 +1,19 @@ +/* + * Copyright 2012 Adrien Destugues + * + * 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 . + */ + +extern struct gui_download_table *beos_download_table; diff --git a/frontends/beos/fetch_rsrc.cpp b/frontends/beos/fetch_rsrc.cpp new file mode 100644 index 000000000..b771f7b2d --- /dev/null +++ b/frontends/beos/fetch_rsrc.cpp @@ -0,0 +1,396 @@ +/* + * Copyright 2008 François Revol + * Copyright 2008 Rob Kendrick + * + * 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 . + */ + +/* rsrc: URL handling. */ + +#define __STDBOOL_H__ 1 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for URL unescaping functions */ +extern "C" { +#include "utils/config.h" +#include "content/fetch.h" +#include "content/fetchers.h" +#include "content/urldb.h" +#include "utils/nsoption.h" +#include "utils/log.h" +#include "utils/messages.h" +#include "utils/utils.h" +#include "utils/ring.h" +#include "utils/base64.h" +} +#include "beos/fetch_rsrc.h" +#include "beos/filetype.h" +#include "beos/gui.h" + +#include +#include +#include + +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; + +BResources *gAppResources = NULL; + +static bool fetch_rsrc_initialise(lwc_string *scheme) +{ + LOG("fetch_rsrc_initialise called for %s", lwc_string_data(scheme)); + return true; +} + +static void fetch_rsrc_finalise(lwc_string *scheme) +{ + LOG("fetch_rsrc_finalise called for %s", lwc_string_data(scheme)); +} + +static bool fetch_rsrc_can_fetch(const nsurl *url) +{ + return true; +} + +static void *fetch_rsrc_setup(struct fetch *parent_fetch, nsurl *url, + bool only_2xx, bool downgrade_tls, const char *post_urlenc, + const struct fetch_multipart_data *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; + /* TODO: keep as nsurl to avoid copy */ + ctx->url = (char *)malloc(nsurl_length(url) + 1); + + if (ctx->url == NULL) { + free(ctx); + return NULL; + } + memcpy(ctx->url, nsurl_access(url), nsurl_length(url) + 1); + + 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(const fetch_msg *msg, + struct fetch_rsrc_context *c) +{ + c->locked = true; + fetch_send_callback(msg, c->parent_fetch); + c->locked = false; +} + +static bool fetch_rsrc_process(struct fetch_rsrc_context *c) +{ + fetch_msg msg; + 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) < 7) { + /* 7 is the minimum possible length (rsrc://) */ + msg.type = FETCH_ERROR; + msg.data.error = "Malformed rsrc: URL"; + fetch_rsrc_send_callback(&msg, c); + return false; + } + + /* skip the rsrc: part */ + params = c->url + sizeof("rsrc://") - 1; + + /* find the slash */ + if ( (slash = strchr(params, '/')) == NULL) { + msg.type = FETCH_ERROR; + msg.data.error = "Malformed rsrc: URL"; + fetch_rsrc_send_callback(&msg, c); + return false; + } + + // doesn't exist in the filesystem but we should hit the internal types. + c->mimetype = strdup(fetch_filetype(slash)); + c->name = strdup(slash + 1); + + if (c->mimetype == NULL) { + msg.type = FETCH_ERROR; + msg.data.error = + "Unable to allocate memory for mimetype in rsrc: URL"; + fetch_rsrc_send_callback(&msg, c); + 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; + LOG("fetch_rsrc: type:%4.4s\n", (char *)&type); + } + } + + LOG("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) { + BString error("Cannot locate resource: "); + if (id) + error << id; + else + error << c->name; + msg.type = FETCH_ERROR; + msg.data.error = error.String(); + fetch_rsrc_send_callback(&msg, c); + 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) { + msg.type = FETCH_ERROR; + msg.data.error = "Cannot load rsrc: URL"; + fetch_rsrc_send_callback(&msg, c); + return false; + } + + c->datalen = len; + c->data = (char *)malloc(c->datalen); + if (c->data == NULL) { + msg.type = FETCH_ERROR; + msg.data.error = "Unable to allocate memory for rsrc: URL"; + fetch_rsrc_send_callback(&msg, c); + return false; + } + memcpy(c->data, data, c->datalen); + + return true; +} + +static void fetch_rsrc_poll(lwc_string *scheme) +{ + fetch_msg msg; + struct fetch_rsrc_context *c, *next; + + if (ring == NULL) return; + + /* 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) { + char header[64]; + + 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(). + */ + snprintf(header, sizeof header, "Content-Type: %s", + c->mimetype); + msg.type = FETCH_HEADER; + msg.data.header_or_data.buf = (const uint8_t *) header; + msg.data.header_or_data.len = strlen(header); + fetch_rsrc_send_callback(&msg, c); + + snprintf(header, sizeof header, "Content-Length: %zd", + c->datalen); + msg.type = FETCH_HEADER; + msg.data.header_or_data.buf = (const uint8_t *) header; + msg.data.header_or_data.len = strlen(header); + fetch_rsrc_send_callback(&msg, c); + + if (!c->aborted) { + msg.type = FETCH_DATA; + msg.data.header_or_data.buf = (const uint8_t *) c->data; + msg.data.header_or_data.len = c->datalen; + fetch_rsrc_send_callback(&msg, c); + } + if (!c->aborted) { + msg.type = FETCH_FINISHED; + fetch_rsrc_send_callback(&msg, c); + } + } 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() +{ + char path[B_PATH_NAME_LENGTH]; + if (nsbeos_find_app_path(path) < B_OK) + 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; +} + +BResources *get_app_resources() +{ + return gAppResources; +} + +void fetch_rsrc_register(void) +{ + lwc_string *scheme; + int err; + nserror ret; + + const struct fetcher_operation_table fetcher_ops_rsrc = { + fetch_rsrc_initialise, + fetch_rsrc_can_fetch, + fetch_rsrc_setup, + fetch_rsrc_start, + fetch_rsrc_abort, + fetch_rsrc_free, + fetch_rsrc_poll, + fetch_rsrc_finalise + }; + + err = find_app_resources(); + + if (err < B_OK) { + beos_warn_user("Resources", strerror(err)); + return; + } + + if (lwc_intern_string("rsrc", SLEN("rsrc"), &scheme) != lwc_error_ok) { + die("Failed to initialise the fetch module " + "(couldn't intern \"rsrc\")."); + } + + ret = fetcher_add(scheme, &fetcher_ops_rsrc); + if (ret != NSERROR_OK) { + die("unable to add rsrc fetcher."); + } +} + +void fetch_rsrc_unregister(void) +{ + delete gAppResources; + gAppResources = NULL; +} diff --git a/frontends/beos/fetch_rsrc.h b/frontends/beos/fetch_rsrc.h new file mode 100644 index 000000000..ce17670a4 --- /dev/null +++ b/frontends/beos/fetch_rsrc.h @@ -0,0 +1,35 @@ +/* + * Copyright 2008 François Revol + * Copyright 2008 Rob Kendrick + * + * 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 . + */ + +/** \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); + +class BResources; +BResources *get_app_resources(); + +#include "beos/res.h" + +#endif diff --git a/frontends/beos/filetype.cpp b/frontends/beos/filetype.cpp new file mode 100644 index 000000000..75a33240a --- /dev/null +++ b/frontends/beos/filetype.cpp @@ -0,0 +1,138 @@ +/* + * Copyright 2008 François Revol + * + * 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 . + */ + +#define __STDBOOL_H__ 1 +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +extern "C" { +#include "content/fetch.h" +#include "utils/log.h" +#include "utils/hashtable.h" +#include "utils/utils.h" +} + +#include "beos/filetype.h" +#include "beos/gui.h" + +static struct { + const char *type; + const char *ext1; + const char *ext2; +} default_types[] = { + { "text/plain", "txt", NULL }, + { "text/html", "htm", "html" }, + { "text/css", "css", NULL }, + { "image/gif", "gif", NULL }, + { "image/jpeg", "jpg", "jpeg" }, + { "image/png", "png", NULL }, + { "image/jng", "jng", NULL }, + { NULL, NULL, NULL } +}; + +void beos_fetch_filetype_init(void) +{ + BMimeType m; + status_t err; + int i; + + // make sure we have basic mime types in the database + for (i = 0; default_types[i].type; i++) { + if (m.SetTo(default_types[i].type) < B_OK) + continue; + if (m.IsInstalled()) + continue; + err = m.Install(); + if (err < B_OK) { + beos_warn_user("Mime", strerror(err)); + continue; + } + // the mime db doesn't know about it yet + BMessage extensions('exts'); + if (default_types[i].ext1) + extensions.AddString("extensions", default_types[i].ext1); + if (default_types[i].ext2) + extensions.AddString("extensions", default_types[i].ext2); + err = m.SetFileExtensions(&extensions); + if (err < B_OK) { + beos_warn_user("Mime", strerror(err)); + } + } +} + +void beos_fetch_filetype_fin(void) +{ +} + +const char *fetch_filetype(const char *unix_path) +{ + struct stat statbuf; + status_t err; + int i; + // NOT THREADSAFE + static char type[B_MIME_TYPE_LENGTH]; + + // override reading the mime type for known types + // avoids getting CSS files as text/x-source-code + // even though it's the mime sniffer rules that should be fixed. + BString ext(unix_path); + ext.Remove(0, ext.FindLast('.') + 1); + for (i = 0; default_types[i].type; i++) { + if (ext == default_types[i].ext1) + return default_types[i].type; + if (ext == default_types[i].ext2) + return default_types[i].type; + } + + BEntry entry(unix_path, true); + BNode node(&entry); + err = node.InitCheck(); + if (err < B_OK) + return "text/plain"; + + if (node.IsDirectory()) + return "application/x-netsurf-directory"; + + BNodeInfo info(&node); + err = info.InitCheck(); + if (err < B_OK) + return "test/plain"; + + err = info.GetType(type); + if (err < B_OK) { + // not there yet, sniff and retry + err = update_mime_info(unix_path, false, true, false); + if (err < B_OK) + return "text/plain"; + err = info.GetType(type); + if (err < B_OK) + return "text/plain"; + } + + return type; +} diff --git a/frontends/beos/filetype.h b/frontends/beos/filetype.h new file mode 100644 index 000000000..72252dbd0 --- /dev/null +++ b/frontends/beos/filetype.h @@ -0,0 +1,21 @@ +/* + * Copyright 2008 François Revol + * + * 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 . + */ + +void beos_fetch_filetype_init(void); +void beos_fetch_filetype_fin(void); +const char *fetch_filetype(const char *unix_path); diff --git a/frontends/beos/font.cpp b/frontends/beos/font.cpp new file mode 100644 index 000000000..003af52b5 --- /dev/null +++ b/frontends/beos/font.cpp @@ -0,0 +1,374 @@ +/* + * Copyright 2008 François Revol + * + * 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 . + */ + +/** \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 ? + */ + + +#define __STDBOOL_H__ 1 +#include +#include +#include +#include +#include +#include + +extern "C" { +#include "utils/utils.h" +#include "utils/log.h" +#include "utils/nsoption.h" +#include "utils/nsurl.h" +#include "desktop/gui_layout.h" +} + +#include "beos/gui.h" +#include "beos/font.h" +#include "beos/plotters.h" + + +/** + * Convert a font style to a PangoFontDescription. + * + * \param font Beos font object. + * \param fstyle style for this text + */ +void nsbeos_style_to_font(BFont &font, const struct plot_font_style *fstyle) +{ + float size; + uint16 face = 0; + const char *family; + + switch (fstyle->family) { + case PLOT_FONT_FAMILY_SERIF: + family = nsoption_charp(font_serif); + break; + case PLOT_FONT_FAMILY_MONOSPACE: + family = nsoption_charp(font_mono); + break; + case PLOT_FONT_FAMILY_CURSIVE: + family = nsoption_charp(font_cursive); + break; + case PLOT_FONT_FAMILY_FANTASY: + family = nsoption_charp(font_fantasy); + break; + case PLOT_FONT_FAMILY_SANS_SERIF: + default: + family = nsoption_charp(font_sans); + break; + } + + if ((fstyle->flags & FONTF_ITALIC)) { + face = B_ITALIC_FACE; + } else if ((fstyle->flags & FONTF_OBLIQUE)) { + face = B_ITALIC_FACE; + // XXX: no OBLIQUE flag ?? + // maybe find "Oblique" style + // or use SetShear() ? + } + +#ifndef __HAIKU__XXX + if (fstyle->weight >= 600) { + face |= B_BOLD_FACE; + } +#else + if (fstyle->weight >= 600) { + if (fstyle->weight >= 800) + face |= B_HEAVY_FACE; + else + face |= B_BOLD_FACE; + } else if (fstyle->weight <= 300) { + face |= B_LIGHT_FACE; + } +#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; +*/ + + if (!face) + face = B_REGULAR_FACE; + +//fprintf(stderr, "nsbeos_style_to_font: %d, %d, %d -> '%s' %04x\n", style->font_family, style->font_style, style->font_weight, family, face); + + if (family) { + font_family beos_family; + + strncpy(beos_family, family, B_FONT_FAMILY_LENGTH); + // Ensure it's terminated + beos_family[B_FONT_FAMILY_LENGTH] = '\0'; + + font.SetFamilyAndFace(beos_family, face); + } else { + //XXX not used + font = be_plain_font; + font.SetFace(face); + } + +//fprintf(stderr, "nsbeos_style_to_font: value %f unit %d\n", style->font_size.value.length.value, style->font_size.value.length.unit); + size = fstyle->size / FONT_SIZE_SCALE; + +//fprintf(stderr, "nsbeos_style_to_font: %f %d\n", size, style->font_size.value.length.unit); + + font.SetSize(size); +} + + +/** + * Measure the width of a string. + * + * \param fstyle style for this text + * \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 + */ +static nserror beos_font_width(const plot_font_style_t *fstyle, + const char *string, size_t length, + int *width) +{ + //fprintf(stderr, "%s(, '%s', %d, )\n", __FUNCTION__, string, length); + BFont font; + + if (length == 0) { + *width = 0; + return NSERROR_OK; + } + + nsbeos_style_to_font(font, fstyle); + *width = (int)font.StringWidth(string, length); + + return NSERROR_OK; +} + + +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 fstyle style for this text + * \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 + */ +static nserror beos_font_position(const plot_font_style_t *fstyle, + 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; + + nsbeos_style_to_font(font, fstyle); + 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++) { + esc += escapements[i]; + current = font.Size() * esc; + index += utf8_char_len(&string[index]); + // is current char already too far away? + if (x < current) + break; + } + *actual_x = (int)current; + *char_offset = i; //index; + + return NSERROR_OK; +} + + +/** + * Find where to split a string to make it fit a width. + * + * \param fstyle style for this text + * \param string UTF-8 string to measure + * \param length length of string, in bytes + * \param x width available + * \param char_offset updated to offset in string of actual_x, [1..length] + * \param actual_x updated to x coordinate of character closest to x + * \return true on success, false on error and error reported + * + * On exit, char_offset indicates first character after split point. + * + * Note: char_offset of 0 should never be returned. + * + * Returns: + * char_offset giving split point closest to x, where actual_x <= x + * else + * char_offset giving split point closest to x, where actual_x > x + * + * Returning char_offset == length means no split possible + */ +static nserror beos_font_split(const plot_font_style_t *fstyle, + 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; + + nsbeos_style_to_font(font, fstyle); + 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); + // very 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 && last_space != 0) { + *actual_x = (int)last_x; + *char_offset = last_space; + return NSERROR_OK;; + } + esc += escapements[i]; + current = font.Size() * esc; + index += utf8_char_len(&string[index]); + } + *actual_x = MIN(*actual_x, (int)current); + *char_offset = index; + + return NSERROR_OK; +} + + +/** + * Render a string. + * + * \param fstyle style for this text + * \param string UTF-8 string to measure + * \param length length of string + * \param x x coordinate + * \param y y coordinate + * \return true on success, false on error and error reported + */ + +bool nsfont_paint(const plot_font_style_t *fstyle, + const char *string, size_t length, + int x, int y) +{ + //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; + + nsbeos_style_to_font(font, fstyle); + background = nsbeos_rgb_colour(fstyle->background); + foreground = nsbeos_rgb_colour(fstyle->foreground); + + view = nsbeos_current_gc/*_lock*/(); + if (view == NULL) { + beos_warn_user("No GC", 0); + return false; + } + + oldbg = view->LowColor(); + drawing_mode oldmode = view->DrawingMode(); + view->SetLowColor(B_TRANSPARENT_32_BIT); + + //view->SetScale() XXX + +//printf("nsfont_paint: Size: %f\n", font.Size()); + size = (float)font.Size(); +#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 (memcmp(&oldbg, &background, sizeof(rgb_color))) + view->SetLowColor(oldbg); + + //nsbeos_current_gc_unlock(); + + return true; +} + + +static struct gui_layout_table layout_table = { + /*.width = */beos_font_width, + /*.position = */beos_font_position, + /*.split = */beos_font_split +}; + +struct gui_layout_table *beos_layout_table = &layout_table; diff --git a/frontends/beos/font.h b/frontends/beos/font.h new file mode 100644 index 000000000..63909efcf --- /dev/null +++ b/frontends/beos/font.h @@ -0,0 +1,37 @@ +/* + * Copyright 2008 François Revol + * + * 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 . + */ + +/** + * \file + * Beos font layout handling interface. + */ + +#ifndef NS_BEOS_FONT_H +#define NS_BEOS_FONT_H + +#include "desktop/plot_style.h" + +bool nsfont_paint(const plot_font_style_t *fstyle, + const char *string, size_t length, + int x, int y); + +void nsbeos_style_to_font(BFont &font, const struct plot_font_style *fstyle); + +extern struct gui_layout_table *beos_layout_table; + +#endif diff --git a/frontends/beos/gui.cpp b/frontends/beos/gui.cpp new file mode 100644 index 000000000..2e0aa4cc5 --- /dev/null +++ b/frontends/beos/gui.cpp @@ -0,0 +1,1109 @@ +/* + * Copyright 2015 Adrián Arroyo Calle + * Copyright 2008 François Revol + * Copyright 2005 James Bursa + * + * 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 . + */ + +#define __STDBOOL_H__ 1 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern "C" { + +#include "utils/nsoption.h" +#include "utils/filename.h" +#include "utils/log.h" +#include "utils/messages.h" +#include "utils/url.h" +#include "utils/corestrings.h" +#include "utils/utf8.h" +#include "utils/utils.h" + +#include "content/content.h" +#include "content/content_protected.h" +#include "content/fetch.h" +#include "content/fetchers.h" +#include "content/fetchers/resource.h" +#include "content/hlcache.h" +#include "content/urldb.h" +#include "desktop/browser.h" +#include "desktop/gui_misc.h" +#include "desktop/gui_clipboard.h" +#include "desktop/gui_search.h" +#include "desktop/gui_fetch.h" +#include "desktop/netsurf.h" + +} + +#include "beos/gui.h" +#include "beos/gui_options.h" +//#include "beos/completion.h" +#include "beos/window.h" +#include "beos/throbber.h" +#include "beos/filetype.h" +#include "beos/download.h" +#include "beos/schedule.h" +#include "beos/fetch_rsrc.h" +#include "beos/scaffolding.h" +#include "beos/bitmap.h" +#include "beos/font.h" + +//TODO: use resources +// enable using resources instead of files +#define USE_RESOURCES 1 + +bool nsbeos_done = false; + +bool replicated = false; /**< if we are running as a replicant */ + +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 thread_id sBAppThreadID; + +static BMessage *gFirstRefsReceived = NULL; + +static int sEventPipe[2]; + +// #pragma mark - class NSBrowserFrameView + + +/* exported function defined in beos/gui.h */ +nserror beos_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; + + alert = new BAlert("NetSurf Warning", text.String(), "Debug", "Ok", + NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT); + if (alert->Go() < 1) { + debugger("warn_user"); + } + + return NSERROR_OK; +} + +NSBrowserApplication::NSBrowserApplication() + : BApplication("application/x-vnd.NetSurf") +{ +} + + +NSBrowserApplication::~NSBrowserApplication() +{ +} + + +void +NSBrowserApplication::MessageReceived(BMessage *message) +{ + switch (message->what) { + case B_REFS_RECEIVED: + case B_UI_SETTINGS_CHANGED: + // 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 'sear': + case 'menu': + // NetPositive messages + case B_NETPOSITIVE_OPEN_URL: + case B_NETPOSITIVE_BACK: + case B_NETPOSITIVE_FORWARD: + case B_NETPOSITIVE_HOME: + case B_NETPOSITIVE_RELOAD: + case B_NETPOSITIVE_STOP: + case B_NETPOSITIVE_DOWN: + case B_NETPOSITIVE_UP: + //DetachCurrentMessage(); + //nsbeos_pipe_message(message, this, fGuiWindow); + break; + default: + BApplication::MessageReceived(message); + } +} + + +void +NSBrowserApplication::ArgvReceived(int32 argc, char **argv) +{ + NSBrowserWindow *win = nsbeos_find_last_window(); + if (!win) { + return; + } + win->Unlock(); + BMessage *message = DetachCurrentMessage(); + nsbeos_pipe_message_top(message, win, win->Scaffolding()); +} + + +void +NSBrowserApplication::RefsReceived(BMessage *message) +{ + DetachCurrentMessage(); + NSBrowserWindow *win = nsbeos_find_last_window(); + if (!win) { + gFirstRefsReceived = message; + return; + } + win->Unlock(); + nsbeos_pipe_message_top(message, win, win->Scaffolding()); +} + + +void +NSBrowserApplication::AboutRequested() +{ + nsbeos_pipe_message(new BMessage(B_ABOUT_REQUESTED), NULL, NULL); +} + + +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 + + + +/* realpath fallback on R5 */ +#if !defined(__HAIKU__) && !defined(B_BEOS_VERSION_DANO) +extern "C" char *realpath(const char *f, char *buf); +char *realpath(const char *f, char *buf) +{ + BPath path(f, NULL, true); + if (path.InitCheck() < 0) { + strncpy(buf, f, MAXPATHLEN); + return NULL; + } + //printf("RP: '%s'\n", path.Path()); + strncpy(buf, path.Path(), MAXPATHLEN); + return buf; +} +#endif + +/* finds the NetSurf binary image ID and path + * + */ +image_id nsbeos_find_app_path(char *path) +{ + image_info info; + 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 *)&nsbeos_find_app_path >= (char *)info.text) + && ((char *)&nsbeos_find_app_path < (char *)info.text + info.text_size)) { +//fprintf(stderr, "match\n"); + if (path) { + memset(path, 0, B_PATH_NAME_LENGTH); + strncpy(path, info.name, B_PATH_NAME_LENGTH-1); + } + return info.id; + } + } + return B_ERROR; +} + +/** + * Locate a shared resource file by searching known places in order. + * + * Search order is: ~/config/settings/NetSurf/, ~/.netsurf/, $NETSURFRES/ + * (where NETSURFRES is an environment variable), and finally the path + * specified by the macro at the top of this file. + * + * \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 path to resource. + */ +char *find_resource(char *buf, const char *filename, const char *def) +{ + const char *cdir = NULL; + status_t err; + BPath path; + char t[PATH_MAX]; + + err = find_directory(B_USER_SETTINGS_DIRECTORY, &path); + path.Append("NetSurf"); + if (err >= B_OK) + cdir = path.Path(); + if (cdir != NULL) { + strcpy(t, cdir); + strcat(t, "/"); + strcat(t, filename); + realpath(t, buf); + if (access(buf, R_OK) == 0) + return buf; + } + + cdir = getenv("HOME"); + 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; + } + + + BPathFinder f((void*)find_resource); + + BPath p; + if (f.FindPath(B_FIND_PATH_APPS_DIRECTORY, "netsurf/res", p) == B_OK) { + strcpy(t, p.Path()); + strcat(t, filename); + realpath(t, buf); + if (access(buf, R_OK) == 0) + return buf; + } + + if (def[0] == '%') { + snprintf(t, PATH_MAX, "%s%s", path.Path(), def + 1); + if (realpath(t, buf) == NULL) { + strcpy(buf, t); + } + } else if (def[0] == '~') { + snprintf(t, PATH_MAX, "%s%s", getenv("HOME"), def + 1); + if (realpath(t, buf) == NULL) { + strcpy(buf, t); + } + } else { + if (realpath(def, buf) == NULL) { + strcpy(buf, def); + } + } + + return buf; +} + +/** + * Check that ~/.netsurf/ exists, and if it doesn't, create it. + */ +static void check_homedir(void) +{ + status_t err; + + BPath path; + err = find_directory(B_USER_SETTINGS_DIRECTORY, &path, true); + + if (err < B_OK) { + /* we really can't continue without a home directory. */ + LOG("Can't find user settings directory - nowhere to store state!"); + die("NetSurf needs to find the user settings directory in order to run.\n"); + } + + path.Append("NetSurf"); + err = create_directory(path.Path(), 0644); + if (err < B_OK) { + LOG("Unable to create %s", path.Path()); + die("NetSurf could not create its settings directory.\n"); + } +} + +static int32 bapp_thread(void *arg) +{ + be_app->Lock(); + be_app->Run(); + return 0; +} + +static nsurl *gui_get_resource_url(const char *path) +{ + nsurl *url = NULL; + BString u("rsrc:///"); + + /* default.css -> beosdefault.css */ + if (strcmp(path, "default.css") == 0) + path = "beosdefault.css"; + + /* favicon.ico -> favicon.png */ + if (strcmp(path, "favicon.ico") == 0) + path = "favicon.png"; + + u << path; + LOG("(%s) -> '%s'\n", path, u.String()); + nsurl_create(u.String(), &url); + return url; +} + + + +#if !defined(__HAIKU__) && !defined(B_BEOS_VERSION_DANO) +/* more ui_colors, R5 only had a few defined... */ +#define B_PANEL_TEXT_COLOR ((color_which)10) +#define B_DOCUMENT_BACKGROUND_COLOR ((color_which)11) +#define B_DOCUMENT_TEXT_COLOR ((color_which)12) +#define B_CONTROL_BACKGROUND_COLOR ((color_which)13) +#define B_CONTROL_TEXT_COLOR ((color_which)14) +#define B_CONTROL_BORDER_COLOR ((color_which)15) +#define B_CONTROL_HIGHLIGHT_COLOR ((color_which)16) +#define B_NAVIGATION_BASE_COLOR ((color_which)4) +#define B_NAVIGATION_PULSE_COLOR ((color_which)17) +#define B_SHINE_COLOR ((color_which)18) +#define B_SHADOW_COLOR ((color_which)19) +#define B_MENU_SELECTED_BORDER_COLOR ((color_which)9) +#define B_TOOL_TIP_BACKGROUND_COLOR ((color_which)20) +#define B_TOOL_TIP_TEXT_COLOR ((color_which)21) +#define B_SUCCESS_COLOR ((color_which)100) +#define B_FAILURE_COLOR ((color_which)101) +#define B_MENU_SELECTED_BACKGROUND_COLOR B_MENU_SELECTION_BACKGROUND_COLOR +#define B_RANDOM_COLOR ((color_which)0x80000000) +#define B_MICHELANGELO_FAVORITE_COLOR ((color_which)0x80000001) +#define B_DSANDLER_FAVORITE_SKY_COLOR ((color_which)0x80000002) +#define B_DSANDLER_FAVORITE_INK_COLOR ((color_which)0x80000003) +#define B_DSANDLER_FAVORITE_SHOES_COLOR ((color_which)0x80000004) +#define B_DAVE_BROWN_FAVORITE_COLOR ((color_which)0x80000005) +#endif +#if defined(B_BEOS_VERSION_DANO) +#define B_TOOL_TIP_BACKGROUND_COLOR B_TOOLTIP_BACKGROUND_COLOR +#define B_TOOL_TIP_TEXT_COLOR B_TOOLTIP_TEXT_COLOR +#define +#endif +#define NOCOL ((color_which)0) + +/** + * set option from pen + */ +static nserror +set_colour_from_ui(struct nsoption_s *opts, + color_which ui, + enum nsoption_e option, + colour def_colour) +{ + if (ui != NOCOL) { + rgb_color c; + if (ui == B_DESKTOP_COLOR) { + BScreen s; + c = s.DesktopColor(); + } else { + c = ui_color(ui); + } + + def_colour = ((((uint32_t)c.blue << 16) & 0xff0000) | + ((c.green << 8) & 0x00ff00) | + ((c.red) & 0x0000ff)); + } + + opts[option].value.c = def_colour; + + return NSERROR_OK; +} + +/** + * Set option defaults for framebuffer frontend + * + * @param defaults The option table to update. + * @return error status. + */ +static nserror set_defaults(struct nsoption_s *defaults) +{ + /* set system colours for beos ui */ + set_colour_from_ui(defaults, NOCOL, NSOPTION_sys_colour_ActiveBorder, 0x00000000); + set_colour_from_ui(defaults, B_WINDOW_TAB_COLOR, NSOPTION_sys_colour_ActiveCaption, 0x00dddddd); + set_colour_from_ui(defaults, B_PANEL_BACKGROUND_COLOR, NSOPTION_sys_colour_AppWorkspace, 0x00eeeeee); + set_colour_from_ui(defaults, B_DESKTOP_COLOR, NSOPTION_sys_colour_Background, 0x00aa0000); + set_colour_from_ui(defaults, B_CONTROL_BACKGROUND_COLOR, NSOPTION_sys_colour_ButtonFace, 0x00aaaaaa); + set_colour_from_ui(defaults, B_CONTROL_HIGHLIGHT_COLOR, NSOPTION_sys_colour_ButtonHighlight, 0x00cccccc); + set_colour_from_ui(defaults, NOCOL, NSOPTION_sys_colour_ButtonShadow, 0x00bbbbbb); + set_colour_from_ui(defaults, B_CONTROL_TEXT_COLOR, NSOPTION_sys_colour_ButtonText, 0x00000000); + set_colour_from_ui(defaults, NOCOL, NSOPTION_sys_colour_CaptionText, 0x00000000); + set_colour_from_ui(defaults, NOCOL, NSOPTION_sys_colour_GrayText, 0x00777777); + set_colour_from_ui(defaults, NOCOL, NSOPTION_sys_colour_Highlight, 0x00ee0000); + set_colour_from_ui(defaults, NOCOL, NSOPTION_sys_colour_HighlightText, 0x00000000); + set_colour_from_ui(defaults, NOCOL, NSOPTION_sys_colour_InactiveBorder, 0x00000000); + set_colour_from_ui(defaults, NOCOL, NSOPTION_sys_colour_InactiveCaption, 0x00ffffff); + set_colour_from_ui(defaults, NOCOL, NSOPTION_sys_colour_InactiveCaptionText, 0x00cccccc); + set_colour_from_ui(defaults, B_TOOL_TIP_BACKGROUND_COLOR, NSOPTION_sys_colour_InfoBackground, 0x00aaaaaa); + set_colour_from_ui(defaults, B_TOOL_TIP_TEXT_COLOR, NSOPTION_sys_colour_InfoText, 0x00000000); + set_colour_from_ui(defaults, B_MENU_BACKGROUND_COLOR, NSOPTION_sys_colour_Menu, 0x00aaaaaa); + set_colour_from_ui(defaults, B_MENU_ITEM_TEXT_COLOR, NSOPTION_sys_colour_MenuText, 0x00000000); + set_colour_from_ui(defaults, NOCOL, NSOPTION_sys_colour_Scrollbar, 0x00aaaaaa); + set_colour_from_ui(defaults, NOCOL, NSOPTION_sys_colour_ThreeDDarkShadow, 0x00555555); + set_colour_from_ui(defaults, NOCOL, NSOPTION_sys_colour_ThreeDFace, 0x00dddddd); + set_colour_from_ui(defaults, NOCOL, NSOPTION_sys_colour_ThreeDHighlight, 0x00aaaaaa); + set_colour_from_ui(defaults, NOCOL, NSOPTION_sys_colour_ThreeDLightShadow, 0x00999999); + set_colour_from_ui(defaults, NOCOL, NSOPTION_sys_colour_ThreeDShadow, 0x00777777); + set_colour_from_ui(defaults, B_DOCUMENT_BACKGROUND_COLOR, NSOPTION_sys_colour_Window, 0x00aaaaaa); + set_colour_from_ui(defaults, NOCOL, NSOPTION_sys_colour_WindowFrame, 0x00000000); + set_colour_from_ui(defaults, B_DOCUMENT_TEXT_COLOR, NSOPTION_sys_colour_WindowText, 0x00000000); + + return NSERROR_OK; +} + +void nsbeos_update_system_ui_colors(void) +{ + set_defaults(nsoptions); +} + +/** + * Ensures output logging stream is correctly configured + */ +static bool nslog_stream_configure(FILE *fptr) +{ + /* set log stream to be non-buffering */ + setbuf(fptr, NULL); + + return true; +} + +static BPath get_messages_path() +{ + BPathFinder f((void*)get_messages_path); + + BPath p; + f.FindPath(B_FIND_PATH_APPS_DIRECTORY, "netsurf/res", p); + // TODO: use Haiku's BLocale stuff + BString lang(getenv("LC_MESSAGES")); + lang.Truncate(2); + BDirectory d(p.Path()); + if (!d.Contains(lang.String(), B_DIRECTORY_NODE)) + lang = "en"; + p.Append(lang.String()); + p.Append("Messages"); + return p; +} + + +static void gui_init(int argc, char** argv) +{ + const char *addr; + nsurl *url; + nserror error; + char buf[PATH_MAX]; + + if (pipe(sEventPipe) < 0) + return; + if (!replicated) { + 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; + } + + nsbeos_update_system_ui_colors(); + + fetch_rsrc_register(); + + check_homedir(); + + // make sure the cache dir exists + create_directory(TEMP_FILENAME_PREFIX, 0700); + + //nsbeos_completion_init(); + + + /* This is an ugly hack to just get the new-style throbber going. + * It, along with the PNG throbber loader, need making more generic. + */ + { +#define STROF(n) #n +#define FIND_THROB(n) filenames[(n)] = \ + "throbber/throbber" STROF(n) ".png"; + const char *filenames[9]; + FIND_THROB(0); + FIND_THROB(1); + FIND_THROB(2); + FIND_THROB(3); + FIND_THROB(4); + FIND_THROB(5); + FIND_THROB(6); + FIND_THROB(7); + FIND_THROB(8); + nsbeos_throbber_initialise_from_png(9, + filenames[0], filenames[1], filenames[2], filenames[3], + filenames[4], filenames[5], filenames[6], filenames[7], + filenames[8]); +#undef FIND_THROB +#undef STROF + } + + if (nsbeos_throbber == NULL) + die("Unable to load throbber image.\n"); + + find_resource(buf, "Choices", "%/Choices"); + LOG("Using '%s' as Preferences file", buf); + options_file_location = strdup(buf); + nsoption_read(buf, NULL); + + + /* check what the font settings are, setting them to a default font + * if they're not set - stops Pango whinging + */ +#define SETFONTDEFAULT(OPTION,y) if (nsoption_charp(OPTION) == NULL) nsoption_set_charp(OPTION, 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(font_sans, family); + SETFONTDEFAULT(font_serif, family); + SETFONTDEFAULT(font_mono, family); + SETFONTDEFAULT(font_cursive, family); + SETFONTDEFAULT(font_fantasy, family); +*/ +#ifdef __HAIKU__ + SETFONTDEFAULT(font_sans, "DejaVu Sans"); + SETFONTDEFAULT(font_serif, "DejaVu Serif"); + SETFONTDEFAULT(font_mono, "DejaVu Mono"); + SETFONTDEFAULT(font_cursive, "DejaVu Sans"); + SETFONTDEFAULT(font_fantasy, "DejaVu Sans"); +#else + SETFONTDEFAULT(font_sans, "Bitstream Vera Sans"); + SETFONTDEFAULT(font_serif, "Bitstream Vera Serif"); + SETFONTDEFAULT(font_mono, "Bitstream Vera Sans Mono"); + SETFONTDEFAULT(font_cursive, "Bitstream Vera Serif"); + SETFONTDEFAULT(font_fantasy, "Bitstream Vera Serif"); +#endif + + nsbeos_options_init(); + + /* We don't yet have an implementation of "select" form elements (they should use a popup menu) + * So we use the cross-platform code instead. */ + nsoption_set_bool(core_select_menu, true); + + if (nsoption_charp(cookie_file) == NULL) { + find_resource(buf, "Cookies", "%/Cookies"); + LOG("Using '%s' as Cookies file", buf); + nsoption_set_charp(cookie_file, strdup(buf)); + } + if (nsoption_charp(cookie_jar) == NULL) { + find_resource(buf, "Cookies", "%/Cookies"); + LOG("Using '%s' as Cookie Jar file", buf); + nsoption_set_charp(cookie_jar, strdup(buf)); + } + if ((nsoption_charp(cookie_file) == NULL) || + (nsoption_charp(cookie_jar) == NULL)) + die("Failed initialising cookie options"); + + if (nsoption_charp(url_file) == NULL) { + find_resource(buf, "URLs", "%/URLs"); + LOG("Using '%s' as URL file", buf); + nsoption_set_charp(url_file, strdup(buf)); + } + + if (nsoption_charp(ca_path) == NULL) { + find_resource(buf, "certs", "/etc/ssl/certs"); + LOG("Using '%s' as certificate path", buf); + nsoption_set_charp(ca_path, strdup(buf)); + } + + //find_resource(buf, "mime.types", "/etc/mime.types"); + beos_fetch_filetype_init(); + + urldb_load(nsoption_charp(url_file)); + urldb_load_cookies(nsoption_charp(cookie_file)); + + //nsbeos_download_initialise(); + + if (!replicated) + be_app->Unlock(); + + if (argc > 1) { + addr = argv[1]; + } else if (nsoption_charp(homepage_url) != NULL) { + addr = nsoption_charp(homepage_url); + } else { + addr = NETSURF_HOMEPAGE; + } + + /* create an initial browser window */ + error = nsurl_create(addr, &url); + if (error == NSERROR_OK) { + error = browser_window_create( + BW_CREATE_HISTORY, + url, + NULL, + NULL, + NULL); + nsurl_unref(url); + } + if (error != NSERROR_OK) { + beos_warn_user(messages_get_errorcode(error), 0); + } + + if (gFirstRefsReceived) { + // resend the refs we got before having a window to send them to + be_app_messenger.SendMessage(gFirstRefsReceived); + delete gFirstRefsReceived; + gFirstRefsReceived = NULL; + } + +} + + + + +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); + write(sEventPipe[1], &message, sizeof(void *)); +} + + +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); + write(sEventPipe[1], &message, sizeof(void *)); +} + + +void nsbeos_gui_poll(void) +{ + fd_set read_fd_set, write_fd_set, exc_fd_set; + int max_fd; + struct timeval timeout; + unsigned int fd_count = 0; + bigtime_t next_schedule = 0; + + /* get any active fetcher fd */ + fetcher_fdset(&read_fd_set, &write_fd_set, &exc_fd_set, &max_fd); + + /* run the scheduler */ + schedule_run(); + + // our own event pipe + FD_SET(sEventPipe[0], &read_fd_set); + + // max of all the fds in the set, plus one for select() + max_fd = MAX(max_fd, sEventPipe[0]) + 1; + + // compute schedule timeout + if (earliest_callback_timeout != B_INFINITE_TIMEOUT) { + next_schedule = earliest_callback_timeout - system_time(); + } else { + next_schedule = earliest_callback_timeout; + } + + // we're quite late already... + if (next_schedule < 0) + next_schedule = 0; + + 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, + &timeout); + //LOG("select: %d\n", fd_count); + + if (fd_count > 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 *)) { + //LOG("gui_poll: BMessage.what %-4.4s\n", &(message->what)); + nsbeos_dispatch_event(message); + } + } +} + + +static void gui_quit(void) +{ + urldb_save_cookies(nsoption_charp(cookie_jar)); + urldb_save(nsoption_charp(url_file)); + //options_save_tree(hotlist,nsoption_charp(hotlist_file),messages_get("TreeHotlist")); + + free(nsoption_charp(cookie_file)); + free(nsoption_charp(cookie_jar)); + beos_fetch_filetype_fin(); + fetch_rsrc_unregister(); +} + +static char *url_to_path(const char *url) +{ + char *url_path = curl_unescape(url, 0); + char *path; + + /* return the absolute path including leading / */ + path = strdup(url_path + (FILE_SCHEME_PREFIX_LEN - 1)); + curl_free(url_path); + + return path; +} + +/** + * Send the source of a content to a text editor. + */ + +void nsbeos_gui_view_source(struct hlcache_handle *content) +{ + char *temp_name; + bool done = false; + BPath path; + status_t err; + size_t size; + const char *source = content_get_source_data(content, &size); + + if (!content || !source) { + beos_warn_user("MiscError", "No document source"); + return; + } + + /* try to load local files directly. */ + temp_name = url_to_path(nsurl_access(hlcache_handle_get_url(content))); + if (temp_name) { + path.SetTo(temp_name); + BEntry entry; + if (entry.SetTo(path.Path()) >= B_OK + && entry.Exists() && entry.IsFile()) + done = true; + } + if (!done) { + /* We cannot release the requested filename until after it + * has finished being used. As we can't easily find out when + * this is, we simply don't bother releasing it and simply + * allow it to be re-used next time NetSurf is started. The + * memory overhead from doing this is under 1 byte per + * filename. */ + const char *filename = filename_request(); + if (!filename) { + beos_warn_user("NoMemory", 0); + return; + } + path.SetTo(TEMP_FILENAME_PREFIX); + path.Append(filename); + BFile file(path.Path(), B_WRITE_ONLY | B_CREATE_FILE); + err = file.InitCheck(); + if (err < B_OK) { + beos_warn_user("IOError", strerror(err)); + return; + } + err = file.Write(source, size); + if (err < B_OK) { + beos_warn_user("IOError", strerror(err)); + return; + } + lwc_string *mime = content_get_mime_type(content); + if (mime) { + file.WriteAttr("BEOS:TYPE", B_MIME_STRING_TYPE, 0LL, + lwc_string_data(mime), lwc_string_length(mime) + 1); + lwc_string_unref(mime); + } + + } + + entry_ref ref; + if (get_ref_for_path(path.Path(), &ref) < B_OK) + return; + + BMessage m(B_REFS_RECEIVED); + m.AddRef("refs", &ref); + + + // apps to try + const char *editorSigs[] = { + "application/x-vnd.beunited.pe", + "application/x-vnd.XEmacs", + "application/x-vnd.Haiku-StyledEdit", + "application/x-vnd.Be-STEE", + "application/x-vnd.yT-STEE", + NULL + }; + int i; + for (i = 0; editorSigs[i]; i++) { + team_id team = -1; + { + BMessenger msgr(editorSigs[i], team); + if (msgr.SendMessage(&m) >= B_OK) + break; + } + + err = be_roster->Launch(editorSigs[i], (BMessage *)&m, &team); + if (err >= B_OK) + break; + } +} + +/** + * Broadcast an URL that we can't handle. + */ + +static nserror gui_launch_url(struct nsurl *url) +{ + status_t status; + // try to open it as an URI + BString mimeType = "application/x-vnd.Be.URL."; + BString arg(nsurl_access(url)); + + mimeType.Append(arg, arg.FindFirst(":")); + + // special case, text/x-email is used traditionally + // use it instead + if (arg.IFindFirst("mailto:") == 0) + mimeType = "text/x-email"; + + // 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 NSERROR_NO_FETCH_HANDLER; + char *args[2] = { (char *)nsurl_access(url), NULL }; + status = be_roster->Launch(mimeType.String(), 1, args); + if (status < B_OK) + beos_warn_user("Cannot launch url", strerror(status)); + return NSERROR_OK; +} + + + +void die(const char * const error) +{ + fprintf(stderr, "%s", error); + BAlert *alert; + BString text("Cannot continue:\n"); + text << error; + + alert = new BAlert("NetSurf Error", text.String(), "Debug", "Ok", NULL, + B_WIDTH_AS_USUAL, B_STOP_ALERT); + if (alert->Go() < 1) + debugger("die"); + + exit(EXIT_FAILURE); +} + + +static struct gui_fetch_table beos_fetch_table = { + fetch_filetype, + gui_get_resource_url, + NULL, // ??? + NULL, // release_resource_data + NULL, // fetch_mimetype +}; + +static struct gui_misc_table beos_misc_table = { + beos_schedule, + beos_warn_user, + gui_quit, + gui_launch_url, + NULL, //cert_verify + gui_401login_open, + NULL, // pdf_password (if we have Haru support) +}; + + +/** Normal entry point from OS */ +int main(int argc, char** argv) +{ + nserror ret; + BPath options; + struct netsurf_table beos_table = { + &beos_misc_table, + beos_window_table, + beos_download_table, + beos_clipboard_table, + &beos_fetch_table, + NULL, /* use POSIX file */ + NULL, /* default utf8 */ + NULL, /* default search */ + NULL, /* default web search */ + NULL, /* default low level cache persistant storage */ + beos_bitmap_table, + beos_layout_table + }; + + ret = netsurf_register(&beos_table); + if (ret != NSERROR_OK) { + die("NetSurf operation table failed registration"); + } + + if (find_directory(B_USER_SETTINGS_DIRECTORY, &options, true) == B_OK) { + options.Append("x-vnd.NetSurf"); + } + + if (!replicated) { + // create the Application object before trying to use messages + // so we can open an alert in case of error. + new NSBrowserApplication; + } + + /* initialise logging. Not fatal if it fails but not much we + * can do about it either. + */ + nslog_init(nslog_stream_configure, &argc, argv); + + /* user options setup */ + ret = nsoption_init(set_defaults, &nsoptions, &nsoptions_default); + if (ret != NSERROR_OK) { + die("Options failed to initialise"); + } + nsoption_read(options.Path(), NULL); + nsoption_commandline(&argc, argv, NULL); + + /* common initialisation */ + BResources resources; + resources.SetToImage((const void*)main); + size_t size = 0; + + char path[12]; + sprintf(path,"%.2s/Messages", getenv("LC_MESSAGES")); + fprintf(stderr, "Loading messages from resource %s\n", path); + + const uint8_t* res = (const uint8_t*)resources.LoadResource('data', path, &size); + if (size > 0 && res != NULL) { + ret = messages_add_from_inline(res, size); + } else { + BPath messages = get_messages_path(); + ret = messages_add_from_file(messages.Path()); + } + + ret = netsurf_init(NULL); + if (ret != NSERROR_OK) { + die("NetSurf failed to initialise"); + } + + gui_init(argc, argv); + + while (!nsbeos_done) { + nsbeos_gui_poll(); + } + + netsurf_exit(); + + return 0; +} + +/** called when replicated from NSBaseView::Instantiate() */ +int gui_init_replicant(int argc, char** argv) +{ + nserror ret; + BPath options; + struct netsurf_table beos_table = { + &beos_misc_table, + beos_window_table, + beos_download_table, + beos_clipboard_table, + &beos_fetch_table, + NULL, /* use POSIX file */ + NULL, /* default utf8 */ + NULL, /* default search */ + NULL, /* default web search */ + NULL, /* default low level cache persistant storage */ + beos_bitmap_table, + beos_layout_table + }; + + ret = netsurf_register(&beos_table); + if (ret != NSERROR_OK) { + die("NetSurf operation table failed registration"); + } + + if (find_directory(B_USER_SETTINGS_DIRECTORY, &options, true) == B_OK) { + options.Append("x-vnd.NetSurf"); + } + + /* initialise logging. Not fatal if it fails but not much we + * can do about it either. + */ + nslog_init(nslog_stream_configure, &argc, argv); + + // FIXME: use options as readonly for replicants + /* user options setup */ + ret = nsoption_init(set_defaults, &nsoptions, &nsoptions_default); + if (ret != NSERROR_OK) { + // FIXME: must not die when in replicant! + die("Options failed to initialise"); + } + nsoption_read(options.Path(), NULL); + nsoption_commandline(&argc, argv, NULL); + + /* common initialisation */ + BPath messages = get_messages_path(); + ret = messages_add_from_file(messages.Path()); + + ret = netsurf_init(NULL); + if (ret != NSERROR_OK) { + // FIXME: must not die when in replicant! + die("NetSurf failed to initialise"); + } + + gui_init(argc, argv); + + return 0; +} diff --git a/frontends/beos/gui.h b/frontends/beos/gui.h new file mode 100644 index 000000000..774820baa --- /dev/null +++ b/frontends/beos/gui.h @@ -0,0 +1,88 @@ +/* + * Copyright 2015 Adrián Arroyo Calle + * Copyright 2008 François Revol + * Copyright 2005 James Bursa + * + * 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 . + */ + +#include +#include +#include +#include +#include + +#ifndef B_BEOS_VERSION_DANO +#define B_UI_SETTINGS_CHANGED '_UIC' +#endif + +#define CALLED() fprintf(stderr, "%s()\n", __FUNCTION__); + +extern bool nsbeos_done; + +extern bool replicated; +int gui_init_replicant(int argc, char** argv); + +extern "C" void gui_401login_open(nsurl *url, const char *realm, + nserror (*cb)(bool proceed, void *pw), void *cbpw); + +extern "C" void nsbeos_gui_poll(void); + +extern char *options_file_location; + +class NSBrowserApplication : public BApplication { +public: + NSBrowserApplication(); +virtual ~NSBrowserApplication(); + +virtual void MessageReceived(BMessage *message); +virtual void RefsReceived(BMessage *message); +virtual void ArgvReceived(int32 argc, char **argv); + +virtual void AboutRequested(); +virtual bool QuitRequested(); +}; + +extern BWindow *wndAbout; + +extern BWindow *wndTooltip; + +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); + +void nsbeos_gui_view_source(struct hlcache_handle *content); +image_id nsbeos_find_app_path(char *path); +char *find_resource(char *buf, const char *filename, const char *def); + +void nsbeos_update_system_ui_colors(void); + +/** + * Cause an abnormal program termination. + * + * \note This never returns and is intended to terminate without any cleanup. + * + * \param error The message to display to the user. + */ +void die(const char * const error) __attribute__ ((noreturn)); + +/** + * Display a warning for a serious problem (eg memory exhaustion). + * + * \param warning message key for warning message + * \param detail additional message, or 0 + */ +nserror beos_warn_user(const char *warning, const char *detail); diff --git a/frontends/beos/gui_options.cpp b/frontends/beos/gui_options.cpp new file mode 100644 index 000000000..035c62941 --- /dev/null +++ b/frontends/beos/gui_options.cpp @@ -0,0 +1,50 @@ +/* + * Copyright 2008 François Revol + * Copyright 2006 Rob Kendrick + * + * 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 . + */ + +#define __STDBOOL_H__ 1 +#include +#include +#include +extern "C" { +#include "utils/log.h" +#include "utils/nsoption.h" +#include "utils/nsurl.h" +} +#include "beos/gui.h" +#include "beos/scaffolding.h" +#include "beos/gui_options.h" + +#include +#include + +BWindow *wndPreferences; + +void nsbeos_options_init(void) { + /* set the widgets to reflect the current options */ + nsbeos_options_load(); +} + +void nsbeos_options_load(void) { +#warning WRITEME +} + + +void nsbeos_options_save(void) { +#warning WRITEME +} diff --git a/frontends/beos/gui_options.h b/frontends/beos/gui_options.h new file mode 100644 index 000000000..e5c91a797 --- /dev/null +++ b/frontends/beos/gui_options.h @@ -0,0 +1,31 @@ +/* + * Copyright 2008 François Revol + * Copyright 2006 Rob Kendrick + * + * 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 . + */ + +#ifndef NETSURF_BEOS_OPTIONS_H +#define NETSURF_BEOS_OPTIONS_H + +#include + +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/frontends/beos/login.cpp b/frontends/beos/login.cpp new file mode 100644 index 000000000..7689c9d35 --- /dev/null +++ b/frontends/beos/login.cpp @@ -0,0 +1,196 @@ +/* + * Copyright 2008 François Revol + * + * 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 . + */ + +#define __STDBOOL_H__ 1 +#include +#include +#include +#include +#include +#include +#include +#include +#include +extern "C" { +#include "utils/log.h" +#include "content/content.h" +#include "content/urldb.h" +#include "desktop/browser.h" +#include "utils/messages.h" +#include "utils/url.h" +#include "utils/utils.h" +#include "desktop/gui_clipboard.h" +} +#include "beos/gui.h" +#include "beos/scaffolding.h" +#include "beos/window.h" + +class LoginAlert : public BAlert { +public: + LoginAlert(nserror (*callback)(bool proceed, void *pw), + void *callbaclpw, + nsurl *url, + const char *host, + const char *realm, + const char *text); + virtual ~LoginAlert(); + void MessageReceived(BMessage *message); + +private: + nsurl* fUrl; /**< URL being fetched */ + BString fHost; /**< Host for user display */ + BString fRealm; /**< Authentication realm */ + nserror (*fCallback)(bool proceed, void *pw); + void *fCallbackPw; + + BTextControl *fUserControl; + BTextControl *fPassControl; +}; + +static void create_login_window(nsurl *host, + lwc_string *realm, const char *fetchurl, + nserror (*cb)(bool proceed, void *pw), void *cbpw); + + +#define TC_H 25 +#define TC_MARGIN 10 + +LoginAlert::LoginAlert(nserror (*callback)(bool proceed, void *pw), + void *callbackpw, + nsurl *url, + const char *host, + const char *realm, + const char *text) + : BAlert("Login", text, "Cancel", "Ok", NULL, + B_WIDTH_AS_USUAL, B_WARNING_ALERT) +{ + fCallback = callback; + fCallbackPw = callbackpw; + fUrl = url; + fHost = host; + fRealm = realm; + + SetFeel(B_MODAL_SUBSET_WINDOW_FEEL); + /* + // XXX: can't do that anymore + nsbeos_scaffolding *s = nsbeos_get_scaffold(bw->window); + if (s) { + NSBrowserWindow *w = nsbeos_get_bwindow_for_scaffolding(s); + if (w) + AddToSubset(w); + }*/ + + // make space for controls + ResizeBy(0, 2 * TC_H); + MoveTo(AlertPosition(Frame().Width() + 1, + Frame().Height() + 1)); + + + BTextView *tv = TextView(); + BRect r(TC_MARGIN, tv->Bounds().bottom - 2 * TC_H, + tv->Bounds().right - TC_MARGIN, tv->Bounds().bottom - TC_H); + + fUserControl = new BTextControl(r, "user", "Username", "", + new BMessage(), B_FOLLOW_BOTTOM | B_FOLLOW_RIGHT); + fUserControl->SetDivider(60); + tv->AddChild(fUserControl); + + r.OffsetBySelf(0, TC_H); + + fPassControl = new BTextControl(r, "pass", "Password", "", + new BMessage(), B_FOLLOW_BOTTOM | B_FOLLOW_RIGHT); + fPassControl->TextView()->HideTyping(true); + fPassControl->SetDivider(60); + tv->AddChild(fPassControl); + + SetShortcut(0, B_ESCAPE); +} + +LoginAlert::~LoginAlert() +{ +} + +void +LoginAlert::MessageReceived(BMessage *message) +{ + switch (message->what) { + case 'ALTB': + { + int32 which; + if (message->FindInt32("which", &which) < B_OK) + break; + // not 'Ok' + if (which != 1) + break; + BMessage *m = new BMessage(*message); + m->what = 'nsLO'; + m->AddPointer("URL", fUrl); + m->AddString("Host", fHost.String()); + m->AddString("Realm", fRealm.String()); + m->AddPointer("callback", (void *)fCallback); + m->AddPointer("callback_pw", (void *)fCallbackPw); + m->AddString("User", fUserControl->Text()); + m->AddString("Pass", fPassControl->Text()); + BString auth(fUserControl->Text()); + auth << ":" << fPassControl->Text(); + m->AddString("Auth", auth.String()); + + // notify the main thread + // the event dispatcher will handle it + nsbeos_pipe_message(m, NULL, NULL); + } + break; + default: + break; + } + BAlert::MessageReceived(message); +} + + +extern "C" void gui_401login_open(nsurl *url, const char *realm, + nserror (*cb)(bool proceed, void *pw), void *cbpw) +{ + lwc_string *host; + + host = nsurl_get_component(url, NSURL_HOST); + + create_login_window(url, host, realm, cb, cbpw); + + free(host); +} + +//void create_login_window(struct browser_window *bw, const char *host, +// const char *realm, const char *fetchurl) +static void create_login_window(nsurl *url, lwc_string *host, + const char *realm, nserror (*cb)(bool proceed, void *pw), + void *cbpw) +{ + BString r("Secure Area"); + if (realm) + r = realm; + BString text(/*messages_get(*/"Please login\n"); + text << "Realm: " << r << "\n"; + text << "Host: " << host << "\n"; + //text << "\n"; + + LoginAlert *a = new LoginAlert(cb, cbpw, url, lwc_string_data(host), + r.String(), text.String()); + // asynchronously + a->Go(NULL); + +} diff --git a/frontends/beos/options.h b/frontends/beos/options.h new file mode 100644 index 000000000..40d23a3bc --- /dev/null +++ b/frontends/beos/options.h @@ -0,0 +1,30 @@ +/* + * Copyright 2008 François Revol + * Copyright 2006 Rob Kendrick + * + * 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 . + */ + + +#ifndef _NETSURF_BEOS_OPTIONS_H_ +#define _NETSURF_BEOS_OPTIONS_H_ + +/* currently nothing here */ + +#endif + +NSOPTION_BOOL(render_resample, false) +NSOPTION_STRING(url_file, NULL) + diff --git a/frontends/beos/plotters.cpp b/frontends/beos/plotters.cpp new file mode 100644 index 000000000..3fd786ecd --- /dev/null +++ b/frontends/beos/plotters.cpp @@ -0,0 +1,659 @@ +/* + * Copyright 2008 François Revol + * Copyright 2006 Rob Kendrick + * Copyright 2005 James Bursa + * + * 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 . + */ + +/** \file + * Target independent plotting (BeOS/Haiku implementation). + */ + +#define __STDBOOL_H__ 1 +#include +#include +#include +#include +#include +#include +#include +extern "C" { +#include "desktop/plotters.h" +#include "utils/log.h" +#include "utils/utils.h" +#include "utils/nsoption.h" +#include "utils/nsurl.h" +} +#include "beos/font.h" +#include "beos/gui.h" +#include "beos/plotters.h" +#include "beos/bitmap.h" + +#warning MAKE ME static +/*static*/ BView *current_view; + +/* + * NOTE: BeOS rects differ from NetSurf ones: + * the right-bottom pixel is actually part of the BRect! + */ + +static bool nsbeos_plot_rectangle(int x0, int y0, int x1, int y1, const plot_style_t *style); +static bool nsbeos_plot_line(int x0, int y0, int x1, int y1, const plot_style_t *style); +static bool nsbeos_plot_polygon(const int *p, unsigned int n, const plot_style_t *style); +static bool nsbeos_plot_path(const float *p, unsigned int n, colour fill, float width, + colour c, const float transform[6]); +static bool nsbeos_plot_clip(const struct rect *ns_clip); +static bool nsbeos_plot_text(int x, int y, const char *text, size_t length, + const plot_font_style_t *fstyle); +static bool nsbeos_plot_disc(int x, int y, int radius, const plot_style_t *style); +static bool nsbeos_plot_arc(int x, int y, int radius, int angle1, int angle2, + const plot_style_t *style); +static bool nsbeos_plot_bitmap(int x, int y, int width, int height, + struct bitmap *bitmap, colour bg, + bitmap_flags_t flags); + + +#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_clip, + nsbeos_plot_arc, + nsbeos_plot_disc, + nsbeos_plot_line, + nsbeos_plot_rectangle, + nsbeos_plot_polygon, + nsbeos_plot_path, + nsbeos_plot_bitmap, + nsbeos_plot_text, + NULL, // Group Start + NULL, // Group End + NULL, // Flush + true // option_knockout +}; + + +// #pragma mark - implementation + + +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_rectangle(int x0, int y0, int x1, int y1, const plot_style_t *style) +{ + if (style->fill_type != PLOT_OP_TYPE_NONE) { + BView *view; + + view = nsbeos_current_gc/*_lock*/(); + if (view == NULL) { + beos_warn_user("No GC", 0); + return false; + } + + nsbeos_set_colour(style->fill_colour); + + BRect rect(x0, y0, x1 - 1, y1 - 1); + view->FillRect(rect); + + //nsbeos_current_gc_unlock(); + + } + + if (style->stroke_type != PLOT_OP_TYPE_NONE) { + pattern pat; + BView *view; + + switch (style->stroke_type) { + case PLOT_OP_TYPE_SOLID: /**< Solid colour */ + default: + pat = B_SOLID_HIGH; + break; + + case PLOT_OP_TYPE_DOT: /**< Doted plot */ + pat = kDottedPattern; + break; + + case PLOT_OP_TYPE_DASH: /**< dashed plot */ + pat = kDashedPattern; + break; + } + + view = nsbeos_current_gc/*_lock*/(); + if (view == NULL) { + beos_warn_user("No GC", 0); + return false; + } + + nsbeos_set_colour(style->stroke_colour); + + float pensize = view->PenSize(); + view->SetPenSize(style->stroke_width); + + BRect rect(x0, y0, x1, y1); + view->StrokeRect(rect, pat); + + view->SetPenSize(pensize); + + //nsbeos_current_gc_unlock(); + + } + + return true; +} + + + +bool nsbeos_plot_line(int x0, int y0, int x1, int y1, const plot_style_t *style) +{ + pattern pat; + BView *view; + + switch (style->stroke_type) { + case PLOT_OP_TYPE_SOLID: /**< Solid colour */ + default: + pat = B_SOLID_HIGH; + break; + + case PLOT_OP_TYPE_DOT: /**< Doted plot */ + pat = kDottedPattern; + break; + + case PLOT_OP_TYPE_DASH: /**< dashed plot */ + pat = kDashedPattern; + break; + } + + view = nsbeos_current_gc/*_lock*/(); + if (view == NULL) { + beos_warn_user("No GC", 0); + return false; + } + + nsbeos_set_colour(style->stroke_colour); + + float pensize = view->PenSize(); + view->SetPenSize(style->stroke_width); + + BPoint start(x0, y0); + BPoint end(x1, y1); + view->StrokeLine(start, end, pat); + + view->SetPenSize(pensize); + + //nsbeos_current_gc_unlock(); + + return true; +} + + +bool nsbeos_plot_polygon(const int *p, unsigned int n, const plot_style_t *style) +{ + unsigned int i; + BView *view; + + view = nsbeos_current_gc/*_lock*/(); + if (view == NULL) { + beos_warn_user("No GC", 0); + return false; + } + + nsbeos_set_colour(style->fill_colour); + + BPoint points[n]; + + for (i = 0; i < n; i++) { + points[i] = BPoint(p[2 * i] - 0.5, p[2 * i + 1] - 0.5); + } + + if (style->fill_colour == NS_TRANSPARENT) + view->StrokePolygon(points, (int32)n); + else + view->FillPolygon(points, (int32)n); + + return true; +} + + + + +bool nsbeos_plot_clip(const struct rect *ns_clip) +{ + 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) { + beos_warn_user("No GC", 0); + return false; + } + + BRect rect(ns_clip->x0, ns_clip->y0, ns_clip->x1 - 1, + ns_clip->y1 - 1); + BRegion clip(rect); + view->ConstrainClippingRegion(NULL); + if (view->Bounds() != rect) + view->ConstrainClippingRegion(&clip); + + + //nsbeos_current_gc_unlock(); + + return true; +} + + +bool nsbeos_plot_text(int x, int y, const char *text, size_t length, + const plot_font_style_t *fstyle) +{ + return nsfont_paint(fstyle, text, length, x, y); +} + + +bool nsbeos_plot_disc(int x, int y, int radius, const plot_style_t *style) +{ + BView *view; + + view = nsbeos_current_gc/*_lock*/(); + if (view == NULL) { + beos_warn_user("No GC", 0); + return false; + } + + nsbeos_set_colour(style->fill_colour); + + BPoint center(x, y); + if (style->fill_type != PLOT_OP_TYPE_NONE) + view->FillEllipse(center, radius, radius); + else + view->StrokeEllipse(center, radius, radius); + + //nsbeos_current_gc_unlock(); + + return true; +} + +bool nsbeos_plot_arc(int x, int y, int radius, int angle1, int angle2, const plot_style_t *style) +{ + BView *view; + + view = nsbeos_current_gc/*_lock*/(); + if (view == NULL) { + beos_warn_user("No GC", 0); + return false; + } + + nsbeos_set_colour(style->fill_colour); + + 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(); + + 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) { + beos_warn_user("No GC", 0); + return false; + } + + drawing_mode oldmode = view->DrawingMode(); + source_alpha alpha; + alpha_function func; + view->GetBlendingMode(&alpha, &func); + //view->SetDrawingMode(B_OP_OVER); + view->SetDrawingMode(B_OP_ALPHA); + view->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY); + + // 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 != NS_TRANSPARENT) { + view->SetLowColor(nsbeos_rgb_colour(bg)); + view->FillRect(rect, B_SOLID_LOW); + } + */ + view->DrawBitmap(b, rect); + // maybe not needed? + //view->SetLowColor(old); + view->SetBlendingMode(alpha, func); + view->SetDrawingMode(oldmode); + + //nsbeos_current_gc_unlock(); + + return true; +} + + +bool nsbeos_plot_bitmap(int x, int y, int width, int height, + struct bitmap *bitmap, colour bg, + bitmap_flags_t flags) +{ + int doneheight = 0, donewidth = 0; + BBitmap *primary; + BBitmap *pretiled; + bool repeat_x = (flags & BITMAPF_REPEAT_X); + bool repeat_y = (flags & BITMAPF_REPEAT_Y); + + if (!(repeat_x || repeat_y)) { + /* Not repeating at all, so just plot it */ + primary = nsbeos_bitmap_get_primary(bitmap); + return nsbeos_plot_bbitmap(x, y, width, height, primary, 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) { + beos_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 + return true; +} + +static BPoint transform_pt(float x, float y, const float transform[6]) +{ +#warning XXX: verify + //return BPoint(x, y); + BPoint pt; + pt.x = x * transform[0] + y * transform[1] + transform[4]; + pt.y = x * transform[2] + y * transform[3] + transform[5]; + /* + printf("TR: {%f, %f} { %f, %f, %f, %f, %f, %f} = { %f, %f }\n", + x, y, + transform[0], transform[1], transform[2], + transform[3], transform[4], transform[5], + pt.x, pt.y); + */ + return pt; +} + +bool nsbeos_plot_path(const float *p, unsigned int n, colour fill, float width, + colour c, const float transform[6]) +{ + unsigned int i; + + if (n == 0) + return true; + + if (p[0] != PLOTTER_PATH_MOVE) { + LOG("path doesn't start with a move"); + return false; + } + + BShape shape; + + for (i = 0; i < n; ) { + if (p[i] == PLOTTER_PATH_MOVE) { + BPoint pt(transform_pt(p[i + 1], p[i + 2], transform)); + shape.MoveTo(pt); + i += 3; + } else if (p[i] == PLOTTER_PATH_CLOSE) { + shape.Close(); + i++; + } else if (p[i] == PLOTTER_PATH_LINE) { + BPoint pt(transform_pt(p[i + 1], p[i + 2], transform)); + shape.LineTo(pt); + i += 3; + } else if (p[i] == PLOTTER_PATH_BEZIER) { + BPoint pt[3] = { + transform_pt(p[i + 1], p[i + 2], transform), + transform_pt(p[i + 3], p[i + 4], transform), + transform_pt(p[i + 5], p[i + 6], transform) + }; + shape.BezierTo(pt); + i += 7; + } else { + LOG("bad path command %f", p[i]); + return false; + } + } + shape.Close(); + + BView *view; + + view = nsbeos_current_gc/*_lock*/(); + if (view == NULL) + return false; + + rgb_color old_high = view->HighColor(); + float old_pen = view->PenSize(); + view->SetPenSize(width); + view->MovePenTo(0, 0); + if (fill != NS_TRANSPARENT) { + view->SetHighColor(nsbeos_rgb_colour(fill)); + view->FillShape(&shape); + } + if (c != NS_TRANSPARENT) { + view->SetHighColor(nsbeos_rgb_colour(c)); + view->StrokeShape(&shape); + } + // restore + view->SetPenSize(old_pen); + view->SetHighColor(old_high); + + //nsbeos_current_gc_unlock(); + + return true; +} + +rgb_color nsbeos_rgb_colour(colour c) +{ + rgb_color color; + if (c == NS_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); +} + +/** 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(); + +} + +#ifdef TEST_PLOTTERS +// +static void test_plotters(void) +{ + int x0, y0; + int x1, y1; + struct rect r; + + x0 = 5; + y0 = 5; + x1 = 35; + y1 = 6; + + plot.line(x0, y0, x1, y1, 1, 0x0000ff00, false, false); + y0+=2; y1+=2; + plot.line(x0, y0, x1, y1, 1, 0x0000ff00, true, false); + y0+=2; y1+=2; + plot.line(x0, y0, x1, y1, 1, 0x0000ff00, false, true); + y0+=2; y1+=2; + plot.line(x0, y0, x1, y1, 1, 0x0000ff00, true, true); + y0+=10; y1+=20; + + plot.fill(x0, y0, x1, y1, 0x00ff0000); + plot.rectangle(x0+10, y0+10, x1-x0+1, y1-y0+1, 2, 0x00ffff00, true, false); + y0+=30; y1+=30; + + r.x0 = x0 + 2; + r.y0 = y0 + 2; + r.x1 = x1 - 2; + r.y1 = y1 - 2; + plot.clip(&r); + + plot.fill(x0, y0, x1, y1, 0x00000000); + plot.disc(x1, y1, 8, 0x000000ff, false); + + r.x0 = 0; + r.y0 = 0; + r.x1 = 300; + r.y1 = 300; + plot.clip(&r); + + y0+=30; y1+=30; + +} + +#include +#include +#include +class PTView : public BView { +public: + PTView(BRect frame) : BView(frame, "view", B_FOLLOW_NONE, B_WILL_DRAW) {}; + virtual ~PTView() {}; + virtual void Draw(BRect update) + { + test_plotters(); + }; + +}; + +extern "C" void test_plotters_main(void); +void test_plotters_main(void) +{ + BApplication app("application/x-vnd.NetSurf"); + memcpy(&plot, &nsbeos_plotters, sizeof(plot)); + BRect frame(0,0,300,300); + PTView *view = new PTView(frame); + frame.OffsetBySelf(100,100); + BWindow *win = new BWindow(frame, "NetSurfPlotterTest", B_TITLED_WINDOW, B_QUIT_ON_WINDOW_CLOSE); + win->AddChild(view); + nsbeos_current_gc_set(view); + win->Show(); + app.Run(); +} +#endif /* TEST_PLOTTERS */ + diff --git a/frontends/beos/plotters.h b/frontends/beos/plotters.h new file mode 100644 index 000000000..523f3c7c6 --- /dev/null +++ b/frontends/beos/plotters.h @@ -0,0 +1,48 @@ +/* + * Copyright 2008 François Revol + * Copyright 2005 James Bursa + * + * 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 . + */ + +/** \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 + +extern BView *current_view; + +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); + +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/frontends/beos/res.h b/frontends/beos/res.h new file mode 100644 index 000000000..278ffb545 --- /dev/null +++ b/frontends/beos/res.h @@ -0,0 +1,18 @@ +/* + * Copyright 2008 François Revol + * + * 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 . + */ + diff --git a/frontends/beos/res.rdef b/frontends/beos/res.rdef new file mode 100644 index 000000000..07012356c --- /dev/null +++ b/frontends/beos/res.rdef @@ -0,0 +1,242 @@ +/* + * Copyright 2008 François Revol + * + * 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 . + */ + +#include "res.h" + +/* files exported as resource: via rsrc:// mapping are added by the makefile */ + +/* application flags (multiple launch) */ +resource(1, "BEOS:APP_FLAGS") (#'APPF') $"01000000"; + +/* application MIME signature */ +resource(1, "BEOS:APP_SIG") (#'MIMS') "application/x-vnd.NetSurf"; + +/* list of supported MIME types */ +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" +}; + +/* BeOS large (32x32) icon */ +resource(101, "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" +}; + +/* BeOS small (16x16) icon */ +resource(101, "BEOS:M:STD_ICON") #'MICN' array { + $"FFFFFFFF0E0900020205000DFFFFFFFF" + $"FFFFFF09038E66666C6C93DD000EFFFF" + $"FFFF00B5AE4666666C6C666CB4050EFF" + $"FF098E464646666666401D4066B400FF" + $"0E05668E664666666C1E3F3F1D6CDDAF" + $"098E668E66666666661F3F3F1E729300" + $"006C66666666666C6C401E1E40729204" + $"026C6CB46C666C6C6C6C6C66929292DE" + $"026C6C8D6C6C6C6C6C6C72729292923D" + $"006C6C6C8D6C6C6C6C72729292927E04" + $"09946C6CB56C6C6C72729292DD935F00" + $"0E009492B49293B492B47E929292DE0D" + $"FF0A7F92937F939392929292927E00FF" + $"FFFF08DD92929292929292927E00FFFF" + $"FFFFFF0B017E93DD92927EDE09FFFFFF" + $"FFFFFFFF0E0B000500000A0EFFFFFFFF" +}; + +/* Haiku vector icon */ +resource(101, "BEOS:ICON") #'VICN' array { + $"6E6369660A02010203AE259A400198BFFA65AE20E548AF9547F2037F30A0FFFF" + $"00E8F1FDFFF131A0FFFB02000602B83B85BC57333C5733B83B8549EAE1481199" + $"00359FFFFFFFFFFF05FF05010400600500020002033D9F21B889EB3A4CEE3F48" + $"204AB4B1440D2D10339DFF51369381810DB3339DFF68020002013E7E6E26628C" + $"A83C7540569A4565A3CA24492BEEF3F70001EEF3F731017D828B95160204BFE6" + $"B413C670B413B95DB413B411BF78B411B92DB411C5C3BFE6CADDB95CCADDC66F" + $"CADDCBBCBF78CBBCC5C4CBBCB92E0204BC63B4EAC0E922B7DDB608B570BBF0B4" + $"C0B92EB61EBEB2BEDDBEE8BA56C007C363BDCBC5D0B7E2C67FBAA5C522B52002" + $"04BFDEB448C60DB448B9ADB448B4ADBF9AB4ADB955B4ADC5DABFDECAEDB9ABCA" + $"EDC60BCAEDCB0FBF9ACB0FC5DCCB0FB9570204BFDFB4D8C5BFB4D8B9FEB4D8B5" + $"3DBF9AB53DB9A5B53DC58ABFDFCA5CB9FCCA5CC5BDCA5CCA81BF9ACA81C58BCA" + $"81B9A70606BA0BBF11CB5CC71BCAFECB92C8F7CA15CAF2CCF9C666CA36C48EC4" + $"A7CA76C78DC943C2BECB40BF11CB5D0A04BB16B6B2BA9C2EB9CFB86BBA5AB65D" + $"0A04BA10BC6AB954BC62B96CBADFBA3EBAE70A04BA21BEB5BA5AC047B98DC071" + $"B93ABEF30A04BAFDC28BBB88C3E9BAD5C43EBA59C2CD0A04BD84C730BCE154BC" + $"1CC679BCAAC5F90A04BEF3C932C015CA3BBF51CAA0BE4FC9AB0A04B812C4E6B8" + $"1CC5AEB693C46DB6DEC3F70A04BA6AC535BBD4C545BBCDC617BAACC6020A04BE" + $"1EC565BF9AC51CBFB2C5E6BE5FC6340A04C1DCC4D3C348C459C381C524C244C5" + $"8D0A04C6D0C2EDC721C39FC5E5C45FC595C3AA0A04C8E6C175C9A042CA54C102" + $"C962C20E0611AAAAAAAE02C14FB955C2EAB96FC38BB7E6C47FB928C628B8C3C6" + $"04BA40C793BB18C64ABC15C6B4BDE0C50CBDCAC479BF41C372BE11C17FBE79C1" + $"FEBCB2C207BCB3C1F5BCB2C047BC1CC1A7BAEBC14EB9540205C03CC10EC030C0" + $"EFC0B9C250BFCBC606BE8FC591C21CC6E2C5DBC385C74DC4AAC5AAC35EC643BC" + $"27C7D2BF42C4B3B90CC27CB994C3B1BA28C084B8A30605EF03B6CFBA0EB779B7" + $"92B672BB6AB633BD29B598BCA2B7B3BE77BD4BBD3EC58CB654C86EB88FC42DB5" + $"45BC71B55CBF70B47FB920B65000000204CB77C91ACB76C797CB79CAACC293CB" + $"88C456CB8AC0CCCB86BAB3C975BAACCAF2BABAC7F6C286C704C0CCC704C44DC7" + $"04250A090115023FFFDCB41DBB3451734030CDBF6EE7C3CF400A000100023F88" + $"1AB4F02F34DE2C3F9E484326CF4422000A060112023CDC96413114C145263E69" + $"DE4C32CFCB0EE00A0301031A4002C300000000000040012FBD3E023BCFC439BF" + $"01178100040A0301031A4002C300000000000040012FBD3E023BCFC42F390117" + $"8200040A0301031A4002C300000000000040012FBD3E023BCFC41A2F01178200" + $"040A050105023EF4D13E9DFDBE66B43EB65E491E02C6E7CA0A0501051A3EE861" + $"3EABC8BE735C3EAAF54929C0C6EFBE1A3901178100040A050106023F4B963E44" + $"75BE44753F4B9648D9CDC72B1A0A0501061A3F4B963E4475BE44753F4B9648D9" + $"CDC72B1A1A3901178100040A0501061A3F4B963E4475BE44753F4B9648D9CDC7" + $"2B1A001901178300040A050107023F4B963E4475BE44753F4B9648D9CDC72B1A" + $"0A0501071A3F4B963E4475BE44753F4B9648D9CDC72B1A1A3901178100040A05" + $"0108023F4B963E4475BE44753F4B9648D9CDC72B1A0A0501081A3F4B963E4475" + $"BE44753F4B9648D9CDC72B1A1A3901178100040A0501081A3F4B963E4475BE44" + $"753F4B9648D9CDC72B1A001901178300040A050109023F70F53E0A00BE0A003F" + $"70F5485F8CC6CD790A0501091A3F70F53E0A00BE0A003F70F5485F8CC6CD791A" + $"3901178100040A05010A023F4B963E4475BD81043E8BD247F0BEC26F710A0501" + $"0A1A3F4B963E4475BD81043E8BD247F0BEC26F711A3901178100040A05010A1A" + $"3F4B963E4475BD81043E8BD247F0BEC26F71001901178300040A05010B023F7B" + $"673D4154BE6C8B3F3385495313C5FE290A05010B1A3F7B673D4154BE6C8B3F33" + $"85495313C5FE291A3901178100040A05010C023F70093E0B8EBE0B8E3F700948" + $"A7CCC721CF0A05010C1A3F70093E0B8EBE0B8E3F700948A7CCC721CF1A390117" + $"8100040A05010D023F70093E0B8EBE0B8E3F700948A7CCC721CF0A05010D1A3F" + $"70093E0B8EBE0B8E3F700948A7CCC721CF1A3901178100040A05010D1A3F7009" + $"3E0B8EBE0B8E3F700948A7CCC721CF001901178300040A05010E023F70093E0B" + $"8EBE0B8E3F700948A7CCC721CF0A05010E1A3F70093E0B8EBE0B8E3F700948A7" + $"CCC721CF1A3901178100040A05010F023FB1173D145ABD145A3FB117474282C6" + $"7CF80A05010F1A3FB1173D145ABD145A3FB117474282C67CF81A390117810004" + $"0A05010F1A3FB1173D145ABD145A3FB117474282C67CF8001901178300040A05" + $"0110023F68373CD78FBD05193F9ECF48132CC5E0A80A0501101A3F68373CD78F" + $"BD05193F9ECF48132CC5E0A81A3901178100040A020111000A0301031A4002C3" + $"00000000000040012FBD3E023BCFC400190117850004" +}; + +/* ZETA SVG icon descriptor */ +resource(101, "BEOS:D:STD_ICON") (#'iICO') $"4944585A055300"; + +/* ZETA SVG compressed icon */ +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" +}; + +/* toolbar icons from Zumi + * (generated by Icon-O-Matic from the HFIV source file, + * can't be automated) + */ + +resource(102, "forward_button") #'VICN' array { + $"6E6369660304006603005900020006020000003C6000C000000000004C000048" + $"A0000080FF80FF00B300010A0748353448343E223E222C342C3422030A000100" + $"30222201178322040A0101001001178322040A02010000" +}; + +resource(103, "back_button") #'VICN' array { + $"6E6369660304006603005900020006020000003C6000C000000000004C000048" + $"A0000080FF80FF00B300010A0722353622362C482C483E363E3648030A000100" + $"30222201178322040A0101001001178322040A02010000" +}; + +resource(104, "stop_button") #'VICN' array { + $"6E6369660304006603800000020006020000003C6000C000000000004C000048" + $"A00000FFABABFFD900000208022A40402A02043525BEE325B7D825253525B7D8" + $"25BEE33545B7D845BEE345453545BEE345B7D8030A0002000130222201178900" + $"040A010200011001178900040A02020100100117850004" +}; + +resource(105, "reload_button") #'VICN' array { + $"6E6369660404006603004080020006020000003A0000C000000000004C000046" + $"7FFF00ABD5FFFF006CD9020006020000003A0000C000000000004C0000467FFF" + $"FFAAD4FF00006CD9010606C60F482232383D2D3D2D3826222A2B2329224327BC" + $"B7B25A4327060A00010030222201178322040A0101001001178322040A020100" + $"000A00010012C00000000000000000C000004AC0004AC00001178422040A0101" + $"0012C00000000000000000C000004AA0004AA00001178422040A03010002C000" + $"00000000000000C000004AA0004AA000" +}; + +resource(106, "home_button") #'VICN' array { + $"6E6369660804006603800000020006020000003A8000C000000000004C000047" + $"000000FFABABFFD900000554020016020000003AC000C000000000004BE00048" + $"A00000FFFFE50300590002000602000000370000C000000000004C00004A5000" + $"0080FF80FF00B20003806040040A064836483035222230223635280A04484848" + $"42224222480A0542404234352A283428400A042C342C4032403234080A030102" + $"1001178400040A040102000A0101001001178402040A020100000A0501011001" + $"178402040A060101000A070103000A0701030240AAAA0000000000003E000045" + $"0000468000" +}; + diff --git a/frontends/beos/res/SearchEngines b/frontends/beos/res/SearchEngines new file mode 120000 index 000000000..df5252e07 --- /dev/null +++ b/frontends/beos/res/SearchEngines @@ -0,0 +1 @@ +../../resources/SearchEngines \ No newline at end of file diff --git a/frontends/beos/res/adblock.css b/frontends/beos/res/adblock.css new file mode 120000 index 000000000..e3811f62b --- /dev/null +++ b/frontends/beos/res/adblock.css @@ -0,0 +1 @@ +../../!NetSurf/Resources/AdBlock,f79 \ No newline at end of file diff --git a/frontends/beos/res/beosdefault.css b/frontends/beos/res/beosdefault.css new file mode 100644 index 000000000..9b457d448 --- /dev/null +++ b/frontends/beos/res/beosdefault.css @@ -0,0 +1,22 @@ +/* + * This file is part of NetSurf, http://netsurf-browser.org/ + */ + +/* Load base stylesheet. */ + +/*@import "default.css";*/ +@import "rsrc:///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/frontends/beos/res/ca-bundle.txt b/frontends/beos/res/ca-bundle.txt new file mode 120000 index 000000000..ad2dd6b55 --- /dev/null +++ b/frontends/beos/res/ca-bundle.txt @@ -0,0 +1 @@ +../../!NetSurf/Resources/ca-bundle \ No newline at end of file diff --git a/frontends/beos/res/credits.html b/frontends/beos/res/credits.html new file mode 120000 index 000000000..ca85d3d27 --- /dev/null +++ b/frontends/beos/res/credits.html @@ -0,0 +1 @@ +en/credits.html \ No newline at end of file diff --git a/frontends/beos/res/de/welcome.html b/frontends/beos/res/de/welcome.html new file mode 120000 index 000000000..b2ddfc796 --- /dev/null +++ b/frontends/beos/res/de/welcome.html @@ -0,0 +1 @@ +../../../!NetSurf/Resources/de/welcome.html,faf \ No newline at end of file diff --git a/frontends/beos/res/default.css b/frontends/beos/res/default.css new file mode 120000 index 000000000..6d2d4da5b --- /dev/null +++ b/frontends/beos/res/default.css @@ -0,0 +1 @@ +../../!NetSurf/Resources/CSS,f79 \ No newline at end of file diff --git a/frontends/beos/res/en/credits.html b/frontends/beos/res/en/credits.html new file mode 120000 index 000000000..1ba17392b --- /dev/null +++ b/frontends/beos/res/en/credits.html @@ -0,0 +1 @@ +../../../!NetSurf/Resources/en/credits.html,faf \ No newline at end of file diff --git a/frontends/beos/res/en/licence.html b/frontends/beos/res/en/licence.html new file mode 120000 index 000000000..147dd6db2 --- /dev/null +++ b/frontends/beos/res/en/licence.html @@ -0,0 +1 @@ +../../../!NetSurf/Resources/en/licence.html,faf \ No newline at end of file diff --git a/frontends/beos/res/en/maps.html b/frontends/beos/res/en/maps.html new file mode 120000 index 000000000..bb1eedd5a --- /dev/null +++ b/frontends/beos/res/en/maps.html @@ -0,0 +1 @@ +../../../!NetSurf/Resources/en/maps.html,faf \ No newline at end of file diff --git a/frontends/beos/res/en/welcome.html b/frontends/beos/res/en/welcome.html new file mode 120000 index 000000000..28362130a --- /dev/null +++ b/frontends/beos/res/en/welcome.html @@ -0,0 +1 @@ +../../../!NetSurf/Resources/en/welcome.html,faf \ No newline at end of file diff --git a/frontends/beos/res/favicon.png b/frontends/beos/res/favicon.png new file mode 120000 index 000000000..d968c3827 --- /dev/null +++ b/frontends/beos/res/favicon.png @@ -0,0 +1 @@ +../../gtk/res/favicon.png \ No newline at end of file diff --git a/frontends/beos/res/icons b/frontends/beos/res/icons new file mode 120000 index 000000000..4a0ebabc6 --- /dev/null +++ b/frontends/beos/res/icons @@ -0,0 +1 @@ +../../!NetSurf/Resources/Icons \ No newline at end of file diff --git a/frontends/beos/res/internal.css b/frontends/beos/res/internal.css new file mode 120000 index 000000000..e777d8ae1 --- /dev/null +++ b/frontends/beos/res/internal.css @@ -0,0 +1 @@ +../../!NetSurf/Resources/internal.css,f79 \ No newline at end of file diff --git a/frontends/beos/res/it/credits.html b/frontends/beos/res/it/credits.html new file mode 120000 index 000000000..6e1e15ed5 --- /dev/null +++ b/frontends/beos/res/it/credits.html @@ -0,0 +1 @@ +../../../!NetSurf/Resources/it/credits.html,faf \ No newline at end of file diff --git a/frontends/beos/res/it/licence.html b/frontends/beos/res/it/licence.html new file mode 120000 index 000000000..3a7c056b6 --- /dev/null +++ b/frontends/beos/res/it/licence.html @@ -0,0 +1 @@ +../../../!NetSurf/Resources/it/licence.html,faf \ No newline at end of file diff --git a/frontends/beos/res/it/welcome.html b/frontends/beos/res/it/welcome.html new file mode 120000 index 000000000..dea1e839c --- /dev/null +++ b/frontends/beos/res/it/welcome.html @@ -0,0 +1 @@ +../../../!NetSurf/Resources/it/welcome.html,faf \ No newline at end of file diff --git a/frontends/beos/res/ja/welcome.html b/frontends/beos/res/ja/welcome.html new file mode 120000 index 000000000..827796f02 --- /dev/null +++ b/frontends/beos/res/ja/welcome.html @@ -0,0 +1 @@ +../../../!NetSurf/Resources/ja/welcome.html,faf \ No newline at end of file diff --git a/frontends/beos/res/licence.html b/frontends/beos/res/licence.html new file mode 120000 index 000000000..86f8c54bf --- /dev/null +++ b/frontends/beos/res/licence.html @@ -0,0 +1 @@ +en/licence.html \ No newline at end of file diff --git a/frontends/beos/res/license b/frontends/beos/res/license new file mode 100644 index 000000000..6c2a58f90 --- /dev/null +++ b/frontends/beos/res/license @@ -0,0 +1,332 @@ +The source code, documentation, translatable messages files and UI +definitions contained within NetSurf are licensed under the following terms: + + 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. + + In addition, as a special exception, permission is granted to link the + code of this release of NetSurf with the OpenSSL project's "OpenSSL" + library (or with modified versions of it that use the same licence as + the "OpenSSL" library), and distribute the linked executables. You must + obey the GNU General Public License version 2 in all respects for all of + the code used other than "OpenSSL". If you modify the code, you may + extend this exception to your version of the code, but you are not + obligated to do so. If you do not wish to do so, delete this exception + statement from your version. + +All visual artwork contained within NetSurf is licensed under the terms of +the MIT License. + +The full text of the MIT and GPL licenses are provided in Annex A and +Annex B of this document. + + +Annex A: The MIT License +------------------------ + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +Annex B: The GNU General Public License +--------------------------------------- + + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software + interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the +Free Software Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS +NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE +LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS +AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF +ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OFMERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU +ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY +MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE +TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE +THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA +BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISE +OF THE POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS diff --git a/frontends/beos/res/maps.html b/frontends/beos/res/maps.html new file mode 120000 index 000000000..a32f725fb --- /dev/null +++ b/frontends/beos/res/maps.html @@ -0,0 +1 @@ +en/maps.html \ No newline at end of file diff --git a/frontends/beos/res/netsurf.png b/frontends/beos/res/netsurf.png new file mode 120000 index 000000000..0fbf42709 --- /dev/null +++ b/frontends/beos/res/netsurf.png @@ -0,0 +1 @@ +../../!NetSurf/Resources/netsurf.png,b60 \ No newline at end of file diff --git a/frontends/beos/res/quirks.css b/frontends/beos/res/quirks.css new file mode 120000 index 000000000..d9fb80334 --- /dev/null +++ b/frontends/beos/res/quirks.css @@ -0,0 +1 @@ +../../!NetSurf/Resources/Quirks,f79 \ No newline at end of file diff --git a/frontends/beos/res/throbber/throbber0.png b/frontends/beos/res/throbber/throbber0.png new file mode 100644 index 000000000..7c79be47b Binary files /dev/null and b/frontends/beos/res/throbber/throbber0.png differ diff --git a/frontends/beos/res/throbber/throbber1.png b/frontends/beos/res/throbber/throbber1.png new file mode 100644 index 000000000..b5b83a465 Binary files /dev/null and b/frontends/beos/res/throbber/throbber1.png differ diff --git a/frontends/beos/res/throbber/throbber2.png b/frontends/beos/res/throbber/throbber2.png new file mode 100644 index 000000000..dc1019dbd Binary files /dev/null and b/frontends/beos/res/throbber/throbber2.png differ diff --git a/frontends/beos/res/throbber/throbber3.png b/frontends/beos/res/throbber/throbber3.png new file mode 100644 index 000000000..5d458ac0b Binary files /dev/null and b/frontends/beos/res/throbber/throbber3.png differ diff --git a/frontends/beos/res/throbber/throbber4.png b/frontends/beos/res/throbber/throbber4.png new file mode 100644 index 000000000..4940aba02 Binary files /dev/null and b/frontends/beos/res/throbber/throbber4.png differ diff --git a/frontends/beos/res/throbber/throbber5.png b/frontends/beos/res/throbber/throbber5.png new file mode 100644 index 000000000..4c70ba64b Binary files /dev/null and b/frontends/beos/res/throbber/throbber5.png differ diff --git a/frontends/beos/res/throbber/throbber6.png b/frontends/beos/res/throbber/throbber6.png new file mode 100644 index 000000000..3242b06b4 Binary files /dev/null and b/frontends/beos/res/throbber/throbber6.png differ diff --git a/frontends/beos/res/throbber/throbber7.png b/frontends/beos/res/throbber/throbber7.png new file mode 100644 index 000000000..c4605101f Binary files /dev/null and b/frontends/beos/res/throbber/throbber7.png differ diff --git a/frontends/beos/res/throbber/throbber8.png b/frontends/beos/res/throbber/throbber8.png new file mode 100644 index 000000000..68f451e5b Binary files /dev/null and b/frontends/beos/res/throbber/throbber8.png differ diff --git a/frontends/beos/res/welcome.html b/frontends/beos/res/welcome.html new file mode 120000 index 000000000..1abdc5e8a --- /dev/null +++ b/frontends/beos/res/welcome.html @@ -0,0 +1 @@ +en/welcome.html \ No newline at end of file diff --git a/frontends/beos/scaffolding.cpp b/frontends/beos/scaffolding.cpp new file mode 100644 index 000000000..630e059f2 --- /dev/null +++ b/frontends/beos/scaffolding.cpp @@ -0,0 +1,2332 @@ +/* + * Copyright 2015 Adrián Arroyo Calle + * Copyright 2008 François Revol + * Copyright 2006 Rob Kendrick + * + * 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 . + */ + +#define __STDBOOL_H__ 1 +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(__HAIKU__) +#include +#include "WindowStack.h" +#endif + +#include +extern "C" { +#include "content/content.h" +#include "desktop/browser_history.h" +#include "desktop/browser.h" +#include "desktop/netsurf.h" +#include "desktop/version.h" +#include "desktop/searchweb.h" +#include "desktop/search.h" +#include "desktop/plotters.h" +#include "utils/nsoption.h" +#include "desktop/textinput.h" +#include "render/form.h" +#include "utils/messages.h" +#include "utils/utils.h" +#include "utils/log.h" +#include "utils/nsurl.h" +#include "desktop/gui_clipboard.h" +} +#include "beos/about.h" +#include "beos/bitmap.h" +#include "beos/gui.h" +#include "beos/plotters.h" +#include "beos/scaffolding.h" +#include "beos/gui_options.h" +//#include "beos/completion.h" +#include "beos/throbber.h" +#include "beos/window.h" +#include "beos/schedule.h" +//#include "beos/download.h" +#include "beos/cookies.h" + +#define TOOLBAR_HEIGHT 32 +#define DRAGGER_WIDTH 8 + +struct beos_history_window; + +class NSIconTextControl; +class NSBrowserWindow; +class NSThrobber; + +struct beos_scaffolding { + NSBrowserWindow *window; // top-level container object + + // top-level view, contains toolbar & top-level browser view + NSBaseView *top_view; + + BMenuBar *menu_bar; + + BPopUpMenu *popup_menu; + +#ifdef ENABLE_DRAGGER + BDragger *dragger; +#endif + + BView *tool_bar; + + BControl *back_button; + BControl *forward_button; + BControl *stop_button; + BControl *reload_button; + BControl *home_button; + + NSIconTextControl *url_bar; + BTextControl *search_bar; + //BMenuField *url_bar_completion; + + NSThrobber *throbber; + + BStringView *status_bar; + + BScrollView *scroll_view; + + struct beos_history_window *history_window; + + int throb_frame; + struct gui_window *top_level; + int being_destroyed; + + bool fullscreen; +}; + +struct beos_history_window { + struct beos_scaffolding *g; + BWindow *window; + +}; + +struct menu_events { + const char *widget; +}; + +// passed to the replicant main thread +struct replicant_thread_info { + char app[B_PATH_NAME_LENGTH]; + BString url; + char *args[3]; +}; + + +static int open_windows = 0; /**< current number of open browsers */ +static NSBaseView *replicant_view = NULL; /**< if not NULL, the replicant View we are running NetSurf for */ +static sem_id replicant_done_sem = -1; +static thread_id replicant_thread = -1; + +static void nsbeos_window_update_back_forward(struct beos_scaffolding *); +static void nsbeos_throb(void *); +static int32 nsbeos_replicant_main_thread(void *_arg); + +// in beos_gui.cpp +extern int main(int argc, char** argv); + +// in fetch_rsrc.cpp +extern BResources *gAppResources; + +// #pragma mark - class NSIconTextControl + +#define ICON_WIDTH 16 + +class NSIconTextControl : public BTextControl { +public: + NSIconTextControl(BRect frame, const char* name, + const char* label, const char* initialText, + BMessage* message, + uint32 resizeMode + = B_FOLLOW_LEFT | B_FOLLOW_TOP, + uint32 flags + = B_WILL_DRAW | B_NAVIGABLE | B_DRAW_ON_CHILDREN); +virtual ~NSIconTextControl(); + +virtual void FrameResized(float newWidth, float newHeight); +virtual void Draw(BRect updateRect); +virtual void DrawAfterChildren(BRect updateRect); +virtual void AttachedToWindow(); + +void SetBitmap(const BBitmap *bitmap); +void FixupTextRect(); + +private: + BPoint fIconOffset; + BRect fIconFrame; + const BBitmap *fIconBitmap; +}; + +NSIconTextControl::NSIconTextControl(BRect frame, const char* name, + const char* label, const char* initialText, + BMessage* message, + uint32 resizeMode, + uint32 flags) + : BTextControl(frame, name, label, initialText, message, resizeMode, flags), + fIconOffset(0,0), + fIconBitmap(NULL) +{ + BRect r(Bounds()); + fIconFrame = r; + fIconFrame.right = fIconFrame.left + ICON_WIDTH - 1; + fIconFrame.bottom = fIconFrame.top + ICON_WIDTH - 1; + fIconFrame.OffsetBy((int32)((r.IntegerHeight() - ICON_WIDTH + 3) / 2), + (int32)((r.IntegerHeight() - ICON_WIDTH + 1) / 2)); + FixupTextRect(); +} + + +NSIconTextControl::~NSIconTextControl() +{ + delete fIconBitmap; +} + + +void +NSIconTextControl::FrameResized(float newWidth, float newHeight) +{ + BTextControl::FrameResized(newWidth, newHeight); + FixupTextRect(); +} + + +void +NSIconTextControl::Draw(BRect updateRect) +{ + FixupTextRect(); + BTextControl::Draw(updateRect); +} + + +void +NSIconTextControl::DrawAfterChildren(BRect updateRect) +{ + BTextControl::DrawAfterChildren(updateRect); + + PushState(); + + SetDrawingMode(B_OP_ALPHA); + DrawBitmap(fIconBitmap, fIconFrame); + + //XXX: is this needed? + PopState(); +} + + +void +NSIconTextControl::AttachedToWindow() +{ + BTextControl::AttachedToWindow(); + FixupTextRect(); +} + + +void +NSIconTextControl::SetBitmap(const BBitmap *bitmap) +{ + delete fIconBitmap; + fIconBitmap = NULL; + + // keep a copy + if (bitmap) + fIconBitmap = new BBitmap(bitmap); + // invalidate just the icon area + Invalidate(fIconFrame); +} + + +void +NSIconTextControl::FixupTextRect() +{ + // FIXME: this flickers on resize, quite ugly + BRect r(TextView()->TextRect()); + + // don't fix the fix + if (r.left > ICON_WIDTH) + return; + + r.left += r.bottom - r.top; + TextView()->SetTextRect(r); +} + + +#undef ICON_WIDTH + +// #pragma mark - class NSResizeKnob + +class NSResizeKnob : public BView { +public: + NSResizeKnob(BRect frame, BView *target); +virtual ~NSResizeKnob(); + +virtual void MouseDown(BPoint where); +virtual void MouseUp(BPoint where); +virtual void MouseMoved(BPoint where, uint32 code, + const BMessage* dragMessage); + +virtual void Draw(BRect updateRect); + +void SetBitmap(const BBitmap *bitmap); + +private: + const BBitmap *fBitmap; + BView *fTarget; + BPoint fOffset; +}; + +NSResizeKnob::NSResizeKnob(BRect frame, BView *target) + : BView(frame, "NSResizeKnob", B_FOLLOW_BOTTOM | B_FOLLOW_RIGHT, B_WILL_DRAW), + fBitmap(NULL), + fTarget(target), + fOffset(-1, -1) +{ + SetViewColor(0, 255, 0); +} + + +NSResizeKnob::~NSResizeKnob() +{ +} + + +void +NSResizeKnob::MouseDown(BPoint where) +{ + SetMouseEventMask(B_POINTER_EVENTS, + B_NO_POINTER_HISTORY | B_LOCK_WINDOW_FOCUS); + fOffset = where; +} + + +void +NSResizeKnob::MouseUp(BPoint where) +{ + fOffset.Set(-1, -1); +} + + +void +NSResizeKnob::MouseMoved(BPoint where, uint32 code, + const BMessage* dragMessage) +{ + if (fOffset.x >= 0) { + fTarget->ResizeBy(where.x - fOffset.x, where.y - fOffset.y); + } +} + + +void +NSResizeKnob::Draw(BRect updateRect) +{ + if (!fBitmap) + return; + DrawBitmap(fBitmap); +} + + +void +NSResizeKnob::SetBitmap(const BBitmap *bitmap) +{ + fBitmap = bitmap; + Invalidate(); +} + + +// #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; + Invalidate(); +} + + +// #pragma mark - class NSBaseView + + +NSBaseView::NSBaseView(BRect frame) + : BView(frame, "NetSurf", B_FOLLOW_ALL_SIDES, + 0 /*B_WILL_DRAW | B_NAVIGABLE | B_FRAME_EVENTS*/ /*| B_SUBPIXEL_PRECISE*/), + fScaffolding(NULL) +{ +} + +NSBaseView::NSBaseView(BMessage *archive) + : BView(archive), + fScaffolding(NULL) +{ +} + + +NSBaseView::~NSBaseView() +{ + //beos_warn_user("~NSBaseView()", NULL); + if (replicated) { + BMessage *message = new BMessage(B_QUIT_REQUESTED); + nsbeos_pipe_message_top(message, NULL, fScaffolding); + while (acquire_sem(replicant_done_sem) == EINTR); + //debugger("plop"); + status_t status = -1; + wait_for_thread(replicant_thread, &status); + } +} + + +void +NSBaseView::MessageReceived(BMessage *message) +{ + switch (message->what) { + case B_SIMPLE_DATA: + case B_ABOUT_REQUESTED: + case B_ARGV_RECEIVED: + case B_REFS_RECEIVED: + case B_COPY: + case B_CUT: + case B_PASTE: + case B_SELECT_ALL: + //case B_MOUSE_WHEEL_CHANGED: + case B_UI_SETTINGS_CHANGED: + // NetPositive messages + case B_NETPOSITIVE_OPEN_URL: + case B_NETPOSITIVE_BACK: + case B_NETPOSITIVE_FORWARD: + case B_NETPOSITIVE_HOME: + case B_NETPOSITIVE_RELOAD: + case B_NETPOSITIVE_STOP: + case B_NETPOSITIVE_DOWN: + case B_NETPOSITIVE_UP: + // messages for top-level + case 'back': + case 'forw': + case 'stop': + case 'relo': + case 'home': + case 'urlc': + case 'urle': + case 'sear': + case 'menu': + case NO_ACTION: + case HELP_OPEN_CONTENTS: + case HELP_OPEN_GUIDE: + case HELP_OPEN_INFORMATION: + case HELP_OPEN_ABOUT: + case HELP_OPEN_LICENCE: + case HELP_LAUNCH_INTERACTIVE: + case HISTORY_SHOW_LOCAL: + case HISTORY_SHOW_GLOBAL: + case HOTLIST_ADD_URL: + case HOTLIST_SHOW: + case COOKIES_SHOW: + case COOKIES_DELETE: + case BROWSER_PAGE: + case BROWSER_PAGE_INFO: + case BROWSER_PRINT: + case BROWSER_NEW_WINDOW: + case BROWSER_VIEW_SOURCE: + case BROWSER_OBJECT: + case BROWSER_OBJECT_INFO: + case BROWSER_OBJECT_RELOAD: + case BROWSER_OBJECT_SAVE: + case BROWSER_OBJECT_EXPORT_SPRITE: + case BROWSER_OBJECT_SAVE_URL_URI: + case BROWSER_OBJECT_SAVE_URL_URL: + case BROWSER_OBJECT_SAVE_URL_TEXT: + case BROWSER_SAVE: + case BROWSER_SAVE_COMPLETE: + case BROWSER_EXPORT_DRAW: + case BROWSER_EXPORT_TEXT: + case BROWSER_SAVE_URL_URI: + case BROWSER_SAVE_URL_URL: + case BROWSER_SAVE_URL_TEXT: + case HOTLIST_EXPORT: + case HISTORY_EXPORT: + case BROWSER_NAVIGATE_HOME: + case BROWSER_NAVIGATE_BACK: + case BROWSER_NAVIGATE_FORWARD: + case BROWSER_NAVIGATE_UP: + case BROWSER_NAVIGATE_RELOAD: + case BROWSER_NAVIGATE_RELOAD_ALL: + case BROWSER_NAVIGATE_STOP: + case BROWSER_NAVIGATE_URL: + case BROWSER_SCALE_VIEW: + case BROWSER_FIND_TEXT: + case BROWSER_IMAGES_FOREGROUND: + case BROWSER_IMAGES_BACKGROUND: + case BROWSER_BUFFER_ANIMS: + case BROWSER_BUFFER_ALL: + case BROWSER_SAVE_VIEW: + case BROWSER_WINDOW_DEFAULT: + case BROWSER_WINDOW_STAGGER: + case BROWSER_WINDOW_COPY: + case BROWSER_WINDOW_RESET: + case TREE_NEW_FOLDER: + case TREE_NEW_LINK: + case TREE_EXPAND_ALL: + case TREE_EXPAND_FOLDERS: + case TREE_EXPAND_LINKS: + case TREE_COLLAPSE_ALL: + case TREE_COLLAPSE_FOLDERS: + case TREE_COLLAPSE_LINKS: + case TREE_SELECTION: + case TREE_SELECTION_EDIT: + case TREE_SELECTION_LAUNCH: + case TREE_SELECTION_DELETE: + case TREE_SELECT_ALL: + case TREE_CLEAR_SELECTION: + case TOOLBAR_BUTTONS: + case TOOLBAR_ADDRESS_BAR: + case TOOLBAR_THROBBER: + case TOOLBAR_EDIT: + case CHOICES_SHOW: + case APPLICATION_QUIT: + if (Window()) + Window()->DetachCurrentMessage(); + nsbeos_pipe_message_top(message, NULL, fScaffolding); + break; + default: + //message->PrintToStream(); + BView::MessageReceived(message); + } +} + + +status_t +NSBaseView::Archive(BMessage *archive, bool deep) const +{ + // force archiving only the base view + deep = false; + status_t err; + err = BView::Archive(archive, deep); + if (err < B_OK) + return err; + // add our own fields + // we try to reuse the same fields as NetPositive + archive->AddString("add_on", "application/x-vnd.NetSurf"); + //archive->AddInt32("version", 2); + archive->AddString("url", fScaffolding->url_bar->Text()); + archive->AddBool("openAsText", false); + archive->AddInt32("encoding", 258); + return err; +} + + +BArchivable * +NSBaseView::Instantiate(BMessage *archive) +{ + if (!validate_instantiation(archive, "NSBaseView")) + return NULL; + const char *url; + if (archive->FindString("url", &url) < B_OK + || url == NULL || strlen(url) == 0) { + url = "about:"; + } + + struct replicant_thread_info *info = new replicant_thread_info; + info->url = BString(url); + if (nsbeos_find_app_path(info->app) < B_OK) + return NULL; + info->args[0] = info->app; + info->args[1] = (char *)info->url.String(); + info->args[2] = NULL; + NSBaseView *view = new NSBaseView(archive); + replicant_view = view; + replicated = true; + + //TODO:FIXME: fix replicants + // do as much as possible in this thread to avoid deadlocks + + gui_init_replicant(2, info->args); + + replicant_done_sem = create_sem(0, "NS Replicant created"); + replicant_thread = spawn_thread(nsbeos_replicant_main_thread, + "NetSurf Main Thread", B_NORMAL_PRIORITY, info); + if (replicant_thread < B_OK) { + delete_sem(replicant_done_sem); + delete info; + delete view; + return NULL; + } + resume_thread(replicant_thread); + //XXX: deadlocks BeHappy + //while (acquire_sem(replicant_done_sem) == EINTR); + + return view; +} + + +void +NSBaseView::SetScaffolding(struct beos_scaffolding *scaf) +{ + fScaffolding = scaf; +} + + +// AttachedToWindow() is not enough to get the dragger and status bar +// stick to the panel color +void +NSBaseView::AllAttached() +{ + BView::AllAttached(); + + struct beos_scaffolding *g = fScaffolding; + if (!g) + return; + // set targets to the topmost ns view + g->back_button->SetTarget(this); + g->forward_button->SetTarget(this); + g->stop_button->SetTarget(this); + g->reload_button->SetTarget(this); + g->home_button->SetTarget(this); + + rgb_color c = ui_color(B_PANEL_BACKGROUND_COLOR); + SetViewColor(c); + + g->tool_bar->SetViewColor(c); + g->back_button->SetViewColor(c); + g->back_button->SetLowColor(c); + g->forward_button->SetViewColor(c); + g->forward_button->SetLowColor(c); + g->stop_button->SetViewColor(c); + g->stop_button->SetLowColor(c); + g->reload_button->SetViewColor(c); + g->reload_button->SetLowColor(c); + g->home_button->SetViewColor(c); + g->home_button->SetLowColor(c); + g->url_bar->SetViewColor(c); + g->search_bar->SetViewColor(c); + g->throbber->SetViewColor(c); + g->scroll_view->SetViewColor(c); + +#ifdef ENABLE_DRAGGER + g->dragger->SetViewColor(c); +#endif + + g->status_bar->SetViewColor(c); + g->status_bar->SetLowColor(c); +#if defined(__HAIKU__) || defined(B_DANO_VERSION) + g->status_bar->SetHighColor(ui_color(B_PANEL_TEXT_COLOR)); +#endif +} + + +// #pragma mark - class NSBrowserWindow + + +NSBrowserWindow::NSBrowserWindow(BRect frame, struct beos_scaffolding *scaf) + : BWindow(frame, "NetSurf", B_DOCUMENT_WINDOW, 0), + fScaffolding(scaf) +{ +} + + +NSBrowserWindow::~NSBrowserWindow() +{ + if(activeWindow == this) + activeWindow = NULL; +} + + +void +NSBrowserWindow::DispatchMessage(BMessage *message, BHandler *handler) +{ + BMessage *msg; + switch (message->what) { + case B_UI_SETTINGS_CHANGED: + msg = new BMessage(*message); + nsbeos_pipe_message_top(msg, this, fScaffolding); + break; + } + BWindow::DispatchMessage(message, handler); +} + + +void +NSBrowserWindow::MessageReceived(BMessage *message) +{ + switch (message->what) { + case B_ARGV_RECEIVED: + case B_REFS_RECEIVED: + case B_UI_SETTINGS_CHANGED: + 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 +} + + +void +NSBrowserWindow::WindowActivated(bool active) +{ + if(active) + activeWindow = this; + else if(activeWindow == this) + activeWindow = NULL; +} + + +// #pragma mark - implementation + +int32 nsbeos_replicant_main_thread(void *_arg) +{ + struct replicant_thread_info *info = (struct replicant_thread_info *)_arg; + int32 ret = 0; + + while (!nsbeos_done) { + nsbeos_gui_poll(); + } + + netsurf_exit(); + delete info; + delete_sem(replicant_done_sem); + return ret; +} + + +/* 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) + nsbeos_done = true; + + if (window) { + window->Lock(); + window->Quit(); + } + + if (!g->being_destroyed) { + g->being_destroyed = 1; + nsbeos_window_destroy_browser(g->top_level); + } +} + + +static void nsbeos_scaffolding_update_colors(nsbeos_scaffolding *g) +{ + if (!g->top_view->LockLooper()) + return; + rgb_color c = ui_color(B_PANEL_BACKGROUND_COLOR); + g->top_view->SetViewColor(c); + + g->tool_bar->SetViewColor(c); + g->back_button->SetViewColor(c); + g->forward_button->SetViewColor(c); + g->stop_button->SetViewColor(c); + g->reload_button->SetViewColor(c); + g->home_button->SetViewColor(c); + g->url_bar->SetViewColor(c); + g->search_bar->SetViewColor(c); + g->throbber->SetViewColor(c); + g->scroll_view->SetViewColor(c); + +#ifdef ENABLE_DRAGGER + g->dragger->SetViewColor(c); +#endif + + g->status_bar->SetViewColor(c); + g->status_bar->SetLowColor(c); +#if defined(__HAIKU__) || defined(B_DANO_VERSION) + g->status_bar->SetHighColor(ui_color(B_PANEL_TEXT_COLOR)); +#endif + g->top_view->UnlockLooper(); +} + + +/*static*/ BWindow* +NSBrowserWindow::activeWindow = NULL; + + +void nsbeos_scaffolding_dispatch_event(nsbeos_scaffolding *scaffold, BMessage *message) +{ + struct browser_window *bw; + bw = nsbeos_get_browser_for_gui(scaffold->top_level); + bool reloadAll = false; + + LOG("nsbeos_scaffolding_dispatch_event() what = 0x%08lx", message->what); + switch (message->what) { + case B_QUIT_REQUESTED: + nsbeos_scaffolding_destroy(scaffold); + break; + case B_ABOUT_REQUESTED: + { + nsbeos_about(scaffold->top_level); + break; + } + case B_NETPOSITIVE_DOWN: + //XXX WRITEME + break; + case B_SIMPLE_DATA: + { + if (!message->HasRef("refs")) { + // XXX handle DnD + break; + } + // FALL THROUGH + // handle refs + } + case B_REFS_RECEIVED: + { + int32 i; + entry_ref ref; + + for (i = 0; message->FindRef("refs", i, &ref) >= B_OK; i++) { + BString url("file://"); + BPath path(&ref); + if (path.InitCheck() < B_OK) + break; + + BNode node(path.Path()); + if (node.InitCheck() < B_OK) + break; + if (node.IsSymLink()) { + // dereference the symlink + BEntry entry(path.Path(), true); + if (entry.InitCheck() < B_OK) + break; + if (entry.GetPath(&path) < B_OK) + break; + if (node.SetTo(path.Path()) < 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(); + + nsurl *nsurl; + nserror error; + + error = nsurl_create(url.String(), &nsurl); + if (error == NSERROR_OK) { + if (/*message->WasDropped() &&*/ i == 0) { + browser_window_navigate(bw, nsurl, NULL, + (browser_window_nav_flags) + (BW_NAVIGATE_HISTORY), + NULL, NULL, NULL); + } else { + error = browser_window_create(BW_CREATE_CLONE, + nsurl, + NULL, + bw, + NULL); + } + nsurl_unref(nsurl); + } + if (error != NSERROR_OK) { + beos_warn_user(messages_get_errorcode(error), 0); + } + } + break; + } + case B_ARGV_RECEIVED: + { + int32 i; + BString urltxt; + nsurl *url; + nserror error; + + for (i = 1; message->FindString("argv", i, &urltxt) >= B_OK; i++) { + error = nsurl_create(urltxt.String(), &url); + if (error == NSERROR_OK) { + error = browser_window_create(BW_CREATE_CLONE, + url, + NULL, + bw, + NULL); + nsurl_unref(url); + } + if (error != NSERROR_OK) { + beos_warn_user(messages_get_errorcode(error), 0); + } + } + break; + } + case B_UI_SETTINGS_CHANGED: + nsbeos_update_system_ui_colors(); + nsbeos_scaffolding_update_colors(scaffold); + break; + case B_NETPOSITIVE_OPEN_URL: + { + BString url; + if (message->FindString("be:url", &url) < B_OK) + break; + + nsurl *nsurl; + nserror error; + + error = nsurl_create(url.String(), &nsurl); + if (error != NSERROR_OK) { + beos_warn_user(messages_get_errorcode(error), 0); + } else { + browser_window_navigate(bw, + nsurl, + NULL, + (browser_window_nav_flags)(BW_NAVIGATE_HISTORY | BW_NAVIGATE_UNVERIFIABLE), + NULL, + NULL, + NULL); + nsurl_unref(nsurl); + } + break; + } + case B_COPY: + browser_window_key_press(bw, NS_KEY_COPY_SELECTION); + break; + case B_CUT: + browser_window_key_press(bw, NS_KEY_CUT_SELECTION); + break; + case B_PASTE: + browser_window_key_press(bw, NS_KEY_PASTE); + break; + case B_SELECT_ALL: + LOG("Selecting all text"); + browser_window_key_press(bw, NS_KEY_SELECT_ALL); + break; + case B_NETPOSITIVE_BACK: + case BROWSER_NAVIGATE_BACK: + case 'back': + if (!browser_window_history_back_available(bw)) + break; + browser_window_history_back(bw, false); + nsbeos_window_update_back_forward(scaffold); + break; + case B_NETPOSITIVE_FORWARD: + case BROWSER_NAVIGATE_FORWARD: + case 'forw': + if (!browser_window_history_forward_available(bw)) + break; + browser_window_history_forward(bw, false); + nsbeos_window_update_back_forward(scaffold); + break; + case B_NETPOSITIVE_STOP: + case BROWSER_NAVIGATE_STOP: + case 'stop': + browser_window_stop(bw); + break; + case B_NETPOSITIVE_RELOAD: + case BROWSER_NAVIGATE_RELOAD_ALL: + case 'relo': + reloadAll = true; + // FALLTHRU + case BROWSER_NAVIGATE_RELOAD: + browser_window_reload(bw, reloadAll); + break; + case B_NETPOSITIVE_HOME: + case BROWSER_NAVIGATE_HOME: + case 'home': + { + nsurl *url; + nserror error; + + static const char *addr = NETSURF_HOMEPAGE; + + if (nsoption_charp(homepage_url) != NULL) { + addr = nsoption_charp(homepage_url); + } + + error = nsurl_create(addr, &url); + if (error != NSERROR_OK) { + beos_warn_user(messages_get_errorcode(error), 0); + } else { + browser_window_navigate(bw, + url, + NULL, + (browser_window_nav_flags)(BW_NAVIGATE_HISTORY), + NULL, + NULL, + NULL); + nsurl_unref(url); + } + break; + } + case 'urle': + { + nsurl *url; + nserror error; + BString text; + + if (!scaffold->url_bar->LockLooper()) + break; + + text = scaffold->url_bar->Text(); + scaffold->scroll_view->Target()->MakeFocus(); + scaffold->url_bar->UnlockLooper(); + + error = nsurl_create(text.String(), &url); + if (error != NSERROR_OK) { + beos_warn_user(messages_get_errorcode(error), 0); + } else { + browser_window_navigate(bw, + url, + NULL, + (browser_window_nav_flags)(BW_NAVIGATE_HISTORY), + NULL, + NULL, + NULL); + nsurl_unref(url); + } + 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 'sear': + { + nserror ret; + nsurl* url; + BString text; + if (!scaffold->search_bar->LockLooper()) + break; + text = scaffold->search_bar->Text(); + scaffold->search_bar->UnlockLooper(); + + char t[PATH_MAX]; + find_resource(t,"SearchEngines","./beos/res/SearchEngines"); + + search_web_init(&t[0]); + + ret = search_web_omni(text.String(),SEARCH_WEB_OMNI_SEARCHONLY + ,&url); + if (ret == NSERROR_OK) { + ret = browser_window_create( + (browser_window_create_flags)(BW_CREATE_HISTORY | BW_CREATE_TAB), + url, + NULL, + bw, + NULL); + nsurl_unref(url); + } + + if (ret != NSERROR_OK) { + beos_warn_user(messages_get_errorcode(ret), 0); + } + + search_web_finalise(); + + 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; + } +*/ + case NO_ACTION: + break; + case HELP_OPEN_CONTENTS: + break; + case HELP_OPEN_GUIDE: + break; + case HELP_OPEN_INFORMATION: + break; + case HELP_OPEN_ABOUT: + { + const char *goto_url = "about:credits"; + nserror nserr; + nsurl *url; + nserr = nsurl_create(goto_url, &url); + if (nserr == NSERROR_OK) { + nserr = browser_window_navigate(bw, + url, NULL, + (browser_window_nav_flags)(BW_NAVIGATE_HISTORY), + NULL, NULL, NULL); + nsurl_unref(url); + } + if (nserr != NSERROR_OK) { + beos_warn_user(messages_get_errorcode(nserr), 0); + } + } + break; + case HELP_OPEN_LICENCE: + { + const char *goto_url = "about:licence"; + nserror nserr; + nsurl *url; + nserr = nsurl_create(goto_url, &url); + if (nserr == NSERROR_OK) { + nserr = browser_window_navigate(bw, + url, NULL, + (browser_window_nav_flags)(BW_NAVIGATE_HISTORY), + NULL, NULL, NULL); + nsurl_unref(url); + } + if (nserr != NSERROR_OK) { + beos_warn_user(messages_get_errorcode(nserr), 0); + } + } + break; + case HELP_LAUNCH_INTERACTIVE: + break; + case HISTORY_SHOW_LOCAL: + break; + case HISTORY_SHOW_GLOBAL: + break; + case HOTLIST_ADD_URL: + break; + case HOTLIST_SHOW: + break; + case COOKIES_SHOW: + { + nsbeos_cookies_init(); + break; + } + case COOKIES_DELETE: + { + nsbeos_cookies_init(); + break; + } + case BROWSER_PAGE: + break; + case BROWSER_PAGE_INFO: + break; + case BROWSER_PRINT: + break; + case BROWSER_NEW_WINDOW: + { + BString text; + nsurl *url; + nserror error; + + if (!scaffold->url_bar->LockLooper()) + break; + text = scaffold->url_bar->Text(); + scaffold->url_bar->UnlockLooper(); + + NSBrowserWindow::activeWindow = scaffold->window; + + error = nsurl_create(text.String(), &url); + if (error == NSERROR_OK) { + error = browser_window_create(BW_CREATE_CLONE, + url, + NULL, + bw, + NULL); + nsurl_unref(url); + } + if (error != NSERROR_OK) { + beos_warn_user(messages_get_errorcode(error), 0); + } + break; + } + case BROWSER_VIEW_SOURCE: + { + if (!bw || browser_window_has_content(bw) == false) + break; + nsbeos_gui_view_source(browser_window_get_content(bw)); + break; + } + case BROWSER_OBJECT: + break; + case BROWSER_OBJECT_INFO: + break; + case BROWSER_OBJECT_RELOAD: + break; + case BROWSER_OBJECT_SAVE: + break; + case BROWSER_OBJECT_EXPORT_SPRITE: + break; + case BROWSER_OBJECT_SAVE_URL_URI: + break; + case BROWSER_OBJECT_SAVE_URL_URL: + break; + case BROWSER_OBJECT_SAVE_URL_TEXT: + break; + case BROWSER_SAVE: + break; + case BROWSER_SAVE_COMPLETE: + break; + case BROWSER_EXPORT_DRAW: + break; + case BROWSER_EXPORT_TEXT: + break; + case BROWSER_SAVE_URL_URI: + break; + case BROWSER_SAVE_URL_URL: + break; + case BROWSER_SAVE_URL_TEXT: + break; + case HOTLIST_EXPORT: + break; + case HISTORY_EXPORT: + break; + case B_NETPOSITIVE_UP: + case BROWSER_NAVIGATE_UP: + break; + case BROWSER_NAVIGATE_URL: + if (!scaffold->url_bar->LockLooper()) + break; + scaffold->url_bar->MakeFocus(); + scaffold->url_bar->UnlockLooper(); + break; + case BROWSER_SCALE_VIEW: + break; + case BROWSER_FIND_TEXT: + break; + case BROWSER_IMAGES_FOREGROUND: + break; + case BROWSER_IMAGES_BACKGROUND: + break; + case BROWSER_BUFFER_ANIMS: + break; + case BROWSER_BUFFER_ALL: + break; + case BROWSER_SAVE_VIEW: + break; + case BROWSER_WINDOW_DEFAULT: + break; + case BROWSER_WINDOW_STAGGER: + break; + case BROWSER_WINDOW_COPY: + break; + case BROWSER_WINDOW_RESET: + break; + case TREE_NEW_FOLDER: + case TREE_NEW_LINK: + case TREE_EXPAND_ALL: + case TREE_EXPAND_FOLDERS: + case TREE_EXPAND_LINKS: + case TREE_COLLAPSE_ALL: + case TREE_COLLAPSE_FOLDERS: + case TREE_COLLAPSE_LINKS: + case TREE_SELECTION: + case TREE_SELECTION_EDIT: + case TREE_SELECTION_LAUNCH: + case TREE_SELECTION_DELETE: + case TREE_SELECT_ALL: + case TREE_CLEAR_SELECTION: + break; + case TOOLBAR_BUTTONS: + break; + case TOOLBAR_ADDRESS_BAR: + break; + case TOOLBAR_THROBBER: + break; + case TOOLBAR_EDIT: + break; + case CHOICES_SHOW: + break; + case APPLICATION_QUIT: + nsbeos_done = true; + 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); +} + + +void nsbeos_window_update_back_forward(struct beos_scaffolding *g) +{ + struct browser_window *bw = nsbeos_get_browser_for_gui(g->top_level); + + if (!g->top_view->LockLooper()) + return; + + g->back_button->SetEnabled(browser_window_history_back_available(bw)); + g->forward_button->SetEnabled(browser_window_history_forward_available(bw)); + + g->top_view->UnlockLooper(); + +} + +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; + + g->throbber->SetBitmap(nsbeos_throbber->framedata[g->throb_frame]); + g->throbber->Invalidate(); + + g->top_view->UnlockLooper(); + + beos_schedule(100, nsbeos_throb, p); + +} + + +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(be_app->WindowAt(i)); + if (win) { + win->Lock(); + be_app->Unlock(); + return win; + } + } + be_app->Unlock(); + return NULL; +} + +NSBrowserWindow *nsbeos_get_bwindow_for_scaffolding(nsbeos_scaffolding *scaffold) +{ + return scaffold->window; +} + +NSBaseView *nsbeos_get_baseview_for_scaffolding(nsbeos_scaffolding *scaffold) +{ + return scaffold->top_view; +} + +static void recursively_set_menu_items_target(BMenu *menu, BHandler *handler) +{ + menu->SetTargetForItems(handler); + for (int i = 0; menu->ItemAt(i); i++) { + if (!menu->SubmenuAt(i)) + continue; + recursively_set_menu_items_target(menu->SubmenuAt(i), handler); + } +} + +void nsbeos_attach_toplevel_view(nsbeos_scaffolding *g, BView *view) +{ + LOG("Attaching view to scaffolding %p", g); + + // this is a replicant,... and it went bad + if (!g->window) { + if (g->top_view->Looper() && !g->top_view->LockLooper()) + return; + } + + BRect rect(g->top_view->Bounds()); + rect.top += TOOLBAR_HEIGHT; + rect.right -= B_V_SCROLL_BAR_WIDTH; + 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); + + // for replicants, add a NSResizeKnob to allow resizing + if (!g->window) { + BRect frame = g->scroll_view->Bounds(); + frame.left = frame.right - B_V_SCROLL_BAR_WIDTH; + frame.top = frame.bottom - B_H_SCROLL_BAR_HEIGHT; + NSResizeKnob *knob = new NSResizeKnob(frame, g->top_view); + //TODO: set bitmap + g->scroll_view->AddChild(knob); + } + + 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); + */ + + g->status_bar->MoveTo(rect.LeftTop()); + g->status_bar->ResizeTo(rect.Width() + 1, rect.Height() + 1); + 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 ?) + // this won't work for replicants, since the base view isn't attached yet + // we'll redo this in NSBaseView::AllAttached + 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); + g->search_bar->SetTarget(view); + + nsbeos_scaffolding_update_colors(g); + + if (g->window) { + recursively_set_menu_items_target(g->menu_bar, view); + + // add toolbar shortcuts + BMessage *message; + + message = new BMessage('back'); + message->AddPointer("scaffolding", g); + g->window->AddShortcut(B_LEFT_ARROW, 0, message, view); + + message = new BMessage('forw'); + message->AddPointer("scaffolding", g); + g->window->AddShortcut(B_RIGHT_ARROW, 0, message, view); + + message = new BMessage('stop'); + message->AddPointer("scaffolding", g); + g->window->AddShortcut('S', 0, message, view); + + message = new BMessage('relo'); + message->AddPointer("scaffolding", g); + g->window->AddShortcut('R', 0, message, view); + + message = new BMessage('home'); + message->AddPointer("scaffolding", g); + g->window->AddShortcut('H', 0, message, view); + + +#if defined(__HAIKU__) + // Make sure the window is layouted and answering to events, but do not + // show it before it is actually resized + g->window->Hide(); + g->window->Show(); + + if(NSBrowserWindow::activeWindow) { + BWindowStack stack(NSBrowserWindow::activeWindow); + stack.AddWindow(g->window); + } +#endif + g->window->Show(); + + } else { + if (g->top_view->Looper()) + g->top_view->UnlockLooper(); + } + + +} + +static BMenuItem *make_menu_item(const char *name, BMessage *message, bool enabled=false) +{ + BMenuItem *item; + BString label(messages_get(name)); + BString accel; + uint32 mods = 0; + char key = 0; + // try to understand accelerators + int32 start = label.IFindLast(" "); + if (start > 0 && (label.Length() - start > 1) + && (label.Length() - start < 7) + && (label[start + 1] == 'F' + || !strcmp(label.String() + start + 1, "PRINT") + || label[start + 1] == '\xe2' + || label[start + 1] == '^')) { + + label.MoveInto(accel, start + 1, label.Length()); + // strip the trailing spaces + while (label[label.Length() - 1] == ' ') + label.Truncate(label.Length() - 1); + + if (accel.FindFirst("\xe2\x87\x91") > -1) { + accel.RemoveFirst("\xe2\x87\x91"); + mods |= B_SHIFT_KEY; + } + if (accel.FindFirst("^") > -1) { + accel.RemoveFirst("^"); + mods |= B_CONTROL_KEY; // ALT!!! + } + if (accel.FindFirst("PRINT") > -1) { + accel.RemoveFirst("PRINT"); + //mods |= ; // ALT!!! + key = B_PRINT_KEY; + } + if (accel.Length() > 1 && accel[0] == 'F') { // Function key + int num; + if (sscanf(accel.String(), "F%d", &num) > 0) { + // + } + } else if (accel.Length() > 0) { + key = accel[0]; + } + //printf("MENU: detected accel '%s' mods 0x%08lx, key %d\n", accel.String(), mods, key); + } + + // turn ... into ellipsis + label.ReplaceAll("...", B_UTF8_ELLIPSIS); + + item = new BMenuItem(label.String(), message, key, mods); + + item->SetEnabled(enabled); + + return item; +} + + +class BBitmapButton: public BButton +{ + public: + BBitmapButton(BRect rect, const char* name, const char* label, + BMessage* message); + ~BBitmapButton(); + + void Draw(BRect updateRect); + void SetBitmap(const char* attrName); + private: + BBitmap* fBitmap; + BBitmap* fDisabledBitmap; +}; + + +BBitmapButton::BBitmapButton(BRect rect, const char* name, const char* label, + BMessage* message) + : BButton(rect, name, label, message) +{ + SetBitmap(name); +} + + +BBitmapButton::~BBitmapButton() +{ + delete fBitmap; + delete fDisabledBitmap; +} + + +void BBitmapButton::Draw(BRect updateRect) +{ + if(fBitmap == NULL) { + BButton::Draw(updateRect); + return; + } + + SetDrawingMode(B_OP_COPY); + FillRect(updateRect, B_SOLID_LOW); + rgb_color color = LowColor(); + + SetDrawingMode(B_OP_ALPHA); + if(IsEnabled()) { + if(Value() != 0) { + // button is clicked + DrawBitmap(fBitmap, BPoint(1, 1)); + } else { + // button is released + DrawBitmap(fBitmap, BPoint(0, 0)); + } + } else + DrawBitmap(fDisabledBitmap, BPoint(0, 0)); +} + + +void BBitmapButton::SetBitmap(const char* attrname) +{ +#ifdef __HAIKU__ + size_t size = 0; + const void* data = gAppResources->LoadResource('VICN', attrname, &size); + + if (!data) { + printf("CANT LOAD RESOURCE %s\n", attrname); + return; + } + + fBitmap = new BBitmap(BRect(0, 0, 32, 32), B_RGB32); + status_t status = BIconUtils::GetVectorIcon((const uint8*)data, size, fBitmap); + + if(status != B_OK) { + fprintf(stderr, "%s > oops %s\n", attrname, strerror(status)); + delete fBitmap; + fBitmap = NULL; + } + + fDisabledBitmap = new BBitmap(fBitmap); + rgb_color* pixel = (rgb_color*)fDisabledBitmap->Bits(); + for(int i = 0; i < fDisabledBitmap->BitsLength()/4; i++) + { + *pixel = tint_color(*pixel, B_DISABLED_MARK_TINT); + pixel++; + } +#else + // No vector icon support on BeOS. We could try to load a bitmap one + fBitmap = NULL; + fDisabledBitmap = NULL; +#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; + g->being_destroyed = 0; + g->fullscreen = false; + + open_windows++; + + BMessage *message; + BRect rect; + + g->window = NULL; + g->menu_bar = NULL; + + if (replicated && !replicant_view) { + beos_warn_user("Error: No subwindow allowed when replicated.", NULL); + return NULL; + } + + + if (!replicant_view) { + BRect frame(0, 0, 600-1, 500-1); + if (nsoption_int(window_width) > 0) { + frame.Set(0, 0, nsoption_int(window_width) - 1, nsoption_int(window_height) - 1); + frame.OffsetToSelf(nsoption_int(window_x), nsoption_int(window_y)); + } else { + BPoint pos(50, 50); + // XXX: use last BApplication::WindowAt()'s dynamic_cast Frame() + NSBrowserWindow *win = nsbeos_find_last_window(); + if (win) { + pos = win->Frame().LeftTop(); + win->UnlockLooper(); + } + 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); + + 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; + BMenuItem *item; + + // App menu + //XXX: use icon item ? + + menu = new BMenu(messages_get("NetSurf")); + g->menu_bar->AddItem(menu); + + message = new BMessage(B_ABOUT_REQUESTED); + item = make_menu_item("Info", message, true); + menu->AddItem(item); + +#if 0 + message = new BMessage(NO_ACTION); + item = make_menu_item("AppHelp", message); + menu->AddItem(item); + + submenu = new BMenu(messages_get("Open")); + menu->AddItem(submenu); + + message = new BMessage(NO_ACTION); + item = make_menu_item("OpenURL", message); + submenu->AddItem(item); + + message = new BMessage(CHOICES_SHOW); + item = make_menu_item("Choices", message); + menu->AddItem(item); +#endif + + message = new BMessage(APPLICATION_QUIT); + item = make_menu_item("Quit", message, true); + menu->AddItem(item); + + // Page menu + + menu = new BMenu(messages_get("Page")); + g->menu_bar->AddItem(menu); + +#if 0 + message = new BMessage(BROWSER_PAGE_INFO); + item = make_menu_item("PageInfo", message); + menu->AddItem(item); + + message = new BMessage(BROWSER_SAVE); + item = make_menu_item("SaveAsNS", message); + menu->AddItem(item); + + message = new BMessage(BROWSER_SAVE_COMPLETE); + item = make_menu_item("SaveCompNS", message); + menu->AddItem(item); + + submenu = new BMenu(messages_get("Export")); + menu->AddItem(submenu); + + /* + message = new BMessage(BROWSER_EXPORT_DRAW); + item = make_menu_item("Draw", message); + submenu->AddItem(item); + */ + + message = new BMessage(BROWSER_EXPORT_TEXT); + item = make_menu_item("LinkText", message); + submenu->AddItem(item); + + + submenu = new BMenu(messages_get("SaveURL")); + menu->AddItem(submenu); + + //XXX + message = new BMessage(BROWSER_OBJECT_SAVE_URL_URL); + item = make_menu_item("URL", message); + submenu->AddItem(item); + + + message = new BMessage(BROWSER_PRINT); + item = make_menu_item("PrintNS", message); + menu->AddItem(item); +#endif + + message = new BMessage(BROWSER_NEW_WINDOW); + item = make_menu_item("NewWindowNS", message, true); + menu->AddItem(item); + + message = new BMessage(BROWSER_VIEW_SOURCE); + item = make_menu_item("ViewSrc", message, true); + menu->AddItem(item); + +#if 0 // FIXME This is supposed to be a popup menu! + // Object menu + + menu = new BMenu(messages_get("Object")); + g->menu_bar->AddItem(menu); + + message = new BMessage(BROWSER_OBJECT_INFO); + item = make_menu_item("ObjInfo", message); + menu->AddItem(item); + + message = new BMessage(BROWSER_OBJECT_SAVE); + item = make_menu_item("ObjSave", message); + menu->AddItem(item); + // XXX: submenu: Sprite ? + + message = new BMessage(BROWSER_OBJECT_RELOAD); + item = make_menu_item("ObjReload", message); + menu->AddItem(item); +#endif + + // Navigate menu + + menu = new BMenu(messages_get("Navigate")); + g->menu_bar->AddItem(menu); + + message = new BMessage(BROWSER_NAVIGATE_HOME); + item = make_menu_item("Home", message, true); + menu->AddItem(item); + + message = new BMessage(BROWSER_NAVIGATE_BACK); + item = make_menu_item("Back", message, true); + menu->AddItem(item); + + message = new BMessage(BROWSER_NAVIGATE_FORWARD); + item = make_menu_item("Forward", message, true); + menu->AddItem(item); + + message = new BMessage(BROWSER_NAVIGATE_UP); + item = make_menu_item("UpLevel", message); + menu->AddItem(item); + + message = new BMessage(BROWSER_NAVIGATE_RELOAD); + item = make_menu_item("Reload", message, true); + menu->AddItem(item); + + message = new BMessage(BROWSER_NAVIGATE_STOP); + item = make_menu_item("Stop", message, true); + menu->AddItem(item); + +#if 0 + // View menu + + menu = new BMenu(messages_get("View")); + g->menu_bar->AddItem(menu); + + message = new BMessage(BROWSER_SCALE_VIEW); + item = make_menu_item("ScaleView", message); + menu->AddItem(item); + + submenu = new BMenu(messages_get("Images")); + menu->AddItem(submenu); + + message = new BMessage(BROWSER_IMAGES_FOREGROUND); + item = make_menu_item("ForeImg", message); + submenu->AddItem(item); + + message = new BMessage(BROWSER_IMAGES_BACKGROUND); + item = make_menu_item("BackImg", message); + submenu->AddItem(item); + + + submenu = new BMenu(messages_get("Toolbars")); + menu->AddItem(submenu); + submenu->SetEnabled(false); + + message = new BMessage(NO_ACTION); + item = make_menu_item("ToolButtons", message); + submenu->AddItem(item); + + message = new BMessage(NO_ACTION); + item = make_menu_item("ToolAddress", message); + submenu->AddItem(item); + + message = new BMessage(NO_ACTION); + item = make_menu_item("ToolThrob", message); + submenu->AddItem(item); + + message = new BMessage(NO_ACTION); + item = make_menu_item("ToolStatus", message); + submenu->AddItem(item); + + + submenu = new BMenu(messages_get("Render")); + menu->AddItem(submenu); + + message = new BMessage(BROWSER_BUFFER_ANIMS); + item = make_menu_item("RenderAnims", message); + submenu->AddItem(item); + + message = new BMessage(BROWSER_BUFFER_ALL); + item = make_menu_item("RenderAll", message); + submenu->AddItem(item); + + + message = new BMessage(NO_ACTION); + item = make_menu_item("OptDefault", message); + menu->AddItem(item); +#endif + + // Utilities menu + + menu = new BMenu(messages_get("Utilities")); + g->menu_bar->AddItem(menu); + +#if 0 + submenu = new BMenu(messages_get("Hotlist")); + menu->AddItem(submenu); + + message = new BMessage(HOTLIST_ADD_URL); + item = make_menu_item("HotlistAdd", message); + submenu->AddItem(item); + + message = new BMessage(HOTLIST_SHOW); + item = make_menu_item("HotlistShowNS", message); + submenu->AddItem(item); + + + submenu = new BMenu(messages_get("History")); + menu->AddItem(submenu); + + message = new BMessage(HISTORY_SHOW_LOCAL); + item = make_menu_item("HistLocal", message); + submenu->AddItem(item); + + message = new BMessage(HISTORY_SHOW_GLOBAL); + item = make_menu_item("HistGlobal", message); + submenu->AddItem(item); +#endif + + message = new BMessage(COOKIES_SHOW); + item = make_menu_item("Cookie manager", message, true); + menu->AddItem(item); + +#if 0 + message = new BMessage(BROWSER_FIND_TEXT); + item = make_menu_item("FindText", message); + menu->AddItem(item); + + submenu = new BMenu(messages_get("Window")); + menu->AddItem(submenu); + + message = new BMessage(BROWSER_WINDOW_DEFAULT); + item = make_menu_item("WindowSave", message); + submenu->AddItem(item); + + message = new BMessage(BROWSER_WINDOW_STAGGER); + item = make_menu_item("WindowStagr", message); + submenu->AddItem(item); + + message = new BMessage(BROWSER_WINDOW_COPY); + item = make_menu_item("WindowSize", message); + submenu->AddItem(item); + + message = new BMessage(BROWSER_WINDOW_RESET); + item = make_menu_item("WindowReset", message); + submenu->AddItem(item); +#endif + + + // Help menu + + menu = new BMenu(messages_get("Help")); + g->menu_bar->AddItem(menu); + +#if 0 + message = new BMessage(HELP_OPEN_CONTENTS); + item = make_menu_item("HelpContent", message); + menu->AddItem(item); + + message = new BMessage(HELP_OPEN_GUIDE); + item = make_menu_item("HelpGuide", message); + menu->AddItem(item); + + message = new BMessage(HELP_OPEN_INFORMATION); + item = make_menu_item("HelpInfo", message); + menu->AddItem(item); +#endif + + message = new BMessage(HELP_OPEN_ABOUT); + item = make_menu_item("HelpCredits", message, true); + menu->AddItem(item); + + message = new BMessage(HELP_OPEN_LICENCE); + item = make_menu_item("HelpLicence", message, true); + menu->AddItem(item); + +#if 0 + message = new BMessage(HELP_LAUNCH_INTERACTIVE); + item = make_menu_item("HelpInter", message); + menu->AddItem(item); +#endif + + // 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 NSBaseView(rect); + // add the top view to the window + g->window->AddChild(g->top_view); + } else { // replicant_view + // the base view has already been created with the archive constructor + g->top_view = replicant_view; + } + g->top_view->SetScaffolding(g); + + // build popup menu + g->popup_menu = new BPopUpMenu(""); + + +#ifdef ENABLE_DRAGGER + // the dragger to allow replicating us + // XXX: try to stuff it in the status bar at the bottom + // (BDragger *must* be a parent, sibiling or direct child of NSBaseView!) + rect = g->top_view->Bounds(); + rect.bottom = rect.top + TOOLBAR_HEIGHT - 1; + rect.left = rect.right - DRAGGER_WIDTH + 1; + g->dragger = new BDragger(rect, g->top_view, + B_FOLLOW_RIGHT | B_FOLLOW_TOP, B_WILL_DRAW); + g->top_view->AddChild(g->dragger); + g->dragger->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + g->dragger->SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR)) ; +#endif + + // tool_bar + // the toolbar is also the dragger for now + // XXX: try to stuff it in the status bar at the bottom + // (BDragger *must* be a parent, sibiling or direct child of NSBaseView!) + // XXX: B_FULL_UPDATE_ON_RESIZE avoids leaving bits on resize, + // but causes flicker + rect = g->top_view->Bounds(); + rect.bottom = rect.top + TOOLBAR_HEIGHT - 1; +#ifdef ENABLE_DRAGGER + rect.right = rect.right - DRAGGER_WIDTH; +#else + rect.right = rect.right + 1; +#endif + g->tool_bar = new BBox(rect, "Toolbar", + B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP, B_WILL_DRAW | B_FRAME_EVENTS + | B_FULL_UPDATE_ON_RESIZE | B_NAVIGABLE_JUMP, B_PLAIN_BORDER); + g->top_view->AddChild(g->tool_bar); + g->tool_bar->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + g->tool_bar->SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR)) ; + + // buttons + rect = g->tool_bar->Bounds(); + rect.right = TOOLBAR_HEIGHT; + rect.InsetBySelf(5, 5); + rect.OffsetBySelf(0, -1); + int nButtons = 0; + + message = new BMessage('back'); + message->AddPointer("scaffolding", g); + g->back_button = new BBitmapButton(rect, "back_button", "<", message); + g->tool_bar->AddChild(g->back_button); + nButtons++; + + rect.OffsetBySelf(TOOLBAR_HEIGHT, 0); + message = new BMessage('forw'); + message->AddPointer("scaffolding", g); + g->forward_button = new BBitmapButton(rect, "forward_button", ">", message); + g->tool_bar->AddChild(g->forward_button); + nButtons++; + + rect.OffsetBySelf(TOOLBAR_HEIGHT, 0); + message = new BMessage('stop'); + message->AddPointer("scaffolding", g); + g->stop_button = new BBitmapButton(rect, "stop_button", "S", message); + g->tool_bar->AddChild(g->stop_button); + nButtons++; + + rect.OffsetBySelf(TOOLBAR_HEIGHT, 0); + message = new BMessage('relo'); + message->AddPointer("scaffolding", g); + g->reload_button = new BBitmapButton(rect, "reload_button", "R", message); + g->tool_bar->AddChild(g->reload_button); + nButtons++; + + rect.OffsetBySelf(TOOLBAR_HEIGHT, 0); + message = new BMessage('home'); + message->AddPointer("scaffolding", g); + g->home_button = new BBitmapButton(rect, "home_button", "H", message); + g->tool_bar->AddChild(g->home_button); + nButtons++; + + + // url bar + rect = g->tool_bar->Bounds(); + rect.left += TOOLBAR_HEIGHT * nButtons; + rect.right -= TOOLBAR_HEIGHT * 1 + 100; + rect.InsetBySelf(5, 5); + message = new BMessage('urle'); + message->AddPointer("scaffolding", g); + g->url_bar = new NSIconTextControl(rect, "url_bar", "", "", message, + B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP); + g->url_bar->SetDivider(0); + rect = g->url_bar->TextView()->TextRect(); + rect.left += 16; + g->url_bar->TextView()->SetTextRect(rect); + g->tool_bar->AddChild(g->url_bar); + + // search bar + + rect = g->tool_bar->Bounds(); + rect.left = g->url_bar->Frame().right; + rect.right -= TOOLBAR_HEIGHT * 1; + rect.InsetBy(5,5); + message = new BMessage('sear'); + message->AddPointer("scaffolding", g); + g->search_bar = new BTextControl(rect, "search_bar", "", + "Search" B_UTF8_ELLIPSIS, message, B_FOLLOW_RIGHT | B_FOLLOW_TOP); + g->search_bar->SetDivider(0); + g->tool_bar->AddChild(g->search_bar); + + // throbber + rect.Set(0, 0, 24, 24); + rect.OffsetTo(g->tool_bar->Bounds().right - 24 - (TOOLBAR_HEIGHT - 24) / 2, + (TOOLBAR_HEIGHT - 24) / 2); + g->throbber = new NSThrobber(rect); + g->tool_bar->AddChild(g->throbber); + g->throbber->SetViewColor(g->tool_bar->ViewColor()); + g->throbber->SetLowColor(g->tool_bar->ViewColor()); + g->throbber->SetDrawingMode(B_OP_ALPHA); + g->throbber->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY); + /* set up the throbber. */ + g->throbber->SetBitmap(nsbeos_throbber->framedata[0]); + g->throb_frame = 0; + + + // the status bar at the bottom + BString status("NetSurf"); + status << " " << netsurf_version; + g->status_bar = new BStringView(BRect(0,0,-1,-1), "StatusBar", + status.String(), B_FOLLOW_LEFT/*_RIGHT*/ | B_FOLLOW_BOTTOM); + + // will be added to the scrollview when adding the top view. + + // notify the thread creating the replicant that we're done + if (replicant_view) + release_sem(replicant_done_sem); + + replicant_view = NULL; + + 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(); +} + +nserror gui_window_set_url(struct gui_window *gw, nsurl *url) +{ + struct beos_scaffolding *g; + + g = nsbeos_get_scaffold(gw); + if (g->top_level != gw) + return NSERROR_OK; + + assert(g->status_bar); + + if (g->top_view->LockLooper()) { + g->url_bar->SetText(nsurl_access(url)); + + g->top_view->UnlockLooper(); + } + + return NSERROR_OK; +} + +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); + + beos_schedule(100, nsbeos_throb, g); +} + +void gui_window_stop_throbber(struct gui_window* _g) +{ + struct beos_scaffolding *g = nsbeos_get_scaffold(_g); + + nsbeos_window_update_back_forward(g); + + beos_schedule(-1, 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(); +} + +/** + * add retrieved favicon to the gui + */ +void gui_window_set_icon(struct gui_window *_g, hlcache_handle *icon) +{ + BBitmap *bitmap = NULL; + struct bitmap *bmp_icon; + + bmp_icon = (icon != NULL) ? content_get_bitmap(icon) : NULL; + + if (bmp_icon) { + bitmap = nsbeos_bitmap_get_primary(bmp_icon); + } + + struct beos_scaffolding *g = nsbeos_get_scaffold(_g); + + if (!g->top_view->LockLooper()) + return; + + g->url_bar->SetBitmap(bitmap); + + g->top_view->UnlockLooper(); +} + + +void nsbeos_scaffolding_popup_menu(nsbeos_scaffolding *g, BPoint where) +{ + g->popup_menu->Go(where); +} + diff --git a/frontends/beos/scaffolding.h b/frontends/beos/scaffolding.h new file mode 100644 index 000000000..3fdca57f6 --- /dev/null +++ b/frontends/beos/scaffolding.h @@ -0,0 +1,210 @@ +/* + * Copyright 2008 François Revol + * Copyright 2005 James Bursa + * + * 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 . + */ + +#ifndef NETSURF_BEOS_SCAFFOLDING_H +#define NETSURF_BEOS_SCAFFOLDING_H 1 + +#include +#include +#include + +extern "C" { +struct hlcache_handle; +struct nsurl; +} + +typedef struct beos_scaffolding nsbeos_scaffolding; + +class NSBaseView : public BView { +public: + NSBaseView(BRect frame); + NSBaseView(BMessage *archive); +virtual ~NSBaseView(); + +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 AllAttached(void); + +virtual status_t Archive(BMessage *archive, bool deep=true) const; +static BArchivable *Instantiate(BMessage *archive); + +void SetScaffolding(struct beos_scaffolding *scaf); +private: + struct beos_scaffolding *fScaffolding; +}; + +class NSBrowserWindow : public BWindow { +public: + NSBrowserWindow(BRect frame, struct beos_scaffolding *scaf); +virtual ~NSBrowserWindow(); + +virtual void DispatchMessage(BMessage *message, BHandler *handler); +virtual void MessageReceived(BMessage *message); +virtual bool QuitRequested(void); +void WindowActivated(bool active); + +struct beos_scaffolding *Scaffolding() const { return fScaffolding; }; + +static BWindow* activeWindow; +private: + struct beos_scaffolding *fScaffolding; + + +}; + + +// XXX: clean up +typedef enum { + + /* no/unknown actions */ + NO_ACTION = 'nsMA', + + /* help actions */ + HELP_OPEN_CONTENTS, + HELP_OPEN_GUIDE, + HELP_OPEN_INFORMATION, + HELP_OPEN_ABOUT, + HELP_OPEN_LICENCE, + 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; + + +NSBrowserWindow *nsbeos_find_last_window(void); + +NSBrowserWindow *nsbeos_get_bwindow_for_scaffolding(nsbeos_scaffolding *scaffold); + +NSBaseView *nsbeos_get_baseview_for_scaffolding(nsbeos_scaffolding *scaffold); + +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); + + +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); + +void gui_window_set_title(struct gui_window *_g, const char *title); +nserror gui_window_set_url(struct gui_window *_g, struct nsurl *url); +void gui_window_set_icon(struct gui_window *_g, struct hlcache_handle *icon); +void gui_window_set_status(struct gui_window *_g, const char *text); +void gui_window_start_throbber(struct gui_window* _g); +void gui_window_stop_throbber(struct gui_window* _g); + +#endif /* NETSURF_BEOS_SCAFFOLDING_H */ diff --git a/frontends/beos/schedule.cpp b/frontends/beos/schedule.cpp new file mode 100644 index 000000000..a9da53501 --- /dev/null +++ b/frontends/beos/schedule.cpp @@ -0,0 +1,142 @@ +/* + * Copyright 2008 François Revol + * + * 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 . + */ + +#define __STDBOOL_H__ 1 +#include +#include +#include +#include + +extern "C" { +#include "utils/errors.h" +#include "beos/schedule.h" +#include "content/content.h" +#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; + + +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; +} + +static 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); +} + +nserror beos_schedule(int t, void (*callback)(void *p), void *p) +{ + LOG("t:%d cb:%p p:%p", t, cb->callback, cb->context); + + if (callbacks == NULL) { + callbacks = new BList; + } + + /* Kill any pending schedule of this kind. */ + schedule_remove(callback, p); + + if (t < 0) { + return NSERROR_OK; + } + + bigtime_t timeout = system_time() + t * 1000LL; + _nsbeos_callback_t *cb = (_nsbeos_callback_t *)malloc(sizeof(_nsbeos_callback_t)); + 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); + + return NSERROR_OK; +} + +bool +schedule_run(void) +{ + LOG("schedule_run()"); + + earliest_callback_timeout = B_INFINITE_TIMEOUT; + if (callbacks == NULL) + return false; /* Nothing to do */ + + bigtime_t now = system_time(); + 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); + } + return true; +} diff --git a/frontends/beos/schedule.h b/frontends/beos/schedule.h new file mode 100644 index 000000000..18f1efd4d --- /dev/null +++ b/frontends/beos/schedule.h @@ -0,0 +1,29 @@ +/* + * Copyright 2008 François Revol + * + * 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 . + */ + +#ifndef NETSURF_BEOS_CALLBACK_H +#define NETSURF_BEOS_CALLBACK_H 1 + +extern bigtime_t earliest_callback_timeout; + +extern "C" nserror beos_schedule(int t, void (*callback)(void *p), void *p); + +extern "C" bool schedule_run(void); + + +#endif /* NETSURF_BEOS_CALLBACK_H */ diff --git a/frontends/beos/search.cpp b/frontends/beos/search.cpp new file mode 100644 index 000000000..97e3d6d5b --- /dev/null +++ b/frontends/beos/search.cpp @@ -0,0 +1,76 @@ +/* + * Copyright 2009 Mark Benjamin + * + * 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 . + */ + +#define __STDBOOL_H__ 1 +//#include +#include + +extern "C" { +#include "utils/log.h" +} +/* callback functions for search implementation */ +static void gui_search_set_status(bool found, void *p); +static void gui_search_set_hourglass(bool active, void *p); +static void gui_search_add_recent(const char *string, void *p); +static void gui_search_set_forward_state(bool active, void *p); +static void gui_search_set_back_state(bool active, void *p); + +/** + * Change the displayed search status. + * \param found search pattern matched in text + * \param p the pointer sent to search_verify_new() / search_create_context() + */ +void gui_search_set_status(bool found, void *p) +{ +} + +/** + * display hourglass while searching + * \param active start/stop indicator + * \param p the pointer sent to search_verify_new() / search_create_context() + */ +void gui_search_set_hourglass(bool active, void *p) +{ +} + +/** + * add search string to recent searches list + * \param string search pattern + * \param p the pointer sent to search_verify_new() / search_create_context() + */ +void gui_search_add_recent(const char *string, void *p) +{ +} + +/** + * activate search forwards button in gui + * \param active activate/inactivate + * \param p the pointer sent to search_verify_new() / search_create_context() + */ +void gui_search_set_forward_state(bool active, void *p) +{ +} + +/** + * activate search forwards button in gui + * \param active activate/inactivate + * \param p the pointer sent to search_verify_new() / search_create_context() + */ +void gui_search_set_back_state(bool active, void *p) +{ +} diff --git a/frontends/beos/throbber.cpp b/frontends/beos/throbber.cpp new file mode 100644 index 000000000..fe40b3edc --- /dev/null +++ b/frontends/beos/throbber.cpp @@ -0,0 +1,118 @@ +/* + * Copyright 2008 François Revol + * + * 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 . + */ + +#define __STDBOOL_H__ 1 +#include +#include +#include +extern "C" { +#include "utils/log.h" +} +#include "beos/throbber.h" +#include "beos/bitmap.h" +#include "beos/fetch_rsrc.h" + +#include +#include +#include + +struct nsbeos_throbber *nsbeos_throbber = NULL; + +/** + * Creates the throbber using a PNG for each frame. The number of frames must + * be at least two. The first frame is the inactive frame, others are the + * active frames. + * + * \param frames The number of frames. Must be at least two. + * \param ... Filenames of PNGs containing frames. + * \return true on success. + */ +bool nsbeos_throbber_initialise_from_png(const int frames, ...) +{ + va_list filenames; + struct nsbeos_throbber *throb; /**< structure we generate */ + bool errors_when_loading = false; /**< true if a frame failed */ + + if (frames < 2) { + /* we need at least two frames - one for idle, one for active */ + LOG("Insufficent number of frames in throbber animation!"); + LOG("(called with %d frames, where 2 is a minimum.)", frames); + return false; + } + + BResources *res = get_app_resources(); + if (res == NULL) { + LOG("Can't find resources for throbber!"); + return false; + } + + throb = (struct nsbeos_throbber *)malloc(sizeof(throb)); + throb->nframes = frames; + throb->framedata = (BBitmap **)malloc(sizeof(BBitmap *) * throb->nframes); + + va_start(filenames, frames); + + for (int i = 0; i < frames; i++) { + const char *fn = va_arg(filenames, const char *); + const void *data; + size_t size; + data = res->LoadResource('data', fn, &size); + throb->framedata[i] = NULL; + if (!data) { + LOG("Error when loading resource %s", fn); + errors_when_loading = true; + continue; + } + BMemoryIO mem(data, size); + throb->framedata[i] = BTranslationUtils::GetBitmap(&mem); + if (throb->framedata[i] == NULL) { + LOG("Error when loading %s: GetBitmap() returned NULL", fn); + errors_when_loading = true; + } + } + + va_end(filenames); + + if (errors_when_loading == true) { + for (int i = 0; i < frames; i++) { + delete throb->framedata[i]; + } + + free(throb->framedata); + free(throb); + + return false; + } + + 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/frontends/beos/throbber.h b/frontends/beos/throbber.h new file mode 100644 index 000000000..670c60a06 --- /dev/null +++ b/frontends/beos/throbber.h @@ -0,0 +1,36 @@ +/* + * Copyright 2008 François Revol + * + * 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 . + */ + +#ifndef __BEOS_THROBBER_H__ +#define __BEOS_THROBBER_H__ + +#include + +struct nsbeos_throbber +{ + int nframes; /**< Number of frames in the throbber */ + BBitmap **framedata; +}; + +extern struct nsbeos_throbber *nsbeos_throbber; + +bool nsbeos_throbber_initialise_from_gif(const char *fn); +bool nsbeos_throbber_initialise_from_png(const int frames, ...); +void nsbeos_throbber_finalise(void); + +#endif /* __BEOS_THROBBER_H__ */ diff --git a/frontends/beos/window.cpp b/frontends/beos/window.cpp new file mode 100644 index 000000000..62624f077 --- /dev/null +++ b/frontends/beos/window.cpp @@ -0,0 +1,1382 @@ +/* + * Copyright 2008 François Revol + * Copyright 2006 Daniel Silverstone + * Copyright 2006 Rob Kendrick + * + * 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 . + */ + +#define __STDBOOL_H__ 1 +#include +#include + +extern "C" { +#include "utils/nsoption.h" +#include "utils/log.h" +#include "utils/utf8.h" +#include "utils/utils.h" +#include "content/content.h" +#include "content/urldb.h" +#include "desktop/browser.h" +#include "desktop/mouse.h" +#include "desktop/textinput.h" +#include "desktop/plotters.h" +#include "desktop/gui_window.h" +#include "desktop/gui_clipboard.h" +} + +#include "beos/about.h" +#include "beos/window.h" +#include "beos/font.h" +#include "beos/gui.h" +#include "beos/scaffolding.h" +#include "beos/plotters.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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; + + struct { + int pressed_x; + int pressed_y; + int state; /* browser_mouse_state */ + } mouse; + + /* 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 + int32 pending_resizes; + // accumulated rects of pending redraws + //volatile BMessage *lastRedraw; + // UNUSED YET + BRect pendingRedraw; + + /* Keep gui_windows in a list for cleanup later */ + struct gui_window *next, *prev; + + float scale; +}; + + + +static const rgb_color kWhiteColor = {255, 255, 255, 255}; + +static struct gui_window *window_list = 0; /**< first entry in win list*/ + +static BString current_selection; +static BList current_selection_textruns; + +/* 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); + + +// #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_ARGV_RECEIVED: + case B_REFS_RECEIVED: + case B_COPY: + case B_CUT: + case B_PASTE: + case B_SELECT_ALL: + //case B_MOUSE_WHEEL_CHANGED: + case B_UI_SETTINGS_CHANGED: + // NetPositive messages + case B_NETPOSITIVE_OPEN_URL: + case B_NETPOSITIVE_BACK: + case B_NETPOSITIVE_FORWARD: + case B_NETPOSITIVE_HOME: + case B_NETPOSITIVE_RELOAD: + case B_NETPOSITIVE_STOP: + case B_NETPOSITIVE_DOWN: + case B_NETPOSITIVE_UP: + // messages for top-level + case 'back': + case 'forw': + case 'stop': + case 'relo': + case 'home': + case 'urlc': + case 'urle': + case 'sear': + case 'menu': + case NO_ACTION: + case HELP_OPEN_CONTENTS: + case HELP_OPEN_GUIDE: + case HELP_OPEN_INFORMATION: + case HELP_OPEN_ABOUT: + case HELP_LAUNCH_INTERACTIVE: + case HISTORY_SHOW_LOCAL: + case HISTORY_SHOW_GLOBAL: + case HOTLIST_ADD_URL: + case HOTLIST_SHOW: + case COOKIES_SHOW: + case COOKIES_DELETE: + case BROWSER_PAGE: + case BROWSER_PAGE_INFO: + case BROWSER_PRINT: + case BROWSER_NEW_WINDOW: + case BROWSER_VIEW_SOURCE: + case BROWSER_OBJECT: + case BROWSER_OBJECT_INFO: + case BROWSER_OBJECT_RELOAD: + case BROWSER_OBJECT_SAVE: + case BROWSER_OBJECT_EXPORT_SPRITE: + case BROWSER_OBJECT_SAVE_URL_URI: + case BROWSER_OBJECT_SAVE_URL_URL: + case BROWSER_OBJECT_SAVE_URL_TEXT: + case BROWSER_SAVE: + case BROWSER_SAVE_COMPLETE: + case BROWSER_EXPORT_DRAW: + case BROWSER_EXPORT_TEXT: + case BROWSER_SAVE_URL_URI: + case BROWSER_SAVE_URL_URL: + case BROWSER_SAVE_URL_TEXT: + case HOTLIST_EXPORT: + case HISTORY_EXPORT: + case BROWSER_NAVIGATE_HOME: + case BROWSER_NAVIGATE_BACK: + case BROWSER_NAVIGATE_FORWARD: + case BROWSER_NAVIGATE_UP: + case BROWSER_NAVIGATE_RELOAD: + case BROWSER_NAVIGATE_RELOAD_ALL: + case BROWSER_NAVIGATE_STOP: + case BROWSER_NAVIGATE_URL: + case BROWSER_SCALE_VIEW: + case BROWSER_FIND_TEXT: + case BROWSER_IMAGES_FOREGROUND: + case BROWSER_IMAGES_BACKGROUND: + case BROWSER_BUFFER_ANIMS: + case BROWSER_BUFFER_ALL: + case BROWSER_SAVE_VIEW: + case BROWSER_WINDOW_DEFAULT: + case BROWSER_WINDOW_STAGGER: + case BROWSER_WINDOW_COPY: + case BROWSER_WINDOW_RESET: + case TREE_NEW_FOLDER: + case TREE_NEW_LINK: + case TREE_EXPAND_ALL: + case TREE_EXPAND_FOLDERS: + case TREE_EXPAND_LINKS: + case TREE_COLLAPSE_ALL: + case TREE_COLLAPSE_FOLDERS: + case TREE_COLLAPSE_LINKS: + case TREE_SELECTION: + case TREE_SELECTION_EDIT: + case TREE_SELECTION_LAUNCH: + case TREE_SELECTION_DELETE: + case TREE_SELECT_ALL: + case TREE_CLEAR_SELECTION: + case TOOLBAR_BUTTONS: + case TOOLBAR_ADDRESS_BAR: + case TOOLBAR_THROBBER: + case TOOLBAR_EDIT: + case CHOICES_SHOW: + case APPLICATION_QUIT: + Window()->DetachCurrentMessage(); + nsbeos_pipe_message_top(message, NULL, fGuiWindow->scaffold); + break; + default: + //message->PrintToStream(); + 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); +} + + + +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); + 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::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->scale; +} + +/* Create a gui_window */ +static struct gui_window *gui_window_create(struct browser_window *bw, + struct gui_window *existing, + gui_window_create_flags flags) +{ + struct gui_window *g; /**< what we're creating to return */ + + g = (struct gui_window *)malloc(sizeof(*g)); + if (!g) { + beos_warn_user("NoMemory", 0); + return 0; + } + + LOG("Creating gui window %p for browser window %p", g, bw); + + g->bw = bw; + g->mouse.state = 0; + g->current_pointer = GUI_POINTER_DEFAULT; + g->scale = browser_window_get_scale(bw); + + 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; + + /* Now construct and attach a scaffold */ + g->scaffold = nsbeos_new_scaffolding(g); + if (!g->scaffold) + return NULL; + + /* 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); + /* NOOO! Since we defer drawing (DetachCurrent()), the white flickers, + * besides sometimes text was drawn twice, making it ugly. + * Instead we set to transparent here, and implement plot_clg() to + * do it just before the rest. This almost removes the flicker. */ + g->view->SetViewColor(B_TRANSPARENT_COLOR); + g->view->SetLowColor(kWhiteColor); + +#ifdef B_BEOS_VERSION_DANO + /* enable double-buffering on the content view */ +/* + XXX: doesn't really work + g->view->SetDoubleBuffering(B_UPDATE_INVALIDATED + | B_UPDATE_SCROLLED + //| B_UPDATE_RESIZED + | B_UPDATE_EXPOSED); +*/ +#endif + + + g->toplevel = true; + + /* Attach our viewport into the scaffold */ + nsbeos_attach_toplevel_view(g->scaffold, g->view); + + + return g; +} + +/* exported interface documented in beos/window.h */ +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"); + delete message; + return; + } + if (scaffold && (!y || scaffold != y->scaffold)) { + LOG("discarding event for destroyed scaffolding"); + delete message; + return; + } + + // messages for top-level + if (scaffold) { + LOG("dispatching to top-level"); + nsbeos_scaffolding_dispatch_event(scaffold, message); + delete message; + return; + } + + //LOG("processing message"); + switch (message->what) { + case B_QUIT_REQUESTED: + // from the BApplication + nsbeos_done = true; + break; + case B_ABOUT_REQUESTED: + { + if (gui == NULL) + gui = window_list; + nsbeos_about(gui); + break; + } + case _UPDATE_: + if (gui && view) + nsbeos_window_expose_event(view, gui, message); + break; + case B_MOUSE_MOVED: + { + if (gui == NULL) + break; + + BPoint where; + int32 mods; + // 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; + } + if (message->FindInt32("modifiers", &mods) < B_OK) + mods = 0; + + + if (gui->mouse.state & BROWSER_MOUSE_PRESS_1) { + /* Start button 1 drag */ + browser_window_mouse_click(gui->bw, BROWSER_MOUSE_DRAG_1, + gui->mouse.pressed_x, gui->mouse.pressed_y); + /* Replace PRESS with HOLDING and declare drag in progress */ + gui->mouse.state ^= (BROWSER_MOUSE_PRESS_1 | + BROWSER_MOUSE_HOLDING_1); + gui->mouse.state |= BROWSER_MOUSE_DRAG_ON; + } else if (gui->mouse.state & BROWSER_MOUSE_PRESS_2) { + /* Start button 2 drag */ + browser_window_mouse_click(gui->bw, BROWSER_MOUSE_DRAG_2, + gui->mouse.pressed_x, gui->mouse.pressed_y); + /* Replace PRESS with HOLDING and declare drag in progress */ + gui->mouse.state ^= (BROWSER_MOUSE_PRESS_2 | + BROWSER_MOUSE_HOLDING_2); + gui->mouse.state |= BROWSER_MOUSE_DRAG_ON; + } + + bool shift = mods & B_SHIFT_KEY; + bool ctrl = mods & B_CONTROL_KEY; + + /* Handle modifiers being removed */ + if (gui->mouse.state & BROWSER_MOUSE_MOD_1 && !shift) + gui->mouse.state ^= BROWSER_MOUSE_MOD_1; + if (gui->mouse.state & BROWSER_MOUSE_MOD_2 && !ctrl) + gui->mouse.state ^= BROWSER_MOUSE_MOD_2; + + browser_window_mouse_track(gui->bw, (browser_mouse_state)gui->mouse.state, + (int)(where.x / gui->scale), + (int)(where.y / gui->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; + int32 mods; + 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; + if (message->FindInt32("modifiers", &mods) < B_OK) + mods = 0; + + if (buttons & B_SECONDARY_MOUSE_BUTTON) { + /* 2 == right button on BeOS */ + + nsbeos_scaffolding_popup_menu(gui->scaffold, screenWhere); + break; + } + + gui->mouse.state = BROWSER_MOUSE_PRESS_1; + + if (buttons & B_TERTIARY_MOUSE_BUTTON) /* 3 == middle button on BeOS */ + gui->mouse.state = BROWSER_MOUSE_PRESS_2; + + if (mods & B_SHIFT_KEY) + gui->mouse.state |= BROWSER_MOUSE_MOD_1; + if (mods & B_CONTROL_KEY) + gui->mouse.state |= BROWSER_MOUSE_MOD_2; + + gui->mouse.pressed_x = where.x / gui->scale; + gui->mouse.pressed_y = where.y / gui->scale; + + // make sure the view is in focus + if (view && view->LockLooper()) { + if (!view->IsFocus()) + view->MakeFocus(); + view->UnlockLooper(); + } + + browser_window_mouse_click(gui->bw, + (browser_mouse_state)gui->mouse.state, + gui->mouse.pressed_x, gui->mouse.pressed_y); + + break; + } + case B_MOUSE_UP: + { + if (gui == NULL) + break; + + BPoint where; + int32 buttons; + int32 mods; + 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; + if (message->FindInt32("modifiers", &mods) < B_OK) + mods = 0; + + /* If the mouse state is PRESS then we are waiting for a release to emit + * a click event, otherwise just reset the state to nothing*/ + if (gui->mouse.state & BROWSER_MOUSE_PRESS_1) + gui->mouse.state ^= (BROWSER_MOUSE_PRESS_1 | BROWSER_MOUSE_CLICK_1); + else if (gui->mouse.state & BROWSER_MOUSE_PRESS_2) + gui->mouse.state ^= (BROWSER_MOUSE_PRESS_2 | BROWSER_MOUSE_CLICK_2); + + bool shift = mods & B_SHIFT_KEY; + bool ctrl = mods & B_CONTROL_KEY; + + /* Handle modifiers being removed */ + if (gui->mouse.state & BROWSER_MOUSE_MOD_1 && !shift) + gui->mouse.state ^= BROWSER_MOUSE_MOD_1; + if (gui->mouse.state & BROWSER_MOUSE_MOD_2 && !ctrl) + gui->mouse.state ^= BROWSER_MOUSE_MOD_2; + + /* + if (view && view->LockLooper()) { + view->MakeFocus(); + view->UnlockLooper(); + } + */ + + if (gui->mouse.state & (BROWSER_MOUSE_CLICK_1|BROWSER_MOUSE_CLICK_2)) + browser_window_mouse_click(gui->bw, + (browser_mouse_state)gui->mouse.state, + where.x / gui->scale, + where.y / gui->scale); + else + browser_window_mouse_track(gui->bw, (browser_mouse_state)0, + where.x, where.y); + + gui->mouse.state = 0; + + 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: + break; + case B_UI_SETTINGS_CHANGED: + nsbeos_update_system_ui_colors(); + break; + case 'nsLO': // login + { + nsurl* url; + BString realm; + BString auth; + void* cbpw; + nserror (*cb)(bool proceed, void* pw); + + if (message->FindPointer("URL", (void**)&url) < B_OK) + break; + if (message->FindString("Realm", &realm) < B_OK) + break; + if (message->FindString("Auth", &auth) < B_OK) + break; + if (message->FindPointer("callback", (void**)&cb) < B_OK) + break; + if (message->FindPointer("callback_pw", (void**)&cbpw) < B_OK) + break; + //printf("login to '%s' with '%s'\n", url.String(), auth.String()); + urldb_set_auth_details(url, realm.String(), auth.String()); + cb(true, cbpw); + break; + } + default: + break; + } + delete message; +} + +void nsbeos_window_expose_event(BView *view, gui_window *g, BMessage *message) +{ + BRect updateRect; + float scale = g->scale; + struct rect clip; + + struct redraw_context ctx = { true, true, &nsbeos_plotters }; + + 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); + + // we'll be resizing = reflowing = redrawing everything anyway... + if (g->pending_resizes > 1) + return; + + if (message->FindRect("rect", &updateRect) < B_OK) + return; + + if (browser_window_has_content(g->bw) == false) + return; + + if (!view->LockLooper()) + return; + nsbeos_current_gc_set(view); + + if (view->Window()) + view->Window()->BeginViewTransaction(); + + clip.x0 = (int)updateRect.left; + clip.y0 = (int)updateRect.top; + clip.x1 = (int)updateRect.right + 1; + clip.y1 = (int)updateRect.bottom + 1; + + browser_window_redraw(g->bw, 0, 0, &clip, &ctx); + + if (g->careth != 0) + nsbeos_plot_caret(g->caretx, g->carety, g->careth); + + if (view->Window()) + view->Window()->EndViewTransaction(); + + // 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); + + LOG("mods 0x%08lx key %ld raw %ld byte[0] %d", mods, key, raw_char, buff[0]); + + 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 = NS_KEY_DELETE_LEFT; break; + case B_TAB: nskey = NS_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 = NS_KEY_DELETE_RIGHT; break; + /* + case B_INSERT: nskey = NS_KEYSYM("insert"); break; + */ + case B_HOME: nskey = NS_KEY_LINE_START; break; // XXX ? + case B_END: nskey = NS_KEY_LINE_END; break; // XXX ? + case B_PAGE_UP: nskey = NS_KEY_PAGE_UP; break; + case B_PAGE_DOWN: nskey = NS_KEY_PAGE_DOWN; break; + case B_LEFT_ARROW: nskey = NS_KEY_LEFT; break; + case B_RIGHT_ARROW: nskey = NS_KEY_RIGHT; break; + case B_UP_ARROW: nskey = NS_KEY_UP; break; + case B_DOWN_ARROW: nskey = NS_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 { + nskey = utf8_to_ucs4(bytes, numbytes); + } + + if(browser_window_key_press(g->bw, nskey)) + return; + + // Remaining events are for scrolling the page around + float hdelta = 0.0f, vdelta = 0.0f; + g->view->LockLooper(); + BRect size = g->view->Bounds(); + switch (byte) { + case B_HOME: + g->view->ScrollTo(0.0f, 0.0f); + break; + case B_END: + { + // TODO + break; + } + case B_PAGE_UP: + vdelta = -size.Height(); + break; + case B_PAGE_DOWN: + vdelta = size.Height(); + break; + case B_LEFT_ARROW: + hdelta = -10; + break; + case B_RIGHT_ARROW: + hdelta = 10; + break; + case B_UP_ARROW: + vdelta = -10; + break; + case B_DOWN_ARROW: + vdelta = 10; + break; + } + + g->view->ScrollBy(hdelta, vdelta); + g->view->UnlockLooper(); +} + + +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 (atomic_add(&g->pending_resizes, -1) > 1) + return; + + if (event->FindInt32("width", &width) < B_OK) + width = -1; + if (event->FindInt32("height", &height) < B_OK) + height = -1; + width++; + height++; + + browser_window_schedule_reformat(g->bw); + + 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(); + + return; +} + + +void nsbeos_reflow_all_windows(void) +{ + for (struct gui_window *g = window_list; g; g = g->next) { + browser_window_schedule_reformat(g->bw); + } +} + + + +/** + * callback from core to reformat a window. + */ +static void beos_window_reformat(struct gui_window *g) +{ + if (g == NULL) { + return; + } + + NSBrowserFrameView *view = g->view; + if (view && view->LockLooper()) { + BRect bounds = view->Bounds(); + view->UnlockLooper(); +#warning XXX why - 1 & - 2 !??? + browser_window_reformat(g->bw, + false, + bounds.Width() + 1 /* - 2*/, + bounds.Height() + 1); + } +} + +void nsbeos_window_destroy_browser(struct gui_window *g) +{ + browser_window_destroy(g->bw); +} + +static void gui_window_destroy(struct gui_window *g) +{ + if (!g) + return; + + 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); + + 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(); + + + free(g); + +} + +void nsbeos_redraw_caret(struct gui_window *g) +{ + if (g->careth == 0) + return; + + if (g->view == NULL) + return; + if (!g->view->LockLooper()) + return; + + nsbeos_current_gc_set(g->view); + + g->view->Invalidate(BRect(g->caretx, g->carety, + g->caretx, g->carety + g->careth)); + + nsbeos_current_gc_set(NULL); + g->view->UnlockLooper(); +} + +static 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(); +} + +static void gui_window_update_box(struct gui_window *g, const struct rect *rect) +{ + if (browser_window_has_content(g->bw) == false) + return; + + if (g->view == NULL) + return; + if (!g->view->LockLooper()) + return; + + nsbeos_current_gc_set(g->view); + +//XXX +1 ?? + g->view->Invalidate(BRect(rect->x0, rect->y0, + rect->x1 - 1, rect->y1 - 1)); + + nsbeos_current_gc_set(NULL); + g->view->UnlockLooper(); +} + +static 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(); + return true; +} + +static 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(); +} + + +static void gui_window_update_extent(struct gui_window *g) +{ + nserror err; + //CALLED(); + if (browser_window_has_content(g->bw) == false) + return; + + if (g->view == NULL) + return; + if (!g->view->LockLooper()) + return; + + int x_max, y_max; + + err = browser_window_get_extents(g->bw, true, &x_max, &y_max); + if (err != NSERROR_OK) + return; + + 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; + + LOG("x_max = %d y_max = %d 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); + } + + + g->view->UnlockLooper(); +} + +/* 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 +}; + + +static 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; + 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; + 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; +} + +static void gui_window_place_caret(struct gui_window *g, int x, int y, int height, + const struct rect *clip) +{ + //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(); +} + +static void gui_window_remove_caret(struct gui_window *g) +{ + int oh = g->careth; + + if (oh == 0) + return; + + g->careth = 0; + + if (g->view == NULL) + return; + if (!g->view->LockLooper()) + return; + + nsbeos_current_gc_set(g->view); + + g->view->Invalidate(BRect(g->caretx, g->carety, g->caretx, g->carety + oh)); + + nsbeos_current_gc_set(NULL); + g->view->UnlockLooper(); +} + +static 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(); +} + +static void gui_start_selection(struct gui_window *g) +{ + if (!g->view->LockLooper()) + return; + + g->view->MakeFocus(); + + g->view->UnlockLooper(); +} + +static void gui_get_clipboard(char **buffer, size_t *length) +{ + BMessage *clip; + *length = 0; + *buffer = NULL; + + if (be_clipboard->Lock()) { + clip = be_clipboard->Data(); + if (clip) { + const char *text; + ssize_t textlen; + if (clip->FindData("text/plain", B_MIME_TYPE, + (const void **)&text, &textlen) >= B_OK) { + *buffer = (char *)malloc(textlen); + *length = textlen; + memcpy(*buffer, text, textlen); + } + } + be_clipboard->Unlock(); + } +} + +static void gui_set_clipboard(const char *buffer, size_t length, + nsclipboard_styles styles[], int n_styles) +{ + BMessage *clip; + + if (be_clipboard->Lock()) { + be_clipboard->Clear(); + clip = be_clipboard->Data(); + if (clip) { + clip->AddData("text/plain", B_MIME_TYPE, buffer, length); + + int arraySize = sizeof(text_run_array) + + n_styles * sizeof(text_run); + text_run_array *array = (text_run_array *)malloc(arraySize); + array->count = n_styles; + for (int i = 0; i < n_styles; i++) { + BFont font; + nsbeos_style_to_font(font, &styles[i].style); + array->runs[i].offset = styles[i].start; + array->runs[i].font = font; + array->runs[i].color = + nsbeos_rgb_colour(styles[i].style.foreground); + } + clip->AddData("application/x-vnd.Be-text_run_array", B_MIME_TYPE, + array, arraySize); + free(array); + be_clipboard->Commit(); + } + be_clipboard->Unlock(); + } +} + +static struct gui_clipboard_table clipboard_table = { + gui_get_clipboard, + gui_set_clipboard, +}; + +struct gui_clipboard_table *beos_clipboard_table = &clipboard_table; + +static 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->scale; + *height /= g->scale; + } +} + +static struct gui_window_table window_table = { + gui_window_create, + gui_window_destroy, + gui_window_redraw_window, + gui_window_update_box, + gui_window_get_scroll, + gui_window_set_scroll, + gui_window_get_dimensions, + gui_window_update_extent, + beos_window_reformat, + + /* from scaffold */ + gui_window_set_title, + gui_window_set_url, + gui_window_set_icon, + gui_window_set_status, + gui_window_set_pointer, + gui_window_place_caret, + gui_window_remove_caret, + gui_window_start_throbber, + gui_window_stop_throbber, + NULL, //drag_start + NULL, //save_link + NULL, //scroll_visible + NULL, //scroll_start + gui_window_new_content, + NULL, //create_form_select_menu + NULL, //file_gadget_open + NULL, //drag_save_object + NULL, //drag_save_selection + gui_start_selection +}; + +struct gui_window_table *beos_window_table = &window_table; diff --git a/frontends/beos/window.h b/frontends/beos/window.h new file mode 100644 index 000000000..928acca22 --- /dev/null +++ b/frontends/beos/window.h @@ -0,0 +1,83 @@ +/* + * Copyright 2008 François Revol + * + * 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 . + */ + +#ifndef NETSURF_BEOS_WINDOW_H +#define NETSURF_BEOS_WINDOW_H 1 + +#include +#include +#include + +extern struct gui_window_table *beos_window_table; +extern struct gui_clipboard_table *beos_clipboard_table; + +struct gui_window; +struct browser_window; +struct beos_scaffolding; + +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; +}; + +/** + * Process beos messages into browser operations. + * + * \param message The beos message to process. + */ +void nsbeos_dispatch_event(BMessage *message); + +/** + * Cause all windows to be reflowed. + */ +void nsbeos_reflow_all_windows(void); + +/** + * Get containing scaffold of a beos gui window + * + * \param g gui window to find scaffold of. + * \return The containing scaffold. + */ +struct beos_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 */ -- cgit v1.2.3