summaryrefslogtreecommitdiff
path: root/src/uicmd.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/uicmd.cc')
-rw-r--r--src/uicmd.cc644
1 files changed, 644 insertions, 0 deletions
diff --git a/src/uicmd.cc b/src/uicmd.cc
new file mode 100644
index 00000000..d5f44e6b
--- /dev/null
+++ b/src/uicmd.cc
@@ -0,0 +1,644 @@
+/*
+ * File: uicmd.cc
+ *
+ * Copyright (C) 2005 Jorge Arellano Cid <jcid@dillo.org>
+ *
+ * This program 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; either version 3 of the License, or
+ * (at your option) any later version.
+ */
+
+// Functions/Methods for commands triggered from the UI
+
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <fltk/Widget.h>
+
+#include "dir.h"
+#include "ui.hh"
+#include "uicmd.hh"
+#include "timeout.hh"
+#include "menu.hh"
+#include "dialog.hh"
+#include "bookmark.h"
+#include "history.h"
+#include "msg.h"
+#include "prefs.h"
+
+#include "dw/fltkviewport.hh"
+
+#include "nav.h"
+
+// Platform idependent part
+using namespace dw::core;
+// FLTK related
+using namespace dw::fltk;
+
+typedef struct {
+ UI *ui;
+ BrowserWindow *bw;
+} Uibw;
+
+/*
+ * Local data
+ */
+// A matching table for all open ui/bw pairs
+// BUG: must be dynamic.
+static Uibw uibws[32];
+static int uibws_num = 0, uibws_max = 32;
+
+static char *save_dir = NULL;
+
+using namespace fltk;
+
+
+/*
+ * Create a new UI and its associated BrowserWindow data structure.
+ */
+BrowserWindow *a_UIcmd_browser_window_new(int ww, int wh)
+{
+ if (ww <= 0 || wh <= 0) {
+ // TODO: set default geometry from dillorc.
+ ww = 780;
+ wh = 580;
+ }
+
+ // Create and set the UI
+ UI *new_ui = new UI(ww, wh, "Dillo: UI");
+ new_ui->set_status("http://www.dillo.org/");
+ //new_ui->set_location("http://dillo.org/");
+ //new_ui->customize(12);
+
+ // Now create the Dw render layout and viewport
+ FltkPlatform *platform = new FltkPlatform ();
+ Layout *layout = new Layout (platform);
+
+ // BUG: This is a workaround for FLTK's non-working replace().
+ new_ui->set_render_layout_begin();
+ int p_h = new_ui->panel_h();
+ int s_h = new_ui->status_h();
+ FltkViewport *viewport = new FltkViewport (0, p_h, ww, wh-p_h-s_h);
+ layout->attachView (viewport);
+ //viewport->addGadget(new_ui->fullscreen_button());
+ new_ui->set_render_layout_end();
+ // This was the original code.
+ // Set the render_layout widget into the UI
+ // new_ui->set_render_layout(*viewport);
+
+ // Now, create a new browser window structure
+ BrowserWindow *new_bw = a_Bw_new(ww, wh, 0);
+
+ // Set new_bw as callback data for UI
+ new_ui->user_data(new_bw);
+ // Reference the UI from the bw
+ new_bw->ui = (void *)new_ui;
+ // Copy the layout pointer into the bw data
+ new_bw->render_layout = (void*)layout;
+
+ // insert the new ui/bw pair in the table
+ if (uibws_num < uibws_max) {
+ uibws[uibws_num].ui = new_ui;
+ uibws[uibws_num].bw = new_bw;
+ uibws_num++;
+ }
+
+ new_ui->show();
+
+ return new_bw;
+}
+
+/*
+ * Close one browser window
+ */
+void a_UIcmd_close_bw(void *vbw)
+{
+ BrowserWindow *bw = (BrowserWindow *)vbw;
+ UI *ui = (UI*)bw->ui;
+ Layout *layout = (Layout*)bw->render_layout;
+
+ MSG("a_UIcmd_close_bw\n");
+ ui->destroy();
+ delete(layout);
+ a_Bw_free(bw);
+}
+
+/*
+ * Close all the browser windows
+ */
+void a_UIcmd_close_all_bw()
+{
+ BrowserWindow *bw;
+
+ while ((bw = a_Bw_get()))
+ a_UIcmd_close_bw((void*)bw);
+}
+
+/*
+ * Open a new URL in the given browser window.
+ *
+ * our custom "file:" URIs are normalized here too.
+ */
+void a_UIcmd_open_urlstr(void *vbw, const char *urlstr)
+{
+ char *new_urlstr;
+ DilloUrl *url;
+ int ch;
+ BrowserWindow *bw = (BrowserWindow*)vbw;
+
+ if (urlstr && *urlstr) {
+ /* Filter URL string */
+ new_urlstr = a_Url_string_strip_delimiters(urlstr);
+
+ if (!dStrncasecmp(new_urlstr, "file:", 5)) {
+ /* file URI */
+ ch = new_urlstr[5];
+ if (!ch || ch == '.') {
+ url = a_Url_new(a_Dir_get_owd(), "file:", 0, 0, 0);
+ } else if (ch == '~') {
+ url = a_Url_new(dGethomedir(), "file:", 0, 0, 0);
+ } else {
+ url = a_Url_new(new_urlstr, "file:", 0, 0, 0);
+ }
+
+ } else {
+ /* common case */
+ url = a_Url_new(new_urlstr, NULL, 0, 0, 0);
+ }
+ dFree(new_urlstr);
+
+ if (url) {
+ a_Nav_push(bw, url);
+ a_Url_free(url);
+ }
+ }
+
+ /* let the rendered area have focus */
+ //gtk_widget_grab_focus(GTK_BIN(bw->render_main_scroll)->child);
+}
+
+/*
+ * Open a new URL in the given browser window
+ */
+void a_UIcmd_open_url_nw(BrowserWindow *bw, DilloUrl *url)
+{
+ a_Nav_push_nw(bw, url);
+}
+
+/*
+ * Send the browser back to previous page
+ */
+void a_UIcmd_back(void *vbw)
+{
+ a_Nav_back((BrowserWindow*)vbw);
+}
+
+/*
+ * Popup the navigation menu of the Back button
+ */
+void a_UIcmd_back_popup(void *vbw)
+{
+ a_Menu_history_popup((BrowserWindow*)vbw, -1);
+}
+
+/*
+ * Send the browser to next page in the history list
+ */
+void a_UIcmd_forw(void *vbw)
+{
+ a_Nav_forw((BrowserWindow*)vbw);
+}
+
+/*
+ * Popup the navigation menu of the Forward button
+ */
+void a_UIcmd_forw_popup(void *vbw)
+{
+ a_Menu_history_popup((BrowserWindow*)vbw, 1);
+}
+
+/*
+ * Send the browser to home URL
+ */
+void a_UIcmd_home(void *vbw)
+{
+ a_Nav_home((BrowserWindow*)vbw);
+}
+
+/*
+ * Reload current URL
+ */
+void a_UIcmd_reload(void *vbw)
+{
+ a_Nav_reload((BrowserWindow*)vbw);
+}
+
+/*
+ * Return a suitable filename for a given URL.
+ */
+char *UIcmd_make_save_filename(const char *urlstr)
+{
+ size_t MaxLen = 64;
+ char *FileName, *name;
+ const char *dir = a_UIcmd_get_save_dir();
+
+ if ((name = strrchr(urlstr, '/'))) {
+ if (strlen(++name) > MaxLen) {
+ name = name + strlen(name) - MaxLen;
+ }
+ FileName = dStrconcat(dir ? dir : "", name, NULL);
+ } else {
+ FileName = dStrconcat(dir ? dir : "", urlstr, NULL);
+ }
+ return FileName;
+}
+
+/*
+ * Get the default directory for saving files.
+ */
+const char *a_UIcmd_get_save_dir()
+{
+ return save_dir;
+}
+
+/*
+ * Set the default directory for saving files.
+ */
+void a_UIcmd_set_save_dir(const char *dir)
+{
+ char *p;
+
+ if (dir && (p = strrchr(dir, '/'))) {
+ dFree(save_dir);
+ // assert a trailing '/'
+ save_dir = dStrconcat(dir, (p[1] != 0) ? "/" : "", NULL);
+ }
+}
+
+/*
+ * Save current URL
+ */
+void a_UIcmd_save(void *vbw)
+{
+ const char *name;
+ char *SuggestedName, *urlstr;
+ DilloUrl *url;
+
+ // BUG: this should be set by preferences.
+ a_UIcmd_set_save_dir("/tmp/k/");
+
+ urlstr = a_UIcmd_get_location_text((BrowserWindow*)vbw);
+ url = a_Url_new(urlstr, NULL, 0, 0, 0);
+ SuggestedName = UIcmd_make_save_filename(urlstr);
+ name = a_Dialog_save_file("Save Page as File", NULL, SuggestedName);
+ MSG("a_UIcmd_save: %s\n", name);
+ dFree(SuggestedName);
+ dFree(urlstr);
+
+ if (name) {
+ a_Nav_save_url((BrowserWindow*)vbw, url, name);
+ }
+
+ a_Url_free(url);
+}
+
+/*
+ * Stop network activity on this bw.
+ * The stop button was pressed: stop page (and images) downloads.
+ */
+void a_UIcmd_stop(void *vbw)
+{
+ BrowserWindow *bw = (BrowserWindow *)vbw;
+
+ MSG("a_UIcmd_stop()\n");
+ a_Bw_stop_clients(bw, BW_Root + BW_Img + Bw_Force);
+ a_UIcmd_set_buttons_sens(bw);
+}
+
+/*
+ * Open URL with dialog chooser
+ */
+void a_UIcmd_open_file(void *vbw)
+{
+ char *name;
+ DilloUrl *url;
+
+ name = a_Dialog_open_file("Open File", NULL, "");
+
+ if (name) {
+ url = a_Url_new(name, "file:", 0, 0, 0);
+ a_Nav_push((BrowserWindow*)vbw, url);
+ a_Url_free(url);
+ dFree(name);
+ }
+}
+
+/*
+ * Get an URL from a dialog and open it
+ */
+void a_UIcmd_open_url_dialog(void *vbw)
+{
+ const char *urlstr;
+
+ if ((urlstr = a_Dialog_input("Please enter a URL:"))) {
+ a_UIcmd_open_urlstr(vbw, urlstr);
+ }
+}
+
+/*
+ * Returns a newly allocated string holding a search url generated from
+ * a string of keywords (separarated by blanks) and prefs.search_url.
+ * The search string is urlencoded.
+ */
+char *UIcmd_make_search_str(const char *str)
+{
+ char *keys = a_Url_encode_hex_str(str), *c = prefs.search_url;
+ Dstr *ds = dStr_sized_new(128);
+ char *search_url;
+
+ for (; *c; c++) {
+ if (*c == '%')
+ switch(*++c) {
+ case 's':
+ dStr_append(ds, keys); break;;
+ case '%':
+ dStr_append_c(ds, '%'); break;;
+ case 0:
+ MSG_WARN("search_url ends with '%%'\n"); c--; break;;
+ default:
+ MSG_WARN("illegal specifier '%%%c' in search_url\n", *c);
+ }
+ else
+ dStr_append_c(ds, *c);
+ }
+ dFree(keys);
+
+ search_url = ds->str;
+ dStr_free(ds, 0);
+ return search_url;
+}
+
+/*
+ * Get a query from a dialog and open it
+ */
+void a_UIcmd_search_dialog(void *vbw)
+{
+ const char *query, *url_str;
+
+ if ((query = a_Dialog_input("Search the Web:"))) {
+ url_str = UIcmd_make_search_str(query);
+ a_UIcmd_open_urlstr(vbw, url_str);
+ }
+}
+
+/*
+ * Save link URL
+ */
+void a_UIcmd_save_link(BrowserWindow *bw, const DilloUrl *url)
+{
+ const char *name;
+ char *SuggestedName;
+
+ // BUG: this should be set by preferences.
+ a_UIcmd_set_save_dir("/tmp/k/");
+
+ SuggestedName = UIcmd_make_save_filename(URL_STR(url));
+ name = a_Dialog_save_file("Save Link as File", NULL, SuggestedName);
+ MSG("a_UIcmd_save_link: %s\n", name);
+ dFree(SuggestedName);
+
+ if (name) {
+ a_Nav_save_url(bw, url, name);
+ }
+}
+
+/*
+ * Request the bookmarks page
+ */
+void a_UIcmd_book(void *vbw)
+{
+ DilloUrl *url = a_Url_new("dpi:/bm/", NULL, 0, 0, 0);
+ a_Nav_push((BrowserWindow*)vbw, url);
+ a_Url_free(url);
+}
+
+/*
+ * Add a bookmark for a certain URL
+ */
+void a_UIcmd_add_bookmark(BrowserWindow *bw, DilloUrl *url)
+{
+ a_Bookmarks_add(bw, url);
+}
+
+
+/*
+ * Popup the page menu
+ */
+void a_UIcmd_page_popup(void *vbw, DilloUrl *url, const char *bugs_txt)
+{
+ a_Menu_page_popup((BrowserWindow*)vbw, url, bugs_txt);
+}
+
+/*
+ * Popup the link menu
+ */
+void a_UIcmd_link_popup(void *vbw, DilloUrl *url)
+{
+ a_Menu_link_popup((BrowserWindow*)vbw, url);
+}
+
+/*
+ * Show a text window with the URL's source
+ */
+void a_UIcmd_view_page_source(DilloUrl *url)
+{
+ char *buf;
+ int buf_size;
+
+ if (a_Nav_get_buf(url, &buf, &buf_size)) {
+ a_Dialog_text_window(buf, "View Page source");
+ }
+}
+
+/*
+ * Show a text window with the URL's source
+ */
+void a_UIcmd_view_page_bugs(void *vbw)
+{
+ BrowserWindow *bw = (BrowserWindow*)vbw;
+
+ if (bw->num_page_bugs > 0) {
+ a_Dialog_text_window(bw->page_bugs->str, "Detected HTML errors");
+ } else {
+ a_Dialog_msg("Zero detected HTML errors!");
+ }
+}
+
+/*
+ * Popup the bug meter menu
+ */
+void a_UIcmd_bugmeter_popup(void *vbw)
+{
+ BrowserWindow *bw = (BrowserWindow*)vbw;
+
+ a_Menu_bugmeter_popup(bw, a_History_get_url(NAV_TOP(bw)));
+}
+
+/*
+ * Make a list of URL indexes for the history popup
+ * based on direction (-1 = back, 1 = forward)
+ */
+int *a_UIcmd_get_history(BrowserWindow *bw, int direction)
+{
+ int i, j, n;
+ int *hlist;
+
+ // Count the number of URLs
+ i = a_Nav_stack_ptr(bw) + direction;
+ for (n = 0 ; i >= 0 && i < a_Nav_stack_size(bw); i+=direction)
+ ++n;
+ hlist = dNew(int, n + 1);
+
+ // Fill the list
+ i = a_Nav_stack_ptr(bw) + direction;
+ for (j = 0 ; i >= 0 && i < a_Nav_stack_size(bw); i+=direction, j += 1) {
+ hlist[j] = NAV_IDX(bw,i);
+ }
+ hlist[j] = -1;
+
+ return hlist;
+}
+
+/*
+ * Jump to a certain URL in the navigation stack.
+ */
+void a_UIcmd_nav_jump(BrowserWindow *bw, int offset, int new_bw)
+{
+ a_Nav_jump(bw, offset, new_bw);
+}
+
+// UI binding functions -------------------------------------------------------
+
+#define BW2UI(bw) ((UI*)(bw->ui))
+
+/*
+ * Return browser window width and height
+ */
+void a_UIcmd_get_wh(BrowserWindow *bw, int *w, int *h)
+{
+ *w = BW2UI(bw)->w();
+ *h = BW2UI(bw)->h();
+ _MSG("a_UIcmd_wh: w=%d, h=%d\n", *w, *h);
+}
+
+/*
+ * Get location's text
+ */
+char *a_UIcmd_get_location_text(BrowserWindow *bw)
+{
+ return dStrdup(BW2UI(bw)->get_location());
+}
+
+/*
+ * Set location's text
+ */
+void a_UIcmd_set_location_text(void *vbw, const char *text)
+{
+ BrowserWindow *bw = (BrowserWindow*)vbw;
+ BW2UI(bw)->set_location(text);
+}
+
+/*
+ * Set the page progress bar
+ * cmd: 0 Deactivate, 1 Update, 2 Clear
+ */
+void a_UIcmd_set_page_prog(BrowserWindow *bw, size_t nbytes, int cmd)
+{
+ BW2UI(bw)->set_page_prog(nbytes, cmd);
+}
+
+/*
+ * Set the images progress bar
+ * cmd: 0 Deactivate, 1 Update, 2 Clear
+ */
+void a_UIcmd_set_img_prog(BrowserWindow *bw, int n_img, int t_img, int cmd)
+{
+ BW2UI(bw)->set_img_prog(n_img, t_img, cmd);
+}
+
+/*
+ * Set the bug meter progress label
+ */
+void a_UIcmd_set_bug_prog(BrowserWindow *bw, int n_bug)
+{
+ BW2UI(bw)->set_bug_prog(n_bug);
+}
+
+/*
+ * Set the page title.
+ * now it goes to the window titlebar (maybe to TAB label in the future).
+ */
+void a_UIcmd_set_page_title(BrowserWindow *bw, const char *label)
+{
+ BW2UI(bw)->set_page_title(label);
+}
+
+/*
+ * Set a printf-like status string on the bottom of the dillo window.
+ * Beware: The safe way to set an arbitrary string is
+ * a_UIcmd_set_msg(bw, "%s", str)
+ */
+void a_UIcmd_set_msg(BrowserWindow *bw, const char *format, ...)
+{
+ va_list argp;
+ Dstr *ds = dStr_sized_new(128);
+ va_start(argp, format);
+ dStr_vsprintf(ds, format, argp);
+ va_end(argp);
+ BW2UI(bw)->set_status(ds->str);
+ dStr_free(ds, 1);
+}
+
+/*
+ * Set the sensitivity of back/forw/stop buttons.
+ */
+static void a_UIcmd_set_buttons_sens_cb(void *vbw)
+{
+ int sens;
+ BrowserWindow *bw = (BrowserWindow*)vbw;
+
+ // Stop
+ sens = (dList_length(bw->ImageClients) || dList_length(bw->RootClients));
+ BW2UI(bw)->button_set_sens(UI_STOP, sens);
+ // Back
+ sens = (a_Nav_stack_ptr(bw) > 0);
+ BW2UI(bw)->button_set_sens(UI_BACK, sens);
+ // Forward
+ sens = (a_Nav_stack_ptr(bw) < a_Nav_stack_size(bw) - 1 &&
+ !bw->nav_expecting);
+ BW2UI(bw)->button_set_sens(UI_FORW, sens);
+
+ bw->sens_idle_up = 0;
+}
+
+
+/*
+ * Set the timeout function for button sensitivity
+ */
+void a_UIcmd_set_buttons_sens(BrowserWindow *bw)
+{
+ if (bw->sens_idle_up == 0) {
+ a_Timeout_add(0.0, a_UIcmd_set_buttons_sens_cb, bw);
+ bw->sens_idle_up = 1;
+ }
+}
+
+/*
+ * Toggle control panel (aka. fullscreen)
+ */
+void a_UIcmd_fullscreen_toggle(BrowserWindow *bw)
+{
+ BW2UI(bw)->fullscreen_toggle();
+}
+