netsurf/frontends/riscos/local_history.c
Vincent Sanders 653ccb78a9 Split local history data from viewer in headers
This separates the local history data object API from the viewing
API. It also changes the api to return nsurl references instead of
strings.
2017-06-10 18:37:21 +01:00

442 lines
10 KiB
C

/*
* Copyright 2017 Vincent Sanders <vince@netsurf-browser.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
/**
* \file
* Implementation of RISC OS local history.
*/
#include <stdint.h>
#include <stdlib.h>
#include <oslib/wimp.h>
#include "utils/nsoption.h"
#include "utils/messages.h"
#include "utils/log.h"
#include "utils/nsurl.h"
#include "netsurf/window.h"
#include "netsurf/plotters.h"
#include "netsurf/keypress.h"
#include "desktop/local_history.h"
#include "riscos/dialog.h"
#include "riscos/gui.h"
#include "riscos/menus.h"
#include "riscos/save.h"
#include "riscos/toolbar.h"
#include "riscos/wimp.h"
#include "riscos/wimp_event.h"
#include "riscos/wimputils.h"
#include "riscos/corewindow.h"
#include "riscos/local_history.h"
struct ro_local_history_window {
struct ro_corewindow core;
/** local history window context */
struct local_history_session *session;
/** tooltip previous x */
int x;
/** tooltip previous y */
int y;
};
/** local_history window is a singleton */
static struct ro_local_history_window *local_history_window = NULL;
/** riscos template for local_history window */
static wimp_window *dialog_local_history_template;
/**
* callback to draw on drawable area of ro local history window
*
* \param ro_cw The riscos core window structure.
* \param r The rectangle of the window that needs updating.
* \param originx The risc os plotter x origin.
* \param originy The risc os plotter y origin.
* \return NSERROR_OK on success otherwise apropriate error code
*/
static nserror
ro_local_history_draw(struct ro_corewindow *ro_cw,
int originx,
int originy,
struct rect *r)
{
struct redraw_context ctx = {
.interactive = true,
.background_images = true,
.plot = &ro_plotters
};
struct ro_local_history_window *lhw;
lhw = (struct ro_local_history_window *)ro_cw;
ro_plot_origin_x = originx;
ro_plot_origin_y = originy;
no_font_blending = true;
local_history_redraw(lhw->session, 0, 0, r, &ctx);
no_font_blending = false;
return NSERROR_OK;
}
/**
* callback for keypress on ro coookie window
*
* \param ro_cw The ro core window structure.
* \param nskey The netsurf key code.
* \return NSERROR_OK if key processed,
* NSERROR_NOT_IMPLEMENTED if key not processed
* otherwise apropriate error code
*/
static nserror
ro_local_history_key(struct ro_corewindow *ro_cw, uint32_t nskey)
{
struct ro_local_history_window *lhw;
lhw = (struct ro_local_history_window *)ro_cw;
if (local_history_keypress(lhw->session, nskey)) {
return NSERROR_OK;
}
return NSERROR_NOT_IMPLEMENTED;
}
/**
* handle hover mouse movement for tooltips
*/
static nserror
ro_local_history_tooltip(struct ro_local_history_window *lhw, int x, int y)
{
int width;
nsurl *url;
wimp_window_state state;
wimp_icon_state ic;
os_box box = {0, 0, 0, 0};
os_error *error;
wimp_pointer pointer;
nserror res;
/* check if tooltip are required */
if (!nsoption_bool(history_tooltip)) {
return NSERROR_OK;
}
/* ensure pointer has moved */
if ((lhw->x == x) && (lhw->y == y)) {
return NSERROR_OK;
}
lhw->x = x;
lhw->y = y;
res = local_history_get_url(lhw->session, x, y, &url);
if (res != NSERROR_OK) {
/* not over a tree entry => close tooltip window. */
error = xwimp_close_window(dialog_tooltip);
if (error) {
LOG("xwimp_close_window: 0x%x: %s",
error->errnum, error->errmess);
ro_warn_user("WimpError", error->errmess);
return NSERROR_NOMEM;
}
return NSERROR_OK;
}
/* get width of string */
error = xwimptextop_string_width(nsurl_access(url),
nsurl_length(url) > 256 ? 256 : nsurl_length(url),
&width);
if (error) {
LOG("xwimptextop_string_width: 0x%x: %s",
error->errnum, error->errmess);
ro_warn_user("WimpError", error->errmess);
nsurl_unref(url);
return NSERROR_NOMEM;
}
ro_gui_set_icon_string(dialog_tooltip, 0, nsurl_access(url), true);
nsurl_unref(url);
/* resize icon appropriately */
ic.w = dialog_tooltip;
ic.i = 0;
error = xwimp_get_icon_state(&ic);
if (error) {
LOG("xwimp_get_icon_state: 0x%x: %s",
error->errnum, error->errmess);
ro_warn_user("WimpError", error->errmess);
return NSERROR_NOMEM;
}
error = xwimp_resize_icon(dialog_tooltip, 0,
ic.icon.extent.x0, ic.icon.extent.y0,
width + 16, ic.icon.extent.y1);
if (error) {
LOG("xwimp_resize_icon: 0x%x: %s",
error->errnum, error->errmess);
ro_warn_user("WimpError", error->errmess);
return NSERROR_NOMEM;
}
state.w = dialog_tooltip;
error = xwimp_get_window_state(&state);
if (error) {
LOG("xwimp_get_window_state: 0x%x: %s",
error->errnum, error->errmess);
ro_warn_user("WimpError", error->errmess);
return NSERROR_NOMEM;
}
/* update window extent */
box.x1 = width + 16;
box.y0 = -36;
error = xwimp_set_extent(dialog_tooltip, &box);
if (error) {
LOG("xwimp_set_extent: 0x%x: %s", error->errnum, error->errmess);
ro_warn_user("WimpError", error->errmess);
return NSERROR_NOMEM;
}
error = xwimp_get_pointer_info(&pointer);
if (error) {
LOG("xwimp_get_pointer_info: 0x%x: %s",
error->errnum, error->errmess);
ro_warn_user("WimpError", error->errmess);
return NSERROR_NOMEM;
}
/* set visible area */
state.visible.x0 = pointer.pos.x + 24;
state.visible.y0 = pointer.pos.y - 22 - 36;
state.visible.x1 = pointer.pos.x + 24 + width + 16;
state.visible.y1 = pointer.pos.y - 22;
state.next = wimp_TOP;
/* open window */
error = xwimp_open_window(PTR_WIMP_OPEN(&state));
if (error) {
LOG("xwimp_open_window: 0x%x: %s",
error->errnum, error->errmess);
ro_warn_user("WimpError", error->errmess);
return NSERROR_NOMEM;
}
return NSERROR_OK;
}
/**
* callback for mouse event on ro local_history window
*
* \param ro_cw The ro core window structure.
* \param mouse_state mouse state
* \param x location of event
* \param y location of event
* \return NSERROR_OK on sucess otherwise apropriate error code.
*/
static nserror
ro_local_history_mouse(struct ro_corewindow *ro_cw,
browser_mouse_state mouse_state,
int x, int y)
{
struct ro_local_history_window *lhw;
lhw = (struct ro_local_history_window *)ro_cw;
switch (mouse_state) {
case BROWSER_MOUSE_HOVER:
ro_local_history_tooltip(lhw, x, y);
break;
case BROWSER_MOUSE_LEAVE:
ro_gui_dialog_close(dialog_tooltip);
break;
default:
local_history_mouse_action(lhw->session, mouse_state, x, y);
break;
}
return NSERROR_OK;
}
/**
* Creates the window for the local_history tree.
*
* \return NSERROR_OK on success else appropriate error code on faliure.
*/
static nserror
ro_local_history_init(struct browser_window *bw,
struct ro_local_history_window **win_out)
{
struct ro_local_history_window *ncwin;
nserror res;
/* memoise window so it can be represented when necessary
* instead of recreating every time.
*/
if ((*win_out) != NULL) {
res = local_history_set((*win_out)->session, bw);
return res;
}
ncwin = malloc(sizeof(struct ro_local_history_window));
if (ncwin == NULL) {
return NSERROR_NOMEM;
}
/* create window from template */
ncwin->core.wh = wimp_create_window(dialog_local_history_template);
/* initialise callbacks */
ncwin->core.draw = ro_local_history_draw;
ncwin->core.key = ro_local_history_key;
ncwin->core.mouse = ro_local_history_mouse;
/* initialise core window */
res = ro_corewindow_init(&ncwin->core,
NULL,
NULL,
0,
NULL);
if (res != NSERROR_OK) {
free(ncwin);
return res;
}
res = local_history_init(ncwin->core.cb_table,
(struct core_window *)ncwin,
bw,
&ncwin->session);
if (res != NSERROR_OK) {
free(ncwin);
return res;
}
*win_out = ncwin;
return NSERROR_OK;
}
/**
* open RISC OS local history window at the correct size
*/
static nserror
ro_local_history_open(struct ro_local_history_window *lhw, wimp_w parent)
{
nserror res;
int width, height;
os_box box = {0, 0, 0, 0};
wimp_window_state state;
os_error *error;
res = local_history_get_size(lhw->session, &width, &height);
if (res != NSERROR_OK) {
return res;
}
width *= 2;
height *= 2;
/* set extent */
box.x1 = width;
box.y0 = -height;
error = xwimp_set_extent(lhw->core.wh, &box);
if (error) {
LOG("xwimp_set_extent: 0x%x: %s",
error->errnum, error->errmess);
ro_warn_user("WimpError", error->errmess);
return NSERROR_NOMEM;
}
/* open full size */
state.w = lhw->core.wh;
error = xwimp_get_window_state(&state);
if (error) {
LOG("xwimp_get_window_state: 0x%x: %s",
error->errnum, error->errmess);
ro_warn_user("WimpError", error->errmess);
return NSERROR_NOMEM;
}
state.visible.x0 = 0;
state.visible.y0 = 0;
state.visible.x1 = width;
state.visible.y1 = height;
state.next = wimp_HIDDEN;
error = xwimp_open_window(PTR_WIMP_OPEN(&state));
if (error) {
LOG("xwimp_open_window: 0x%x: %s",
error->errnum, error->errmess);
ro_warn_user("WimpError", error->errmess);
return NSERROR_NOMEM;
}
ro_gui_dialog_open_persistent(parent, lhw->core.wh, true);
return NSERROR_OK;
}
/* exported interface documented in riscos/local_history.h */
nserror ro_gui_local_history_present(wimp_w parent, struct browser_window *bw)
{
nserror res;
res = ro_local_history_init(bw, &local_history_window);
if (res == NSERROR_OK) {
LOG("Presenting");
res = ro_local_history_open(local_history_window, parent);
} else {
LOG("Failed presenting error code %d", res);
}
return res;
}
/* exported interface documented in riscos/local_history.h */
void ro_gui_local_history_initialise(void)
{
dialog_local_history_template = ro_gui_dialog_load_template("history");
}
/* exported interface documented in riscos/local_history.h */
nserror ro_gui_local_history_finalise(void)
{
nserror res;
if (local_history_window == NULL) {
return NSERROR_OK;
}
res = local_history_fini(local_history_window->session);
if (res == NSERROR_OK) {
res = ro_corewindow_fini(&local_history_window->core);
free(local_history_window);
local_history_window = NULL;
}
return res;
}