diff options
author | Chris Young <chris@unsatisfactorysoftware.co.uk> | 2017-01-02 19:18:28 +0000 |
---|---|---|
committer | Chris Young <chris@unsatisfactorysoftware.co.uk> | 2017-01-02 19:18:28 +0000 |
commit | 3b1ef784fd53095213fa8b89806982567359dca4 (patch) | |
tree | ba63814479453a3618afb6b51aafd19aa3506ca1 | |
parent | eb63c1cc50847b88e598cdf0f775814a43a2799e (diff) | |
parent | 2bd8eb8c0b468799109191e63e939ea7bd69f8a1 (diff) | |
download | netsurf-3b1ef784fd53095213fa8b89806982567359dca4.tar.gz netsurf-3b1ef784fd53095213fa8b89806982567359dca4.tar.bz2 |
Partially implement Amiga core window
Migrate SSL cert window to use core window
Core window implementation has some features missing but is good enough for SSL cert
I will improve it as I migrate the other windows.
-rw-r--r-- | frontends/amiga/Makefile | 2 | ||||
-rw-r--r-- | frontends/amiga/corewindow.c | 798 | ||||
-rw-r--r-- | frontends/amiga/corewindow.h | 155 | ||||
-rw-r--r-- | frontends/amiga/gui.c | 33 | ||||
-rw-r--r-- | frontends/amiga/gui.h | 14 | ||||
-rwxr-xr-x | frontends/amiga/object.h | 1 | ||||
-rw-r--r-- | frontends/amiga/sslcert.c | 350 | ||||
-rw-r--r-- | frontends/amiga/sslcert.h | 22 | ||||
-rw-r--r-- | frontends/amiga/tree.c | 2 |
9 files changed, 1335 insertions, 42 deletions
diff --git a/frontends/amiga/Makefile b/frontends/amiga/Makefile index f3c178ee6..8115f2f74 100644 --- a/frontends/amiga/Makefile +++ b/frontends/amiga/Makefile @@ -46,7 +46,7 @@ S_FRONTEND := gui.c tree.c history.c hotlist.c schedule.c file.c \ stringview/stringview.c stringview/urlhistory.c rtg.c \ agclass/amigaguide_class.c os3support.c font_diskfont.c \ selectmenu.c hash/xxhash.c font_cache.c font_bullet.c \ - nsoption.c desktop-tree.c + nsoption.c desktop-tree.c corewindow.c # This is the final source build list # Note this is deliberately *not* expanded here as common and image diff --git a/frontends/amiga/corewindow.c b/frontends/amiga/corewindow.c new file mode 100644 index 000000000..38b980a28 --- /dev/null +++ b/frontends/amiga/corewindow.c @@ -0,0 +1,798 @@ +/* + * Copyright 2017 Chris Young <chris@unsatisfactorysoftware.co.uk> + * + * 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 + * Amiga core window interface. + * + * Provides interface for core renderers to the Amiga Intuition drawable area. + * + * This module is an object that must be encapsulated. Client users + * should embed a struct ami_corewindow at the beginning of their + * context for this display surface, fill in relevant data and then + * call ami_corewindow_init() + * + * The Amiga core window structure requires the callback for draw, key and + * mouse operations. + */ + +#include "amiga/os3support.h" + +#include <assert.h> +#include <string.h> +#include <math.h> + +#include "utils/log.h" +#include "utils/utils.h" +#include "utils/messages.h" +#include "utils/utf8.h" +#include "netsurf/keypress.h" +#include "netsurf/mouse.h" +#include "desktop/plot_style.h" + +#include <proto/exec.h> +#include <proto/intuition.h> +#include <proto/layout.h> +#include <proto/utility.h> + +#include <classes/window.h> +#include <gadgets/layout.h> +#include <gadgets/scroller.h> +#include <gadgets/space.h> +#include <intuition/icclass.h> +#include <reaction/reaction_macros.h> + +#include "amiga/corewindow.h" +#include "amiga/memory.h" +#include "amiga/misc.h" +#include "amiga/object.h" +#include "amiga/schedule.h" +#include "amiga/utf8.h" + +static void +ami_cw_scroller_top(struct ami_corewindow *ami_cw, ULONG *restrict x, ULONG *restrict y) +{ + ULONG xs = 0; + ULONG ys = 0; + + if(ami_cw->scroll_x_visible == true) { + GetAttr(SCROLLER_Top, ami_cw->objects[GID_CW_HSCROLL], (ULONG *)&xs); + } + + if(ami_cw->scroll_y_visible == true) { + GetAttr(SCROLLER_Top, ami_cw->objects[GID_CW_VSCROLL], (ULONG *)&ys); + } + + *x = xs; + *y = ys; +} + + +/** + * Convert co-ordinates relative to space.gadget + * into document co-ordinates + * + * @param ami_cw core window + * @param x co-ordinate, will be updated to new x co-ordinate + * @param y co-ordinate, will be updated to new y co-ordinate + */ +static void +ami_cw_coord_amiga_to_ns(struct ami_corewindow *ami_cw, int *restrict x, int *restrict y) +{ + ULONG xs = 0; + ULONG ys = 0; + + ami_cw_scroller_top(ami_cw, &xs, &ys); + + *x = *x + xs; + *y = *y + ys; +} + + +/* get current mouse position in the draw area, adjusted for scroll. + * @return true if the mouse was in the draw area and co-ordinates updated + */ +static bool +ami_cw_mouse_pos(struct ami_corewindow *ami_cw, int *restrict x, int *restrict y) +{ + int16 xm, ym; + ULONG xs, ys; + struct IBox *bbox; + + xm = ami_cw->win->MouseX; + ym = ami_cw->win->MouseY; + + if(ami_gui_get_space_box((Object *)ami_cw->objects[GID_CW_DRAW], &bbox) != NSERROR_OK) { + amiga_warn_user("NoMemory", ""); + return false; + } + + xm -= bbox->Left; + ym -= bbox->Top; + + ami_gui_free_space_box(bbox); + + if((xm < 0) || (ym < 0) || (xm > bbox->Width) || (ym > bbox->Height)) + return false; + + ami_cw_scroller_top(ami_cw, &xs, &ys); + + xm += xs; + ym += ys; + *x = xm; + *y = ym; + + return true; +} + +/* handle keypress */ +static void +ami_cw_key(struct ami_corewindow *ami_cw, int nskey) +{ + ami_cw->key(ami_cw, nskey); + + switch(nskey) { + case NS_KEY_COPY_SELECTION: + /* if we've copied a selection we need to clear it - style guide rules */ + ami_cw->key(ami_cw, NS_KEY_CLEAR_SELECTION); + break; + + /* we may need to deal with scroll-related keys here */ + } +} + + +/** + * Redraw functions + * + * This is slightly over-engineered as it was taken from the main browser/old tree redraws + * and supports deferred drawing of rectangles and tiling + */ + +/** + * Redraw an area of a core window + * + * \param g a struct ami_corewindow + * \param r rect (in document co-ordinates) + */ + +static void +ami_cw_redraw_rect(struct ami_corewindow *ami_cw, struct rect *r) +{ + struct IBox *bbox; + ULONG pos_x, pos_y; + struct rect draw_rect; + int tile_size_x = ami_cw->gg.width; + int tile_size_y = ami_cw->gg.height; + int tile_x, tile_y, tile_w, tile_h; + int x = r->x0; + int y = r->y0; + int width = r->x1 - r->x0; + int height = r->y1 - r->y0; + + struct redraw_context ctx = { + .interactive = true, + .background_images = true, + .plot = &amiplot + }; + + if(ami_gui_get_space_box((Object *)ami_cw->objects[GID_CW_DRAW], &bbox) != NSERROR_OK) { + amiga_warn_user("NoMemory", ""); + return; + } + + ami_cw_scroller_top(ami_cw, &pos_x, &pos_y); + + glob = &ami_cw->gg; + + if(x - pos_x + width > bbox->Width) width = bbox->Width - (x - pos_x); + if(y - pos_y + height > bbox->Height) height = bbox->Height - (y - pos_y); + + if(x < pos_x) { + width -= pos_x - x; + x = pos_x; + } + + if(y < pos_y) { + height -= pos_y - y; + y = pos_y; + } + + for(tile_y = y; tile_y < (y + height); tile_y += tile_size_y) { + tile_h = tile_size_y; + if(((y + height) - tile_y) < tile_size_y) + tile_h = (y + height) - tile_y; + + for(tile_x = x; tile_x < (x + width); tile_x += tile_size_x) { + tile_w = tile_size_x; + if(((x + width) - tile_x) < tile_size_x) + tile_w = (x + width) - tile_x; + + draw_rect.x0 = tile_x; // was - + draw_rect.y0 = tile_y; // was - + draw_rect.x1 = tile_x + tile_w; + draw_rect.y1 = tile_y + tile_h; + + ami_cw->draw(ami_cw, -tile_x, -tile_y, &draw_rect, &ctx); + +#ifdef __amigaos4__ + BltBitMapTags(BLITA_SrcType, BLITT_BITMAP, + BLITA_Source, ami_cw->gg.bm, + BLITA_SrcX, 0, + BLITA_SrcY, 0, + BLITA_DestType, BLITT_RASTPORT, + BLITA_Dest, ami_cw->win->RPort, + BLITA_DestX, bbox->Left + tile_x - pos_x, + BLITA_DestY, bbox->Top + tile_y - pos_y, + BLITA_Width, tile_w, + BLITA_Height, tile_h, + TAG_DONE); +#else + BltBitMapRastPort(ami_cw->gg.bm, 0, 0, + ami_cw->win->RPort, bbox->Left + tile_x - pos_x, bbox->Top + tile_y - pos_y, + tile_w, tile_h, 0xC0); +#endif + } + } + + ami_gui_free_space_box(bbox); + ami_clearclipreg(glob); + ami_gui_set_default_gg(); +} + + +/** + * Draw the deferred rectangles + * + * @param draw set to false to just delete the queue + */ +static void ami_cw_redraw_queue(struct ami_corewindow *ami_cw, bool draw) +{ + struct nsObject *node; + struct nsObject *nnode; + struct rect *rect; + + if(IsMinListEmpty(ami_cw->deferred_rects)) return; + + if(draw == false) { + LOG("Ignoring deferred box redraw queue"); + } // else should probably show busy pointer + + node = (struct nsObject *)GetHead((struct List *)ami_cw->deferred_rects); + + do { + if(draw == true) { + rect = (struct rect *)node->objstruct; + ami_cw_redraw_rect(ami_cw, rect); + } + nnode = (struct nsObject *)GetSucc((struct Node *)node); + ami_memory_itempool_free(ami_cw->deferred_rects_pool, node->objstruct, sizeof(struct rect)); + DelObjectNoFree(node); + } while((node = nnode)); +} + +static void +ami_cw_redraw_cb(void *p) +{ + struct ami_corewindow *ami_cw = (struct ami_corewindow *)p; + + ami_cw_redraw_queue(ami_cw, true); +} + +/** + * Queue a redraw of a rectangle + * + * @param ami_cw the core window to redraw + * @param r the rectangle (in doc coords) to redraw, or NULL for full window + */ + +static void +ami_cw_redraw(struct ami_corewindow *ami_cw, const struct rect *restrict r) +{ + struct nsObject *nsobj; + struct rect *restrict deferred_rect; + struct rect new_rect; + + if(r == NULL) { + struct IBox *bbox; + if(ami_gui_get_space_box((Object *)ami_cw->objects[GID_CW_DRAW], &bbox) != NSERROR_OK) { + amiga_warn_user("NoMemory", ""); + return; + } + + new_rect.x0 = 0; + new_rect.y0 = 0; + ami_cw_coord_amiga_to_ns(ami_cw, &new_rect.x0, &new_rect.y0); + new_rect.x1 = new_rect.x0 + bbox->Width; + new_rect.y1 = new_rect.y0 + bbox->Height; + + ami_gui_free_space_box(bbox); + + r = &new_rect; + } + + if(ami_gui_window_update_box_deferred_check(ami_cw->deferred_rects, r, + ami_cw->deferred_rects_pool)) { + deferred_rect = ami_memory_itempool_alloc(ami_cw->deferred_rects_pool, sizeof(struct rect)); + CopyMem(r, deferred_rect, sizeof(struct rect)); + nsobj = AddObject(ami_cw->deferred_rects, AMINS_RECT); + nsobj->objstruct = deferred_rect; + } else { + LOG("Ignoring duplicate or subset of queued box redraw"); + } + ami_schedule(1, ami_cw_redraw_cb, ami_cw); +} + +static void +ami_cw_toggle_scrollbar(struct ami_corewindow *ami_cw, bool vert, bool visible) +{ + Object *scroller; + Object *layout; + ULONG tag; + + if(vert == true) { + if(visible == ami_cw->scroll_y_visible) { + return; + } else { + scroller = ami_cw->objects[GID_CW_VSCROLL]; + layout = ami_cw->objects[GID_CW_VSCROLLLAYOUT]; + tag = WINDOW_VertProp; + ami_cw->scroll_y_visible = visible; + } + } else { + if(visible == ami_cw->scroll_x_visible) { + return; + } else { + scroller = ami_cw->objects[GID_CW_HSCROLL]; + layout = ami_cw->objects[GID_CW_HSCROLLLAYOUT]; + tag = WINDOW_HorizProp; + ami_cw->scroll_x_visible = visible; + } + } + + if(visible == true) { + if(ami_cw->in_border_scroll == true) { + SetAttrs(ami_cw->objects[GID_CW_WIN], + tag, 1, + TAG_DONE); + } else { +#ifdef __amigaos4__ + IDoMethod(layout, LM_ADDCHILD, ami_cw->win, scroller, NULL); +#else + SetAttrs(layout, LAYOUT_AddChild, scroller, TAG_DONE); +#endif + } + } else { + if(ami_cw->in_border_scroll == true) { + SetAttrs(ami_cw->objects[GID_CW_WIN], + tag, -1, + TAG_DONE); + } else { +#ifdef __amigaos4__ + IDoMethod(layout, LM_REMOVECHILD, ami_cw->win, scroller); +#else + SetAttrs(layout, LAYOUT_RemoveChild, scroller, TAG_DONE); +#endif + } + } + +#if 0 + /* in-window scrollbars aren't getting hidden until the window is resized + * this code should fix it, but it isn't working */ + if(ami_cw->in_border_scroll == false) { + FlushLayoutDomainCache((struct Gadget *)ami_cw->objects[GID_CW_WIN]); + RethinkLayout((struct Gadget *)ami_cw->objects[GID_CW_WIN], + ami_cw->win, NULL, TRUE); + + /* probably need to redraw here */ + ami_cw_redraw(ami_cw, NULL); + } +#endif +} + +static void +ami_cw_close(void *w) +{ + struct ami_corewindow *ami_cw = (struct ami_corewindow *)w; + + ami_cw->close(ami_cw); +} + +HOOKF(void, ami_cw_idcmp_hook, Object *, object, struct IntuiMessage *) +{ + struct ami_corewindow *ami_cw = hook->h_Data; + struct IntuiWheelData *wheel; + ULONG gid = GetTagData( GA_ID, 0, msg->IAddress ); + + switch(msg->Class) + { + case IDCMP_IDCMPUPDATE: + switch(gid) + { + case GID_CW_HSCROLL: + case GID_CW_VSCROLL: + ami_cw_redraw(ami_cw, NULL); + break; + } + break; +#ifdef __amigaos4__ + case IDCMP_EXTENDEDMOUSE: + if(msg->Code == IMSGCODE_INTUIWHEELDATA) + { + wheel = (struct IntuiWheelData *)msg->IAddress; + + //ami_tree_scroll(twin, (wheel->WheelX * 20), (wheel->WheelY * 20)); + } + break; +#endif + } +} + + +/** + * Main event loop for our core window + * + * \return TRUE if window destroyed + */ +static BOOL +ami_cw_event(void *w) +{ + struct ami_corewindow *ami_cw = (struct ami_corewindow *)w; + + ULONG result; + ULONG storage; + uint16 code; + struct InputEvent *ie; + int nskey; + int key_state = 0; + struct timeval curtime; + int x = 0, y = 0; + + while((result = RA_HandleInput(ami_cw->objects[GID_CW_WIN], &code)) != WMHI_LASTMSG) { + switch(result & WMHI_CLASSMASK) { + case WMHI_MOUSEMOVE: + if(ami_cw_mouse_pos(ami_cw, &x, &y)) { + key_state = ami_gui_get_quals(ami_cw->objects[GID_CW_WIN]); + ami_cw->mouse(ami_cw, ami_cw->mouse_state | key_state, x, y); + } + break; + + case WMHI_MOUSEBUTTONS: + if(ami_cw_mouse_pos(ami_cw, &x, &y) == false) + break; + + key_state = ami_gui_get_quals(ami_cw->objects[GID_CW_WIN]); + + switch(code) { + case SELECTDOWN: + ami_cw->mouse_state = BROWSER_MOUSE_PRESS_1; + break; + + case MIDDLEDOWN: + ami_cw->mouse_state = BROWSER_MOUSE_PRESS_2; + break; + + case SELECTUP: + if(ami_cw->mouse_state & BROWSER_MOUSE_PRESS_1) { + CurrentTime((ULONG *)&curtime.tv_sec, (ULONG *)&curtime.tv_usec); + + ami_cw->mouse_state = BROWSER_MOUSE_CLICK_1; + + if(ami_cw->lastclick.tv_sec) { + if(DoubleClick(ami_cw->lastclick.tv_sec, + ami_cw->lastclick.tv_usec, + curtime.tv_sec, curtime.tv_usec)) + ami_cw->mouse_state |= BROWSER_MOUSE_DOUBLE_CLICK; + } + + if(ami_cw->mouse_state & BROWSER_MOUSE_DOUBLE_CLICK) { + ami_cw->lastclick.tv_sec = 0; + ami_cw->lastclick.tv_usec = 0; + } else { + ami_cw->lastclick.tv_sec = curtime.tv_sec; + ami_cw->lastclick.tv_usec = curtime.tv_usec; + } + } + + ami_cw->mouse(ami_cw, ami_cw->mouse_state | key_state, x, y); + ami_cw->mouse_state = BROWSER_MOUSE_HOVER; + break; + + case MIDDLEUP: + if(ami_cw->mouse_state & BROWSER_MOUSE_PRESS_2) + ami_cw->mouse_state = BROWSER_MOUSE_CLICK_2; + + ami_cw->mouse(ami_cw, ami_cw->mouse_state | key_state, x, y); + ami_cw->mouse_state = BROWSER_MOUSE_HOVER; + break; + } + ami_cw->mouse(ami_cw, ami_cw->mouse_state | key_state, x, y); + break; + + case WMHI_RAWKEY: + storage = result & WMHI_GADGETMASK; + + GetAttr(WINDOW_InputEvent, ami_cw->objects[GID_CW_WIN], (ULONG *)&ie); + nskey = ami_key_to_nskey(storage, ie); + + ami_cw_key(ami_cw, nskey); + break; + + case WMHI_NEWSIZE: + ami_cw_redraw(ami_cw, NULL); + break; + + case WMHI_CLOSEWINDOW: + ami_cw_close(ami_cw); + return TRUE; + break; + + case WMHI_GADGETUP: + switch(result & WMHI_GADGETMASK) { + case GID_CW_HSCROLL: + case GID_CW_VSCROLL: + ami_cw_redraw(ami_cw, NULL); + break; + + default: + /* pass the event to the window owner */ + if(ami_cw->event != NULL) + if(ami_cw->event(ami_cw, result) == TRUE) { + return TRUE; + } + break; + } + + default: + /* pass the event to the window owner */ + if(ami_cw->event != NULL) + if(ami_cw->event(ami_cw, result) == TRUE) { + return TRUE; + } + break; + } + }; + + return FALSE; +} + +static const struct ami_win_event_table ami_cw_table = { + ami_cw_event, + ami_cw_close, +}; + +/** + * callback from core to request a redraw + */ +static void +ami_cw_redraw_request(struct core_window *cw, const struct rect *r) +{ + struct ami_corewindow *ami_cw = (struct ami_corewindow *)cw; + + ami_cw_redraw(ami_cw, r); +} + + +static void +ami_cw_get_window_dimensions(struct core_window *cw, int *width, int *height) +{ + struct ami_corewindow *ami_cw = (struct ami_corewindow *)cw; + struct IBox *bbox; + + if(ami_gui_get_space_box((Object *)ami_cw->objects[GID_CW_DRAW], &bbox) != NSERROR_OK) { + amiga_warn_user("NoMemory", ""); + return; + } + + *width = bbox->Width; + *height = bbox->Height; + + ami_gui_free_space_box(bbox); +} + + +static void +ami_cw_update_size(struct core_window *cw, int width, int height) +{ + struct ami_corewindow *ami_cw = (struct ami_corewindow *)cw; + int win_w, win_h; + + ami_cw_get_window_dimensions((struct core_window *)ami_cw, &win_w, &win_h); + + if(width == -1) { + ami_cw_toggle_scrollbar(ami_cw, false, false); + return; + } + + if(height == -1) { + ami_cw_toggle_scrollbar(ami_cw, true, false); + return; + } + + if(ami_cw->objects[GID_CW_VSCROLL]) { + ami_cw_toggle_scrollbar(ami_cw, true, true); + RefreshSetGadgetAttrs((struct Gadget *)ami_cw->objects[GID_CW_VSCROLL], ami_cw->win, NULL, + SCROLLER_Total, (ULONG)height, + SCROLLER_Visible, win_h, + TAG_DONE); + } + + if(ami_cw->objects[GID_CW_HSCROLL]) { + ami_cw_toggle_scrollbar(ami_cw, false, true); + RefreshSetGadgetAttrs((struct Gadget *)ami_cw->objects[GID_CW_HSCROLL], ami_cw->win, NULL, + SCROLLER_Total, (ULONG)width, + SCROLLER_Visible, win_w, + TAG_DONE); + } +} + + +static void +ami_cw_scroll_visible(struct core_window *cw, const struct rect *r) +{ + struct ami_corewindow *ami_cw = (struct ami_corewindow *)cw; + + int scrollsetx; + int scrollsety; + int win_w = 0, win_h = 0; + ULONG win_x0, win_y0; + int win_x1, win_y1; + + ami_cw_get_window_dimensions((struct core_window *)ami_cw, &win_w, &win_h); + + ami_cw_scroller_top(ami_cw, &win_x0, &win_y0); + + win_x1 = win_x0 + win_w; + win_y1 = win_y0 + win_h; + + if(r->y1 > win_y1) scrollsety = r->y1 - win_h; + if(r->y0 < win_y0) scrollsety = r->y0; + if(r->x1 > win_x1) scrollsetx = r->x1 - win_w; + if(r->x0 < win_x0) scrollsetx = r->x0; + + if(ami_cw->scroll_y_visible == true) { + RefreshSetGadgetAttrs((APTR)ami_cw->objects[GID_CW_VSCROLL], ami_cw->win, NULL, + SCROLLER_Top, scrollsety, + TAG_DONE); + } + + if(ami_cw->scroll_x_visible == true) { + RefreshSetGadgetAttrs((APTR)ami_cw->objects[GID_CW_HSCROLL], ami_cw->win, NULL, + SCROLLER_Top, scrollsetx, + TAG_DONE); + } + + /* probably need to redraw here */ + ami_cw_redraw(ami_cw, NULL); +} + + +static void +ami_cw_drag_status(struct core_window *cw, core_window_drag_status ds) +{ + struct ami_corewindow *ami_cw = (struct ami_corewindow *)cw; + ami_cw->drag_status = ds; +} + + +struct core_window_callback_table ami_cw_cb_table = { + .redraw_request = ami_cw_redraw_request, + .update_size = ami_cw_update_size, + .scroll_visible = ami_cw_scroll_visible, + .get_window_dimensions = ami_cw_get_window_dimensions, + .drag_status = ami_cw_drag_status +}; + +/* exported function documented example/corewindow.h */ +nserror ami_corewindow_init(struct ami_corewindow *ami_cw) +{ + /* setup the core window callback table */ + ami_cw->cb_table = &ami_cw_cb_table; + + /* clear some vars */ + ami_cw->mouse_state = BROWSER_MOUSE_HOVER; + ami_cw->lastclick.tv_sec = 0; + ami_cw->lastclick.tv_usec = 0; + ami_cw->scroll_x_visible = true; + ami_cw->scroll_y_visible = true; + ami_cw->in_border_scroll = false; + + /* allocate drawing area etc */ + ami_init_layers(&ami_cw->gg, 0, 0, false); + ami_cw->gg.shared_pens = ami_AllocMinList(); + + ami_cw->deferred_rects = NewObjList(); + ami_cw->deferred_rects_pool = ami_memory_itempool_create(sizeof(struct rect)); + + /* add the core window to our window list so we process events */ + ami_gui_win_list_add(ami_cw, AMINS_COREWINDOW, &ami_cw_table); + + /* set up the IDCMP hook for event processing (extended mouse, scrollbars) */ + ami_cw->idcmp_hook.h_Entry = (void *)ami_cw_idcmp_hook; + ami_cw->idcmp_hook.h_Data = ami_cw; + + /* open the window */ + ami_cw->win = (struct Window *)RA_OpenWindow(ami_cw->objects[GID_CW_WIN]); + + /* attach the scrollbars for event processing _if they are in the window border_ */ + if(ami_cw->objects[GID_CW_HSCROLL] == NULL) { + GetAttr(WINDOW_HorizObject, ami_cw->objects[GID_CW_WIN], + (ULONG *)&ami_cw->objects[GID_CW_HSCROLL]); + + RefreshSetGadgetAttrs((APTR)ami_cw->objects[GID_CW_HSCROLL], ami_cw->win, NULL, + GA_ID, GID_CW_HSCROLL, + ICA_TARGET, ICTARGET_IDCMP, + TAG_DONE); + + ami_cw->in_border_scroll = true; + } + + if(ami_cw->objects[GID_CW_VSCROLL] == NULL) { + GetAttr(WINDOW_VertObject, ami_cw->objects[GID_CW_WIN], + (ULONG *)&ami_cw->objects[GID_CW_VSCROLL]); + + RefreshSetGadgetAttrs((APTR)ami_cw->objects[GID_CW_VSCROLL], ami_cw->win, NULL, + GA_ID, GID_CW_VSCROLL, + ICA_TARGET, ICTARGET_IDCMP, + TAG_DONE); + + ami_cw->in_border_scroll = true; + } + + return NSERROR_OK; +} + +/* exported interface documented in example/corewindow.h */ +nserror ami_corewindow_fini(struct ami_corewindow *ami_cw) +{ + /* remove any pending redraws */ + ami_schedule(-1, ami_cw_redraw_cb, ami_cw); + FreeObjList(ami_cw->deferred_rects); + ami_memory_itempool_delete(ami_cw->deferred_rects_pool); + + /* destroy the window */ + ami_cw->win = NULL; + DisposeObject(ami_cw->objects[GID_CW_WIN]); + +#if 0 + /* ensure our scrollbars are destroyed */ + /* it appears these are disposed anyway, + * even if the gadgets are no longer attached to the window */ + if(ami_cw->in_border_scroll == false) { + if(ami_cw->scroll_x_visible == false) { + DisposeObject(ami_cw->objects[GID_CW_HSCROLL]); + } + if(ami_cw->scroll_y_visible == false) { + DisposeObject(ami_cw->objects[GID_CW_VSCROLL]); + } + } +#endif + + /* release off-screen bitmap stuff */ + ami_plot_release_pens(ami_cw->gg.shared_pens); + ami_free_layers(&ami_cw->gg); + + /* free the window title */ + ami_utf8_free(ami_cw->wintitle); + + /* remove the core window from our window list */ + ami_gui_win_list_remove(ami_cw); + + return NSERROR_OK; +} + diff --git a/frontends/amiga/corewindow.h b/frontends/amiga/corewindow.h new file mode 100644 index 000000000..8d93882d7 --- /dev/null +++ b/frontends/amiga/corewindow.h @@ -0,0 +1,155 @@ +/* + * Copyright 2017 Chris Young <chris@unsatisfactorysoftware.co.uk> + * + * 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/>. + */ + +#ifndef AMIGA_COREWINDOW_H +#define AMIGA_COREWINDOW_H + +#include "netsurf/core_window.h" + +#include "amiga/gui.h" /* need to know the size of ami_generic_window :( */ +#include "amiga/plotters.h" + +/** + * BOOPSI objects + */ + +enum { + GID_CW_WIN = 0, /* window object */ + GID_CW_MAIN, /* root layout object */ + GID_CW_DRAW, /* drawing area (space.gadget) */ + GID_CW_HSCROLL, /* horizontal scroller */ + GID_CW_VSCROLL, /* vertical scroller */ + GID_CW_HSCROLLLAYOUT, /* horizontal scroller container*/ + GID_CW_VSCROLLLAYOUT, /* vertical scroller container */ + GID_CW_LAST +}; + +/** + * Amiga core window state + */ +struct ami_corewindow { + /* + * Any variables common to any frontend window would go here. + * e.g. drawing area handles, toolkit pointers or other state + */ + struct ami_generic_window w; + struct Window *win; + Object *objects[GID_CW_LAST]; + + struct Hook idcmp_hook; + struct timeval lastclick; + + int mouse_state; + + APTR deferred_rects_pool; + struct MinList *deferred_rects; + + /** keep track of the scrollbar type we're using */ + bool in_border_scroll; + bool scroll_x_visible; + bool scroll_y_visible; + + /** window title, must be allocated wth ami_utf8 function */ + char *wintitle; + + /** stuff for our off-screen render bitmap */ + struct gui_globals gg; + struct MinList *shared_pens; + + /** drag status set by core */ + core_window_drag_status drag_status; + + /** table of callbacks for core window operations */ + struct core_window_callback_table *cb_table; + + /** + * callback to draw on drawable area of Amiga core window + * + * \param ami_cw The Amiga core window structure. + * \param x Plot origin (X) + * \param r Plot origin (Y) + * \param r The rectangle of the window that needs updating. + * \param ctx Redraw context + * \return NSERROR_OK on success otherwise apropriate error code + */ + nserror (*draw)(struct ami_corewindow *ami_cw, int x, int y, struct rect *r, + struct redraw_context *ctx); + + /** + * callback for keypress on Amiga core window + * + * \param ami_cw The Amiga 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 + */ + nserror (*key)(struct ami_corewindow *ami_cw, uint32_t nskey); + + /** + * callback for mouse event on Amiga core window + * + * \param ami_cw The Amiga 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. + */ + nserror (*mouse)(struct ami_corewindow *ami_cw, browser_mouse_state mouse_state, int x, int y); + + /** + * callback for unknown events on Amiga core window + * eg. buttons in the ssl cert window + * (result & WMHI_CLASSMASK) gives the class of event (eg. WMHI_GADGETUP) + * (result & WMHI_GADGETMASK) gives the gadget ID (eg. GID_SSLCERT_ACCEPT) + * + * \param ami_cw The Amiga core window structure. + * \param result event as returned by RA_HandleInput() + * \return TRUE if window closed during event processing + */ + BOOL (*event)(struct ami_corewindow *ami_cw, ULONG result); + + /** + * callback to close an Amiga core window + * + * \param ami_cw The Amiga core window structure. + */ + void (*close)(struct ami_corewindow *ami_cw); + +}; + +/** + * initialise elements of Amiga core window. + * + * As a pre-requisite the draw, key and mouse callbacks must be defined + * + * \param example_cw An Amiga core window structure to initialise + * \return NSERROR_OK on successful initialisation otherwise error code. + */ +nserror ami_corewindow_init(struct ami_corewindow *ami_cw); + +/** + * finalise elements of Amiga core window. + * + * \param ami_cw An Amiga core window structure to finialise + * \return NSERROR_OK on successful finalisation otherwise error code. + */ +nserror ami_corewindow_fini(struct ami_corewindow *ami_cw); + +#endif + diff --git a/frontends/amiga/gui.c b/frontends/amiga/gui.c index ba0a786e3..f94090b75 100644 --- a/frontends/amiga/gui.c +++ b/frontends/amiga/gui.c @@ -1376,27 +1376,34 @@ int ami_key_to_nskey(ULONG keycode, struct InputEvent *ie) return nskey; } -static void ami_update_quals(struct gui_window_2 *gwin) +int ami_gui_get_quals(Object *win_obj) { uint32 quals = 0; + int key_state = 0; #ifdef __amigaos4__ - GetAttr(WINDOW_Qualifier,gwin->objects[OID_MAIN],(uint32 *)&quals); + GetAttr(WINDOW_Qualifier, win_obj, (uint32 *)&quals); #else #warning qualifier needs fixing for OS3 #endif - gwin->key_state = 0; if(quals & NSA_QUAL_SHIFT) { - gwin->key_state |= BROWSER_MOUSE_MOD_1; + key_state |= BROWSER_MOUSE_MOD_1; } if(quals & IEQUALIFIER_CONTROL) { - gwin->key_state |= BROWSER_MOUSE_MOD_2; + key_state |= BROWSER_MOUSE_MOD_2; } if(quals & NSA_QUAL_ALT) { - gwin->key_state |= BROWSER_MOUSE_MOD_3; + key_state |= BROWSER_MOUSE_MOD_3; } + + return key_state; +} + +static void ami_update_quals(struct gui_window_2 *gwin) +{ + gwin->key_state = ami_gui_get_quals(gwin->objects[OID_MAIN]); } /* exported interface documented in amiga/gui.h */ @@ -1682,7 +1689,7 @@ static bool ami_gui_hscroll_remove(struct gui_window_2 *gwin) IDoMethod(gwin->objects[GID_HSCROLLLAYOUT], LM_REMOVECHILD, gwin->win, gwin->objects[GID_HSCROLL]); #else - SetAttrs(gwin->objects[GID_HSCROLLLAYOUT], LAYOUT_RemoveChild, gwin->objects[GID_HSCROLL]); + SetAttrs(gwin->objects[GID_HSCROLLLAYOUT], LAYOUT_RemoveChild, gwin->objects[GID_HSCROLL], TAG_DONE); #endif gwin->objects[GID_HSCROLL] = NULL; @@ -1727,7 +1734,7 @@ static bool ami_gui_vscroll_remove(struct gui_window_2 *gwin) IDoMethod(gwin->objects[GID_VSCROLLLAYOUT], LM_REMOVECHILD, gwin->win, gwin->objects[GID_VSCROLL]); #else - SetAttrs(gwin->objects[GID_VSCROLLLAYOUT], LAYOUT_RemoveChild, gwin->objects[GID_VSCROLL]); + SetAttrs(gwin->objects[GID_VSCROLLLAYOUT], LAYOUT_RemoveChild, gwin->objects[GID_VSCROLL], TAG_DONE); #endif gwin->objects[GID_VSCROLL] = NULL; @@ -3259,8 +3266,10 @@ static void ami_gui_hotlist_toolbar_remove(struct gui_window_2 *gwin) IDoMethod(gwin->objects[GID_HOTLISTLAYOUT], LM_REMOVECHILD, gwin->win, gwin->objects[GID_HOTLISTSEPBAR]); #else - SetAttrs(gwin->objects[GID_HOTLISTLAYOUT], LAYOUT_RemoveChild, gwin->objects[GID_HOTLIST]); - SetAttrs(gwin->objects[GID_HOTLISTLAYOUT], LAYOUT_RemoveChild, gwin->objects[GID_HOTLISTSEPBAR]); + SetAttrs(gwin->objects[GID_HOTLISTLAYOUT], + LAYOUT_RemoveChild, gwin->objects[GID_HOTLIST], TAG_DONE); + SetAttrs(gwin->objects[GID_HOTLISTLAYOUT], + LAYOUT_RemoveChild, gwin->objects[GID_HOTLISTSEPBAR], TAG_DONE); #endif FlushLayoutDomainCache((struct Gadget *)gwin->objects[GID_MAIN]); @@ -4734,7 +4743,7 @@ static void ami_gui_window_update_box_deferred(struct gui_window *g, bool draw) if(draw == true) ami_reset_pointer(g->shared); } -static bool ami_gui_window_update_box_deferred_check(struct MinList *deferred_rects, +bool ami_gui_window_update_box_deferred_check(struct MinList *deferred_rects, const struct rect *restrict new_rect, APTR mempool) { struct nsObject *node; @@ -5603,7 +5612,7 @@ static struct gui_misc_table amiga_misc_table = { .quit = gui_quit, .launch_url = gui_launch_url, - .cert_verify = gui_cert_verify, + .cert_verify = ami_cert_verify, .login = gui_401login_open, }; diff --git a/frontends/amiga/gui.h b/frontends/amiga/gui.h index eb39e9e47..4c3e586d7 100644 --- a/frontends/amiga/gui.h +++ b/frontends/amiga/gui.h @@ -1,5 +1,5 @@ /* - * Copyright 2008-2016 Chris Young <chris@unsatisfactorysoftware.co.uk> + * Copyright 2008-2017 Chris Young <chris@unsatisfactorysoftware.co.uk> * * This file is part of NetSurf, http://www.netsurf-browser.org/ * @@ -282,5 +282,17 @@ nserror ami_gui_win_list_add(void *win, int type, const struct ami_win_event_tab * Remove a window from the NetSurf window list */ void ami_gui_win_list_remove(void *win); + +/** + * Get which qualifier keys are being pressed + */ +int ami_gui_get_quals(Object *win_obj); + +/** + * Check rect is not already queued for redraw + */ +bool ami_gui_window_update_box_deferred_check(struct MinList *deferred_rects, + const struct rect *restrict new_rect, APTR mempool); + #endif diff --git a/frontends/amiga/object.h b/frontends/amiga/object.h index be9650413..70bb550f8 100755 --- a/frontends/amiga/object.h +++ b/frontends/amiga/object.h @@ -33,6 +33,7 @@ enum AMINS_HISTORYWINDOW, AMINS_GUIOPTSWINDOW, AMINS_PRINTWINDOW, + AMINS_COREWINDOW, AMINS_FONT, AMINS_MIME, AMINS_RECT diff --git a/frontends/amiga/sslcert.c b/frontends/amiga/sslcert.c index 83798f2e2..d56a1fe13 100644 --- a/frontends/amiga/sslcert.c +++ b/frontends/amiga/sslcert.c @@ -1,5 +1,5 @@ /* - * Copyright 2009 Chris Young <chris@unsatisfactorysoftware.co.uk> + * Copyright 2017 Chris Young <chris@unsatisfactorysoftware.co.uk> * * This file is part of NetSurf, http://www.netsurf-browser.org/ * @@ -16,39 +16,347 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <proto/exec.h> +/** + * \file + * Implementation of Amiga certificate viewing using core windows. + */ + +#include <stdint.h> +#include <stdlib.h> + +#include <proto/intuition.h> + +#include <classes/window.h> +#include <gadgets/button.h> +#include <gadgets/layout.h> +#include <gadgets/scroller.h> +#include <gadgets/space.h> +#include <images/label.h> + +#include <reaction/reaction_macros.h> -#include "utils/nsurl.h" -#include "content/llcache.h" -#include "netsurf/mouse.h" -#include "netsurf/window.h" +#include "utils/log.h" +#include "netsurf/keypress.h" +#include "netsurf/plotters.h" #include "desktop/sslcert_viewer.h" +#include "utils/messages.h" -#include "amiga/tree.h" +#include "amiga/corewindow.h" +#include "amiga/libs.h" #include "amiga/sslcert.h" +#include "amiga/utf8.h" + + +/** + * Amiga certificate viewing window context + */ +enum { + GID_SSLCERT_ACCEPT = GID_CW_LAST, + GID_SSLCERT_REJECT, + GID_SSLCERT_LAST +}; + +#define GID_SSLCERT_SIZE GID_SSLCERT_LAST - GID_CW_LAST + +struct ami_crtvrfy_window { + /** Amiga core window context */ + struct ami_corewindow core; + + /** Amiga GUI stuff */ + Object *sslcert_objects[GID_SSLCERT_LAST]; // technically wasting a few bytes here + + char *sslerr; + char *sslaccept; + char *sslreject; + + /** SSL certificate viewer context data */ + struct sslcert_session_data *ssl_data; +}; + +/** + * destroy a previously created certificate view + */ +static nserror +ami_crtvrfy_destroy(struct ami_crtvrfy_window *crtvrfy_win) +{ + nserror res; + + res = sslcert_viewer_fini(crtvrfy_win->ssl_data); + if (res == NSERROR_OK) { + ami_utf8_free(crtvrfy_win->sslerr); + ami_utf8_free(crtvrfy_win->sslaccept); + ami_utf8_free(crtvrfy_win->sslreject); + res = ami_corewindow_fini(&crtvrfy_win->core); /* closes the window for us */ + } + return res; +} -nserror gui_cert_verify(nsurl *url, - const struct ssl_cert_info *certs, unsigned long num, - nserror (*cb)(bool proceed, void *pw), void *cbpw) +static void +ami_crtvrfy_accept(struct ami_corewindow *ami_cw) { - struct sslcert_session_data *data; - struct treeview_window *ssl_window; + struct ami_crtvrfy_window *crtvrfy_win; + /* technically degenerate container of */ + crtvrfy_win = (struct ami_crtvrfy_window *)ami_cw; - sslcert_viewer_create_session_data(num, url, cb, cbpw, - certs, &data); - ssl_current_session = data; + sslcert_viewer_accept(crtvrfy_win->ssl_data); - ssl_window = ami_tree_create(TREE_SSLCERT, data); - if (!ssl_window) { - return NSERROR_INIT_FAILED; + ami_crtvrfy_destroy(crtvrfy_win); +} + +static void +ami_crtvrfy_reject(struct ami_corewindow *ami_cw) +{ + struct ami_crtvrfy_window *crtvrfy_win; + /* technically degenerate container of */ + crtvrfy_win = (struct ami_crtvrfy_window *)ami_cw; + + sslcert_viewer_reject(crtvrfy_win->ssl_data); + + ami_crtvrfy_destroy(crtvrfy_win); +} + +/** + * callback for unknown events on Amiga core window + * eg. buttons in the ssl cert window + * (result & WMHI_CLASSMASK) gives the class of event (eg. WMHI_GADGETUP) + * (result & WMHI_GADGETMASK) gives the gadget ID (eg. GID_SSLCERT_ACCEPT) + * + * \param ami_cw The Amiga core window structure. + * \param result event as returned by RA_HandleInput() + * \return TRUE if window closed during event processing + */ +static BOOL +ami_crtvrfy_event(struct ami_corewindow *ami_cw, ULONG result) +{ + if((result & WMHI_CLASSMASK) == WMHI_GADGETUP) { + switch(result & WMHI_GADGETMASK) { + case GID_SSLCERT_ACCEPT: + ami_crtvrfy_accept(ami_cw); + return TRUE; + break; + + case GID_SSLCERT_REJECT: + ami_crtvrfy_reject(ami_cw); + return TRUE; + break; + } } + return FALSE; +} - ami_tree_open(ssl_window, AMI_TREE_SSLCERT); +/** + * callback for mouse action for certificate verify on core window + * + * \param ami_cw The Amiga core window structure. + * \param mouse_state netsurf mouse state on event + * \param x location of event + * \param y location of event + * \return NSERROR_OK on success otherwise apropriate error code + */ +static nserror +ami_crtvrfy_mouse(struct ami_corewindow *ami_cw, + browser_mouse_state mouse_state, + int x, int y) +{ + struct ami_crtvrfy_window *crtvrfy_win; + /* technically degenerate container of */ + crtvrfy_win = (struct ami_crtvrfy_window *)ami_cw; + + sslcert_viewer_mouse_action(crtvrfy_win->ssl_data, mouse_state, x, y); return NSERROR_OK; } -void ami_ssl_free(struct treeview_window *twin) +/** + * callback for keypress for certificate verify on core window + * + * \param example_cw The Amiga core window structure. + * \param nskey The netsurf key code + * \return NSERROR_OK on success otherwise apropriate error code + */ +static nserror +ami_crtvrfy_key(struct ami_corewindow *ami_cw, uint32_t nskey) { - ami_tree_destroy(twin); + struct ami_crtvrfy_window *crtvrfy_win; + + /* technically degenerate container of */ + crtvrfy_win = (struct ami_crtvrfy_window *)ami_cw; + + if (sslcert_viewer_keypress(crtvrfy_win->ssl_data, nskey)) { + return NSERROR_OK; + } + return NSERROR_NOT_IMPLEMENTED; +} + +/** + * callback on draw event for certificate verify on core window + * + * \param ami_cw The Amiga core window structure. + * \param r The rectangle of the window that needs updating. + * \param ctx The drawing context + * \return NSERROR_OK on success otherwise apropriate error code + */ +static nserror +ami_crtvrfy_draw(struct ami_corewindow *ami_cw, int x, int y, struct rect *r, struct redraw_context *ctx) +{ + struct ami_crtvrfy_window *crtvrfy_win; + + /* technically degenerate container of */ + crtvrfy_win = (struct ami_crtvrfy_window *)ami_cw; + + sslcert_viewer_redraw(crtvrfy_win->ssl_data, x, y, r, ctx); + + return NSERROR_OK; +} + +static nserror +ami_crtvrfy_create_window(struct ami_crtvrfy_window *crtvrfy_win) +{ + struct ami_corewindow *ami_cw = (struct ami_corewindow *)&crtvrfy_win->core; + + ami_cw->objects[GID_CW_WIN] = WindowObj, + WA_ScreenTitle, ami_gui_get_screen_title(), + WA_Title, ami_cw->wintitle, + WA_Activate, TRUE, + WA_DepthGadget, TRUE, + WA_DragBar, TRUE, + WA_CloseGadget, FALSE, + WA_SizeGadget, TRUE, + WA_SizeBBottom, TRUE, + WA_Height, scrn->Height / 2, + WA_PubScreen, scrn, + WA_ReportMouse, TRUE, + WA_IDCMP, IDCMP_MOUSEMOVE | IDCMP_MOUSEBUTTONS | IDCMP_NEWSIZE | + IDCMP_RAWKEY | IDCMP_GADGETUP | IDCMP_IDCMPUPDATE | + IDCMP_EXTENDEDMOUSE | IDCMP_SIZEVERIFY, + WINDOW_IDCMPHook, &ami_cw->idcmp_hook, + WINDOW_IDCMPHookBits, IDCMP_IDCMPUPDATE | IDCMP_EXTENDEDMOUSE, + WINDOW_SharedPort, sport, + WINDOW_UserData, crtvrfy_win, + /* WINDOW_NewMenu, twin->menu, -> No menu for SSL Cert */ + WINDOW_IconifyGadget, FALSE, + WINDOW_Position, WPOS_CENTERSCREEN, + WINDOW_ParentGroup, ami_cw->objects[GID_CW_MAIN] = LayoutVObj, + LAYOUT_AddImage, LabelObj, + LABEL_Text, crtvrfy_win->sslerr, + LabelEnd, + LAYOUT_AddChild, ami_cw->objects[GID_CW_HSCROLLLAYOUT] = LayoutVObj, + LAYOUT_AddChild, ami_cw->objects[GID_CW_VSCROLLLAYOUT] = LayoutHObj, + LAYOUT_AddChild, ami_cw->objects[GID_CW_DRAW] = SpaceObj, + GA_ID, GID_CW_DRAW, + SPACE_Transparent, TRUE, + SPACE_BevelStyle, BVS_DISPLAY, + GA_RelVerify, TRUE, + SpaceEnd, + LAYOUT_AddChild, ami_cw->objects[GID_CW_VSCROLL] = ScrollerObj, + GA_ID, GID_CW_VSCROLL, + GA_RelVerify, TRUE, + ScrollerEnd, + LayoutEnd, + LAYOUT_AddChild, ami_cw->objects[GID_CW_HSCROLL] = ScrollerObj, + GA_ID, GID_CW_HSCROLL, + GA_RelVerify, TRUE, + SCROLLER_Orientation, SORIENT_HORIZ, + ScrollerEnd, + LayoutEnd, + LAYOUT_AddChild, LayoutHObj, + LAYOUT_AddChild, crtvrfy_win->sslcert_objects[GID_SSLCERT_ACCEPT] = ButtonObj, + GA_ID, GID_SSLCERT_ACCEPT, + GA_Text, crtvrfy_win->sslaccept, + GA_RelVerify, TRUE, + ButtonEnd, + LAYOUT_AddChild, crtvrfy_win->sslcert_objects[GID_SSLCERT_REJECT] = ButtonObj, + GA_ID, GID_SSLCERT_REJECT, + GA_Text, crtvrfy_win->sslreject, + GA_RelVerify, TRUE, + ButtonEnd, + EndGroup, + CHILD_WeightedHeight, 0, + EndGroup, + EndWindow; + + if(ami_cw->objects[GID_CW_WIN] == NULL) { + return NSERROR_NOMEM; + } + + return NSERROR_OK; } + +/* exported interface documented in amiga/ssl_cert.h */ +nserror ami_cert_verify(struct nsurl *url, + const struct ssl_cert_info *certs, + unsigned long num, + nserror (*cb)(bool proceed, void *pw), + void *cbpw) +{ + struct ami_crtvrfy_window *ncwin; + nserror res; + + ncwin = calloc(1, sizeof(struct ami_crtvrfy_window)); + if (ncwin == NULL) { + return NSERROR_NOMEM; + } + + ncwin->core.wintitle = ami_utf8_easy((char *)messages_get("SSLCerts")); + ncwin->sslerr = ami_utf8_easy((char *)messages_get("SSLError")); + ncwin->sslaccept = ami_utf8_easy((char *)messages_get("SSL_Certificate_Accept")); + ncwin->sslreject = ami_utf8_easy((char *)messages_get("SSL_Certificate_Reject")); + + res = ami_crtvrfy_create_window(ncwin); + if (res != NSERROR_OK) { + LOG("SSL UI builder init failed"); + ami_utf8_free(ncwin->core.wintitle); + ami_utf8_free(ncwin->sslerr); + ami_utf8_free(ncwin->sslaccept); + ami_utf8_free(ncwin->sslreject); + free(ncwin); + return res; + } + + /* initialise example core window */ + ncwin->core.draw = ami_crtvrfy_draw; + ncwin->core.key = ami_crtvrfy_key; + ncwin->core.mouse = ami_crtvrfy_mouse; + ncwin->core.close = ami_crtvrfy_reject; + ncwin->core.event = ami_crtvrfy_event; + + res = ami_corewindow_init(&ncwin->core); + if (res != NSERROR_OK) { + ami_utf8_free(ncwin->core.wintitle); + ami_utf8_free(ncwin->sslerr); + ami_utf8_free(ncwin->sslaccept); + ami_utf8_free(ncwin->sslreject); + DisposeObject(ncwin->core.objects[GID_CW_WIN]); + free(ncwin); + return res; + } + + /* initialise certificate viewing interface */ + res = sslcert_viewer_create_session_data(num, url, cb, cbpw, certs, + &ncwin->ssl_data); + if (res != NSERROR_OK) { + ami_utf8_free(ncwin->core.wintitle); + ami_utf8_free(ncwin->sslerr); + ami_utf8_free(ncwin->sslaccept); + ami_utf8_free(ncwin->sslreject); + DisposeObject(ncwin->core.objects[GID_CW_WIN]); + free(ncwin); + return res; + } + + res = sslcert_viewer_init(ncwin->core.cb_table, + (struct core_window *)ncwin, + ncwin->ssl_data); + if (res != NSERROR_OK) { + ami_utf8_free(ncwin->core.wintitle); + ami_utf8_free(ncwin->sslerr); + ami_utf8_free(ncwin->sslaccept); + ami_utf8_free(ncwin->sslreject); + DisposeObject(ncwin->core.objects[GID_CW_WIN]); + free(ncwin); + return res; + } + + return NSERROR_OK; +} + diff --git a/frontends/amiga/sslcert.h b/frontends/amiga/sslcert.h index 86ce9c476..392989f02 100644 --- a/frontends/amiga/sslcert.h +++ b/frontends/amiga/sslcert.h @@ -1,5 +1,5 @@ /* - * Copyright 2009 Chris Young <chris@unsatisfactorysoftware.co.uk> + * Copyright 2017 Chris Young <chris@unsatisfactorysoftware.co.uk> * * This file is part of NetSurf, http://www.netsurf-browser.org/ * @@ -18,11 +18,21 @@ #ifndef AMIGA_SSLCERT_H #define AMIGA_SSLCERT_H +struct nsurl; +struct ssl_cert_info; -nserror gui_cert_verify(nsurl *url, +/** + * Prompt the user to verify a certificate with issues. + * + * \param url The URL being verified. + * \param certs The certificate to be verified + * \param num The number of certificates to be verified. + * \param cb Callback upon user decision. + * \param cbpw Context pointer passed to cb + * \return NSERROR_OK or error code if prompt creation failed. + */ +nserror ami_cert_verify(struct nsurl *url, const struct ssl_cert_info *certs, unsigned long num, - nserror (*cb)(bool proceed, void *pw), void *cbpw); - -void ami_ssl_free(struct treeview_window *twin); - + nserror (*cb)(bool proceed, void *pw), void *cbpw); #endif + diff --git a/frontends/amiga/tree.c b/frontends/amiga/tree.c index f1c5327c7..b9747c095 100644 --- a/frontends/amiga/tree.c +++ b/frontends/amiga/tree.c @@ -916,7 +916,7 @@ void ami_tree_close(void *w) ami_utf8_free(twin->sslerr); ami_utf8_free(twin->sslaccept); ami_utf8_free(twin->sslreject); - ami_ssl_free(twin); + //ami_ssl_free(twin); } if(twin->type == AMI_TREE_HOTLIST) |