/* * 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 #if defined(__HAIKU__) #include #include "WindowStack.h" #endif #include extern "C" { #include "content/content.h" #include "desktop/browser_private.h" #include "desktop/history_core.h" #include "desktop/gui.h" #include "desktop/netsurf.h" #include "desktop/plotters.h" #include "desktop/options.h" #include "desktop/selection.h" #include "desktop/textinput.h" #include "render/font.h" #include "render/form.h" #include "utils/messages.h" #include "utils/schedule.h" #include "utils/utils.h" #include "utils/log.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" #define TOOLBAR_HEIGHT 32 #define DRAGGER_WIDTH 8 struct beos_history_window; class NSBrowserWindow; class NSThrobber; struct beos_scaffolding { NSBrowserWindow *window; // top-level container object // top-level view, contains toolbar & top-level browser view NSBaseView *top_view; BMenuBar *menu_bar; BPopUpMenu *popup_menu; BDragger *dragger; BView *tool_bar; BControl *back_button; BControl *forward_button; BControl *stop_button; BControl *reload_button; BControl *home_button; BTextControl *url_bar; //BMenuField *url_bar_completion; NSThrobber *throbber; BStringView *status_bar; BScrollView *scroll_view; #warning XXX #if 0 /* GTK */ GtkEntryCompletion *url_bar_completion; GtkMenuBar *menu_bar; GtkMenuItem *back_menu; GtkMenuItem *forward_menu; GtkMenuItem *stop_menu; GtkMenuItem *reload_menu; GladeXML *popup_xml; GtkMenu *popup_menu; #endif 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; #warning XXX #if 0 /* GTK */ GtkWindow *window; GtkScrolledWindow *scrolled; GtkDrawingArea *drawing_area; #endif }; struct menu_events { const char *widget; #warning XXX #if 0 /* GTK */ GCallback handler; #endif }; // 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 struct beos_scaffolding *current_model; /**< current window for model dialogue use */ static NSBaseView *replicant_view = NULL; /**< if not NULL, the replicant View we are running NetSurf for */ static sem_id replicant_done_sem = -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; #warning XXX #if 0 /* GTK */ static gboolean nsbeos_window_url_activate_event(beosWidget *, gpointer); static gboolean nsbeos_window_url_changed(beosWidget *, GdkEventKey *, gpointer); static gboolean nsbeos_history_expose_event(beosWidget *, GdkEventExpose *, gpointer); static gboolean nsbeos_history_button_press_event(beosWidget *, GdkEventButton *, gpointer); static void nsbeos_attach_menu_handlers(GladeXML *, gpointer); gboolean nsbeos_openfile_open(beosWidget *widget, gpointer data); #define MENUEVENT(x) { #x, G_CALLBACK(nsbeos_on_##x##_activate) } #define MENUPROTO(x) static gboolean nsbeos_on_##x##_activate( \ beosMenuItem *widget, gpointer g) /* prototypes for menu handlers */ /* file menu */ MENUPROTO(new_window); MENUPROTO(open_location); MENUPROTO(open_file); MENUPROTO(close_window); MENUPROTO(quit); /* edit menu */ MENUPROTO(preferences); /* view menu */ MENUPROTO(stop); MENUPROTO(reload); MENUPROTO(zoom_in); MENUPROTO(normal_size); MENUPROTO(zoom_out); MENUPROTO(full_screen); MENUPROTO(menu_bar); MENUPROTO(tool_bar); MENUPROTO(status_bar); MENUPROTO(downloads); MENUPROTO(save_window_size); MENUPROTO(toggle_debug_rendering); MENUPROTO(save_box_tree); /* navigate menu */ MENUPROTO(back); MENUPROTO(forward); MENUPROTO(home); MENUPROTO(local_history); MENUPROTO(global_history); /* help menu */ MENUPROTO(about); /* structure used by nsbeos_attach_menu_handlers to connect menu items to * their handling functions. */ static struct menu_events menu_events[] = { /* file menu */ MENUEVENT(new_window), MENUEVENT(open_location), MENUEVENT(open_file), MENUEVENT(close_window), MENUEVENT(quit), /* edit menu */ MENUEVENT(preferences), /* view menu */ MENUEVENT(stop), MENUEVENT(reload), MENUEVENT(zoom_in), MENUEVENT(normal_size), MENUEVENT(zoom_out), MENUEVENT(full_screen), MENUEVENT(menu_bar), MENUEVENT(tool_bar), MENUEVENT(status_bar), MENUEVENT(downloads), MENUEVENT(save_window_size), MENUEVENT(toggle_debug_rendering), MENUEVENT(save_box_tree), /* navigate menu */ MENUEVENT(back), MENUEVENT(forward), MENUEVENT(home), MENUEVENT(local_history), MENUEVENT(global_history), /* help menu */ MENUEVENT(about), /* sentinel */ { NULL, NULL } }; void nsbeos_attach_menu_handlers(GladeXML *xml, gpointer g) { struct menu_events *event = menu_events; while (event->widget != NULL) { beosWidget *w = glade_xml_get_widget(xml, event->widget); g_signal_connect(G_OBJECT(w), "activate", event->handler, g); event++; } } #endif // #pragma mark - class NSThrobber class NSThrobber : public BView { public: NSThrobber(BRect frame); virtual ~NSThrobber(); virtual void MessageReceived(BMessage *message); virtual void Draw(BRect updateRect); void SetBitmap(const BBitmap *bitmap); private: const BBitmap *fBitmap; }; NSThrobber::NSThrobber(BRect frame) : BView(frame, "NSThrobber", B_FOLLOW_TOP | B_FOLLOW_RIGHT, B_WILL_DRAW), fBitmap(NULL) { } NSThrobber::~NSThrobber() { } void NSThrobber::MessageReceived(BMessage *message) { BView::MessageReceived(message); } void NSThrobber::Draw(BRect updateRect) { if (!fBitmap) return; DrawBitmap(fBitmap); } void NSThrobber::SetBitmap(const BBitmap *bitmap) { fBitmap = bitmap; 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() { //warn_user ("~NSBaseView()", NULL); BMessage *message = new BMessage(B_QUIT_REQUESTED); nsbeos_pipe_message_top(message, NULL, fScaffolding); while (acquire_sem(replicant_done_sem) == EINTR); } void NSBaseView::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 '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: 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 // netsurf_init() needs different args now... //netsurf_init(2, info->args); //return NULL; // 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"); thread_id nsMainThread = spawn_thread(nsbeos_replicant_main_thread, "NetSurf Main Thread", B_NORMAL_PRIORITY, info); if (nsMainThread < B_OK) { delete_sem(replicant_done_sem); delete info; delete view; return NULL; } resume_thread(nsMainThread); //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); g->url_bar->SetTarget(this); SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); g->tool_bar->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); g->dragger->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 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 } // #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; netsurf_main_loop(); 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) netsurf_quit = true; if (window) { window->Lock(); window->Quit(); } if (!g->being_destroyed) { g->being_destroyed = 1; nsbeos_window_destroy_browser(g->top_level); } } 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->throbber->SetViewColor(c); g->scroll_view->SetViewColor(c); g->dragger->SetViewColor(c); 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) { int width, height; 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_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(); if (/*message->WasDropped() &&*/ i == 0) browser_window_go(bw, url.String(), 0, true); else browser_window_create(url.String(), bw, NULL, false, false); } break; } case B_ARGV_RECEIVED: { int32 i; BString url; for (i = 1; message->FindString("argv", i, &url) >= B_OK; i++) { browser_window_create(url.String(), bw, NULL, false, false); } break; } case B_UI_SETTINGS_CHANGED: nsbeos_update_system_ui_colors(); nsbeos_scaffolding_update_colors(scaffold); break; case B_NETPOSITIVE_OPEN_URL: { int32 i; BString url; if (message->FindString("be:url", &url) < B_OK) break; browser_window_go(bw, url.String(), 0, true); break; } case B_COPY: gui_copy_to_clipboard(browser_window_get_selection(bw)); break; case B_CUT: browser_window_key_press(bw, 24); break; case B_PASTE: gui_paste_from_clipboard(scaffold->top_level, 0, 0); break; case B_SELECT_ALL: LOG(("Selecting all text")); selection_select_all(browser_window_get_selection(bw)); break; case B_NETPOSITIVE_BACK: case BROWSER_NAVIGATE_BACK: case 'back': if (!history_back_available(bw->history)) break; history_back(bw, bw->history); nsbeos_window_update_back_forward(scaffold); break; case B_NETPOSITIVE_FORWARD: case BROWSER_NAVIGATE_FORWARD: case 'forw': if (!history_forward_available(bw->history)) break; history_forward(bw, bw->history); 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': { static const char *addr = NETSURF_HOMEPAGE; if (nsoption_charp(homepage_url) != NULL) addr = nsoption_charp(homepage_url); browser_window_go(bw, addr, 0, true); break; } case 'urle': { BString text; if (!scaffold->url_bar->LockLooper()) break; text = scaffold->url_bar->Text(); scaffold->scroll_view->Target()->MakeFocus(); scaffold->url_bar->UnlockLooper(); browser_window_go(bw, text.String(), 0, true); break; } case 'urlc': { BString text; if (!scaffold->url_bar->LockLooper()) break; text = scaffold->url_bar->Text(); scaffold->url_bar->UnlockLooper(); //nsbeos_completion_update(text.String()); break; } /* case 'menu': { menu_action action; if (message->FindInt32("action", (int32 *)&action) < B_OK) break; switch (action) { case NO_ACTION: case HELP_OPEN_CONTENTS: case HELP_OPEN_GUIDE: case HELP_OPEN_INFORMATION: case HELP_OPEN_ABOUT: case HELP_LAUNCH_INTERACTIVE: break; } #warning XXX break; } */ case NO_ACTION: break; case HELP_OPEN_CONTENTS: break; case HELP_OPEN_GUIDE: break; case HELP_OPEN_INFORMATION: break; case HELP_OPEN_ABOUT: 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: break; case COOKIES_DELETE: break; case BROWSER_PAGE: break; case BROWSER_PAGE_INFO: break; case BROWSER_PRINT: break; case BROWSER_NEW_WINDOW: { BString text; if (!scaffold->url_bar->LockLooper()) break; text = scaffold->url_bar->Text(); scaffold->url_bar->UnlockLooper(); NSBrowserWindow::activeWindow = scaffold->window; browser_window_create(text.String(), bw, NULL, false, false); break; } case BROWSER_VIEW_SOURCE: { if (!bw || !bw->current_content) break; nsbeos_gui_view_source(bw->current_content, browser_window_get_selection(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: netsurf_quit = 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) { int width, height; struct browser_window *bw = nsbeos_get_browser_for_gui(g->top_level); if (!g->top_view->LockLooper()) return; g->back_button->SetEnabled(history_back_available(bw->history)); g->forward_button->SetEnabled(history_forward_available(bw->history)); g->top_view->UnlockLooper(); #warning XXX #if 0 /* GTK */ beos_widget_set_sensitive(beos_WIDGET(g->back_button), history_back_available(bw->history)); beos_widget_set_sensitive(beos_WIDGET(g->forward_button), history_forward_available(bw->history)); beos_widget_set_sensitive(beos_WIDGET(g->back_menu), history_back_available(bw->history)); beos_widget_set_sensitive(beos_WIDGET(g->forward_menu), history_forward_available(bw->history)); /* update the local history window, as well as queuing a redraw * for it. */ history_size(bw->history, &width, &height); beos_widget_set_size_request(beos_WIDGET(g->history_window->drawing_area), width, height); beos_widget_queue_draw(beos_WIDGET(g->history_window->drawing_area)); #endif } void nsbeos_throb(void *p) { struct beos_scaffolding *g = (struct beos_scaffolding *)p; if (g->throb_frame >= (nsbeos_throbber->nframes - 1)) g->throb_frame = 1; else g->throb_frame++; if (!g->top_view->LockLooper()) return; #if 0 g->throbber->SetViewBitmap(nsbeos_throbber->framedata[g->throb_frame], B_FOLLOW_RIGHT | B_FOLLOW_TOP); #endif g->throbber->SetBitmap(nsbeos_throbber->framedata[g->throb_frame]); g->throbber->Invalidate(); g->top_view->UnlockLooper(); schedule(10, nsbeos_throb, p); } #warning XXX #if 0 /* GTK */ gboolean nsbeos_openfile_open(beosWidget *widget, gpointer data) { struct browser_window *bw = nsbeos_get_browser_for_gui( current_model->top_level); char *filename = beos_file_chooser_get_filename( beos_FILE_CHOOSER(wndOpenFile)); char *url = malloc(strlen(filename) + sizeof("file://")); sprintf(url, "file://%s", filename); browser_window_go(bw, url, 0, true); g_free(filename); free(url); return TRUE; } #endif #warning XXX #if 0 /* GTK */ /* signal handlers for menu entries */ #define MENUHANDLER(x) gboolean nsbeos_on_##x##_activate(beosMenuItem *widget, \ gpointer g) MENUHANDLER(new_window) { struct beos_scaffolding *gw = (struct beos_scaffolding *)g; struct browser_window *bw = nsbeos_get_browser_for_gui(gw->top_level); const char *url = beos_entry_get_text(beos_ENTRY(gw->url_bar)); browser_window_create(url, bw, NULL, false); return TRUE; } MENUHANDLER(open_location) { struct beos_scaffolding *gw = (struct beos_scaffolding *)g; beos_widget_grab_focus(beos_WIDGET(gw->url_bar)); return TRUE; } MENUHANDLER(open_file) { current_model = (struct beos_scaffolding *)g; beos_dialog_run(wndOpenFile); return TRUE; } MENUHANDLER(close_window) { struct beos_scaffolding *gw = (struct beos_scaffolding *)g; beos_widget_destroy(beos_WIDGET(gw->window)); return TRUE; } MENUHANDLER(quit) { netsurf_quit = true; return TRUE; } MENUHANDLER(preferences) { beos_widget_show(beos_WIDGET(wndPreferences)); return TRUE; } MENUHANDLER(zoom_in) { struct beos_scaffolding *gw = (struct beos_scaffolding *)g; struct browser_window *bw = nsbeos_get_browser_for_gui(gw->top_level); float old_scale = nsbeos_get_scale_for_gui(gw->top_level); browser_window_set_scale(bw, old_scale + 0.05, true); return TRUE; } MENUHANDLER(normal_size) { struct beos_scaffolding *gw = (struct beos_scaffolding *)g; struct browser_window *bw = nsbeos_get_browser_for_gui(gw->top_level); browser_window_set_scale(bw, 1.0, true); return TRUE; } MENUHANDLER(zoom_out) { struct beos_scaffolding *gw = (struct beos_scaffolding *)g; struct browser_window *bw = nsbeos_get_browser_for_gui(gw->top_level); float old_scale = nsbeos_get_scale_for_gui(gw->top_level); browser_window_set_scale(bw, old_scale - 0.05, true); return TRUE; } MENUHANDLER(full_screen) { struct beos_scaffolding *gw = (struct beos_scaffolding *)g; if (gw->fullscreen) { beos_window_unfullscreen(gw->window); } else { beos_window_fullscreen(gw->window); } gw->fullscreen = !gw->fullscreen; return TRUE; } MENUHANDLER(menu_bar) { struct beos_scaffolding *gw = (struct beos_scaffolding *)g; if (beos_check_menu_item_get_active(beos_CHECK_MENU_ITEM(widget))) { beos_widget_show(beos_WIDGET(gw->menu_bar)); } else { beos_widget_hide(beos_WIDGET(gw->menu_bar)); } return TRUE; } MENUHANDLER(tool_bar) { struct beos_scaffolding *gw = (struct beos_scaffolding *)g; if (beos_check_menu_item_get_active(beos_CHECK_MENU_ITEM(widget))) { beos_widget_show(beos_WIDGET(gw->tool_bar)); } else { beos_widget_hide(beos_WIDGET(gw->tool_bar)); } return TRUE; } MENUHANDLER(status_bar) { struct beos_scaffolding *gw = (struct beos_scaffolding *)g; if (beos_check_menu_item_get_active(beos_CHECK_MENU_ITEM(widget))) { beos_widget_show(beos_WIDGET(gw->status_bar)); } else { beos_widget_hide(beos_WIDGET(gw->status_bar)); } return TRUE; } MENUHANDLER(downloads) { nsbeos_download_show(); return TRUE; } MENUHANDLER(save_window_size) { struct beos_scaffolding *gw = (struct beos_scaffolding *)g; int x,y,w,h; nsoption_set_int(toolbar_status_width, beos_paned_get_position(gw->status_pane)); beos_window_get_position(gw->window, &x, &y); beos_window_get_size(gw->window, &w, &h); nsoption_set_int(window_x, x); nsoption_set_int(window_y, y); nsoption_set_int(window_width, w); nsoption_set_int(window_height, h); nsoption_write(options_file_location); return TRUE; } MENUHANDLER(toggle_debug_rendering) { html_redraw_debug = !html_redraw_debug; nsbeos_reflow_all_windows(); return TRUE; } MENUHANDLER(save_box_tree) { beosWidget *save_dialog; struct beos_scaffolding *gw = (struct beos_scaffolding *)g; save_dialog = beos_file_chooser_dialog_new("Save File", gw->window, beos_FILE_CHOOSER_ACTION_SAVE, beos_STOCK_CANCEL, beos_RESPONSE_CANCEL, beos_STOCK_SAVE, beos_RESPONSE_ACCEPT, NULL); beos_file_chooser_set_current_folder(beos_FILE_CHOOSER(save_dialog), getenv("HOME") ? getenv("HOME") : "/"); beos_file_chooser_set_current_name(beos_FILE_CHOOSER(save_dialog), "boxtree.txt"); if (beos_dialog_run(beos_DIALOG(save_dialog)) == beos_RESPONSE_ACCEPT) { char *filename = beos_file_chooser_get_filename( beos_FILE_CHOOSER(save_dialog)); FILE *fh; LOG(("Saving box tree dump to %s...\n", filename)); fh = fopen(filename, "w"); if (fh == NULL) { warn_user("Error saving box tree dump.", "Unable to open file for writing."); } else { struct browser_window *bw; bw = nsbeos_get_browser_window(gw->top_level); browser_window_debug_dump(bw, f); fclose(fh); } g_free(filename); } beos_widget_destroy(save_dialog); } MENUHANDLER(stop) { return nsbeos_window_stop_button_clicked(beos_WIDGET(widget), g); } MENUHANDLER(reload) { return nsbeos_window_reload_button_clicked(beos_WIDGET(widget), g); } MENUHANDLER(back) { return nsbeos_window_back_button_clicked(beos_WIDGET(widget), g); } MENUHANDLER(forward) { return nsbeos_window_forward_button_clicked(beos_WIDGET(widget), g); } MENUHANDLER(home) { return nsbeos_window_home_button_clicked(beos_WIDGET(widget), g); } MENUHANDLER(local_history) { struct beos_scaffolding *gw = (struct beos_scaffolding *)g; beos_widget_show(beos_WIDGET(gw->history_window->window)); gdk_window_raise(beos_WIDGET(gw->history_window->window)->window); return TRUE; } MENUHANDLER(global_history) { beos_widget_show(beos_WIDGET(wndHistory)); gdk_window_raise(beos_WIDGET(wndHistory)->window); return TRUE; } MENUHANDLER(about) { beos_widget_show(beos_WIDGET(wndAbout)); gdk_window_raise(beos_WIDGET(wndAbout)->window); return TRUE; } /* signal handler functions for the local history window */ gboolean nsbeos_history_expose_event(beosWidget *widget, GdkEventExpose *event, gpointer g) { struct beos_history_window *hw = (struct beos_history_window *)g; struct browser_window *bw = nsbeos_get_browser_for_gui(hw->g->top_level); struct redraw_context ctx = { .interactive = true, .background_images = true, .plot = &nsbeos_plotters }; current_widget = widget; current_drawable = widget->window; current_gc = gdk_gc_new(current_drawable); #ifdef CAIRO_VERSION current_cr = gdk_cairo_create(current_drawable); #endif plot = nsbeos_plotters; history_redraw(bw->history, &ctx); g_object_unref(current_gc); #ifdef CAIRO_VERSION cairo_destroy(current_cr); #endif return FALSE; } gboolean nsbeos_history_button_press_event(beosWidget *widget, GdkEventButton *event, gpointer g) { struct beos_history_window *hw = (struct beos_history_window *)g; struct browser_window *bw = nsbeos_get_browser_for_gui(hw->g->top_level); LOG(("X=%g, Y=%g", event->x, event->y)); history_click(bw, bw->history, event->x, event->y, false); return TRUE; } #define GET_WIDGET(x) glade_xml_get_widget(g->xml, (x)) static gboolean do_scroll_event(beosWidget *widget, GdkEvent *ev, gpointer data) { switch (((GdkEventScroll *)ev)->direction) { case GDK_SCROLL_UP: case GDK_SCROLL_DOWN: beos_widget_event(g_object_get_data( G_OBJECT(widget), "vScroll"), ev); break; default: beos_widget_event(g_object_get_data( G_OBJECT(widget), "hScroll"), ev); } return TRUE; } #endif NSBrowserWindow *nsbeos_find_last_window(void) { int32 i; if (!be_app || !be_app->Lock()) return NULL; for (i = be_app->CountWindows() - 1; i >= 0; i--) { if (be_app->WindowAt(i) == NULL) continue; NSBrowserWindow *win; win = dynamic_cast(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; } 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); 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); 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(); } #warning XXX #if 0 /* GTK */ beosWidget *scrollbar; /* Insert the viewport into the right part of our table */ beosTable *table = beos_TABLE(GET_WIDGET("centreTable")); LOG(("Attaching viewport to scaffolding %p", g)); beos_table_attach_defaults(table, beos_WIDGET(vp), 0, 1, 0, 1); /* connect our scrollbars to the viewport */ scrollbar = GET_WIDGET("coreScrollHorizontal"); beos_viewport_set_hadjustment(vp, beos_range_get_adjustment(beos_RANGE(scrollbar))); g_object_set_data(G_OBJECT(vp), "hScroll", scrollbar); scrollbar = GET_WIDGET("coreScrollVertical"); beos_viewport_set_vadjustment(vp, beos_range_get_adjustment(beos_RANGE(scrollbar))); g_object_set_data(G_OBJECT(vp), "vScroll", scrollbar); g_signal_connect(G_OBJECT(vp), "scroll_event", G_CALLBACK(do_scroll_event), NULL); gdk_window_set_accept_focus (beos_WIDGET(vp)->window, TRUE); /* And set the size-request to zero to cause it to get its act together */ beos_widget_set_size_request(beos_WIDGET(vp), 0, 0); #endif } static BMenuItem *make_menu_item(const char *name, BMessage *message) { 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); 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) { 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; BMenu *submenu; BMenuItem *item; // App menu //XXX: use icon item ? menu = new BMenu(messages_get("NetSurf")); g->menu_bar->AddItem(menu); message = new BMessage(NO_ACTION); item = make_menu_item("Info", message); menu->AddItem(item); 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); message = new BMessage(APPLICATION_QUIT); item = make_menu_item("Quit", message); menu->AddItem(item); // Page menu menu = new BMenu(messages_get("Page")); g->menu_bar->AddItem(menu); message = new BMessage(BROWSER_PAGE_INFO); item = make_menu_item("PageInfo", message); menu->AddItem(item); message = new BMessage(BROWSER_SAVE); item = make_menu_item("Save", message); menu->AddItem(item); message = new BMessage(BROWSER_SAVE_COMPLETE); item = make_menu_item("SaveComp", 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("Text", 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("Print", message); menu->AddItem(item); message = new BMessage(BROWSER_NEW_WINDOW); item = make_menu_item("NewWindow", message); menu->AddItem(item); message = new BMessage(BROWSER_VIEW_SOURCE); item = make_menu_item("ViewSrc", message); menu->AddItem(item); // 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); // 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); menu->AddItem(item); message = new BMessage(BROWSER_NAVIGATE_BACK); item = make_menu_item("Back", message); menu->AddItem(item); message = new BMessage(BROWSER_NAVIGATE_FORWARD); item = make_menu_item("Forward", message); 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); menu->AddItem(item); message = new BMessage(BROWSER_NAVIGATE_STOP); item = make_menu_item("Stop", message); menu->AddItem(item); // 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); // Utilities menu menu = new BMenu(messages_get("Utilities")); g->menu_bar->AddItem(menu); 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("HotlistShow", 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); submenu = new BMenu(messages_get("Cookies")); menu->AddItem(submenu); message = new BMessage(COOKIES_SHOW); item = make_menu_item("ShowCookies", message); submenu->AddItem(item); message = new BMessage(COOKIES_DELETE); item = make_menu_item("DeleteCookies", message); submenu->AddItem(item); 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); // Help menu menu = new BMenu(messages_get("Help")); g->menu_bar->AddItem(menu); 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); message = new BMessage(HELP_OPEN_ABOUT); item = make_menu_item("HelpAbout", message); menu->AddItem(item); message = new BMessage(HELP_LAUNCH_INTERACTIVE); item = make_menu_item("HelpInter", message); menu->AddItem(item); // 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(""); // 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)) ; // 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; rect.right = rect.right - DRAGGER_WIDTH; 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; rect.InsetBySelf(5, 5); message = new BMessage('urle'); message->AddPointer("scaffolding", g); g->url_bar = new BTextControl(rect, "url_bar", "url", "", message, B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP); g->url_bar->SetDivider(g->url_bar->StringWidth("url ")); g->tool_bar->AddChild(g->url_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; #warning XXX #if 0 /* GTK */ /* load the window template from the glade xml file, and extract * widget references from it for later use. */ g->xml = glade_xml_new(glade_file_location, "wndBrowser", NULL); glade_xml_signal_autoconnect(g->xml); g->window = beos_WINDOW(GET_WIDGET("wndBrowser")); g->url_bar = beos_ENTRY(GET_WIDGET("URLBar")); g->menu_bar = beos_MENU_BAR(GET_WIDGET("menubar")); g->status_bar = beos_LABEL(GET_WIDGET("statusBar")); g->tool_bar = beos_TOOLBAR(GET_WIDGET("toolbar")); g->back_button = beos_TOOL_BUTTON(GET_WIDGET("toolBack")); g->forward_button = beos_TOOL_BUTTON(GET_WIDGET("toolForward")); g->stop_button = beos_TOOL_BUTTON(GET_WIDGET("toolStop")); g->reload_button = beos_TOOL_BUTTON(GET_WIDGET("toolReload")); g->back_menu = beos_MENU_ITEM(GET_WIDGET("back")); g->forward_menu = beos_MENU_ITEM(GET_WIDGET("forward")); g->stop_menu = beos_MENU_ITEM(GET_WIDGET("stop")); g->reload_menu = beos_MENU_ITEM(GET_WIDGET("reload")); g->throbber = beos_IMAGE(GET_WIDGET("throbber")); g->status_pane = beos_PANED(GET_WIDGET("hpaned1")); /* set this window's size and position to what's in the options, or * or some sensible default if they're not set yet. */ if (nsoption_int(window_width) > 0) { beos_window_move(g->window, nsoption_int(window_x), nsoption_int(window_y)); beos_window_resize(g->window, nsoption_int(window_width), nsoption_int(window_height)); } else { beos_window_set_default_size(g->window, 600, 600); } /* set the size of the hpane with status bar and h scrollbar */ beos_paned_set_position(g->status_pane, nsoption_int(toolbar_status_width)); /* set the URL entry box to expand, as we can't do this from within * glade because of the way it emulates toolbars. */ beos_tool_item_set_expand(beos_TOOL_ITEM(GET_WIDGET("toolURLBar")), TRUE); /* disable toolbar buttons that make no sense initially. */ beos_widget_set_sensitive(beos_WIDGET(g->back_button), FALSE); beos_widget_set_sensitive(beos_WIDGET(g->forward_button), FALSE); beos_widget_set_sensitive(beos_WIDGET(g->stop_button), FALSE); /* create the local history window to be assoicated with this browser */ g->history_window = malloc(sizeof(struct beos_history_window)); g->history_window->g = g; g->history_window->window = beos_WINDOW( beos_window_new(beos_WINDOW_TOPLEVEL)); beos_window_set_transient_for(g->history_window->window, g->window); beos_window_set_default_size(g->history_window->window, 400, 400); beos_window_set_title(g->history_window->window, "NetSurf History"); beos_window_set_type_hint(g->history_window->window, GDK_WINDOW_TYPE_HINT_UTILITY); g->history_window->scrolled = beos_SCROLLED_WINDOW( beos_scrolled_window_new(0, 0)); beos_container_add(beos_CONTAINER(g->history_window->window), beos_WIDGET(g->history_window->scrolled)); beos_widget_show(beos_WIDGET(g->history_window->scrolled)); g->history_window->drawing_area = beos_DRAWING_AREA( beos_drawing_area_new()); beos_widget_set_events(beos_WIDGET(g->history_window->drawing_area), GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK); beos_widget_modify_bg(beos_WIDGET(g->history_window->drawing_area), beos_STATE_NORMAL, &((GdkColor) { 0, 0xffff, 0xffff, 0xffff } )); beos_scrolled_window_add_with_viewport(g->history_window->scrolled, beos_WIDGET(g->history_window->drawing_area)); beos_widget_show(beos_WIDGET(g->history_window->drawing_area)); /* set up URL bar completion */ g->url_bar_completion = beos_entry_completion_new(); beos_entry_set_completion(g->url_bar, g->url_bar_completion); beos_entry_completion_set_match_func(g->url_bar_completion, nsbeos_completion_match, NULL, NULL); beos_entry_completion_set_model(g->url_bar_completion, beos_TREE_MODEL(nsbeos_completion_list)); beos_entry_completion_set_text_column(g->url_bar_completion, 0); beos_entry_completion_set_minimum_key_length(g->url_bar_completion, 1); beos_entry_completion_set_popup_completion(g->url_bar_completion, TRUE); g_object_set(G_OBJECT(g->url_bar_completion), "popup-set-width", TRUE, "popup-single-match", TRUE, NULL); /* set up the throbber. */ beos_image_set_from_pixbuf(g->throbber, nsbeos_throbber->framedata[0]); g->throb_frame = 0; #define CONNECT(obj, sig, callback, ptr) \ g_signal_connect(G_OBJECT(obj), (sig), G_CALLBACK(callback), (ptr)) /* connect history window signals to their handlers */ CONNECT(g->history_window->drawing_area, "expose_event", nsbeos_history_expose_event, g->history_window); // CONNECT(g->history_window->drawing_area, "motion_notify_event", // nsbeos_history_motion_notify_event, g->history_window); CONNECT(g->history_window->drawing_area, "button_press_event", nsbeos_history_button_press_event, g->history_window); CONNECT(g->history_window->window, "delete_event", beos_widget_hide_on_delete, NULL); /* connect signals to handlers. */ CONNECT(g->window, "destroy", nsbeos_window_destroy_event, g); /* toolbar and URL bar signal handlers */ CONNECT(g->back_button, "clicked", nsbeos_window_back_button_clicked, g); CONNECT(g->forward_button, "clicked", nsbeos_window_forward_button_clicked, g); CONNECT(g->stop_button, "clicked", nsbeos_window_stop_button_clicked, g); CONNECT(g->reload_button, "clicked", nsbeos_window_reload_button_clicked, g); CONNECT(GET_WIDGET("toolHome"), "clicked", nsbeos_window_home_button_clicked, g); CONNECT(g->url_bar, "activate", nsbeos_window_url_activate_event, g); CONNECT(g->url_bar, "changed", nsbeos_window_url_changed, g); /* set up the menu signal handlers */ nsbeos_attach_menu_handlers(g->xml, g); g->being_destroyed = 0; g->fullscreen = false; /* create the popup version of the menu */ g->popup_xml = glade_xml_new(glade_file_location, "menuPopup", NULL); g->popup_menu = beos_MENU(glade_xml_get_widget(g->popup_xml, "menuPopup")); #define POPUP_ATTACH(x, y) beos_menu_item_set_submenu( \ beos_MENU_ITEM(glade_xml_get_widget(g->popup_xml, x)),\ beos_WIDGET(glade_xml_get_widget(g->xml, y))) POPUP_ATTACH("menupopup_file", "menumain_file"); POPUP_ATTACH("menupopup_edit", "menumain_edit"); POPUP_ATTACH("menupopup_view", "menumain_view"); POPUP_ATTACH("menupopup_navigate", "menumain_navigate"); POPUP_ATTACH("menupopup_help", "menumain_help"); #undef POPUP_ATTACH /* finally, show the window. */ beos_widget_show(beos_WIDGET(g->window)); #endif return g; } void gui_window_set_title(struct gui_window *_g, const char *title) { struct beos_scaffolding *g = nsbeos_get_scaffold(_g); if (g->top_level != _g) return; // if we're a replicant, discard if (!g->window) return; BString nt(title); if (nt.Length()) nt << " - "; nt << "NetSurf"; if (!g->top_view->LockLooper()) return; g->window->SetTitle(nt.String()); g->top_view->UnlockLooper(); } void gui_window_set_status(struct gui_window *_g, const char *text) { struct beos_scaffolding *g = nsbeos_get_scaffold(_g); assert(g); assert(g->status_bar); if (!g->top_view->LockLooper()) return; if (text == NULL || text[0] == '\0') { BString status("NetSurf"); status << " " << netsurf_version; g->status_bar->SetText(status.String()); } else { g->status_bar->SetText(text); } g->top_view->UnlockLooper(); } void gui_window_set_url(struct gui_window *_g, const char *url) { struct beos_scaffolding *g = nsbeos_get_scaffold(_g); if (g->top_level != _g) return; assert(g->status_bar); if (!g->top_view->LockLooper()) return; g->url_bar->SetText(url); g->top_view->UnlockLooper(); } void gui_window_start_throbber(struct gui_window* _g) { struct beos_scaffolding *g = nsbeos_get_scaffold(_g); if (!g->top_view->LockLooper()) return; g->stop_button->SetEnabled(true); g->reload_button->SetEnabled(false); g->top_view->UnlockLooper(); nsbeos_window_update_back_forward(g); schedule(10, nsbeos_throb, g); } void gui_window_stop_throbber(struct gui_window* _g) { struct beos_scaffolding *g = nsbeos_get_scaffold(_g); nsbeos_window_update_back_forward(g); schedule_remove(nsbeos_throb, g); if (!g->top_view->LockLooper()) return; g->stop_button->SetEnabled(false); g->reload_button->SetEnabled(true); g->throbber->SetBitmap(nsbeos_throbber->framedata[0]); g->throbber->Invalidate(); g->top_view->UnlockLooper(); } /** * add retrieved favicon to the gui */ void gui_window_set_icon(struct gui_window *g, hlcache_handle *icon) { } /** * set gui display of a retrieved favicon representing the search provider * \param ico may be NULL for local calls; then access current cache from * search_web_ico() */ void gui_window_set_search_ico(hlcache_handle *ico) { } #warning XXX #if 0 /* GTK */ gboolean nsbeos_scaffolding_is_busy(nsbeos_scaffolding *scaffold) { /* We are considered "busy" if the stop button is sensitive */ return beos_WIDGET_SENSITIVE((beos_WIDGET(scaffold->stop_button))); } #endif void nsbeos_scaffolding_popup_menu(nsbeos_scaffolding *g, BPoint where) { g->popup_menu->Go(where); }