/* * Copyright 2008 - 2013 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/>. */ #include "amiga/os3support.h" #include <proto/window.h> #include <proto/layout.h> #include <proto/space.h> #include <proto/label.h> #include <proto/scroller.h> #include <proto/exec.h> #include <proto/intuition.h> #include <proto/button.h> #include <proto/bitmap.h> #include <proto/graphics.h> #include <proto/asl.h> #include <proto/utility.h> #include <proto/dos.h> #include <libraries/gadtools.h> #include <gadgets/button.h> #include <classes/window.h> #include <gadgets/space.h> #include <images/label.h> #include <images/bitmap.h> #include <gadgets/layout.h> #include <gadgets/scroller.h> #include <reaction/reaction_macros.h> #include <intuition/icclass.h> #ifdef __amigaos4__ #include <graphics/blitattr.h> #endif #include <assert.h> #include <string.h> #include "utils/nsoption.h" #include "utils/utils.h" #include "utils/messages.h" #include "content/urldb.h" #include "content/llcache.h" #include "desktop/browser.h" #include "desktop/cookie_manager.h" #include "desktop/global_history.h" #include "desktop/hotlist.h" #include "desktop/gui_window.h" #include "desktop/sslcert_viewer.h" #include "amiga/gui.h" #include "amiga/tree.h" #include "amiga/file.h" #include "amiga/libs.h" #include "amiga/misc.h" #include "amiga/utf8.h" #include "amiga/sslcert.h" #include "amiga/drag.h" /* drag icon stuff */ #include "amiga/theme.h" /* pointers */ #include "amiga/filetype.h" #include "amiga/schedule.h" #define AMI_TREE_MENU_ITEMS 26 #define AMI_TREE_MENU_NEWDIR FULLMENUNUM(1,0,0) #define AMI_TREE_MENU_NEWURL FULLMENUNUM(1,1,0) #define AMI_TREE_MENU_EDIT FULLMENUNUM(1,3,0) #define AMI_TREE_MENU_DELETE FULLMENUNUM(1,5,0) #define AMI_TREE_MENU_CLEAR FULLMENUNUM(1,8,0) enum { GID_OPEN = GID_LAST, GID_TREE_LAST }; struct treeview_window { struct nsObject *node; struct Window *win; Object *objects[GID_TREE_LAST]; int type; struct NewMenu *menu; char *menu_name[AMI_TREE_MENU_ITEMS]; struct tree *tree; struct Hook scrollerhook; uint32 key_state; uint32 mouse_state; int drag_x; int drag_y; struct timeval lastclick; int max_width; int max_height; struct gui_globals globals; struct sslcert_session_data *ssl_data; BOOL rmbtrapped; char *wintitle; char *sslerr; char *sslaccept; char *sslreject; struct MinList shared_pens; }; struct ami_tree_redraw_req { int x; int y; int width; int height; struct treeview_window *twin; }; #if 0 void ami_tree_draw(struct treeview_window *twin); static void ami_tree_resized(struct tree *tree, int width, int height, void *data); static void ami_tree_scroll_visible(int y, int height, void *data); static void ami_tree_get_window_dimensions(int *width, int *height, void *data); #endif void ami_tree_destroy(struct treeview_window *twin) { tree_delete(twin->tree); FreeVec(twin); } struct tree *ami_tree_get_tree(struct treeview_window *twin) { return twin->tree; } static void ami_tree_resized(struct tree *tree, int width, int height, void *data) { struct treeview_window *twin = data; struct IBox *bbox; twin->max_height = height; twin->max_width = width; if(twin->win) { if(ami_gui_get_space_box(twin->objects[GID_BROWSER], &bbox) != NSERROR_OK) { warn_user("NoMemory", ""); return; } if(height == -1) { SetAttrs((APTR)twin->objects[OID_MAIN], WINDOW_VertProp, -1, TAG_DONE); } else { RefreshSetGadgetAttrs((APTR)twin->objects[OID_VSCROLL], twin->win, NULL, SCROLLER_Total, height, SCROLLER_Visible, bbox->Height, TAG_DONE); } if(width == -1) { SetAttrs((APTR)twin->objects[OID_MAIN], WINDOW_HorizProp, -1, TAG_DONE); } else { RefreshSetGadgetAttrs((APTR)twin->objects[OID_HSCROLL], twin->win, NULL, SCROLLER_Total, width, SCROLLER_Visible, bbox->Width, TAG_DONE); } ami_gui_free_space_box(bbox); } } /** * Retrieves the dimensions of the window with the tree * * \param data user data assigned to the tree on tree creation * \param width will be updated to window width if not NULL * \param height will be updated to window height if not NULL */ static void ami_tree_get_window_dimensions(int *width, int *height, void *data) { struct treeview_window *twin = data; struct IBox *bbox; if(ami_gui_get_space_box(twin->objects[GID_BROWSER], &bbox) != NSERROR_OK) { warn_user("NoMemory", ""); return; } if(width) *width = bbox->Width; if(height) *height = bbox->Height; ami_gui_free_space_box(bbox); } static void ami_tree_redraw_req_dr(void *p) { struct ami_tree_redraw_req *atrr_data = (struct ami_tree_redraw_req *)p; int x = atrr_data->x; int y = atrr_data->y; int width = atrr_data->width; int height = atrr_data->height; struct treeview_window *twin = atrr_data->twin; struct IBox *bbox; int pos_x, pos_y; struct RastPort *temprp; struct redraw_context ctx = { .interactive = true, .background_images = true, .plot = &amiplot }; if(!twin->win) return; ami_update_pointer(twin->win, GUI_POINTER_WAIT); glob = &twin->globals; temprp = glob->rp; glob->rp = twin->win->RPort; GetAttr(SCROLLER_Top, twin->objects[OID_HSCROLL], (ULONG *)&pos_x); GetAttr(SCROLLER_Top, twin->objects[OID_VSCROLL], (ULONG *)&pos_y); if(ami_gui_get_space_box(twin->objects[GID_BROWSER], &bbox) != NSERROR_OK) { warn_user("NoMemory", ""); return; } x += bbox->Left; y += bbox->Top; 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; } tree_draw(twin->tree, bbox->Left - pos_x, bbox->Top - pos_y, atrr_data->x, atrr_data->y, atrr_data->width, atrr_data->height, &ctx); FreeVec(atrr_data); ami_gui_free_space_box(bbox); ami_update_pointer(twin->win, GUI_POINTER_DEFAULT); ami_clearclipreg(glob); glob->rp = temprp; glob = &browserglob; } static void ami_tree_redraw_req(void *p) { struct ami_tree_redraw_req *atrr_data = (struct ami_tree_redraw_req *)p; int x = atrr_data->x; int y = atrr_data->y; int width = atrr_data->width; int height = atrr_data->height; struct treeview_window *twin = atrr_data->twin; struct IBox *bbox; int pos_x, pos_y; int tile_x, tile_y, tile_w, tile_h; struct redraw_context ctx = { .interactive = true, .background_images = true, .plot = &amiplot }; if(!twin->win) return; ami_update_pointer(twin->win, GUI_POINTER_WAIT); glob = &twin->globals; GetAttr(SCROLLER_Top, twin->objects[OID_HSCROLL], (ULONG *)&pos_x); GetAttr(SCROLLER_Top, twin->objects[OID_VSCROLL], (ULONG *)&pos_y); if(ami_gui_get_space_box(twin->objects[GID_BROWSER], &bbox) != NSERROR_OK) { warn_user("NoMemory", ""); return; } 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 += nsoption_int(redraw_tile_size_y)) { tile_h = nsoption_int(redraw_tile_size_y); if(((y + height) - tile_y) < nsoption_int(redraw_tile_size_y)) tile_h = (y + height) - tile_y; for(tile_x = x; tile_x < (x + width); tile_x += nsoption_int(redraw_tile_size_x)) { tile_w = nsoption_int(redraw_tile_size_x); if(((x + width) - tile_x) < nsoption_int(redraw_tile_size_x)) tile_w = (x + width) - tile_x; tree_draw(twin->tree, - tile_x, - tile_y, tile_x, tile_y, tile_w, tile_h, &ctx); #ifdef __amigaos4__ BltBitMapTags(BLITA_SrcType, BLITT_BITMAP, BLITA_Source, twin->globals.bm, BLITA_SrcX, 0, BLITA_SrcY, 0, BLITA_DestType, BLITT_RASTPORT, BLITA_Dest, twin->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(twin->globals.bm, 0, 0, twin->win->RPort, bbox->Left + tile_x - pos_x, bbox->Top + tile_y - pos_y, tile_w, tile_h, 0xC0); #endif } } FreeVec(atrr_data); ami_gui_free_space_box(bbox); ami_update_pointer(twin->win, GUI_POINTER_DEFAULT); ami_clearclipreg(glob); glob = &browserglob; } static void ami_tree_redraw_request(int x, int y, int width, int height, void *data) { struct ami_tree_redraw_req *atrr_data = AllocVecTagList(sizeof(struct ami_tree_redraw_req), NULL); atrr_data->x = x; atrr_data->y = y; atrr_data->width = width; atrr_data->height = height; atrr_data->twin = (struct treeview_window *)data; /** /todo Queue these requests properly like the main browser code does **/ if(nsoption_bool(direct_render) == false) ami_schedule(0, ami_tree_redraw_req, atrr_data); else ami_schedule(0, ami_tree_redraw_req_dr, atrr_data); } static void ami_tree_draw(struct treeview_window *twin) { struct IBox *bbox; int x, y; if(!twin) return; GetAttr(SCROLLER_Top, twin->objects[OID_HSCROLL], (ULONG *)&x); GetAttr(SCROLLER_Top, twin->objects[OID_VSCROLL], (ULONG *)&y); if(ami_gui_get_space_box(twin->objects[GID_BROWSER], &bbox) != NSERROR_OK) { warn_user("NoMemory", ""); return; } ami_tree_redraw_request(x, y, bbox->Width, bbox->Height, twin); ami_gui_free_space_box(bbox); } /** * Scrolls the tree to make an element visible * * \param y Y coordinate of the element * \param height height of the element * \param data user data assigned to the tree on tree creation */ static void ami_tree_scroll_visible(int y, int height, void *data) { int sy, scrollset; struct IBox *bbox; struct treeview_window *twin = data; GetAttr(SCROLLER_Top, twin->objects[OID_VSCROLL], (ULONG *)&sy); if(ami_gui_get_space_box(twin->objects[GID_BROWSER], &bbox) != NSERROR_OK) { warn_user("NoMemory", ""); return; } if((y > sy) && ((y + height) < (sy + bbox->Height))) { ami_gui_free_space_box(bbox); return; } if((y <= sy) || (height > bbox->Height)) scrollset = (ULONG)y; else scrollset = sy + (y + height) - (sy + bbox->Height); RefreshSetGadgetAttrs((APTR)twin->objects[OID_VSCROLL], twin->win, NULL, SCROLLER_Top, scrollset, TAG_DONE); ami_gui_free_space_box(bbox); ami_tree_draw(twin); } static void ami_tree_scroll(struct treeview_window *twin, int sx, int sy) { int x, y; if(!twin) return; GetAttr(SCROLLER_Top, twin->objects[OID_HSCROLL], (ULONG *)&x); GetAttr(SCROLLER_Top, twin->objects[OID_VSCROLL], (ULONG *)&y); x += sx; y += sy; if(y < 0) y = 0; if(x < 0) x = 0; RefreshSetGadgetAttrs((APTR)twin->objects[OID_VSCROLL], twin->win, NULL, SCROLLER_Top, y, TAG_DONE); RefreshSetGadgetAttrs((APTR)twin->objects[OID_HSCROLL], twin->win, NULL, SCROLLER_Top, x, TAG_DONE); ami_tree_draw(twin); } static void ami_tree_drag_icon_show(struct treeview_window *twin) { const char *type = "project"; nsurl *url = NULL; const char *title = NULL; if((twin->type == AMI_TREE_COOKIES) || (twin->type == AMI_TREE_SSLCERT)) return; /* No permissable drag operations */ if((tree_drag_status(twin->tree) == TREE_SELECT_DRAG) || (tree_drag_status(twin->tree) == TREE_TEXTAREA_DRAG)) return; if((twin->type == AMI_TREE_HOTLIST) && (hotlist_has_selection())) { hotlist_get_selection(&url, &title); } else if((twin->type == AMI_TREE_HISTORY) && (global_history_has_selection())) { global_history_get_selection(&url, &title); } if(title && (url == NULL)) { ami_drag_icon_show(twin->win, "drawer"); } else { ami_drag_icon_show(twin->win, type); } } static void ami_tree_drag_end(struct treeview_window *twin, int x, int y) { struct gui_window_2 *gwin; struct treeview_window *tw; BOOL drag; nsurl *url = NULL; const char *title = NULL; bool ok = false; if((drag = ami_drag_in_progress())) ami_drag_icon_close(twin->win); if(drag && (twin != ami_window_at_pointer(AMINS_TVWINDOW))) { if((twin->type == AMI_TREE_HOTLIST) && (hotlist_has_selection())) { ok = hotlist_get_selection(&url, &title); } else if((twin->type == AMI_TREE_HISTORY) && (global_history_has_selection())) { ok = global_history_get_selection(&url, &title); } if((ok == false) || (url == NULL)) { DisplayBeep(scrn); } else if(url) { if((gwin = ami_window_at_pointer(AMINS_WINDOW))) { browser_window_navigate(gwin->gw->bw, url, NULL, BW_NAVIGATE_HISTORY, NULL, NULL, NULL); } else if((tw = ami_window_at_pointer(AMINS_TVWINDOW)) && (tw != twin) && (tw->type == AMI_TREE_HOTLIST)) { hotlist_add_entry(url, title, true, y); } } tree_mouse_action(twin->tree, twin->mouse_state | twin->key_state, twin->drag_x, twin->drag_y); /* Keep the tree happy */ tree_drag_end(twin->tree, twin->mouse_state, twin->drag_x, twin->drag_y, twin->drag_x, twin->drag_y); /* Keep the tree happier */ } else { if(tree_drag_status(twin->tree) == TREE_UNKNOWN_DRAG) DisplayBeep(scrn); tree_drag_end(twin->tree, twin->mouse_state, twin->drag_x, twin->drag_y, x, y); } } HOOKF(void, ami_tree_scroller_hook, Object *, object, struct IntuiMessage *) { ULONG gid; struct treeview_window *twin = hook->h_Data; struct IntuiWheelData *wheel; switch(msg->Class) { case IDCMP_IDCMPUPDATE: gid = GetTagData( GA_ID, 0, msg->IAddress ); switch( gid ) { case OID_HSCROLL: case OID_VSCROLL: ami_tree_draw(twin); 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 } } static void ami_tree_menu(struct treeview_window *twin) { if(twin->menu) return; if((twin->menu = ami_misc_allocvec_clear(sizeof(struct NewMenu) * AMI_TREE_MENU_ITEMS, 0))) { twin->menu[0].nm_Type = NM_TITLE; twin->menu_name[0] = ami_utf8_easy((char *)messages_get("Tree")); twin->menu[0].nm_Label = twin->menu_name[0]; twin->menu[1].nm_Type = NM_ITEM; twin->menu_name[1] = ami_utf8_easy((char *)messages_get("TreeExport")); twin->menu[1].nm_Label = twin->menu_name[1]; if(twin->type == AMI_TREE_COOKIES) twin->menu[1].nm_Flags = NM_ITEMDISABLED; twin->menu[1].nm_CommKey = "S"; twin->menu[2].nm_Type = NM_ITEM; twin->menu[2].nm_Label = NM_BARLABEL; twin->menu[3].nm_Type = NM_ITEM; twin->menu_name[3] = ami_utf8_easy((char *)messages_get("Expand")); twin->menu[3].nm_Label = twin->menu_name[3]; twin->menu[4].nm_Type = NM_SUB; twin->menu_name[4] = ami_utf8_easy((char *)messages_get("All")); twin->menu[4].nm_Label = twin->menu_name[4]; twin->menu[4].nm_CommKey = "+"; if(twin->type == AMI_TREE_COOKIES) { twin->menu_name[5] = ami_utf8_easy((char *)messages_get("Domains")); twin->menu_name[6] = ami_utf8_easy((char *)messages_get("Cookies")); } else { twin->menu_name[5] = ami_utf8_easy((char *)messages_get("Folders")); twin->menu_name[6] = ami_utf8_easy((char *)messages_get("Links")); } twin->menu[5].nm_Type = NM_SUB; twin->menu[5].nm_Label = twin->menu_name[5]; // tree-specific title twin->menu[6].nm_Type = NM_SUB; twin->menu[6].nm_Label = twin->menu_name[6]; // tree-specific title twin->menu[7].nm_Type = NM_ITEM; twin->menu_name[7] = ami_utf8_easy((char *)messages_get("Collapse")); twin->menu[7].nm_Label = twin->menu_name[7]; twin->menu[8].nm_Type = NM_SUB; twin->menu[8].nm_Label = twin->menu_name[4]; twin->menu[8].nm_CommKey = "-"; twin->menu[9].nm_Type = NM_SUB; twin->menu[9].nm_Label = twin->menu_name[5]; // tree-specific title twin->menu[10].nm_Type = NM_SUB; twin->menu[10].nm_Label = twin->menu_name[6]; // tree-specific title twin->menu[11].nm_Type = NM_ITEM; twin->menu[11].nm_Label = NM_BARLABEL; twin->menu[12].nm_Type = NM_ITEM; twin->menu_name[12] = ami_utf8_easy((char *)messages_get("SnapshotWindow")); twin->menu[12].nm_Label = twin->menu_name[12]; twin->menu[13].nm_Type = NM_ITEM; twin->menu[13].nm_Label = NM_BARLABEL; twin->menu[14].nm_Type = NM_ITEM; twin->menu_name[14] = ami_utf8_easy((char *)messages_get("CloseWindow")); twin->menu[14].nm_Label = twin->menu_name[14]; twin->menu[14].nm_CommKey = "K"; twin->menu[15].nm_Type = NM_TITLE; twin->menu_name[15] = ami_utf8_easy((char *)messages_get("Edit")); twin->menu[15].nm_Label = twin->menu_name[15]; twin->menu[16].nm_Type = NM_ITEM; twin->menu_name[16] = ami_utf8_easy((char *)messages_get("TreeNewFolder")); twin->menu[16].nm_Label = twin->menu_name[16]; twin->menu[16].nm_CommKey = "N"; twin->menu[17].nm_Type = NM_ITEM; twin->menu_name[17] = ami_utf8_easy((char *)messages_get("TreeNewLink")); twin->menu[17].nm_Label = twin->menu_name[17]; twin->menu[18].nm_Type = NM_ITEM; twin->menu[18].nm_Label = NM_BARLABEL; twin->menu[19].nm_Type = NM_ITEM; twin->menu_name[19] = ami_utf8_easy((char *)messages_get("TreeEdit")); twin->menu[19].nm_Label = twin->menu_name[19]; twin->menu[19].nm_CommKey = "E"; twin->menu[20].nm_Type = NM_ITEM; twin->menu[20].nm_Label = NM_BARLABEL; twin->menu[21].nm_Type = NM_ITEM; twin->menu_name[21] = ami_utf8_easy((char *)messages_get("TreeDelete")); twin->menu[21].nm_Label = twin->menu_name[21]; twin->menu[21].nm_CommKey = "D"; twin->menu[22].nm_Type = NM_ITEM; twin->menu[22].nm_Label = NM_BARLABEL; twin->menu[23].nm_Type = NM_ITEM; twin->menu_name[23] = ami_utf8_easy((char *)messages_get("SelectAllNS")); twin->menu[23].nm_Label = twin->menu_name[23]; twin->menu[23].nm_CommKey = "A"; twin->menu[24].nm_Type = NM_ITEM; twin->menu_name[24] = ami_utf8_easy((char *)messages_get("ClearNS")); twin->menu[24].nm_Label = twin->menu_name[24]; twin->menu[25].nm_Type = NM_END; } } static void ami_tree_update_buttons(struct treeview_window *twin) { if(twin->type == AMI_TREE_SSLCERT) return; if(twin->type != AMI_TREE_HOTLIST) { OffMenu(twin->win, AMI_TREE_MENU_NEWDIR); OffMenu(twin->win, AMI_TREE_MENU_NEWURL); } if((twin->type == AMI_TREE_HOTLIST) && (hotlist_has_selection())) { OnMenu(twin->win, AMI_TREE_MENU_EDIT); } else { OffMenu(twin->win, AMI_TREE_MENU_EDIT); } if(((twin->type == AMI_TREE_HOTLIST) && (hotlist_has_selection())) || ((twin->type == AMI_TREE_COOKIES) && (cookie_manager_has_selection())) || ((twin->type == AMI_TREE_HISTORY) && (global_history_has_selection()))) { OnMenu(twin->win, AMI_TREE_MENU_DELETE); OnMenu(twin->win, AMI_TREE_MENU_CLEAR); } else { OffMenu(twin->win, AMI_TREE_MENU_DELETE); OffMenu(twin->win, AMI_TREE_MENU_CLEAR); } } void ami_tree_open(struct treeview_window *twin,int type) { if(twin->win) { WindowToFront(twin->win); ActivateWindow(twin->win); return; } twin->type = type; switch(twin->type) { case AMI_TREE_HOTLIST: twin->wintitle = ami_utf8_easy((char *)messages_get("Hotlist")); break; case AMI_TREE_COOKIES: twin->wintitle = ami_utf8_easy((char *)messages_get("Cookies")); break; case AMI_TREE_HISTORY: twin->wintitle = ami_utf8_easy((char *)messages_get("GlobalHistory")); break; case AMI_TREE_SSLCERT: twin->wintitle = ami_utf8_easy((char *)messages_get("SSLCerts")); twin->sslerr = ami_utf8_easy((char *)messages_get("SSLError")); twin->sslaccept = ami_utf8_easy((char *)messages_get("SSL_Certificate_Accept")); twin->sslreject = ami_utf8_easy((char *)messages_get("SSL_Certificate_Reject")); break; } twin->scrollerhook.h_Entry = (void *)ami_tree_scroller_hook; twin->scrollerhook.h_Data = twin; ami_init_layers(&twin->globals, 0, 0); ami_tree_menu(twin); if(type == AMI_TREE_SSLCERT) { twin->objects[OID_MAIN] = WindowObj, WA_ScreenTitle, ami_gui_get_screen_title(), WA_Title, twin->wintitle, WA_Activate, TRUE, WA_DepthGadget, TRUE, WA_DragBar, TRUE, WA_CloseGadget, TRUE, WA_SizeGadget, TRUE, WA_SizeBRight, 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_HorizProp,1, WINDOW_VertProp,1, WINDOW_IDCMPHook,&twin->scrollerhook, WINDOW_IDCMPHookBits,IDCMP_IDCMPUPDATE | IDCMP_EXTENDEDMOUSE, WINDOW_SharedPort,sport, WINDOW_UserData,twin, /* WINDOW_NewMenu, twin->menu, -> No menu for SSL Cert */ WINDOW_IconifyGadget, FALSE, WINDOW_Position, WPOS_CENTERSCREEN, WINDOW_ParentGroup, twin->objects[GID_MAIN] = LayoutVObj, LAYOUT_AddImage, LabelObject, LABEL_Text, twin->sslerr, LabelEnd, LAYOUT_AddChild, twin->objects[GID_BROWSER] = SpaceObj, GA_ID, GID_BROWSER, SPACE_Transparent,TRUE, SPACE_BevelStyle, BVS_DISPLAY, SpaceEnd, LAYOUT_AddChild, HGroupObject, LAYOUT_AddChild, twin->objects[GID_OPEN] = ButtonObj, GA_ID,GID_OPEN, GA_Text, twin->sslaccept, GA_RelVerify,TRUE, ButtonEnd, LAYOUT_AddChild, twin->objects[GID_CANCEL] = ButtonObj, GA_ID,GID_CANCEL, GA_Text, twin->sslreject, GA_RelVerify,TRUE, ButtonEnd, EndGroup, CHILD_WeightedHeight,0, EndGroup, EndWindow; } else { ULONG width = scrn->Width / 2; ULONG height = scrn->Height / 2; ULONG top = (scrn->Height / 2) - (height / 2); ULONG left = (scrn->Width / 2) - (width / 2); if((type == AMI_TREE_HOTLIST) && (nsoption_int(hotlist_window_xsize) > 0)) { top = nsoption_int(hotlist_window_ypos); left = nsoption_int(hotlist_window_xpos); width = nsoption_int(hotlist_window_xsize); height = nsoption_int(hotlist_window_ysize); } else if((type == AMI_TREE_HISTORY) && (nsoption_int(history_window_xsize) > 0)) { top = nsoption_int(history_window_ypos); left = nsoption_int(history_window_xpos); width = nsoption_int(history_window_xsize); height = nsoption_int(history_window_ysize); } else if((type == AMI_TREE_COOKIES) && (nsoption_int(cookies_window_xsize) > 0)) { top = nsoption_int(cookies_window_ypos); left = nsoption_int(cookies_window_xpos); width = nsoption_int(cookies_window_xsize); height = nsoption_int(cookies_window_ysize); } twin->objects[OID_MAIN] = WindowObj, WA_ScreenTitle, ami_gui_get_screen_title(), WA_Title, twin->wintitle, WA_Activate, TRUE, WA_DepthGadget, TRUE, WA_DragBar, TRUE, WA_CloseGadget, TRUE, WA_SizeGadget, TRUE, WA_SizeBRight, TRUE, WA_Top, top, WA_Left, left, WA_Width, width, WA_Height, height, WA_PubScreen,scrn, WA_ReportMouse,TRUE, WA_IDCMP, IDCMP_MOUSEMOVE | IDCMP_MOUSEBUTTONS | IDCMP_NEWSIZE | IDCMP_RAWKEY | IDCMP_GADGETUP | IDCMP_IDCMPUPDATE | IDCMP_EXTENDEDMOUSE | IDCMP_SIZEVERIFY | IDCMP_INTUITICKS, WINDOW_HorizProp,1, WINDOW_VertProp,1, WINDOW_IDCMPHook,&twin->scrollerhook, WINDOW_IDCMPHookBits,IDCMP_IDCMPUPDATE | IDCMP_EXTENDEDMOUSE, WINDOW_SharedPort,sport, WINDOW_UserData,twin, WINDOW_NewMenu, twin->menu, WINDOW_IconifyGadget, FALSE, // WINDOW_Position, WPOS_CENTERSCREEN, WINDOW_ParentGroup, twin->objects[GID_MAIN] = LayoutVObj, LAYOUT_AddChild, twin->objects[GID_BROWSER] = SpaceObj, GA_ID, GID_BROWSER, SPACE_Transparent,TRUE, SPACE_BevelStyle, BVS_DISPLAY, SpaceEnd, EndGroup, EndWindow; } twin->win = (struct Window *)RA_OpenWindow(twin->objects[OID_MAIN]); GetAttr(WINDOW_HorizObject, twin->objects[OID_MAIN], (ULONG *)&twin->objects[OID_HSCROLL]); GetAttr(WINDOW_VertObject, twin->objects[OID_MAIN], (ULONG *)&twin->objects[OID_VSCROLL]); RefreshSetGadgetAttrs((APTR)twin->objects[OID_VSCROLL], twin->win, NULL, GA_ID,OID_VSCROLL, ICA_TARGET,ICTARGET_IDCMP, TAG_DONE); RefreshSetGadgetAttrs((APTR)twin->objects[OID_HSCROLL], twin->win, NULL, GA_ID,OID_HSCROLL, ICA_TARGET,ICTARGET_IDCMP, TAG_DONE); twin->node = AddObject(window_list,AMINS_TVWINDOW); twin->node->objstruct = twin; ami_tree_update_buttons(twin); ami_tree_resized(twin->tree, twin->max_width, twin->max_height, twin); ami_tree_draw(twin); } void ami_tree_close(struct treeview_window *twin) { int i; twin->win = NULL; DisposeObject(twin->objects[OID_MAIN]); DelObjectNoFree(twin->node); ami_free_layers(&twin->globals); ami_plot_release_pens(&twin->shared_pens); for(i=0;i<AMI_TREE_MENU_ITEMS;i++) { if(twin->menu_name[i] && (twin->menu_name[i] != NM_BARLABEL)) ami_utf8_free(twin->menu_name[i]); } FreeVec(twin->menu); twin->menu = NULL; ami_utf8_free(twin->wintitle); if(twin->type == AMI_TREE_SSLCERT) { ami_utf8_free(twin->sslerr); ami_utf8_free(twin->sslaccept); ami_utf8_free(twin->sslreject); ami_ssl_free(twin); } if(twin->type == AMI_TREE_HOTLIST) ami_gui_hotlist_update_all(); } static void ami_tree_update_quals(struct treeview_window *twin) { uint32 quals = 0; #ifdef __amigaos4__ GetAttr(WINDOW_Qualifier, twin->objects[OID_MAIN], (uint32 *)&quals); #else #warning FIXME not reading qualifiers on OS3 #endif twin->key_state = 0; if((quals & IEQUALIFIER_LSHIFT) || (quals & IEQUALIFIER_RSHIFT)) { twin->key_state |= BROWSER_MOUSE_MOD_1; } if(quals & IEQUALIFIER_CONTROL) { twin->key_state |= BROWSER_MOUSE_MOD_2; } if((quals & IEQUALIFIER_LALT) || (quals & IEQUALIFIER_RALT)) { twin->key_state |= BROWSER_MOUSE_MOD_3; } } BOOL ami_tree_event(struct treeview_window *twin) { /* return TRUE if window destroyed */ ULONG result,storage = 0; uint16 code; struct MenuItem *item; ULONG menunum=0,itemnum=0,subnum=0; int xs, ys, x, y; struct IBox *bbox; struct timeval curtime; struct InputEvent *ie; int nskey; char fname[1024]; static int drag_x_move = 0, drag_y_move = 0; while((result = RA_HandleInput(twin->objects[OID_MAIN],&code)) != WMHI_LASTMSG) { switch(result & WMHI_CLASSMASK) // class { case WMHI_GADGETUP: switch(result & WMHI_GADGETMASK) { case GID_OPEN: sslcert_viewer_accept(twin->ssl_data); ami_tree_close(twin); return TRUE; break; case GID_CANCEL: sslcert_viewer_reject(twin->ssl_data); ami_tree_close(twin); return TRUE; break; } break; case WMHI_MOUSEMOVE: drag_x_move = 0; drag_y_move = 0; if(ami_gui_get_space_box(twin->objects[GID_BROWSER], &bbox) != NSERROR_OK) { warn_user("NoMemory", ""); break; } if((twin->win->MouseX - bbox->Left >=0) && (twin->win->MouseX - bbox->Width - bbox->Left <=0) && (twin->win->MouseY - bbox->Top >=0) && (twin->win->MouseY - bbox->Height - bbox->Top <=0)) { if((twin->type != AMI_TREE_SSLCERT) && (twin->rmbtrapped == FALSE)) { #ifdef __amigaos4__ SetWindowAttr(twin->win, WA_RMBTrap, (APTR)(BOOL)TRUE, sizeof(BOOL)); #endif twin->rmbtrapped = TRUE; } } else { if(twin->rmbtrapped == TRUE) { #ifdef __amigaos4__ SetWindowAttr(twin->win, WA_RMBTrap, (APTR)(BOOL)FALSE, sizeof(BOOL)); #endif twin->rmbtrapped = FALSE; } } GetAttr(SCROLLER_Top, twin->objects[OID_HSCROLL], (ULONG *)&xs); x = twin->win->MouseX - bbox->Left + xs; GetAttr(SCROLLER_Top, twin->objects[OID_VSCROLL], (ULONG *)&ys); y = twin->win->MouseY - bbox->Top + ys; if(twin->mouse_state & BROWSER_MOUSE_DRAG_ON) { ami_drag_icon_move(); if((twin->win->MouseX < bbox->Left) && ((twin->win->MouseX - bbox->Left) > -AMI_DRAG_THRESHOLD)) drag_x_move = twin->win->MouseX - bbox->Left; if((twin->win->MouseX > (bbox->Left + bbox->Width)) && ((twin->win->MouseX - (bbox->Left + bbox->Width)) < AMI_DRAG_THRESHOLD)) drag_x_move = twin->win->MouseX - (bbox->Left + bbox->Width); if((twin->win->MouseY < bbox->Top) && ((twin->win->MouseY - bbox->Top) > -AMI_DRAG_THRESHOLD)) drag_y_move = twin->win->MouseY - bbox->Top; if((twin->win->MouseY > (bbox->Top + bbox->Height)) && ((twin->win->MouseY - (bbox->Top + bbox->Height)) < AMI_DRAG_THRESHOLD)) drag_y_move = twin->win->MouseY - (bbox->Top + bbox->Height); tree_mouse_action(twin->tree, twin->mouse_state | twin->key_state, x, y); } if((x >= xs) && (y >= ys) && (x < bbox->Width + xs) && (y < bbox->Height + ys)) { ami_tree_update_quals(twin); if(twin->mouse_state & BROWSER_MOUSE_PRESS_1) { if((abs(x - twin->drag_x) + abs(y - twin->drag_y)) > 2) { tree_mouse_action(twin->tree, BROWSER_MOUSE_DRAG_1 | twin->key_state, x, y); twin->mouse_state = BROWSER_MOUSE_HOLDING_1 | BROWSER_MOUSE_DRAG_ON; ami_tree_drag_icon_show(twin); } } else if(twin->mouse_state & BROWSER_MOUSE_PRESS_2) { if((abs(x - twin->drag_x) + abs(y - twin->drag_y)) > 2) { tree_mouse_action(twin->tree, BROWSER_MOUSE_DRAG_2 | twin->key_state, x, y); twin->mouse_state = BROWSER_MOUSE_HOLDING_2 | BROWSER_MOUSE_DRAG_ON; ami_tree_drag_icon_show(twin); } } } ami_gui_free_space_box(bbox); twin->lastclick.tv_sec = 0; twin->lastclick.tv_usec = 0; break; case WMHI_MOUSEBUTTONS: if(ami_gui_get_space_box((Object *)twin->objects[GID_BROWSER], &bbox) != NSERROR_OK) { warn_user("NoMemory", ""); break; } GetAttr(SCROLLER_Top, twin->objects[OID_HSCROLL], (ULONG *)&xs); x = twin->win->MouseX - bbox->Left + xs; GetAttr(SCROLLER_Top, twin->objects[OID_VSCROLL], (ULONG *)&ys); y = twin->win->MouseY - bbox->Top + ys; ami_tree_update_quals(twin); if((x >= xs) && (y >= ys) && (x < bbox->Width + xs) && (y < bbox->Height + ys)) { switch(code) { case SELECTDOWN: twin->mouse_state = BROWSER_MOUSE_PRESS_1; if(twin->drag_x == 0) twin->drag_x = x; if(twin->drag_y == 0) twin->drag_y = y; break; case MIDDLEDOWN: twin->mouse_state = BROWSER_MOUSE_PRESS_2; if(twin->drag_x == 0) twin->drag_x = x; if(twin->drag_y == 0) twin->drag_y = y; break; case MENUDOWN: #if 0 if(tree_node_has_selection(tree_get_root(twin->tree)) == false) { tree_set_node_selected_at(twin->tree, x, y, true); } ami_context_menu_show_tree(twin->tree, twin->win, twin->type); #endif break; } } if(x < xs) x = xs; if(y < ys) y = ys; if(x >= bbox->Width + xs) x = bbox->Width + xs - 1; if(y >= bbox->Height + ys) y = bbox->Height + ys - 1; ami_gui_free_space_box(bbox); switch(code) { case SELECTUP: if(twin->mouse_state & BROWSER_MOUSE_PRESS_1) { CurrentTime((ULONG *)&curtime.tv_sec, (ULONG *)&curtime.tv_usec); twin->mouse_state = BROWSER_MOUSE_CLICK_1; if(twin->lastclick.tv_sec) { if(DoubleClick(twin->lastclick.tv_sec, twin->lastclick.tv_usec, curtime.tv_sec, curtime.tv_usec)) twin->mouse_state |= BROWSER_MOUSE_DOUBLE_CLICK; } tree_mouse_action(twin->tree, twin->mouse_state | twin->key_state, x, y); if(twin->mouse_state & BROWSER_MOUSE_DOUBLE_CLICK) { twin->lastclick.tv_sec = 0; twin->lastclick.tv_usec = 0; } else { twin->lastclick.tv_sec = curtime.tv_sec; twin->lastclick.tv_usec = curtime.tv_usec; } } else ami_tree_drag_end(twin, x, y); twin->mouse_state=0; twin->drag_x = 0; twin->drag_y = 0; break; case MIDDLEUP: if(twin->mouse_state & BROWSER_MOUSE_PRESS_2) { CurrentTime((ULONG *)&curtime.tv_sec, (ULONG *)&curtime.tv_usec); twin->mouse_state = BROWSER_MOUSE_CLICK_2; if(twin->lastclick.tv_sec) { if(DoubleClick(twin->lastclick.tv_sec, twin->lastclick.tv_usec, curtime.tv_sec, curtime.tv_usec)) twin->mouse_state |= BROWSER_MOUSE_DOUBLE_CLICK; } tree_mouse_action(twin->tree, twin->mouse_state | twin->key_state, x, y); if(twin->mouse_state & BROWSER_MOUSE_DOUBLE_CLICK) { twin->lastclick.tv_sec = 0; twin->lastclick.tv_usec = 0; } else { twin->lastclick.tv_sec = curtime.tv_sec; twin->lastclick.tv_usec = curtime.tv_usec; } } else ami_tree_drag_end(twin, x, y); twin->mouse_state=0; twin->drag_x = 0; twin->drag_y = 0; break; case SELECTDOWN: case MIDDLEDOWN: tree_mouse_action(twin->tree, twin->mouse_state | twin->key_state, x, y); break; } ami_tree_update_buttons(twin); break; case WMHI_RAWKEY: storage = result & WMHI_GADGETMASK; GetAttr(WINDOW_InputEvent,twin->objects[OID_MAIN],(ULONG *)&ie); nskey = ami_key_to_nskey(storage, ie); tree_keypress(twin->tree, nskey); if(nskey == NS_KEY_COPY_SELECTION) { /* if we've copied a selection we need to clear it - style guide rules */ tree_keypress(twin->tree, NS_KEY_CLEAR_SELECTION); } break; case WMHI_MENUPICK: item = ItemAddress(twin->win->MenuStrip,code); while (code != MENUNULL) { menunum = MENUNUM(code); itemnum = ITEMNUM(code); subnum = SUBNUM(code); switch(menunum) { case 0: // tree switch(itemnum) { case 0: // export if(AslRequestTags(savereq, ASLFR_Window, twin->win, ASLFR_SleepWindow, TRUE, ASLFR_TitleText,messages_get("NetSurf"), ASLFR_Screen,scrn, ASLFR_InitialFile,"tree_export.html", TAG_DONE)) { strlcpy(fname,savereq->fr_Drawer,1024); AddPart(fname,savereq->fr_File,1024); ami_update_pointer(twin->win, GUI_POINTER_WAIT); if(twin->type == AMI_TREE_HISTORY) global_history_export(fname, NULL); else if(twin->type == AMI_TREE_HOTLIST) hotlist_export(fname, NULL); ami_update_pointer(twin->win, GUI_POINTER_DEFAULT); } break; case 2: // expand switch(subnum) { case 0: // all switch(twin->type) { case AMI_TREE_HISTORY: global_history_expand(false); break; case AMI_TREE_COOKIES: cookie_manager_expand(false); break; case AMI_TREE_HOTLIST: hotlist_expand(false); break; } break; case 1: // lev 1 switch(twin->type) { case AMI_TREE_HISTORY: global_history_expand(true); break; case AMI_TREE_COOKIES: cookie_manager_expand(true); break; case AMI_TREE_HOTLIST: hotlist_expand(true); break; } break; case 2: // lev 2 switch(twin->type) { case AMI_TREE_HISTORY: global_history_expand(false); break; case AMI_TREE_COOKIES: cookie_manager_expand(false); break; case AMI_TREE_HOTLIST: hotlist_expand(false); break; } break; } break; case 3: // collapse switch(subnum) { case 0: // all switch(twin->type) { case AMI_TREE_HISTORY: global_history_contract(true); break; case AMI_TREE_COOKIES: cookie_manager_contract(true); break; case AMI_TREE_HOTLIST: hotlist_contract(true); break; } break; case 1: // lev 1 switch(twin->type) { case AMI_TREE_HISTORY: global_history_contract(true); break; case AMI_TREE_COOKIES: cookie_manager_contract(true); break; case AMI_TREE_HOTLIST: hotlist_contract(true); break; } break; case 2: // lev 2 switch(twin->type) { case AMI_TREE_HISTORY: global_history_contract(false); break; case AMI_TREE_COOKIES: cookie_manager_contract(false); break; case AMI_TREE_HOTLIST: hotlist_contract(false); break; } break; } break; case 5: // snapshot switch(twin->type) { case AMI_TREE_HISTORY: nsoption_set_int(history_window_ypos, twin->win->TopEdge); nsoption_set_int(history_window_xpos, twin->win->LeftEdge); nsoption_set_int(history_window_xsize, twin->win->Width); nsoption_set_int(history_window_ysize, twin->win->Height); break; case AMI_TREE_COOKIES: nsoption_set_int(cookies_window_ypos, twin->win->TopEdge); nsoption_set_int(cookies_window_xpos, twin->win->LeftEdge); nsoption_set_int(cookies_window_xsize, twin->win->Width); nsoption_set_int(cookies_window_ysize, twin->win->Height); break; case AMI_TREE_HOTLIST: nsoption_set_int(hotlist_window_ypos, twin->win->TopEdge); nsoption_set_int(hotlist_window_xpos, twin->win->LeftEdge); nsoption_set_int(hotlist_window_xsize, twin->win->Width); nsoption_set_int(hotlist_window_ysize, twin->win->Height); break; } break; case 7: // close ami_tree_close(twin); return TRUE; break; } break; case 1: // edit switch(itemnum) { case 0: // new folder hotlist_add_folder(NULL, false, 0); break; case 1: // new entry hotlist_add_entry(NULL, NULL, false, 0); break; case 3: // edit hotlist_edit_selection(); break; case 5: // delete switch(twin->type) { case AMI_TREE_HISTORY: global_history_keypress(NS_KEY_DELETE_LEFT); break; case AMI_TREE_COOKIES: cookie_manager_keypress(NS_KEY_DELETE_LEFT); break; case AMI_TREE_HOTLIST: hotlist_keypress(NS_KEY_DELETE_LEFT); break; } ami_tree_update_buttons(twin); break; case 7: // select all switch(twin->type) { case AMI_TREE_HISTORY: global_history_keypress(NS_KEY_SELECT_ALL); break; case AMI_TREE_COOKIES: cookie_manager_keypress(NS_KEY_SELECT_ALL); break; case AMI_TREE_HOTLIST: hotlist_keypress(NS_KEY_SELECT_ALL); break; } ami_tree_update_buttons(twin); break; case 8: // clear switch(twin->type) { case AMI_TREE_HISTORY: global_history_keypress(NS_KEY_CLEAR_SELECTION); break; case AMI_TREE_COOKIES: cookie_manager_keypress(NS_KEY_CLEAR_SELECTION); break; case AMI_TREE_HOTLIST: hotlist_keypress(NS_KEY_CLEAR_SELECTION); break; } ami_tree_update_buttons(twin); break; } break; } code = item->NextSelect; } break; case WMHI_NEWSIZE: ami_tree_resized(twin->tree, twin->max_width, twin->max_height, twin); ami_tree_draw(twin); break; case WMHI_CLOSEWINDOW: if(twin->type == AMI_TREE_SSLCERT) sslcert_viewer_reject(twin->ssl_data); ami_tree_close(twin); return TRUE; break; } } if(drag_x_move || drag_y_move) ami_tree_scroll(twin, drag_x_move, drag_y_move); return FALSE; } const struct treeview_table ami_tree_callbacks = { .redraw_request = ami_tree_redraw_request, .resized = ami_tree_resized, .scroll_visible = ami_tree_scroll_visible, .get_window_dimensions = ami_tree_get_window_dimensions }; struct treeview_window *ami_tree_create(int flags, struct sslcert_session_data *ssl_data) { struct treeview_window *twin; twin = ami_misc_allocvec_clear(sizeof(struct treeview_window), 0); if(!twin) { warn_user("NoMemory", 0); return NULL; } twin->ssl_data = ssl_data; twin->tree = tree_create(flags, &ami_tree_callbacks, twin); ami_NewMinList(&twin->shared_pens); twin->globals.shared_pens = &twin->shared_pens; return twin; }