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/scaffolding.cpp | 2332 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2332 insertions(+) create mode 100644 frontends/beos/scaffolding.cpp (limited to 'frontends/beos/scaffolding.cpp') 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); +} + -- cgit v1.2.3