From d21447d096a320a08b3efb2b8768fad0dcdcfd64 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Thu, 5 May 2016 22:28:51 +0100 Subject: move frontends into sub directory --- frontends/atari/rootwin.c | 1540 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1540 insertions(+) create mode 100644 frontends/atari/rootwin.c (limited to 'frontends/atari/rootwin.c') diff --git a/frontends/atari/rootwin.c b/frontends/atari/rootwin.c new file mode 100644 index 000000000..605ce45ae --- /dev/null +++ b/frontends/atari/rootwin.c @@ -0,0 +1,1540 @@ +/* + * Copyright 2010 Ole Loots + * + * 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 . + * + * Module Description: + * + * This File implements the NetSurf Browser window, or passed functionality to + * the appropriate widget's. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "utils/log.h" +#include "desktop/browser.h" +#include "desktop/mouse.h" +#include "desktop/plotters.h" +#include "desktop/textinput.h" +#include "content/content.h" +#include "content/hlcache.h" +#include "content/urldb.h" + +#include "atari/res/netsurf.rsh" +#include "atari/gemtk/gemtk.h" +#include "atari/ctxmenu.h" +#include "atari/gui.h" +#include "atari/rootwin.h" +#include "atari/misc.h" +#include "atari/plot/plot.h" +#include "atari/toolbar.h" +#include "atari/statusbar.h" +#include "atari/search.h" +#include "atari/osspec.h" +#include "atari/encoding.h" +#include "atari/redrawslots.h" +#include "atari/toolbar.h" +#include "atari/findfile.h" +#include "atari/bitmap.h" + +extern struct gui_window *input_window; +extern EVMULT_OUT aes_event_out; +extern GRECT desk_area; + +struct rootwin_data_s { + struct s_gui_win_root *rootwin; +}; + +/* -------------------------------------------------------------------------- */ +/* Static module event handlers */ +/* -------------------------------------------------------------------------- */ +static void on_redraw(ROOTWIN *rootwin, short msg[8]); +static void on_resized(ROOTWIN *rootwin); +static void on_file_dropped(ROOTWIN *rootwin, short msg[8]); +static short on_window_key_input(ROOTWIN * rootwin, unsigned short nkc); +static void on_content_mouse_click(ROOTWIN *rootwin); +static void on_content_mouse_move(ROOTWIN *rootwin, GRECT *content_area); +static void toolbar_redraw_cb(GUIWIN *win, uint16_t msg, GRECT *clip); + +bool gui_window_get_scroll(struct gui_window *w, int *sx, int *sy); + +static bool redraw_active = false; + +static const struct redraw_context rootwin_rdrw_ctx = { + .interactive = true, + .background_images = true, + .plot = &atari_plotters +}; + +static short handle_event(GUIWIN *win, EVMULT_OUT *ev_out, short msg[8]) +{ + short retval = 0; + GRECT area; + static bool prev_url = false; + struct rootwin_data_s * data = gemtk_wm_get_user_data(win); + struct gui_window *tmp; + + + if ((ev_out->emo_events & MU_MESAG) != 0) { + // handle message + //printf("root win msg: %d\n", msg[0]); + switch (msg[0]) { + + case WM_REDRAW: + LOG("WM_REDRAW"); + on_redraw(data->rootwin, msg); + break; + + case WM_REPOSED: + case WM_SIZED: + case WM_MOVED: + case WM_FULLED: + LOG("WM_SIZED"); + on_resized(data->rootwin); + break; + + case WM_ICONIFY: + // TODO: find next active gui window and schedule redraw for that. + tmp = window_list; + while(tmp != NULL){ + if(tmp->root != data->rootwin){ + gemtk_wm_send_msg(tmp->root->win, WM_TOPPED, 0, 0, 0, 0); + break; + } + tmp = tmp->next; + } + break; + + case WM_TOPPED: + case WM_NEWTOP: + case WM_UNICONIFY: + LOG("WM_TOPPED"); + gui_set_input_gui_window(data->rootwin->active_gui_window); + //window_restore_active_gui_window(data->rootwin); + // TODO: use something like "restore_active_gui_window_state()" + + break; + + case WM_CLOSED: + // TODO: this needs to iterate through all gui windows and + // check if the rootwin is this window... + if (data->rootwin->active_gui_window != NULL) { + LOG("WM_CLOSED initiated destroy for bw %p", data->rootwin->active_gui_window->browser->bw); + browser_window_destroy( + data->rootwin->active_gui_window->browser->bw); + } + break; + + case AP_DRAGDROP: + on_file_dropped(data->rootwin, msg); + break; + + case WM_TOOLBAR: + toolbar_mouse_input(data->rootwin->toolbar, msg[4], msg[7]); + break; + + default: + break; + } + } + if ((ev_out->emo_events & MU_KEYBD) != 0) { + + // handle key + uint16_t nkc = gem_to_norm( (short)ev_out->emo_kmeta, + (short)ev_out->emo_kreturn); + LOG("rootwin MU_KEYBD input, nkc: %x\n", nkc); + retval = on_window_key_input(data->rootwin, nkc); + // printf("on_window_key_input: %d\n", retval); + + } + if ((ev_out->emo_events & MU_BUTTON) != 0) { + LOG("rootwin MU_BUTTON input, x: %d, y: %d\n", ev_out->emo_mouse.p_x, ev_out->emo_mouse.p_x); + window_get_grect(data->rootwin, BROWSER_AREA_CONTENT, + &area); + if (POINT_WITHIN(ev_out->emo_mouse.p_x, ev_out->emo_mouse.p_y, + area)) { + on_content_mouse_click(data->rootwin); + } + } + if ((ev_out->emo_events & (MU_M1)) != 0) { + + short ghandle = wind_find(ev_out->emo_mouse.p_x, ev_out->emo_mouse.p_y); + + if (data->rootwin->aes_handle==ghandle) { + // The window found at x,y is an gui_window + // and it's the input window. + window_get_grect(data->rootwin, BROWSER_AREA_CONTENT, + &area); + if (POINT_WITHIN(ev_out->emo_mouse.p_x, ev_out->emo_mouse.p_y, + area)) { + on_content_mouse_move(data->rootwin, &area); + } else { + GRECT tb_area; + window_get_grect(data->rootwin, BROWSER_AREA_URL_INPUT, &tb_area); + if (POINT_WITHIN(ev_out->emo_mouse.p_x, ev_out->emo_mouse.p_y, + tb_area)) { + gem_set_cursor(&gem_cursors.ibeam); + prev_url = true; + } else { + if(prev_url) { + struct gui_window *gw; + gw = window_get_active_gui_window(data->rootwin); + gem_set_cursor(gw->cursor); + prev_url = false; + } + } + } + } + } + + return(retval); +} + +/* -------------------------------------------------------------------------- */ +/* Module public functions: */ +/* -------------------------------------------------------------------------- */ + +int window_create(struct gui_window * gw, + struct browser_window * bw, + struct gui_window * existing, + unsigned long inflags) +{ + int err = 0; + bool tb, sb; + int flags; + struct rootwin_data_s *data; + struct gemtk_wm_scroll_info_s *slid; + + tb = (inflags & WIDGET_TOOLBAR); + sb = (inflags & WIDGET_STATUSBAR); + + flags = CLOSER | MOVER | NAME | FULLER | SMALLER; + if( inflags & WIDGET_SCROLL ) { + flags |= (UPARROW | DNARROW | LFARROW | RTARROW | VSLIDE | HSLIDE); + } + if( inflags & WIDGET_RESIZE ) { + flags |= ( SIZER ); + } + if( inflags & WIDGET_STATUSBAR ) { + flags |= ( INFO ); + } + + gw->root = malloc(sizeof(struct s_gui_win_root)); + if (gw->root == NULL) + return(-1); + memset(gw->root, 0, sizeof(struct s_gui_win_root) ); + gw->root->title = malloc(atari_sysinfo.aes_max_win_title_len+1); + + redraw_slots_init(&gw->root->redraw_slots, 8); + + gw->root->aes_handle = wind_create(flags, 40, 40, desk_area.g_w, + desk_area.g_h); + if(gw->root->aes_handle<0) { + free(gw->root->title); + free(gw->root); + return( -1 ); + } + gw->root->win = gemtk_wm_add(gw->root->aes_handle, + GEMTK_WM_FLAG_PREPROC_WM | GEMTK_WM_FLAG_RECV_PREPROC_WM, handle_event); + + data = malloc(sizeof(struct rootwin_data_s)); + data->rootwin = gw->root; + gemtk_wm_set_user_data(gw->root->win, (void*)data); + slid = gemtk_wm_get_scroll_info(gw->root->win); + slid->y_unit_px = 32; + slid->x_unit_px = 32; + + /* create */ + if(tb) { + gw->root->toolbar = toolbar_create(gw->root); + assert(gw->root->toolbar); + gemtk_wm_set_toolbar(gw->root->win, gw->root->toolbar->form, 0, 0); + gemtk_wm_set_toolbar_redraw_func(gw->root->win, toolbar_redraw_cb); + } else { + gw->root->toolbar = NULL; + } + + /* create browser component: */ + gw->browser = (struct s_browser *)malloc( sizeof(struct s_browser)); + + assert(gw->browser); + + gw->browser->bw = bw; + gw->scale = browser_window_get_scale(bw); + + + /* create statusbar component: */ + if(sb) { + gw->root->statusbar = sb_create( gw ); + } else { + gw->root->statusbar = NULL; + } + + // Setup some window defaults: + wind_set_str(gw->root->aes_handle, WF_NAME, (char*)"NetSurf"); + wind_set(gw->root->aes_handle, WF_OPTS, 1, WO0_FULLREDRAW, 0, 0); + wind_set(gw->root->aes_handle, WF_OPTS, 1, WO0_NOBLITW, 0, 0); + wind_set(gw->root->aes_handle, WF_OPTS, 1, WO0_NOBLITH, 0, 0); + + if (inflags & WIN_TOP) { + window_set_focus(gw->root, BROWSER, gw->browser); + } + + return (err); +} + +void window_unref_gui_window(ROOTWIN *rootwin, struct gui_window *gw) +{ + struct gui_window *w; + input_window = NULL; + + LOG("window: %p, gui_window: %p", rootwin, gw); + + w = window_list; + // find the next active tab: + while( w != NULL ) { + if(w->root == rootwin && w != gw) { + LOG("activating next tab %p", w); + gui_set_input_gui_window(w); + break; + } + w = w->next; + } + if(input_window == NULL) { + // the last gui window for this rootwin was removed: + redraw_slots_free(&rootwin->redraw_slots); + window_destroy(rootwin); + } +} + +int window_destroy(ROOTWIN *rootwin) +{ + int err = 0; + struct gui_window *w; + + assert(rootwin != NULL); + + LOG("%p", rootwin); + + if (gemtk_wm_get_user_data(rootwin->win) != NULL) { + free(gemtk_wm_get_user_data(rootwin->win)); + } + + // make sure we do not destroy windows which have gui_windows attached: + w = window_list; + while( w != NULL ) { + if(w->root == rootwin) { + assert(rootwin == NULL); + } + w = w->next; + } + + if (rootwin->toolbar) + toolbar_destroy(rootwin->toolbar); + + if(rootwin->statusbar) + sb_destroy(rootwin->statusbar); + + if(rootwin->title) + free(rootwin->title); + + gemtk_wm_remove(rootwin->win); + wind_close(rootwin->aes_handle); + wind_delete(rootwin->aes_handle); + free(rootwin); + return(err); +} + + +void window_open(ROOTWIN *rootwin, struct gui_window *gw, GRECT pos) +{ + GRECT g; + + rootwin->active_gui_window = gw; + + assert(rootwin->active_gui_window != NULL); + + wind_open(rootwin->aes_handle, pos.g_x, pos.g_y, pos.g_w, pos.g_h ); + wind_set_str(rootwin->aes_handle, WF_NAME, (char *)""); + + rootwin->active_gui_window->browser->attached = true; + if(rootwin->statusbar != NULL) { + sb_attach(rootwin->statusbar, rootwin->active_gui_window); + } + + /* Set initial size of the toolbar region: */ + gemtk_wm_get_grect(rootwin->win, GEMTK_WM_AREA_TOOLBAR, &g); + toolbar_set_attached(rootwin->toolbar, true); + toolbar_set_dimensions(rootwin->toolbar, &g); + + /* initially hide the search area of the toolbar: */ + window_close_search(rootwin); + + window_update_back_forward(rootwin); + + window_set_focus(rootwin, BROWSER, rootwin->active_gui_window->browser); +} + +void window_restore_active_gui_window(ROOTWIN *rootwin) +{ + GRECT tb_area; + struct gui_window *gw; + + LOG("rootwin %p", rootwin); + + assert(rootwin->active_gui_window); + + gw = rootwin->active_gui_window; + + window_set_icon(rootwin, gw->icon); + window_set_stauts(rootwin, gw->status); + window_set_title(rootwin, gw->title); + + if (gw->search != NULL) { + // TODO: update search session (especially browser window) + } + + toolbar_get_grect(rootwin->toolbar, 0, &tb_area); + gemtk_wm_set_toolbar_size(rootwin->win, tb_area.g_h); + + window_update_back_forward(rootwin); + + toolbar_set_url(rootwin->toolbar, gw->url); +} + + +/* update back forward buttons (see tb_update_buttons (bug) ) */ +void window_update_back_forward(struct s_gui_win_root *rootwin) +{ + struct gui_window * active_gw = rootwin->active_gui_window; + toolbar_update_buttons(rootwin->toolbar, active_gw->browser->bw, -1); +} + +void window_set_stauts(struct s_gui_win_root *rootwin, char * text) +{ + assert(rootwin != NULL); + + CMP_STATUSBAR sb = rootwin->statusbar; + + if( sb == NULL) + return; + + if(text != NULL) + sb_set_text(sb, text); + else + sb_set_text(sb, ""); +} + +void window_set_title(struct s_gui_win_root * rootwin, char *title) +{ + wind_set_str(rootwin->aes_handle, WF_NAME, title); +} + +void window_scroll_by(ROOTWIN *root, int sx, int sy) +{ + struct gemtk_wm_scroll_info_s *slid = gemtk_wm_get_scroll_info(root->win); + + if (sx < 0) { + sx = 0; + } + if (sy < 0) { + sy = 0; + } + int xunits = sx / slid->x_unit_px; + int yunits = sy / slid->y_unit_px; + + gemtk_wm_scroll(root->win, GEMTK_WM_VSLIDER, yunits - slid->y_pos, false); + gemtk_wm_scroll(root->win, GEMTK_WM_HSLIDER, xunits - slid->x_pos, false); + gemtk_wm_update_slider(root->win, GEMTK_WM_VH_SLIDER); +} + +/** +* Set the dimensions of the scrollable content. +* +*/ +void window_set_content_size(ROOTWIN *rootwin, int width, int height) +{ + GRECT area; + struct gemtk_wm_scroll_info_s *slid = gemtk_wm_get_scroll_info(rootwin->win); + + window_get_grect(rootwin, BROWSER_AREA_CONTENT, &area); + + slid->x_units = (width/slid->x_unit_px); + slid->y_units = (height/slid->y_unit_px); + if(slid->x_units < slid->x_pos) + slid->x_pos = 0; + if(slid->y_units < slid->y_pos) + slid->y_pos = 0; + gemtk_wm_update_slider(rootwin->win, GEMTK_WM_VH_SLIDER); +} + +/* set focus to an arbitary element */ +void window_set_focus(struct s_gui_win_root *rootwin, + enum focus_element_type type, void * element) +{ + assert(rootwin != NULL); + + if (rootwin->focus.type != type || rootwin->focus.element != element) { + LOG("Set focus: %p (%d)\n", element, type); + rootwin->focus.type = type; + rootwin->focus.element = element; + switch( type ) { + + case URL_WIDGET: + // TODO: make something like: toolbar_text_select_all(); + toolbar_key_input(rootwin->toolbar, (short)(NKF_CTRL | 'A') ); +/* + ta = toolbar_get_textarea(rootwin->toolbar, + URL_INPUT_TEXT_AREA); + textarea_keypress(ta, NS_KEY_SELECT_ALL); + */ + break; + + case SEARCH_INPUT: + gemtk_wm_set_toolbar_edit_obj(rootwin->win, TOOLBAR_TB_SRCH, 0); + break; + + default: + break; + + } + } +} + +/* check if the url widget has focus */ +bool window_url_widget_has_focus(struct s_gui_win_root *rootwin) +{ + assert(rootwin != NULL); + + if (rootwin->focus.type == URL_WIDGET) { + return true; + } + return false; +} + +/* check if an arbitary window widget / or frame has the focus */ +bool window_widget_has_focus(struct s_gui_win_root *rootwin, + enum focus_element_type t, void * element) +{ + assert(rootwin != NULL); + if( element == NULL ) { + return((rootwin->focus.type == t)); + } + + return((element == rootwin->focus.element && t == rootwin->focus.type)); +} + +void window_set_icon(ROOTWIN *rootwin, struct bitmap * bmp ) +{ + rootwin->icon = bmp; + /* redraw window when it is iconyfied: */ + if (rootwin->icon != NULL) { + if (gemtk_wm_get_state(rootwin->win) & GEMTK_WM_STATUS_ICONIFIED) { + window_redraw_favicon(rootwin, NULL); + } + } +} + +void window_set_active_gui_window(ROOTWIN *rootwin, struct gui_window *gw) +{ + struct gui_window *old_gw = rootwin->active_gui_window; + + LOG("gw %p",gw); + + if (rootwin->active_gui_window != NULL) { + if(rootwin->active_gui_window == gw) { + LOG("nothing to do..."); + return; + } + } + + // TODO: when the window isn't on top, initiate WM_TOPPED. + + rootwin->active_gui_window = gw; + if (old_gw != NULL) { + LOG("restoring window..."); + window_restore_active_gui_window(rootwin); + } +} + +struct gui_window * window_get_active_gui_window(ROOTWIN * rootwin) +{ + return(rootwin->active_gui_window); +} + +void window_get_scroll(ROOTWIN *rootwin, int *x, int *y) +{ + struct gemtk_wm_scroll_info_s *slid; + + slid = gemtk_wm_get_scroll_info(rootwin->win); + + *x = slid->x_pos * slid->x_unit_px; + *y = slid->y_pos * slid->y_unit_px; +} + +void window_get_grect(ROOTWIN *rootwin, enum browser_area_e which, GRECT *d) +{ + + d->g_x = 0; + d->g_y = 0; + d->g_w = 0; + d->g_h = 0; + + if (which == BROWSER_AREA_TOOLBAR) { + // gemtk_wm_get_grect(rootwin->win, GEMTK_WM_AREA_TOOLBAR, d); + toolbar_get_grect(rootwin->toolbar, 0, d); + + } else if (which == BROWSER_AREA_CONTENT) { + + GRECT tb_area; + + gemtk_wm_get_grect(rootwin->win, GEMTK_WM_AREA_WORK, d); + toolbar_get_grect(rootwin->toolbar, 0, &tb_area); + + d->g_y += tb_area.g_h; + d->g_h -= tb_area.g_h; + + } else if (which == BROWSER_AREA_URL_INPUT) { + + toolbar_get_grect(rootwin->toolbar, TOOLBAR_AREA_URL, d); + + } else if (which == BROWSER_AREA_SEARCH) { + // todo: check if search is visible + toolbar_get_grect(rootwin->toolbar, TOOLBAR_AREA_SEARCH, d); + } else { + + } + + + // sanitize the results + if (d->g_h < 0) { + d->g_h = 0; + } + if (d->g_w < 0) { + d->g_w = 0; + } + + //printf("window_get_grect %d:", which); + //dbg_grect("", d); + +} + + +void window_open_search(ROOTWIN *rootwin, bool reformat) +{ + struct browser_window *bw; + struct gui_window *gw; + GRECT area; + OBJECT *obj; + + LOG("rootwin %p", rootwin); + + gw = rootwin->active_gui_window; + bw = gw->browser->bw; + obj = toolbar_get_form(rootwin->toolbar); + + if (gw->search == NULL) { + gw->search = nsatari_search_session_create(obj, gw); + } + + toolbar_set_visible(rootwin->toolbar, TOOLBAR_AREA_SEARCH, true); + window_get_grect(rootwin, BROWSER_AREA_TOOLBAR, &area); + gemtk_wm_set_toolbar_size(rootwin->win, area.g_h); + window_get_grect(rootwin, BROWSER_AREA_SEARCH, &area); + window_schedule_redraw_grect(rootwin, &area); + window_process_redraws(rootwin); + window_set_focus(rootwin, SEARCH_INPUT, NULL); + + window_get_grect(rootwin, BROWSER_AREA_CONTENT, &area); + if (reformat) { + browser_window_reformat(bw, false, area.g_w, area.g_h); + } +} + +void window_close_search(ROOTWIN *rootwin) +{ + struct browser_window *bw; + struct gui_window *gw; + GRECT area; + OBJECT *obj; + + + gw = rootwin->active_gui_window; + bw = gw->browser->bw; + obj = gemtk_obj_get_tree(TOOLBAR); + + if (gw->search != NULL) { + nsatari_search_session_destroy(gw->search); + gw->search = NULL; + } + + toolbar_set_visible(rootwin->toolbar, TOOLBAR_AREA_SEARCH, false); + window_get_grect(rootwin, BROWSER_AREA_TOOLBAR, &area); + gemtk_wm_set_toolbar_size(rootwin->win, area.g_h); + window_get_grect(rootwin, BROWSER_AREA_CONTENT, &area); + browser_window_reformat(bw, false, area.g_w, area.g_h); +} + +/** + * Redraw the favicon +*/ +void window_redraw_favicon(ROOTWIN *rootwin, GRECT *clip_ro) +{ + GRECT work, visible, clip; + + assert(rootwin); + + //printf("window_redraw_favicon: root: %p, win: %p\n", rootwin, rootwin->win); + + gemtk_wm_clear(rootwin->win); + gemtk_wm_get_grect(rootwin->win, GEMTK_WM_AREA_WORK, &work); + + if (clip_ro == NULL) { + clip = work; + } else { + clip = *clip_ro; + if(!rc_intersect(&work, &clip)) { + return; + } + } + + //dbg_grect("favicon redrw area", clip); + //dbg_grect("favicon work area", &work); + + if (rootwin->icon == NULL) { + //printf("window_redraw_favicon OBJCTREE\n"); + + OBJECT * tree = gemtk_obj_get_tree(ICONIFY); + tree->ob_x = work.g_x; + tree->ob_y = work.g_y; + tree->ob_width = work.g_w; + tree->ob_height = work.g_h; + + wind_get_grect(rootwin->aes_handle, WF_FIRSTXYWH, &visible); + while (visible.g_h > 0 && visible.g_w > 0) { + + if (rc_intersect(&clip, &visible)) { + //dbg_grect("redraw vis area", &visible); + objc_draw(tree, 0, 8, visible.g_x, visible.g_y, visible.g_w, + visible.g_h); + } else { + //dbg_grect("redraw vis area outside", &visible); + } + + wind_get_grect(rootwin->aes_handle, WF_NEXTXYWH, &visible); + } + + } else { + //printf("window_redraw_favicon image %p\n", rootwin->icon); + VdiHdl plot_vdi_handle = plot_get_vdi_handle(); + short pxy[4]; + int xoff=0; + + if (work.g_w > work.g_h) { + xoff = ((work.g_w-work.g_h)/2); + work.g_w = work.g_h; + } + plot_set_dimensions( work.g_x+xoff, work.g_y, work.g_w, + work.g_h); + + wind_get_grect(rootwin->aes_handle, WF_FIRSTXYWH, &visible); + while (visible.g_h > 0 && visible.g_w > 0) { + + if (rc_intersect(&clip, &visible)) { + + //dbg_grect("redraw vis area", &visible); + + // Manually clip drawing region: + pxy[0] = visible.g_x; + pxy[1] = visible.g_y; + pxy[2] = pxy[0] + visible.g_w-1; + pxy[3] = pxy[1] + visible.g_h-1; + vs_clip(plot_vdi_handle, 1, (short*)&pxy); + //dbg_pxy("vdi clip", (short*)&pxy); + + atari_plotters.bitmap(0, 0, work.g_w, work.g_h, + rootwin->icon, 0xffffff, 0); + } else { + //dbg_grect("redraw vis area outside", &visible); + } + + wind_get_grect(rootwin->aes_handle, WF_NEXTXYWH, &visible); + } + } +} + +/*** +* Schedule an redraw area, redraw requests during redraw are +* not optimized (merged) into other areas, so that the redraw +* functions can spot the change. +* +*/ +void window_schedule_redraw_grect(ROOTWIN *rootwin, GRECT *area) +{ + GRECT work; + + + //dbg_grect("window_schedule_redraw_grect input ", area); + + gemtk_wm_get_grect(rootwin->win, GEMTK_WM_AREA_WORK, &work); + if(!rc_intersect(area, &work)) + return; + + //dbg_grect("window_schedule_redraw_grect intersection ", &work); + + redraw_slot_schedule_grect(&rootwin->redraw_slots, &work, redraw_active); +} + +static void window_redraw_content(ROOTWIN *rootwin, GRECT *content_area, + GRECT *clip, + struct gemtk_wm_scroll_info_s * slid, + struct browser_window *bw) +{ + + struct rect redraw_area; + GRECT content_area_rel; + float oldscale = 1.0; + + //dbg_grect("browser redraw, content area", content_area); + //dbg_grect("browser redraw, content clip", clip); + + plot_set_dimensions(content_area->g_x, content_area->g_y, + content_area->g_w, content_area->g_h); + oldscale = plot_set_scale(browser_window_get_scale(rootwin->active_gui_window->browser->bw)); + + /* first, we make the coords relative to the content area: */ + content_area_rel.g_x = clip->g_x - content_area->g_x; + content_area_rel.g_y = clip->g_y - content_area->g_y; + content_area_rel.g_w = clip->g_w; + content_area_rel.g_h = clip->g_h; + + if (content_area_rel.g_x < 0) { + content_area_rel.g_w += content_area_rel.g_x; + content_area_rel.g_x = 0; + } + + if (content_area_rel.g_y < 0) { + content_area_rel.g_h += content_area_rel.g_y; + content_area_rel.g_y = 0; + } + + //dbg_grect("browser redraw, relative plot coords:", &content_area_rel); + + redraw_area.x0 = content_area_rel.g_x; + redraw_area.y0 = content_area_rel.g_y; + redraw_area.x1 = content_area_rel.g_x + content_area_rel.g_w; + redraw_area.y1 = content_area_rel.g_y + content_area_rel.g_h; + + plot_clip(&redraw_area); + + //dbg_rect("rdrw area", &redraw_area); + + browser_window_redraw( bw, -(slid->x_pos*slid->x_unit_px), + -(slid->y_pos*slid->y_unit_px), &redraw_area, &rootwin_rdrw_ctx); + + plot_set_scale(oldscale); +} + + +void window_place_caret(ROOTWIN *rootwin, short mode, int content_x, + int content_y, int h, GRECT *work) +{ + struct s_caret *caret = &rootwin->caret; + VdiHdl vh = gemtk_wm_get_vdi_handle(rootwin->win); + short pxy[8]; + GRECT mywork, caret_pos; + MFDB screen; + int scroll_x, scroll_y; + uint16_t *fd_addr; + struct gemtk_wm_scroll_info_s *slid; + short colors[2] = {G_BLACK, G_WHITE}; + bool render_required = false; + + // avoid duplicate draw of the caret: + if (mode == 1 &&(caret->state&CARET_STATE_VISIBLE)!=0) { + if (caret->dimensions.g_x == content_x + && caret->dimensions.g_y == content_y + && caret->dimensions.g_h == h) { + return; + } + } + + if(work == NULL) { + window_get_grect(rootwin, BROWSER_AREA_CONTENT, &mywork); + work = &mywork; + } + slid = gemtk_wm_get_scroll_info(rootwin->win); + + scroll_x = slid->x_pos * slid->x_unit_px; + scroll_y = slid->y_pos * slid->y_unit_px; + + init_mfdb(0, 1, h, 0, &screen); + + // enable clipping: + pxy[0] = work->g_x; + pxy[1] = work->g_y; + pxy[2] = pxy[0] + work->g_w - 1; + pxy[3] = pxy[1] + work->g_h - 1; + vs_clip(vh, 1, pxy); + + // when the caret is visible, undraw it: + if (caret->symbol.fd_addr != NULL + && (caret->state&CARET_STATE_VISIBLE)!=0) { + + caret_pos.g_x = work->g_x + (caret->dimensions.g_x - scroll_x); + caret_pos.g_y = work->g_y + (caret->dimensions.g_y - scroll_y); + caret_pos.g_w = caret->dimensions.g_w; + caret_pos.g_h = caret->dimensions.g_h; + + if (rc_intersect(work, &caret_pos)) { + + pxy[0] = 0; + pxy[1] = 0; + pxy[2] = caret->dimensions.g_w-1; + pxy[3] = caret->dimensions.g_h-1; + + pxy[4] = caret_pos.g_x; + pxy[5] = caret_pos.g_y; + pxy[6] = pxy[4] + caret_pos.g_w-1; + pxy[7] = pxy[5] + caret_pos.g_h-1; + + vrt_cpyfm(vh, MD_XOR, pxy, &caret->symbol, &screen, colors); + } + } + if (mode == 0) { + // update state: + caret->state &= ~CARET_STATE_VISIBLE; + goto exit; + } + + // when the caret isn't allocated, create it: + if (caret->symbol.fd_addr == NULL) { + caret->fd_size = init_mfdb(1, 16, h, MFDB_FLAG_ZEROMEM, + &caret->symbol); + render_required = true; + } else { + // the caret may need more memory: + if (caret->dimensions.g_h < h) { + caret->fd_size = init_mfdb(1, 16, h, MFDB_FLAG_NOALLOC, + &caret->symbol); + realloc(caret->symbol.fd_addr, caret->fd_size); + render_required = true; + } + } + + // set new caret position: + caret->dimensions.g_x = content_x; + caret->dimensions.g_y = content_y; + caret->dimensions.g_w = 1; + caret->dimensions.g_h = h; + + // draw the caret into the mfdb buffer: + if (render_required) { + int i; + + assert(caret->symbol.fd_nplanes == 1); + assert(caret->symbol.fd_w == 16); + + // draw an vertical line into the mfdb buffer + fd_addr = (uint16_t*)caret->symbol.fd_addr; + for(i = 0; isymbol.fd_h; i++) { + fd_addr[i] = 0xFFFF; + } + } + + // convert content coords to screen coords: + + caret_pos.g_x = work->g_x + (content_x - scroll_x); + caret_pos.g_y = work->g_y + (content_y - scroll_y); + caret_pos.g_w = caret->dimensions.g_w; + caret_pos.g_h = caret->dimensions.g_h; + + if (rc_intersect(work, &caret_pos) && redraw_active == false) { + + pxy[0] = 0; + pxy[1] = 0; + pxy[2] = caret->dimensions.g_w-1; + pxy[3] = caret->dimensions.g_h-1; + + pxy[4] = caret_pos.g_x; + pxy[5] = caret_pos.g_y; + pxy[6] = pxy[4] + caret_pos.g_w-1; + pxy[7] = pxy[5] + caret_pos.g_h-1; + + //dbg_pxy("caret screen coords (md_repl)", &pxy[4]); + + // TODO: walk rectangle list (use MD_REPLACE then) + // draw caret to screen coords: + vrt_cpyfm(vh, /*MD_REPLACE*/ MD_XOR, pxy, &caret->symbol, &screen, colors); + + // update state: + caret->state |= CARET_STATE_VISIBLE; + } + +exit: + // disable clipping: + vs_clip(gemtk_wm_get_vdi_handle(rootwin->win), 0, pxy); +} + +void window_process_redraws(ROOTWIN * rootwin) +{ + GRECT visible_ro, tb_area, content_area; + short i; + short scroll_x=0, scroll_y=0; + bool caret_rdrw_required = false; + struct gemtk_wm_scroll_info_s *slid =NULL; + int caret_h = 0; + struct s_caret *caret = &rootwin->caret; + + redraw_active = true; + + window_get_grect(rootwin, BROWSER_AREA_TOOLBAR, &tb_area); + //gemtk_wm_set_toolbar_size(rootwin->win, tb_area.g_h); + window_get_grect(rootwin, BROWSER_AREA_CONTENT, &content_area); + + //dbg_grect("content area", &content_area); + //dbg_grect("window_process_redraws toolbar area", &tb_area); + + while(plot_lock() == false); + + if (((rootwin->caret.state & CARET_STATE_ENABLED)!=0) + && rootwin->caret.dimensions.g_h > 0) { + // hide caret: + window_place_caret(rootwin, 0, -1, -1, -1, &content_area); + } +/* + short pxy_clip[4]; + pxy_clip[0] = tb_area.g_x; + pxy_clip[0] = tb_area.g_y; + pxy_clip[0] = pxy_clip[0] + tb_area.g_w + content_area.g_w - 1; + pxy_clip[0] = pxy_clip[1] + tb_area.g_h + content_area.g_h - 1; + vs_clip(gemtk_wm_get_vdi_handle(rootwin->win), 1, pxy_clip); + //gemtk_wm_clear(rootwin->win); +*/ + wind_get_grect(rootwin->aes_handle, WF_FIRSTXYWH, &visible_ro); + while (visible_ro.g_w > 0 && visible_ro.g_h > 0) { + plot_set_abs_clipping(&visible_ro); + + //dbg_grect("visible ", &visible_ro); + + // TODO: optimze the rectangle list - + // remove rectangles which were completly inside the visible area. + // that way we don't have to loop over again... + for(i=0; iredraw_slots.areas_used; i++) { + + GRECT rdrw_area_ro = { + rootwin->redraw_slots.areas[i].x0, + rootwin->redraw_slots.areas[i].y0, + rootwin->redraw_slots.areas[i].x1 - + rootwin->redraw_slots.areas[i].x0, + rootwin->redraw_slots.areas[i].y1 - + rootwin->redraw_slots.areas[i].y0 + }; + + if (!rc_intersect(&visible_ro, &rdrw_area_ro)) { + continue; + } + GRECT rdrw_area = rdrw_area_ro; + + if (rc_intersect(&tb_area, &rdrw_area)) { + toolbar_redraw(rootwin->toolbar, &rdrw_area); + } + + rdrw_area = rdrw_area_ro; + if (rc_intersect(&content_area, &rdrw_area)) { + + if(slid == NULL) { + slid = gemtk_wm_get_scroll_info(rootwin->win); + + scroll_x = slid->x_pos * slid->x_unit_px; + scroll_y = slid->y_pos * slid->y_unit_px; + } + + window_redraw_content(rootwin, &content_area, &rdrw_area, + slid, + rootwin->active_gui_window->browser->bw); + if (((rootwin->caret.state & CARET_STATE_ENABLED)!=0)) { + + GRECT caret_pos; + + caret_pos.g_x = content_area.g_x + + (caret->dimensions.g_x - scroll_x); + caret_pos.g_y = content_area.g_y + + (caret->dimensions.g_y - scroll_y); + caret_pos.g_w = caret->dimensions.g_w; + caret_pos.g_h = caret->dimensions.g_h; + + if (gemtk_rc_intersect_ro(&caret_pos, &content_area)) { + caret_rdrw_required = true; + } + } + + } + } + wind_get_grect(rootwin->aes_handle, WF_NEXTXYWH, &visible_ro); + } + + + // disable clipping: + //vs_clip(gemtk_wm_get_vdi_handle(rootwin->win), 0, pxy_clip); + + if (caret_rdrw_required && ((rootwin->caret.state & CARET_STATE_ENABLED)!=0)) { + + // force redraw of caret: + caret_h = rootwin->caret.dimensions.g_h; + rootwin->caret.dimensions.g_h = 0; + redraw_active = false; + window_place_caret(rootwin, 1, rootwin->caret.dimensions.g_x, + rootwin->caret.dimensions.g_y, + caret_h, &content_area); + } + + rootwin->redraw_slots.areas_used = 0; + redraw_active = false; + + plot_unlock(); +} + + +/* -------------------------------------------------------------------------- */ +/* Event Handlers: */ +/* -------------------------------------------------------------------------- */ +static void on_content_mouse_move(ROOTWIN *rootwin, GRECT *content_area) +{ + int mx, my, sx, sy; + struct gemtk_wm_scroll_info_s *slid; + struct gui_window *gw; + struct browser_window *bw; + + // make relative mouse coords: + mx = aes_event_out.emo_mouse.p_x - content_area->g_x; + my = aes_event_out.emo_mouse.p_y - content_area->g_y; + + slid = gemtk_wm_get_scroll_info(rootwin->win); + gw = window_get_active_gui_window(rootwin); + bw = gw->browser->bw; + + // calculate scroll pos. in pixel: + sx = slid->x_pos * slid->x_unit_px; + sy = slid->y_pos * slid->y_unit_px; + + browser_window_mouse_track(bw, 0, mx + sx, my + sy); +} + +static void on_content_mouse_click(ROOTWIN *rootwin) +{ + short dummy, mbut, mx, my; + GRECT cwork; + browser_mouse_state bmstate = 0; + struct gui_window *gw; + struct gemtk_wm_scroll_info_s *slid; + + gw = window_get_active_gui_window(rootwin); + if(input_window != gw) { + gui_set_input_gui_window(gw); + } + + window_set_focus(gw->root, BROWSER, (void*)gw->browser ); + window_get_grect(gw->root, BROWSER_AREA_CONTENT, &cwork); + + /* convert screen coords to component coords: */ + mx = aes_event_out.emo_mouse.p_x - cwork.g_x; + my = aes_event_out.emo_mouse.p_y - cwork.g_y; + //printf("content click at %d,%d\n", mx, my); + + /* Translate GEM key state to netsurf mouse modifier */ + if ( aes_event_out.emo_kmeta & (K_RSHIFT | K_LSHIFT)) { + bmstate |= BROWSER_MOUSE_MOD_1; + } else { + bmstate &= ~(BROWSER_MOUSE_MOD_1); + } + if ( (aes_event_out.emo_kmeta & K_CTRL) ) { + bmstate |= BROWSER_MOUSE_MOD_2; + } else { + bmstate &= ~(BROWSER_MOUSE_MOD_2); + } + if ( (aes_event_out.emo_kmeta & K_ALT) ) { + bmstate |= BROWSER_MOUSE_MOD_3; + } else { + bmstate &= ~(BROWSER_MOUSE_MOD_3); + } + + /* convert component coords to scrolled content coords: */ + slid = gemtk_wm_get_scroll_info(rootwin->win); + int sx_origin = mx; + int sy_origin = my; + + short rel_cur_x, rel_cur_y; + short prev_x=sx_origin, prev_y=sy_origin; + bool dragmode = false; + + /* Detect left mouse button state and compare with event state: */ + graf_mkstate(&rel_cur_x, &rel_cur_y, &mbut, &dummy); + if( (mbut & 1) && (aes_event_out.emo_mbutton & 1) ) { + /* Mouse still pressed, report drag */ + rel_cur_x = (rel_cur_x - cwork.g_x); + rel_cur_y = (rel_cur_y - cwork.g_y); + browser_window_mouse_click( gw->browser->bw, + BROWSER_MOUSE_DRAG_ON|BROWSER_MOUSE_DRAG_1, + rel_cur_x + slid->x_pos * slid->x_unit_px, + rel_cur_y + slid->y_pos * slid->y_unit_px); + do { + // only consider movements of 5px or more as drag...: + if( abs(prev_x-rel_cur_x) > 5 || abs(prev_y-rel_cur_y) > 5 ) { + browser_window_mouse_track( gw->browser->bw, + BROWSER_MOUSE_DRAG_ON|BROWSER_MOUSE_DRAG_1, + rel_cur_x + slid->x_pos * slid->x_unit_px, + rel_cur_y + slid->y_pos * slid->y_unit_px); + prev_x = rel_cur_x; + prev_y = rel_cur_y; + dragmode = true; + } else { + if( dragmode == false ) { + browser_window_mouse_track( gw->browser->bw,BROWSER_MOUSE_PRESS_1, + rel_cur_x + slid->x_pos * slid->x_unit_px, + rel_cur_y + slid->y_pos * slid->y_unit_px); + } + } + + // we may need to process scrolling: + // TODO: this doesn't work, because gemtk schedules redraw via + // AES window messages but we do not process them right here... + if (rootwin->redraw_slots.areas_used > 0) { + window_process_redraws(rootwin); + } + evnt_timer(150); + + graf_mkstate(&rel_cur_x, &rel_cur_y, &mbut, &dummy); + rel_cur_x = (rel_cur_x - cwork.g_x); + rel_cur_y = (rel_cur_y - cwork.g_y); + } while( mbut & 1 ); + browser_window_mouse_track(gw->browser->bw, 0, + rel_cur_x + slid->x_pos * slid->x_unit_px, + rel_cur_y + slid->y_pos * slid->y_unit_px); + } else { + /* Right button pressed? */ + if ((aes_event_out.emo_mbutton & 2 ) ) { + context_popup(gw, aes_event_out.emo_mouse.p_x, + aes_event_out.emo_mouse.p_y); + } else { + browser_window_mouse_click(gw->browser->bw, + bmstate|BROWSER_MOUSE_PRESS_1, + sx_origin + slid->x_pos * slid->x_unit_px, + sy_origin + slid->y_pos * slid->y_unit_px); + browser_window_mouse_click(gw->browser->bw, + bmstate|BROWSER_MOUSE_CLICK_1, + sx_origin + slid->x_pos * slid->x_unit_px, + sy_origin + slid->y_pos * slid->y_unit_px); + } + } + if (rootwin->redraw_slots.areas_used > 0) { + window_process_redraws(rootwin); + } +} + +/* + Report keypress to browser component. + parameter: + - unsigned short nkc ( CFLIB normalised key code ) +*/ +static bool on_content_keypress(struct gui_window *gw, unsigned short nkc) +{ + bool r = false; + unsigned char ascii = (nkc & 0xFF); + long ucs4; + long ik = nkc_to_input_key( nkc, &ucs4 ); + + // pass event to specific control? + + if (ik == 0) { + if (ascii >= 9) { + r = browser_window_key_press(gw->browser->bw, ucs4); + } + } else { + r = browser_window_key_press(gw->browser->bw, ik); + if (r == false) { + + GRECT g; + GUIWIN * w = gw->root->win; + window_get_grect(gw->root, BROWSER_AREA_CONTENT, &g); + + struct gemtk_wm_scroll_info_s *slid = gemtk_wm_get_scroll_info(w); + + switch( ik ) { + case NS_KEY_LINE_START: + gemtk_wm_scroll(w, GEMTK_WM_HSLIDER, -(g.g_w/slid->x_unit_px), + false); + r = true; + break; + + case NS_KEY_LINE_END: + gemtk_wm_scroll(w, GEMTK_WM_HSLIDER, (g.g_w/slid->x_unit_px), + false); + r = true; + break; + + case NS_KEY_PAGE_UP: + gemtk_wm_scroll(w, GEMTK_WM_VSLIDER, -(g.g_h/slid->y_unit_px), + false); + r = true; + break; + + case NS_KEY_PAGE_DOWN: + gemtk_wm_scroll(w, GEMTK_WM_VSLIDER, (g.g_h/slid->y_unit_px), + false); + r = true; + break; + + case NS_KEY_RIGHT: + gemtk_wm_scroll(w, GEMTK_WM_HSLIDER, -1, false); + r = true; + break; + + case NS_KEY_LEFT: + gemtk_wm_scroll(w, GEMTK_WM_HSLIDER, 1, false); + r = true; + break; + + case NS_KEY_UP: + gemtk_wm_scroll(w, GEMTK_WM_VSLIDER, -1, false); + r = true; + break; + + case NS_KEY_DOWN: + gemtk_wm_scroll(w, GEMTK_WM_VSLIDER, 1, false); + r = true; + break; + + case NS_KEY_TEXT_START: + window_scroll_by(gw->root, 0, 0); + r = true; + break; + + default: + break; + } + gemtk_wm_update_slider(w, GEMTK_WM_VSLIDER|GEMTK_WM_HSLIDER); + } + } + + return(r); +} + +static short on_window_key_input(ROOTWIN *rootwin, unsigned short nkc) +{ + bool done = false; + struct gui_window * gw = window_get_active_gui_window(rootwin); + + if( gw == NULL ) + return(false); + + if(window_url_widget_has_focus((void*)gw->root)) { + /* make sure we report for the root window and report...: */ + done = toolbar_key_input(gw->root->toolbar, nkc); + } else { + if( window_widget_has_focus(input_window->root, BROWSER, + (void*)input_window->browser)) { + done = on_content_keypress(input_window, nkc); + } + else if(window_widget_has_focus(input_window->root, SEARCH_INPUT, NULL)) { + OBJECT * obj; + obj = toolbar_get_form(input_window->root->toolbar); + obj[TOOLBAR_BT_SEARCH_FWD].ob_state &= ~OS_DISABLED; + obj[TOOLBAR_BT_SEARCH_BACK].ob_state &= ~OS_DISABLED; + window_schedule_redraw_grect(input_window->root, + gemtk_obj_screen_rect(obj, TOOLBAR_BT_SEARCH_FWD)); + window_schedule_redraw_grect(input_window->root, + gemtk_obj_screen_rect(obj, TOOLBAR_BT_SEARCH_BACK)); + } + } + return((done==true) ? 1 : 0); +} + + +static void on_redraw(ROOTWIN *rootwin, short msg[8]) +{ + GRECT clip = {msg[4], msg[5], msg[6], msg[7]}; + + //dbg_grect("on_redraw", &clip); + + if(gemtk_wm_get_state(rootwin->win) & GEMTK_WM_STATUS_ICONIFIED) { + // TODO: remove asignment: + window_redraw_favicon(rootwin, NULL); + } else { + window_schedule_redraw_grect(rootwin, &clip); + } +} + +static void on_resized(ROOTWIN *rootwin) +{ + GRECT g, work; + struct gui_window *gw; + + gw = window_get_active_gui_window(rootwin); + + //printf("resized...\n"); + + assert(gw != NULL); + + if(gw == NULL) + return; + + wind_get_grect(rootwin->aes_handle, WF_CURRXYWH, &g); + gemtk_wm_get_grect(rootwin->win, GEMTK_WM_AREA_WORK, &work); + + if (rootwin->loc.g_w != g.g_w || rootwin->loc.g_h != g.g_h) { + + /* resized */ + toolbar_set_width(rootwin->toolbar, work.g_w); + + if ( browser_window_has_content(gw->browser->bw) ) { + browser_window_reformat(gw->browser->bw, true, work.g_w, work.g_h); + } + } + if (rootwin->loc.g_x != g.g_x || rootwin->loc.g_y != g.g_y) { + /* moved */ + toolbar_set_origin(rootwin->toolbar, work.g_x, work.g_y); + } + + rootwin->loc = g; +} + +static void on_file_dropped(ROOTWIN *rootwin, short msg[8]) +{ + char file[DD_NAMEMAX]; + char name[DD_NAMEMAX]; + char *buff=NULL; + int dd_hdl; + int dd_msg; /* pipe-handle */ + long size; + char ext[32]; + short mx,my,bmstat,mkstat; + struct gui_window *gw; + + graf_mkstate(&mx, &my, &bmstat, &mkstat); + + gw = window_get_active_gui_window(rootwin); + + if( gw == NULL ) + return; + + if(gemtk_wm_get_state(rootwin->win) & GEMTK_WM_STATUS_ICONIFIED) + return; + + dd_hdl = gemtk_dd_open( msg[7], DD_OK); + if( dd_hdl<0) + return; /* pipe not open */ + memset( ext, 0, 32); + strcpy( ext, "ARGS"); + dd_msg = gemtk_dd_sexts( dd_hdl, ext); + if( dd_msg<0) + goto error; + dd_msg = gemtk_dd_rtry( dd_hdl, (char*)&name[0], (char*)&file[0], (char*)&ext[0], &size); + if( size+1 >= PATH_MAX ) + goto error; + if( !strncmp( ext, "ARGS", 4) && dd_msg > 0) { + gemtk_dd_reply(dd_hdl, DD_OK); + buff = (char*)malloc(sizeof(char)*(size+1)); + if (buff != NULL) { + if (Fread(dd_hdl, size, buff ) == size) { + + int sx, sy; + bool processed = false; + GRECT content_area; + + buff[size] = 0; + + LOG("file: %s, ext: %s, size: %ld dropped at: %d,%d\n", (char *)buff, (char *)&ext, size, mx, my); + + gui_window_get_scroll(gw, &sx, &sy); + + window_get_grect(rootwin, BROWSER_AREA_CONTENT, &content_area); + mx = mx - content_area.g_x; + my = my - content_area.g_y; + if((mx < 0 || mx > content_area.g_w) + || (my < 0 || my > content_area.g_h)) + return; + + processed = browser_window_drop_file_at_point(gw->browser->bw, + mx+sx, my+sy, + NULL); + if(processed == true) { + nserror ret; + char *utf8_fn; + + ret = utf8_from_local_encoding(buff, 0, &utf8_fn); + if (ret != NSERROR_OK) { + free(buff); + /* A bad encoding should never happen */ + LOG("utf8_from_local_encoding failed"); + assert(ret != NSERROR_BAD_ENCODING); + /* no memory */ + goto error; + } + processed = browser_window_drop_file_at_point(gw->browser->bw, + mx+sx, my+sy, + utf8_fn); + free(utf8_fn); + } + + if(processed == false) { + // TODO: use localized string: + if(gemtk_msg_box_show(GEMTK_MSG_BOX_CONFIRM, "Open File?") > 0) { + nsurl * ns_url = NULL; + char * tmp_url = local_file_to_url(buff); + if ((tmp_url != NULL) + && nsurl_create(tmp_url, &ns_url) == NSERROR_OK) { + browser_window_navigate(gw->browser->bw, ns_url, NULL, + BW_NAVIGATE_HISTORY, + NULL, NULL, NULL); + nsurl_unref(ns_url); + } + } + } + } + } + } +error: + if (buff) { + free(buff); + } + gemtk_dd_close( dd_hdl); +} + +static void toolbar_redraw_cb(GUIWIN *win, uint16_t msg, GRECT *clip) +{ + struct rootwin_data_s * ud; + + if (msg != WM_REDRAW) { + ud = gemtk_wm_get_user_data(win); + + assert(ud); + + toolbar_redraw(ud->rootwin->toolbar, clip); + } +} -- cgit v1.2.3