mirror of
https://github.com/netsurf-browser/netsurf
synced 2024-12-12 07:24:00 +03:00
9aecf47408
Previously the expected behaviour for front ends using the correct API for hotlist, global history, cookie manager, and ssl cert viewer was that the front end would initialise the treeview module on startup and finalise it on application exit. However, this meant that the front ends had to include the core treeview header, which they didn't otherwise need. Since the tree module provided access to the new treeview utilities through the old tree API, and was used by front ends with no changes for the new treeview API, the tree layer refcounted initialisations of treeview-based widgets, and only called the underlying treeview init/fini functions when needed. This change moves that refcounting into the treeview module. Now the hotlist, global history, cookie manager, and ssl cert viewer widgets call call treeview init/fini as part of their own initialisation and finalisation. This means that front ends using the correct APIs for treeview-based widgets don't need to know anything about the underlying treeview, and the tree module compatibility layer has had its treeview refcounting removed. Finally, the treeview_init function took a font size parameter. Now it does not and lit gets font size from config. We probably want to add a new `treeview_font_size` option to nsoptions, and have differnent defaults on different platforms. 12pt on RISC OS, and 11pt elsewhere, most likely.
1211 lines
29 KiB
C
1211 lines
29 KiB
C
/*
|
|
* Copyright 2010 <ole@monochrom.net>
|
|
*
|
|
* 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
|
|
*
|
|
* Provides all the mandatory functions prefixed with gui_ for atari
|
|
*/
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <unistd.h>
|
|
|
|
#include "utils/log.h"
|
|
#include "utils/messages.h"
|
|
#include "utils/corestrings.h"
|
|
#include "netsurf/browser_window.h"
|
|
#include "netsurf/layout.h"
|
|
#include "netsurf/window.h"
|
|
#include "netsurf/clipboard.h"
|
|
#include "netsurf/fetch.h"
|
|
#include "netsurf/misc.h"
|
|
#include "netsurf/netsurf.h"
|
|
#include "netsurf/content.h"
|
|
#include "netsurf/cookie_db.h"
|
|
#include "netsurf/url_db.h"
|
|
#include "content/backing_store.h"
|
|
|
|
#include "atari/gemtk/gemtk.h"
|
|
#include "atari/gui.h"
|
|
#include "atari/misc.h"
|
|
#include "atari/findfile.h"
|
|
#include "atari/schedule.h"
|
|
#include "atari/rootwin.h"
|
|
#include "atari/statusbar.h"
|
|
#include "atari/toolbar.h"
|
|
#include "atari/hotlist.h"
|
|
#include "atari/cookies.h"
|
|
#include "atari/certview.h"
|
|
#include "atari/history.h"
|
|
#include "atari/login.h"
|
|
#include "atari/encoding.h"
|
|
#include "atari/res/netsurf.rsh"
|
|
#include "atari/plot/plot.h"
|
|
#include "atari/clipboard.h"
|
|
#include "atari/osspec.h"
|
|
#include "atari/search.h"
|
|
#include "atari/deskmenu.h"
|
|
#include "atari/download.h"
|
|
#include "atari/file.h"
|
|
#include "atari/filetype.h"
|
|
#include "atari/bitmap.h"
|
|
#include "atari/font.h"
|
|
#include "cflib.h"
|
|
|
|
static bool atari_quit = false;
|
|
|
|
struct gui_window *input_window = NULL;
|
|
struct gui_window *window_list = NULL;
|
|
void *h_gem_rsrc;
|
|
long next_poll;
|
|
bool rendering = false;
|
|
GRECT desk_area;
|
|
|
|
/* Comandline / Options: */
|
|
int option_window_width;
|
|
int option_window_height;
|
|
int option_window_x;
|
|
int option_window_y;
|
|
|
|
/* Defaults to option_homepage_url, commandline options overwrites that value */
|
|
const char *option_homepage_url;
|
|
|
|
/* path to choices file: */
|
|
char options[PATH_MAX];
|
|
|
|
EVMULT_IN aes_event_in = {
|
|
.emi_flags = MU_MESAG | MU_TIMER | MU_KEYBD | MU_BUTTON | MU_M1,
|
|
.emi_bclicks = 258,
|
|
.emi_bmask = 3,
|
|
.emi_bstate = 0,
|
|
.emi_m1leave = MO_ENTER,
|
|
.emi_m1 = {0,0,0,0},
|
|
.emi_m2leave = 0,
|
|
.emi_m2 = {0,0,0,0},
|
|
.emi_tlow = 0,
|
|
.emi_thigh = 0
|
|
};
|
|
EVMULT_OUT aes_event_out;
|
|
short aes_msg_out[8];
|
|
|
|
bool gui_window_get_scroll(struct gui_window *w, int *sx, int *sy);
|
|
static nserror gui_window_set_url(struct gui_window *w, nsurl *url);
|
|
|
|
/**
|
|
* Core atari event processing.
|
|
*/
|
|
static void atari_poll(void)
|
|
{
|
|
|
|
struct gui_window *tmp;
|
|
short mx, my, dummy;
|
|
|
|
aes_event_in.emi_tlow = schedule_run();
|
|
|
|
if(rendering){
|
|
aes_event_in.emi_tlow = nsoption_int(atari_gui_poll_timeout);
|
|
}
|
|
|
|
if(aes_event_in.emi_tlow < 0) {
|
|
aes_event_in.emi_tlow = 10000;
|
|
printf("long poll!\n");
|
|
}
|
|
|
|
if(input_window && input_window->root->redraw_slots.areas_used > 0) {
|
|
window_process_redraws(input_window->root);
|
|
}
|
|
|
|
|
|
graf_mkstate(&mx, &my, &dummy, &dummy);
|
|
aes_event_in.emi_m1.g_x = mx;
|
|
aes_event_in.emi_m1.g_y = my;
|
|
evnt_multi_fast(&aes_event_in, aes_msg_out, &aes_event_out);
|
|
if(gemtk_wm_dispatch_event(&aes_event_in, &aes_event_out, aes_msg_out) == 0) {
|
|
if( (aes_event_out.emo_events & MU_MESAG) != 0 ) {
|
|
LOG("WM: %d\n", aes_msg_out[0]);
|
|
switch(aes_msg_out[0]) {
|
|
|
|
case MN_SELECTED:
|
|
LOG("Menu Item: %d\n", aes_msg_out[4]);
|
|
deskmenu_dispatch_item(aes_msg_out[3], aes_msg_out[4]);
|
|
break;
|
|
|
|
case AP_TERM:
|
|
atari_quit = true;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
if((aes_event_out.emo_events & MU_KEYBD) != 0) {
|
|
uint16_t nkc = gem_to_norm( (short)aes_event_out.emo_kmeta,
|
|
(short)aes_event_out.emo_kreturn);
|
|
deskmenu_dispatch_keypress(aes_event_out.emo_kreturn,
|
|
aes_event_out.emo_kmeta, nkc);
|
|
}
|
|
}
|
|
|
|
tmp = window_list;
|
|
while(tmp){
|
|
if(tmp->root->redraw_slots.areas_used > 0){
|
|
window_process_redraws(tmp->root);
|
|
}
|
|
tmp = tmp->next;
|
|
}
|
|
|
|
/** @todo implement generic treeview redraw function. */
|
|
/** @todo rename hl to atari_hotlist or create getter for it... */
|
|
|
|
atari_treeview_flush_redraws();
|
|
}
|
|
|
|
/**
|
|
* Create and open a gui window for a browsing context.
|
|
*
|
|
* \param bw bw to create gui_window for
|
|
* \param existing an existing gui_window, may be NULL
|
|
* \param flags flags for gui window creation
|
|
* \return gui window, or NULL on error
|
|
*
|
|
* If GW_CREATE_CLONE flag is set existing is non-NULL.
|
|
*
|
|
* The created gui_window must include a reference to the browser
|
|
* window passed in the bw param.
|
|
*/
|
|
static struct gui_window *
|
|
gui_window_create(struct browser_window *bw,
|
|
struct gui_window *existing,
|
|
gui_window_create_flags flags)
|
|
{
|
|
struct gui_window *gw=NULL;
|
|
LOG("gw: %p, BW: %p, existing %p, flags: %d\n", gw, bw, existing, (int)flags);
|
|
|
|
gw = calloc(1, sizeof(struct gui_window));
|
|
if (gw == NULL)
|
|
return NULL;
|
|
|
|
LOG("new window: %p, bw: %p\n", gw, bw);
|
|
window_create(gw, bw, existing, WIDGET_STATUSBAR|WIDGET_TOOLBAR|WIDGET_RESIZE\
|
|
|WIDGET_SCROLL);
|
|
if (gw->root->win) {
|
|
GRECT pos = {
|
|
option_window_x, option_window_y,
|
|
option_window_width, option_window_height
|
|
};
|
|
gui_window_set_url(gw, corestring_nsurl_about_blank);
|
|
gui_window_set_pointer(gw, BROWSER_POINTER_DEFAULT);
|
|
gui_set_input_gui_window(gw);
|
|
window_open(gw->root, gw, pos);
|
|
}
|
|
|
|
/* add the window to the window list: */
|
|
if( window_list == NULL ) {
|
|
window_list = gw;
|
|
gw->next = NULL;
|
|
gw->prev = NULL;
|
|
} else {
|
|
struct gui_window * tmp = window_list;
|
|
while( tmp->next != NULL ) {
|
|
tmp = tmp->next;
|
|
}
|
|
tmp->next = gw;
|
|
gw->prev = tmp;
|
|
gw->next = NULL;
|
|
}
|
|
|
|
/* Loose focus: */
|
|
window_set_focus(gw->root, WIDGET_NONE, NULL );
|
|
|
|
/* trigger on-focus event (select all text): */
|
|
window_set_focus(gw->root, URL_WIDGET, NULL);
|
|
|
|
/* delete selection: */
|
|
toolbar_key_input(gw->root->toolbar, NK_DEL);
|
|
|
|
return( gw );
|
|
|
|
}
|
|
|
|
/**
|
|
* Destroy previously created gui window
|
|
*
|
|
* \param gw The gui window to destroy.
|
|
*/
|
|
void gui_window_destroy(struct gui_window *gw)
|
|
{
|
|
if (gw == NULL)
|
|
return;
|
|
|
|
LOG("%s\n", __FUNCTION__);
|
|
|
|
if (input_window == gw) {
|
|
gui_set_input_gui_window(NULL);
|
|
}
|
|
|
|
nsatari_search_session_destroy(gw->search);
|
|
free(gw->browser);
|
|
free(gw->status);
|
|
free(gw->title);
|
|
free(gw->url);
|
|
|
|
/* unlink the window: */
|
|
if(gw->prev != NULL ) {
|
|
gw->prev->next = gw->next;
|
|
} else {
|
|
window_list = gw->next;
|
|
}
|
|
if( gw->next != NULL ) {
|
|
gw->next->prev = gw->prev;
|
|
}
|
|
|
|
window_unref_gui_window(gw->root, gw);
|
|
|
|
free(gw);
|
|
gw = NULL;
|
|
|
|
if(input_window == NULL) {
|
|
gw = window_list;
|
|
while( gw != NULL ) {
|
|
if(gw->root) {
|
|
gui_set_input_gui_window(gw);
|
|
break;
|
|
}
|
|
gw = gw->next;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Find the current dimensions of a browser window's content area.
|
|
*
|
|
* \param w gui_window to measure
|
|
* \param width receives width of window
|
|
* \param height receives height of window
|
|
* \param scaled whether to return scaled values
|
|
*/
|
|
static void
|
|
gui_window_get_dimensions(struct gui_window *w,
|
|
int *width,
|
|
int *height,
|
|
bool scaled)
|
|
{
|
|
if (w == NULL)
|
|
return;
|
|
GRECT rect;
|
|
window_get_grect(w->root, BROWSER_AREA_CONTENT, &rect);
|
|
*width = rect.g_w;
|
|
*height = rect.g_h;
|
|
}
|
|
|
|
/**
|
|
* Set the title of a window.
|
|
*
|
|
* \param gw window to update
|
|
* \param title new window title
|
|
*/
|
|
static void gui_window_set_title(struct gui_window *gw, const char *title)
|
|
{
|
|
if (gw == NULL)
|
|
return;
|
|
|
|
if (gw->root) {
|
|
|
|
int l;
|
|
char * conv;
|
|
l = strlen(title)+1;
|
|
if (utf8_to_local_encoding(title, l-1, &conv) == NSERROR_OK ) {
|
|
l = MIN((uint32_t)atari_sysinfo.aes_max_win_title_len, strlen(conv));
|
|
if(gw->title == NULL)
|
|
gw->title = malloc(l);
|
|
else
|
|
gw->title = realloc(gw->title, l);
|
|
|
|
strncpy(gw->title, conv, l);
|
|
free( conv );
|
|
} else {
|
|
l = MIN((size_t)atari_sysinfo.aes_max_win_title_len, strlen(title));
|
|
if(gw->title == NULL)
|
|
gw->title = malloc(l);
|
|
else
|
|
gw->title = realloc(gw->title, l);
|
|
strncpy(gw->title, title, l);
|
|
}
|
|
gw->title[l] = 0;
|
|
if(input_window == gw)
|
|
window_set_title(gw->root, gw->title);
|
|
}
|
|
}
|
|
|
|
/* exported interface documented in atari/gui.h */
|
|
void atari_window_set_status(struct gui_window *w, const char *text)
|
|
{
|
|
int l;
|
|
if (w == NULL || text == NULL)
|
|
return;
|
|
|
|
assert(w->root);
|
|
|
|
l = strlen(text)+1;
|
|
if(w->status == NULL)
|
|
w->status = malloc(l);
|
|
else
|
|
w->status = realloc(w->status, l);
|
|
|
|
strncpy(w->status, text, l);
|
|
w->status[l] = 0;
|
|
|
|
if(input_window == w)
|
|
window_set_stauts(w->root, (char*)text);
|
|
}
|
|
|
|
static void atari_window_reformat(struct gui_window *gw)
|
|
{
|
|
int width = 0, height = 0;
|
|
|
|
if (gw != NULL) {
|
|
gui_window_get_dimensions(gw, &width, &height, true);
|
|
browser_window_reformat(gw->browser->bw, false, width, height);
|
|
}
|
|
}
|
|
|
|
static void gui_window_redraw_window(struct gui_window *gw)
|
|
{
|
|
CMP_BROWSER b;
|
|
GRECT rect;
|
|
if (gw == NULL)
|
|
return;
|
|
b = gw->browser;
|
|
window_get_grect(gw->root, BROWSER_AREA_CONTENT, &rect);
|
|
window_schedule_redraw_grect(gw->root, &rect);
|
|
}
|
|
|
|
static void gui_window_update_box(struct gui_window *gw, const struct rect *rect)
|
|
{
|
|
GRECT area;
|
|
struct gemtk_wm_scroll_info_s *slid;
|
|
|
|
if (gw == NULL)
|
|
return;
|
|
|
|
slid = gemtk_wm_get_scroll_info(gw->root->win);
|
|
|
|
window_get_grect(gw->root, BROWSER_AREA_CONTENT, &area);
|
|
area.g_x += rect->x0 - (slid->x_pos * slid->x_unit_px);
|
|
area.g_y += rect->y0 - (slid->y_pos * slid->y_unit_px);
|
|
area.g_w = rect->x1 - rect->x0;
|
|
area.g_h = rect->y1 - rect->y0;
|
|
//dbg_grect("update box", &area);
|
|
window_schedule_redraw_grect(gw->root, &area);
|
|
}
|
|
|
|
bool gui_window_get_scroll(struct gui_window *w, int *sx, int *sy)
|
|
{
|
|
if (w == NULL)
|
|
return false;
|
|
|
|
window_get_scroll(w->root, sx, sy);
|
|
|
|
return( true );
|
|
}
|
|
|
|
static void gui_window_set_scroll(struct gui_window *w, int sx, int sy)
|
|
{
|
|
if ( (w == NULL)
|
|
|| (w->browser->bw == NULL)
|
|
|| (!browser_window_has_content(w->browser->bw)))
|
|
return;
|
|
|
|
LOG("scroll (gui_window: %p) %d, %d\n", w, sx, sy);
|
|
window_scroll_by(w->root, sx, sy);
|
|
return;
|
|
|
|
}
|
|
|
|
/**
|
|
* Update the extent of the inside of a browser window to that of the
|
|
* current content.
|
|
*
|
|
* It seems this method is called when content size got adjusted, so
|
|
* that we can adjust scroll info. We also have to call it when tab
|
|
* change occurs.
|
|
*
|
|
* \param gw gui_window to update the extent of
|
|
*/
|
|
static void gui_window_update_extent(struct gui_window *gw)
|
|
{
|
|
|
|
if(browser_window_has_content(gw->browser->bw)) {
|
|
/** @todo store content size. */
|
|
if(window_get_active_gui_window(gw->root) == gw) {
|
|
int width, height;
|
|
GRECT area;
|
|
browser_window_get_extents(gw->browser->bw, false, &width, &height);
|
|
window_set_content_size(gw->root, width, height);
|
|
window_update_back_forward(gw->root);
|
|
window_get_grect(gw->root, BROWSER_AREA_CONTENT, &area);
|
|
window_schedule_redraw_grect(gw->root, &area);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* set the pointer shape
|
|
*/
|
|
void gui_window_set_pointer(struct gui_window *gw, gui_pointer_shape shape)
|
|
{
|
|
if (gw == NULL)
|
|
return;
|
|
|
|
switch (shape) {
|
|
case GUI_POINTER_POINT: /* link */
|
|
gw->cursor = &gem_cursors.hand;
|
|
break;
|
|
|
|
case GUI_POINTER_MENU:
|
|
gw->cursor = &gem_cursors.menu;
|
|
break;
|
|
|
|
case GUI_POINTER_CARET: /* input */
|
|
gw->cursor = &gem_cursors.ibeam;
|
|
break;
|
|
|
|
case GUI_POINTER_CROSS:
|
|
gw->cursor = &gem_cursors.cross;
|
|
break;
|
|
|
|
case GUI_POINTER_MOVE:
|
|
gw->cursor = &gem_cursors.sizeall;
|
|
break;
|
|
|
|
case GUI_POINTER_RIGHT:
|
|
case GUI_POINTER_LEFT:
|
|
gw->cursor = &gem_cursors.sizewe;
|
|
break;
|
|
|
|
case GUI_POINTER_UP:
|
|
case GUI_POINTER_DOWN:
|
|
gw->cursor = &gem_cursors.sizens;
|
|
break;
|
|
|
|
case GUI_POINTER_RU:
|
|
case GUI_POINTER_LD:
|
|
gw->cursor = &gem_cursors.sizenesw;
|
|
break;
|
|
|
|
case GUI_POINTER_RD:
|
|
case GUI_POINTER_LU:
|
|
gw->cursor = &gem_cursors.sizenwse;
|
|
break;
|
|
|
|
case GUI_POINTER_WAIT:
|
|
gw->cursor = &gem_cursors.wait;
|
|
break;
|
|
|
|
case GUI_POINTER_PROGRESS:
|
|
gw->cursor = &gem_cursors.appstarting;
|
|
break;
|
|
|
|
case GUI_POINTER_NO_DROP:
|
|
gw->cursor = &gem_cursors.nodrop;
|
|
break;
|
|
|
|
case GUI_POINTER_NOT_ALLOWED:
|
|
gw->cursor = &gem_cursors.deny;
|
|
break;
|
|
|
|
case GUI_POINTER_HELP:
|
|
gw->cursor = &gem_cursors.help;
|
|
break;
|
|
|
|
default:
|
|
gw->cursor = &gem_cursors.arrow;
|
|
break;
|
|
}
|
|
|
|
if (input_window == gw) {
|
|
gem_set_cursor(gw->cursor);
|
|
}
|
|
}
|
|
|
|
|
|
static nserror gui_window_set_url(struct gui_window *w, nsurl *url)
|
|
{
|
|
int l;
|
|
|
|
if (w == NULL)
|
|
return NSERROR_OK;
|
|
|
|
l = strlen(nsurl_access(url))+1;
|
|
|
|
if (w->url == NULL) {
|
|
w->url = malloc(l);
|
|
} else {
|
|
w->url = realloc(w->url, l);
|
|
}
|
|
strncpy(w->url, nsurl_access(url), l);
|
|
w->url[l] = 0;
|
|
if(input_window == w->root->active_gui_window) {
|
|
toolbar_set_url(w->root->toolbar, nsurl_access(url));
|
|
}
|
|
|
|
return NSERROR_OK;
|
|
}
|
|
|
|
char * gui_window_get_url(struct gui_window *gw)
|
|
{
|
|
if (gw == NULL) {
|
|
return(NULL);
|
|
}
|
|
return(gw->url);
|
|
}
|
|
|
|
char * gui_window_get_title(struct gui_window *gw)
|
|
{
|
|
if (gw == NULL) {
|
|
return(NULL);
|
|
}
|
|
return(gw->title);
|
|
}
|
|
|
|
static void throbber_advance( void * data )
|
|
{
|
|
|
|
struct gui_window * gw = (struct gui_window *)data;
|
|
|
|
if (gw->root == NULL)
|
|
return;
|
|
if (gw->root->toolbar == NULL)
|
|
return;
|
|
|
|
if (gw->root->toolbar->throbber.running == false)
|
|
return;
|
|
|
|
toolbar_throbber_progress(gw->root->toolbar);
|
|
atari_schedule(1000, throbber_advance, gw );
|
|
}
|
|
|
|
static void gui_window_start_throbber(struct gui_window *w)
|
|
{
|
|
if (w == NULL)
|
|
return;
|
|
|
|
toolbar_set_throbber_state(w->root->toolbar, true);
|
|
atari_schedule(1000, throbber_advance, w );
|
|
rendering = true;
|
|
}
|
|
|
|
static void gui_window_stop_throbber(struct gui_window *w)
|
|
{
|
|
if (w == NULL)
|
|
return;
|
|
if (w->root->toolbar->throbber.running == false)
|
|
return;
|
|
|
|
atari_schedule(-1, throbber_advance, w);
|
|
|
|
toolbar_set_throbber_state(w->root->toolbar, false);
|
|
|
|
rendering = false;
|
|
}
|
|
|
|
/**
|
|
* Place caret in window
|
|
*/
|
|
static void
|
|
gui_window_place_caret(struct gui_window *w, int x, int y, int height,
|
|
const struct rect *clip)
|
|
{
|
|
window_place_caret(w->root, 1, x, y, height, NULL);
|
|
w->root->caret.state |= CARET_STATE_ENABLED;
|
|
return;
|
|
}
|
|
|
|
|
|
/**
|
|
* clear window caret
|
|
*/
|
|
static void
|
|
gui_window_remove_caret(struct gui_window *w)
|
|
{
|
|
if (w == NULL)
|
|
return;
|
|
|
|
if ((w->root->caret.state & CARET_STATE_ENABLED) != 0) {
|
|
//printf("gw hide caret\n");
|
|
window_place_caret(w->root, 0, -1, -1, -1, NULL);
|
|
w->root->caret.state &= ~CARET_STATE_ENABLED;
|
|
}
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* Set a favicon for a gui window.
|
|
*
|
|
* \param g window to update.
|
|
* \param icon handle to object to use as icon.
|
|
*/
|
|
static void
|
|
gui_window_set_icon(struct gui_window *g, struct hlcache_handle *icon)
|
|
{
|
|
struct bitmap *bmp_icon;
|
|
|
|
bmp_icon = (icon != NULL) ? content_get_bitmap(icon) : NULL;
|
|
g->icon = bmp_icon;
|
|
if(input_window == g) {
|
|
window_set_icon(g->root, bmp_icon);
|
|
}
|
|
}
|
|
|
|
static void gui_window_new_content(struct gui_window *w)
|
|
{
|
|
struct gemtk_wm_scroll_info_s *slid = gemtk_wm_get_scroll_info(w->root->win);
|
|
slid->x_pos = 0;
|
|
slid->y_pos = 0;
|
|
gemtk_wm_update_slider(w->root->win, GEMTK_WM_VH_SLIDER);
|
|
gui_window_redraw_window(w);
|
|
}
|
|
|
|
|
|
/**
|
|
* Core asks front end for clipboard contents.
|
|
*
|
|
* \param buffer UTF-8 text, allocated by front end, ownership yeilded to core
|
|
* \param length Byte length of UTF-8 text in buffer
|
|
*/
|
|
static void gui_get_clipboard(char **buffer, size_t *length)
|
|
{
|
|
char *clip;
|
|
|
|
*length = 0;
|
|
*buffer = 0;
|
|
|
|
clip = scrap_txt_read();
|
|
|
|
if(clip == NULL) {
|
|
return;
|
|
} else {
|
|
|
|
// clipboard is in atari encoding, convert it to utf8:
|
|
|
|
size_t clip_len;
|
|
char *utf8 = NULL;
|
|
|
|
clip_len = strlen(clip);
|
|
if (clip_len > 0) {
|
|
nserror ret;
|
|
ret = utf8_to_local_encoding(clip, clip_len, &utf8);
|
|
if (ret == NSERROR_OK && utf8 != NULL) {
|
|
*buffer = utf8;
|
|
*length = strlen(utf8);
|
|
} else {
|
|
assert(ret == NSERROR_OK && utf8 != NULL);
|
|
}
|
|
}
|
|
|
|
free(clip);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Core tells front end to put given text in clipboard
|
|
*
|
|
* \param buffer UTF-8 text, owned by core
|
|
* \param length Byte length of UTF-8 text in buffer
|
|
* \param styles Array of styles given to text runs, owned by core, or NULL
|
|
* \param n_styles Number of text run styles in array
|
|
*/
|
|
static void gui_set_clipboard(const char *buffer, size_t length,
|
|
nsclipboard_styles styles[], int n_styles)
|
|
{
|
|
if (length > 0 && buffer != NULL) {
|
|
|
|
// convert utf8 input to atari encoding:
|
|
|
|
nserror ret;
|
|
char *clip = NULL;
|
|
|
|
ret = utf8_to_local_encoding(buffer,length, &clip);
|
|
if (ret == NSERROR_OK) {
|
|
scrap_txt_write(clip);
|
|
} else {
|
|
assert(ret == NSERROR_OK);
|
|
}
|
|
free(clip);
|
|
}
|
|
}
|
|
|
|
static void gui_401login_open(nsurl *url, const char *realm,
|
|
nserror (*cb)(bool proceed, void *pw), void *cbpw)
|
|
{
|
|
bool bres;
|
|
char * out = NULL;
|
|
bres = login_form_do( url, (char*)realm, &out);
|
|
if (bres) {
|
|
LOG("url: %s, realm: %s, auth: %s\n", nsurl_access(url), realm, out);
|
|
urldb_set_auth_details(url, realm, out);
|
|
}
|
|
if (out != NULL) {
|
|
free( out );
|
|
}
|
|
if (cb != NULL) {
|
|
cb(bres, cbpw);
|
|
}
|
|
|
|
}
|
|
|
|
static nserror
|
|
gui_cert_verify(nsurl *url, const struct ssl_cert_info *certs,
|
|
unsigned long num, nserror (*cb)(bool proceed, void *pw),
|
|
void *cbpw)
|
|
{
|
|
struct sslcert_session_data *data;
|
|
LOG("url %s", nsurl_access(url));
|
|
|
|
// TODO: localize string
|
|
int b = form_alert(1, "[2][SSL Verify failed, continue?][Continue|Abort|Details...]");
|
|
if(b == 1){
|
|
// Accept
|
|
urldb_set_cert_permissions(url, true);
|
|
cb(true, cbpw);
|
|
} else if(b == 2) {
|
|
// Reject
|
|
urldb_set_cert_permissions(url, false);
|
|
cb(false, cbpw);
|
|
} else if(b == 3) {
|
|
// Inspect
|
|
sslcert_viewer_create_session_data(num, url, cb, cbpw, certs,
|
|
&data);
|
|
atari_sslcert_viewer_open(data);
|
|
}
|
|
return NSERROR_OK;
|
|
}
|
|
|
|
void gui_set_input_gui_window(struct gui_window *gw)
|
|
{
|
|
LOG("Setting input window from: %p to %p\n", input_window, gw);
|
|
input_window = gw;
|
|
}
|
|
|
|
struct gui_window * gui_get_input_window(void)
|
|
{
|
|
return(input_window);
|
|
}
|
|
|
|
static void gui_quit(void)
|
|
{
|
|
LOG("quitting");
|
|
|
|
struct gui_window *gw = window_list;
|
|
struct gui_window *tmp = window_list;
|
|
|
|
/* Destroy all remaining browser windows: */
|
|
while (gw) {
|
|
tmp = gw->next;
|
|
browser_window_destroy(gw->browser->bw);
|
|
gw = tmp;
|
|
}
|
|
|
|
/* destroy the treeview windows: */
|
|
atari_global_history_destroy();
|
|
atari_hotlist_destroy();
|
|
atari_cookie_manager_destroy();
|
|
|
|
/* shutdown the toolbar framework: */
|
|
toolbar_exit();
|
|
|
|
/* save persistent informations: */
|
|
urldb_save_cookies(nsoption_charp(cookie_file));
|
|
urldb_save(nsoption_charp(url_file));
|
|
|
|
deskmenu_destroy();
|
|
gemtk_wm_exit();
|
|
|
|
rsrc_free();
|
|
|
|
LOG("Shutting down plotter");
|
|
plot_finalise();
|
|
LOG("done");
|
|
}
|
|
|
|
/**
|
|
* Process commandline parameters.
|
|
*/
|
|
static bool
|
|
process_cmdline(int argc, char** argv)
|
|
{
|
|
int opt;
|
|
bool set_default_dimensions = true;
|
|
|
|
LOG("argc %d, argv %p", argc, argv);
|
|
|
|
if ((nsoption_int(window_width) != 0) && (nsoption_int(window_height) != 0)) {
|
|
|
|
option_window_width = nsoption_int(window_width);
|
|
option_window_height = nsoption_int(window_height);
|
|
option_window_x = nsoption_int(window_x);
|
|
option_window_y = nsoption_int(window_y);
|
|
|
|
if (option_window_width <= desk_area.g_w
|
|
&& option_window_height < desk_area.g_h) {
|
|
set_default_dimensions = false;
|
|
}
|
|
}
|
|
|
|
if (set_default_dimensions) {
|
|
if( sys_type() == SYS_TOS ) {
|
|
/* on single tasking OS, start as fulled window: */
|
|
option_window_width = desk_area.g_w;
|
|
option_window_height = desk_area.g_h;
|
|
option_window_x = desk_area.g_w/2-(option_window_width/2);
|
|
option_window_y = (desk_area.g_h/2)-(option_window_height/2);
|
|
} else {
|
|
option_window_width = 600;
|
|
option_window_height = 360;
|
|
option_window_x = 10;
|
|
option_window_y = 30;
|
|
}
|
|
}
|
|
|
|
if (nsoption_charp(homepage_url) != NULL)
|
|
option_homepage_url = nsoption_charp(homepage_url);
|
|
else
|
|
option_homepage_url = NETSURF_HOMEPAGE;
|
|
|
|
while((opt = getopt(argc, argv, "w:h:")) != -1) {
|
|
switch (opt) {
|
|
case 'w':
|
|
option_window_width = atoi(optarg);
|
|
break;
|
|
|
|
case 'h':
|
|
option_window_height = atoi(optarg);
|
|
break;
|
|
|
|
default:
|
|
fprintf(stderr,
|
|
"Usage: %s [w,h,v] url\n",
|
|
argv[0]);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (optind < argc) {
|
|
option_homepage_url = argv[optind];
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static inline void create_cursor(int flags, short mode, void * form,
|
|
MFORM_EX * m)
|
|
{
|
|
m->flags = flags;
|
|
m->number = mode;
|
|
if( flags & MFORM_EX_FLAG_USERFORM ) {
|
|
m->number = mode;
|
|
m->tree = (OBJECT*)form;
|
|
}
|
|
}
|
|
|
|
static nsurl *gui_get_resource_url(const char *path)
|
|
{
|
|
char buf[PATH_MAX];
|
|
nsurl *url = NULL;
|
|
|
|
atari_find_resource((char*)&buf, path, path);
|
|
|
|
netsurf_path_to_nsurl(buf, &url);
|
|
|
|
return url;
|
|
}
|
|
|
|
/**
|
|
* Set option defaults for atari frontend
|
|
*
|
|
* @param defaults The option table to update.
|
|
* @return error status.
|
|
*/
|
|
static nserror set_defaults(struct nsoption_s *defaults)
|
|
{
|
|
/* Set defaults for absent option strings */
|
|
nsoption_setnull_charp(cookie_file, strdup("cookies"));
|
|
if (nsoption_charp(cookie_file) == NULL) {
|
|
LOG("Failed initialising string options");
|
|
return NSERROR_BAD_PARAMETER;
|
|
}
|
|
return NSERROR_OK;
|
|
}
|
|
|
|
static char *theapp = (char*)"NetSurf";
|
|
|
|
/**
|
|
* Initialise atari gui.
|
|
*/
|
|
static void gui_init(int argc, char** argv)
|
|
{
|
|
char buf[PATH_MAX];
|
|
OBJECT * cursors;
|
|
|
|
atari_find_resource(buf, "netsurf.rsc", "./res/netsurf.rsc");
|
|
LOG("Using RSC file: %s ", (char *)&buf);
|
|
if (rsrc_load(buf)==0) {
|
|
|
|
char msg[1024];
|
|
|
|
snprintf(msg, 1024, "Unable to open GEM Resource file (%s)!", buf);
|
|
die(msg);
|
|
}
|
|
|
|
wind_get_grect(0, WF_WORKXYWH, &desk_area);
|
|
|
|
create_cursor(0, POINT_HAND, NULL, &gem_cursors.hand );
|
|
create_cursor(0, TEXT_CRSR, NULL, &gem_cursors.ibeam );
|
|
create_cursor(0, THIN_CROSS, NULL, &gem_cursors.cross);
|
|
create_cursor(0, BUSY_BEE, NULL, &gem_cursors.wait);
|
|
create_cursor(0, ARROW, NULL, &gem_cursors.arrow);
|
|
create_cursor(0, OUTLN_CROSS, NULL, &gem_cursors.sizeall);
|
|
create_cursor(0, OUTLN_CROSS, NULL, &gem_cursors.sizenesw);
|
|
create_cursor(0, OUTLN_CROSS, NULL, &gem_cursors.sizenwse);
|
|
cursors = gemtk_obj_get_tree(CURSOR);
|
|
create_cursor(MFORM_EX_FLAG_USERFORM, CURSOR_APPSTART,
|
|
cursors, &gem_cursors.appstarting);
|
|
gem_set_cursor( &gem_cursors.appstarting );
|
|
create_cursor(MFORM_EX_FLAG_USERFORM, CURSOR_SIZEWE,
|
|
cursors, &gem_cursors.sizewe);
|
|
create_cursor(MFORM_EX_FLAG_USERFORM, CURSOR_SIZENS,
|
|
cursors, &gem_cursors.sizens);
|
|
create_cursor(MFORM_EX_FLAG_USERFORM, CURSOR_NODROP,
|
|
cursors, &gem_cursors.nodrop);
|
|
create_cursor(MFORM_EX_FLAG_USERFORM, CURSOR_DENY,
|
|
cursors, &gem_cursors.deny);
|
|
create_cursor(MFORM_EX_FLAG_USERFORM, CURSOR_MENU,
|
|
cursors, &gem_cursors.menu);
|
|
create_cursor(MFORM_EX_FLAG_USERFORM, CURSOR_HELP,
|
|
cursors, &gem_cursors.help);
|
|
|
|
LOG("Enabling core select menu");
|
|
nsoption_set_bool(core_select_menu, true);
|
|
|
|
LOG("Loading url.db from: %s", nsoption_charp(url_file));
|
|
if( strlen(nsoption_charp(url_file)) ) {
|
|
urldb_load(nsoption_charp(url_file));
|
|
}
|
|
|
|
LOG("Loading cookies from: %s", nsoption_charp(cookie_file));
|
|
if( strlen(nsoption_charp(cookie_file)) ) {
|
|
urldb_load_cookies(nsoption_charp(cookie_file));
|
|
}
|
|
|
|
if (process_cmdline(argc,argv) != true)
|
|
die("unable to process command line.\n");
|
|
|
|
LOG("Initializing NKC...");
|
|
nkc_init();
|
|
|
|
LOG("Initializing plotters...");
|
|
plot_init(nsoption_charp(atari_font_driver));
|
|
|
|
aes_event_in.emi_m1leave = MO_LEAVE;
|
|
aes_event_in.emi_m1.g_w = 1;
|
|
aes_event_in.emi_m1.g_h = 1;
|
|
//next_poll = clock() + (CLOCKS_PER_SEC>>3);
|
|
|
|
deskmenu_init();
|
|
menu_register( -1, theapp);
|
|
if (sys_type() & (SYS_MAGIC|SYS_NAES|SYS_XAAES)) {
|
|
menu_register( _AESapid, (char*)" NetSurf ");
|
|
}
|
|
gemtk_wm_init();
|
|
|
|
/* Initialize the specific treeview windows: */
|
|
atari_global_history_init();
|
|
atari_hotlist_init();
|
|
atari_cookie_manager_init();
|
|
|
|
/* Initialize the toolbar framework: */
|
|
toolbar_init();
|
|
}
|
|
|
|
static struct gui_window_table atari_window_table = {
|
|
.create = gui_window_create,
|
|
.destroy = gui_window_destroy,
|
|
.redraw = gui_window_redraw_window,
|
|
.update = gui_window_update_box,
|
|
.get_scroll = gui_window_get_scroll,
|
|
.set_scroll = gui_window_set_scroll,
|
|
.get_dimensions = gui_window_get_dimensions,
|
|
.update_extent = gui_window_update_extent,
|
|
.reformat = atari_window_reformat,
|
|
|
|
.set_title = gui_window_set_title,
|
|
.set_url = gui_window_set_url,
|
|
.set_icon = gui_window_set_icon,
|
|
.set_status = atari_window_set_status,
|
|
.set_pointer = gui_window_set_pointer,
|
|
.place_caret = gui_window_place_caret,
|
|
.remove_caret = gui_window_remove_caret,
|
|
.new_content = gui_window_new_content,
|
|
.start_throbber = gui_window_start_throbber,
|
|
.stop_throbber = gui_window_stop_throbber,
|
|
};
|
|
|
|
static struct gui_clipboard_table atari_clipboard_table = {
|
|
.get = gui_get_clipboard,
|
|
.set = gui_set_clipboard,
|
|
};
|
|
|
|
static struct gui_fetch_table atari_fetch_table = {
|
|
.filetype = fetch_filetype,
|
|
|
|
.get_resource_url = gui_get_resource_url,
|
|
};
|
|
|
|
static struct gui_misc_table atari_misc_table = {
|
|
.schedule = atari_schedule,
|
|
.warning = atari_warn_user,
|
|
|
|
.quit = gui_quit,
|
|
.cert_verify = gui_cert_verify,
|
|
.login = gui_401login_open,
|
|
};
|
|
|
|
/* #define WITH_DBG_LOGFILE 1 */
|
|
/**
|
|
* Entry point from OS.
|
|
*
|
|
* /param argc The number of arguments in the string vector.
|
|
* /param argv The argument string vector.
|
|
* /return The return code to the OS
|
|
*/
|
|
int main(int argc, char** argv)
|
|
{
|
|
char messages[PATH_MAX];
|
|
char store[PATH_MAX];
|
|
const char *addr;
|
|
char * file_url = NULL;
|
|
struct stat stat_buf;
|
|
nsurl *url;
|
|
nserror ret;
|
|
|
|
struct netsurf_table atari_table = {
|
|
.misc = &atari_misc_table,
|
|
.window = &atari_window_table,
|
|
.clipboard = &atari_clipboard_table,
|
|
.download = atari_download_table,
|
|
.fetch = &atari_fetch_table,
|
|
.file = atari_file_table,
|
|
.utf8 = atari_utf8_table,
|
|
.search = atari_search_table,
|
|
.llcache = filesystem_llcache_table,
|
|
.bitmap = atari_bitmap_table,
|
|
.layout = atari_layout_table
|
|
};
|
|
|
|
ret = netsurf_register(&atari_table);
|
|
if (ret != NSERROR_OK) {
|
|
die("NetSurf operation table failed registration");
|
|
}
|
|
|
|
/** @todo logging file descriptor update belongs in a nslog_init callback */
|
|
setbuf(stderr, NULL);
|
|
setbuf(stdout, NULL);
|
|
#ifdef WITH_DBG_LOGFILE
|
|
freopen("stdout.log", "a+", stdout);
|
|
freopen("stderr.log", "a+", stderr);
|
|
#endif
|
|
|
|
graf_mouse(BUSY_BEE, NULL);
|
|
|
|
init_app(NULL);
|
|
|
|
init_os_info();
|
|
|
|
atari_find_resource((char*)&messages, "messages", "res/messages");
|
|
atari_find_resource((char*)&options, "Choices", "Choices");
|
|
atari_find_resource((char*)&store, "cache", "res/cache");
|
|
|
|
/* initialise logging - not fatal if it fails but not much we can
|
|
* do about it
|
|
*/
|
|
nslog_init(NULL, &argc, argv);
|
|
|
|
/* user options setup */
|
|
ret = nsoption_init(set_defaults, &nsoptions, &nsoptions_default);
|
|
if (ret != NSERROR_OK) {
|
|
die("Options failed to initialise");
|
|
}
|
|
nsoption_read(options, NULL);
|
|
nsoption_commandline(&argc, argv, NULL);
|
|
|
|
ret = messages_add_from_file(messages);
|
|
|
|
/* common initialisation */
|
|
LOG("Initialising core...");
|
|
ret = netsurf_init(store);
|
|
if (ret != NSERROR_OK) {
|
|
die("NetSurf failed to initialise");
|
|
}
|
|
|
|
LOG("Initializing GUI...");
|
|
gui_init(argc, argv);
|
|
|
|
graf_mouse( ARROW , NULL);
|
|
|
|
LOG("Creating initial browser window...");
|
|
addr = option_homepage_url;
|
|
if (strncmp(addr, "file://", 7) && strncmp(addr, "http://", 7)) {
|
|
if (stat(addr, &stat_buf) == 0) {
|
|
file_url = local_file_to_url(addr);
|
|
addr = file_url;
|
|
}
|
|
}
|
|
|
|
/* create an initial browser window */
|
|
ret = nsurl_create(addr, &url);
|
|
if (ret == NSERROR_OK) {
|
|
ret = browser_window_create(BW_CREATE_HISTORY,
|
|
url,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
nsurl_unref(url);
|
|
}
|
|
if (ret != NSERROR_OK) {
|
|
atari_warn_user(messages_get_errorcode(ret), 0);
|
|
} else {
|
|
LOG("Entering Atari event mainloop...");
|
|
while (!atari_quit) {
|
|
atari_poll();
|
|
}
|
|
}
|
|
|
|
netsurf_exit();
|
|
|
|
free(file_url);
|
|
|
|
#ifdef WITH_DBG_LOGFILE
|
|
fclose(stdout);
|
|
fclose(stderr);
|
|
#endif
|
|
LOG("exit_gem");
|
|
exit_gem();
|
|
|
|
return 0;
|
|
}
|