diff options
Diffstat (limited to 'src/uicmd.cc')
-rw-r--r-- | src/uicmd.cc | 644 |
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(); +} + |