netsurf/amiga/tree.c
Chris Young e19d30027a Remove RMB trapping from the treeviews, previously used for context menus
The context menus for treeviews were removed ages ago, and any replacement won't need RMB trapping
2016-02-14 14:21:52 +00:00

1469 lines
40 KiB
C

/*
* 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;
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, false);
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, LabelObj,
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, LayoutHObj,
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_plot_release_pens(twin->shared_pens);
ami_free_layers(&twin->globals);
FreeVec(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;
}
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);
twin->shared_pens = ami_AllocMinList();
twin->globals.shared_pens = twin->shared_pens;
return twin;
}