1 /*
2  * Copyright 2015 Chris Young <chris@unsatisfactorysoftware.co.uk>
3  *
4  * This file is part of NetSurf, http://www.netsurf-browser.org/
5  *
6  * NetSurf is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; version 2 of the License.
9  *
10  * NetSurf is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 /** \file
20  * Intuition-based context menu operations
21  */
22 
23 #ifdef __amigaos4__
24 #include <string.h>
25 
26 #include <stdlib.h>
27 #include <proto/exec.h>
28 #include <proto/intuition.h>
29 
30 #include <proto/bitmap.h>
31 #include <images/bitmap.h>
32 #include <proto/window.h>
33 #include <classes/window.h>
34 
35 #include <intuition/menuclass.h>
36 #include <reaction/reaction_macros.h>
37 
38 #include "utils/utils.h"
39 #include "utils/log.h"
40 #include "utils/messages.h"
41 #include "utils/nsoption.h"
42 #include "utils/nsurl.h"
43 #include "netsurf/content.h"
44 #include "netsurf/browser_window.h"
45 #include "netsurf/mouse.h"
46 #include "netsurf/keypress.h"
47 #include "desktop/browser_history.h"
48 #include "desktop/searchweb.h"
49 
50 #include "amiga/bitmap.h"
51 #include "amiga/clipboard.h"
52 #include "amiga/ctxmenu.h"
53 #include "amiga/filetype.h"
54 #include "amiga/gui.h"
55 #include "amiga/libs.h"
56 #include "amiga/plugin_hack.h"
57 #include "amiga/theme.h"
58 #include "amiga/utf8.h"
59 #include "amiga/misc.h"
60 
61 enum {
62 	AMI_CTX_ID_NONE = 0,
63 
64 	/* Text selection */
65 	AMI_CTX_ID_SELCOPY,
66 	AMI_CTX_ID_WEBSEARCH,
67 
68 	/* Links */
69 	AMI_CTX_ID_URLOPENTAB,
70 	AMI_CTX_ID_URLOPENWIN,
71 	AMI_CTX_ID_URLDOWNLOAD,
72 	AMI_CTX_ID_URLCOPY,
73 
74 	/* Objects */
75 	AMI_CTX_ID_OBJSHOW,
76 	AMI_CTX_ID_OBJCOPY,
77 	AMI_CTX_ID_OBJCMD,
78 
79 	/* Frames */
80 	AMI_CTX_ID_FRAMESHOW,
81 
82 	/* History */
83 	AMI_CTX_ID_HISTORY,
84 	AMI_CTX_ID_HISTORY0,
85 	AMI_CTX_ID_HISTORY9F = AMI_CTX_ID_HISTORY0 + 19,
86 
87 	/* Tabs */
88 	AMI_CTX_ID_TABNEW,
89 	AMI_CTX_ID_TABCLOSE_OTHER,
90 
91 	AMI_CTX_ID_MAX
92 };
93 
94 static Object *ctxmenu_obj = NULL;
95 
96 static struct Hook ctxmenu_item_hook[AMI_CTX_ID_MAX];
97 static char *ctxmenu_item_label[AMI_CTX_ID_MAX];
98 static char *ctxmenu_item_shortcut[AMI_CTX_ID_MAX];
99 static Object *ctxmenu_item_image[AMI_CTX_ID_MAX];
100 
101 /****************************
102  * Menu item hook functions *
103  ****************************/
104 
105 /** Menu functions - called automatically by RA_HandleInput **/
HOOKF(void,ami_ctxmenu_item_selcopy,APTR,window,struct IntuiMessage *)106 HOOKF(void, ami_ctxmenu_item_selcopy, APTR, window, struct IntuiMessage *)
107 {
108 	struct gui_window_2 *gwin = (struct gui_window_2 *)hook->h_Data;
109 
110 	browser_window_key_press(ami_gui2_get_browser_window(gwin), NS_KEY_COPY_SELECTION);
111 	browser_window_key_press(ami_gui2_get_browser_window(gwin), NS_KEY_CLEAR_SELECTION);
112 }
113 
HOOKF(void,ami_ctxmenu_item_websearch,APTR,window,struct IntuiMessage *)114 HOOKF(void, ami_ctxmenu_item_websearch, APTR, window, struct IntuiMessage *)
115 {
116 	nserror ret = NSERROR_OK;
117 	nsurl *url;
118 
119 	struct gui_window_2 *gwin = (struct gui_window_2 *)hook->h_Data;
120 	char *sel = browser_window_get_selection(ami_gui2_get_browser_window(gwin));
121 
122 	ret = search_web_omni(sel, SEARCH_WEB_OMNI_SEARCHONLY, &url);
123 	if (ret == NSERROR_OK) {
124 			browser_window_navigate(ami_gui2_get_browser_window(gwin),
125 					url,
126 					NULL,
127 					BW_NAVIGATE_HISTORY,
128 					NULL,
129 					NULL,
130 					NULL);
131 		nsurl_unref(url);
132 	}
133 	if (ret != NSERROR_OK) {
134 		amiga_warn_user(messages_get_errorcode(ret), 0);
135 	}
136 
137 	free(sel);
138 }
139 
HOOKF(void,ami_ctxmenu_item_urlopentab,APTR,window,struct IntuiMessage *)140 HOOKF(void, ami_ctxmenu_item_urlopentab, APTR, window, struct IntuiMessage *)
141 {
142 	struct browser_window *bw;
143 	nsurl *url = (nsurl *)hook->h_Data;
144 	struct gui_window_2 *gwin;
145 
146 	GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);
147 	nserror error = browser_window_create(BW_CREATE_CLONE | BW_CREATE_HISTORY | BW_CREATE_TAB,
148 								      url,
149 								      browser_window_access_url(ami_gui2_get_browser_window(gwin)),
150 								      ami_gui2_get_browser_window(gwin),
151 								      &bw);
152 
153 	if (error != NSERROR_OK)
154 		amiga_warn_user(messages_get_errorcode(error), 0);
155 }
156 
HOOKF(void,ami_ctxmenu_item_urlopenwin,APTR,window,struct IntuiMessage *)157 HOOKF(void, ami_ctxmenu_item_urlopenwin, APTR, window, struct IntuiMessage *)
158 {
159 	struct browser_window *bw;
160 	nsurl *url = (nsurl *)hook->h_Data;
161 	struct gui_window_2 *gwin;
162 
163 	GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);
164 	nserror error = browser_window_create(BW_CREATE_CLONE | BW_CREATE_HISTORY,
165 								      url,
166 								      browser_window_access_url(ami_gui2_get_browser_window(gwin)),
167 								      ami_gui2_get_browser_window(gwin),
168 								      &bw);
169 
170 	if (error != NSERROR_OK)
171 		amiga_warn_user(messages_get_errorcode(error), 0);
172 }
173 
HOOKF(void,ami_ctxmenu_item_urldownload,APTR,window,struct IntuiMessage *)174 HOOKF(void, ami_ctxmenu_item_urldownload, APTR, window, struct IntuiMessage *)
175 {
176 	nsurl *url = (nsurl *)hook->h_Data;
177 	struct gui_window_2 *gwin;
178 
179 	GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);
180 
181 	browser_window_navigate(ami_gui2_get_browser_window(gwin),
182 		url,
183 		browser_window_access_url(ami_gui2_get_browser_window(gwin)),
184 		BW_NAVIGATE_DOWNLOAD,
185 		NULL,
186 		NULL,
187 		NULL);
188 }
189 
HOOKF(void,ami_ctxmenu_item_urlcopy,APTR,window,struct IntuiMessage *)190 HOOKF(void, ami_ctxmenu_item_urlcopy, APTR, window, struct IntuiMessage *)
191 {
192 	nsurl *url = (nsurl *)hook->h_Data;
193 	ami_easy_clipboard(nsurl_access(url));
194 }
195 
HOOKF(void,ami_ctxmenu_item_objshow,APTR,window,struct IntuiMessage *)196 HOOKF(void, ami_ctxmenu_item_objshow, APTR, window, struct IntuiMessage *)
197 {
198 	struct gui_window_2 *gwin;
199 	GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);
200 
201 	browser_window_navigate(ami_gui2_get_browser_window(gwin),
202 							hlcache_handle_get_url(hook->h_Data),
203 							browser_window_access_url(ami_gui2_get_browser_window(gwin)),
204 							BW_NAVIGATE_HISTORY,
205 							NULL,
206 							NULL,
207 							NULL);
208 }
209 
HOOKF(void,ami_ctxmenu_item_objcopy,APTR,window,struct IntuiMessage *)210 HOOKF(void, ami_ctxmenu_item_objcopy, APTR, window, struct IntuiMessage *)
211 {
212 	struct bitmap *bm;
213 	struct gui_window_2 *gwin;
214 	GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);
215 
216 	struct hlcache_handle *object = (struct hlcache_handle *)hook->h_Data;
217 	if((bm = content_get_bitmap(object)))
218 	{
219 		ami_bitmap_set_url(bm, hlcache_handle_get_url(object));
220 		ami_bitmap_set_title(bm, content_get_title(object));
221 		ami_easy_clipboard_bitmap(bm);
222 	}
223 #ifdef WITH_NS_SVG
224 	else if(ami_mime_compare(object, "svg") == true)
225 	{
226 		ami_easy_clipboard_svg(object);
227 	}
228 #endif
229 }
230 
HOOKF(void,ami_ctxmenu_item_objcmd,APTR,window,struct IntuiMessage *)231 HOOKF(void, ami_ctxmenu_item_objcmd, APTR, window, struct IntuiMessage *)
232 {
233 	amiga_plugin_hack_execute((struct hlcache_handle *)hook->h_Data);
234 }
235 
HOOKF(void,ami_ctxmenu_item_frameshow,APTR,window,struct IntuiMessage *)236 HOOKF(void, ami_ctxmenu_item_frameshow, APTR, window, struct IntuiMessage *)
237 {
238 	struct gui_window_2 *gwin;
239 	GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);
240 
241 	browser_window_navigate(ami_gui2_get_browser_window(gwin),
242 							hlcache_handle_get_url(hook->h_Data),
243 							browser_window_access_url(ami_gui2_get_browser_window(gwin)),
244 							BW_NAVIGATE_HISTORY,
245 							NULL,
246 							NULL,
247 							NULL);
248 }
249 
250 /** Hooks for clicktab context menu entries **/
HOOKF(void,ami_ctxmenu_item_tabnew,APTR,window,struct IntuiMessage *)251 HOOKF(void, ami_ctxmenu_item_tabnew, APTR, window, struct IntuiMessage *)
252 {
253 	struct gui_window_2 *gwin;
254 
255 	GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);
256 	ami_gui_new_blank_tab(gwin);
257 }
258 
HOOKF(void,ami_ctxmenu_item_tabclose_other,APTR,window,struct IntuiMessage *)259 HOOKF(void, ami_ctxmenu_item_tabclose_other, APTR, window, struct IntuiMessage *)
260 {
261 	struct gui_window_2 *gwin;
262 
263 	GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);
264 	ami_gui_close_inactive_tabs(gwin);
265 }
266 
267 /** Hook for history context menu entries **/
HOOKF(void,ami_ctxmenu_item_history,APTR,window,struct IntuiMessage *)268 HOOKF(void, ami_ctxmenu_item_history, APTR, window, struct IntuiMessage *)
269 {
270 	struct gui_window_2 *gwin;
271 
272 	GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);
273 
274 	browser_window_history_go(ami_gui2_get_browser_window(gwin),
275 		(struct history_entry *)hook->h_Data, false);
276 }
277 
278 
279 /*************************
280  * Browser context menus *
281  *************************/
282 
283 /** Add an initialised item to a context menu **/
ami_ctxmenu_add_item(Object * root_menu,int id,APTR data)284 static void ami_ctxmenu_add_item(Object *root_menu, int id, APTR data)
285 {
286 	ctxmenu_item_hook[id].h_Data = data;
287 
288 	IDoMethod(root_menu, OM_ADDMEMBER, MStrip,
289 							MA_Type, T_ITEM,
290 							MA_ID, id,
291 							MA_Label, ctxmenu_item_label[id],
292 							MA_Key, ctxmenu_item_shortcut[id],
293 							MA_Image, ctxmenu_item_image[id],
294 							MA_UserData, &ctxmenu_item_hook[id],
295 						MEnd);
296 }
297 
298 /** Hook function called by Intuition, creates context menu structure **/
ami_ctxmenu_hook_func(struct Hook * hook,struct Window * window,struct ContextMenuMsg * msg)299 static uint32 ami_ctxmenu_hook_func(struct Hook *hook, struct Window *window, struct ContextMenuMsg *msg)
300 {
301 	Object *root_menu;
302 	bool ctxmenu_has_content = false;
303 	struct gui_window_2 *gwin = hook->h_Data;
304 	struct hlcache_handle *cc = browser_window_get_content(ami_gui2_get_browser_window(gwin));
305 	struct browser_window_features ccdata;
306 	int mx = window->MouseX;
307 	int my = window->MouseY;
308 	int x, y;
309 	char *sel;
310 
311 	if(msg->State != CM_QUERY) return 0;
312 	if(nsoption_bool(kiosk_mode) == true) return 0;
313 // check window is active
314 
315 	if(ctxmenu_obj != NULL) DisposeObject(ctxmenu_obj);
316 
317 	ctxmenu_obj = MStrip,
318 					MA_Type, T_ROOT,
319 					MA_AddChild, root_menu = MStrip,
320 						MA_Type, T_MENU,
321 						MA_Label, NULL, //"NetSurf",
322 						MA_EmbeddedKey, FALSE,
323 						MA_FreeImage, FALSE,
324 					MEnd,
325 				MEnd;
326 
327 	if(ami_mouse_to_ns_coords(gwin, &x, &y, mx, my) == false) {
328 		/* Outside browser render area */
329 		return 0;
330 	}
331 
332 	browser_window_get_features(ami_gui2_get_browser_window(gwin), x, y, &ccdata);
333 
334 	if((browser_window_can_select(ami_gui2_get_browser_window(gwin))) &&
335 		((browser_window_get_editor_flags(ami_gui2_get_browser_window(gwin)) & BW_EDITOR_CAN_COPY)) &&
336 		(sel = browser_window_get_selection(ami_gui2_get_browser_window(gwin)))) {
337 
338 		ami_ctxmenu_add_item(root_menu, AMI_CTX_ID_SELCOPY, gwin);
339 		ami_ctxmenu_add_item(root_menu, AMI_CTX_ID_WEBSEARCH, gwin);
340 
341 		ctxmenu_has_content = true;
342 		free(sel);
343 	}
344 
345 	if(ccdata.link) {
346 		if(ctxmenu_has_content == true)
347 			ami_ctxmenu_add_item(root_menu, AMI_CTX_ID_NONE, NULL);
348 
349 		ami_ctxmenu_add_item(root_menu, AMI_CTX_ID_URLOPENTAB, ccdata.link);
350 		ami_ctxmenu_add_item(root_menu, AMI_CTX_ID_URLOPENWIN, ccdata.link);
351 		ami_ctxmenu_add_item(root_menu, AMI_CTX_ID_URLDOWNLOAD, ccdata.link);
352 		ami_ctxmenu_add_item(root_menu, AMI_CTX_ID_URLCOPY, ccdata.link);
353 		ctxmenu_has_content = true;
354 	}
355 
356 	if(ccdata.object) {
357 		if(ctxmenu_has_content == true)
358 			ami_ctxmenu_add_item(root_menu, AMI_CTX_ID_NONE, NULL);
359 
360 		ami_ctxmenu_add_item(root_menu, AMI_CTX_ID_OBJSHOW, ccdata.object);
361 
362 		if(content_get_type(ccdata.object) == CONTENT_IMAGE)
363 			ami_ctxmenu_add_item(root_menu, AMI_CTX_ID_OBJCOPY, ccdata.object);
364 
365 		if(ami_mime_content_to_cmd(ccdata.object))
366 			ami_ctxmenu_add_item(root_menu, AMI_CTX_ID_OBJCMD, ccdata.object);
367 
368 		ctxmenu_has_content = true;
369 	}
370 
371 	if(ccdata.main && (ccdata.main != cc)) {
372 		if(ctxmenu_has_content == true)
373 			ami_ctxmenu_add_item(root_menu, AMI_CTX_ID_NONE, NULL);
374 
375 		ami_ctxmenu_add_item(root_menu, AMI_CTX_ID_FRAMESHOW, ccdata.main);
376 
377 		ctxmenu_has_content = true;
378 	}
379 
380 	if(ctxmenu_has_content == true) {
381 		msg->Menu = ctxmenu_obj;
382 		ami_set_pointer(gwin, GUI_POINTER_DEFAULT, false);
383 	}
384 
385 	return 0;
386 }
387 
388 /** Initial menu item creation **/
ami_ctxmenu_alloc_item(int id,const char * label,const char * key,const char * image,void * func)389 static void ami_ctxmenu_alloc_item(int id, const char *label, const char *key, const char *image, void *func)
390 {
391 	if(label == ML_SEPARATOR) {
392 		ctxmenu_item_label[id] = ML_SEPARATOR;
393 	} else {
394 		ctxmenu_item_label[id] = ami_utf8_easy(messages_get(label));
395 	}
396 
397 	if(key != NULL) {
398 		ctxmenu_item_shortcut[id] = strdup(key);
399 	} else {
400 		ctxmenu_item_shortcut[id] = NULL;
401 	}
402 
403 	if(image != NULL) {
404 		ctxmenu_item_image[id] = BitMapObj,
405 									BITMAP_Screen, ami_gui_get_screen(),
406 									BITMAP_SourceFile, image,
407 									BITMAP_Masking, TRUE,
408 									BitMapEnd;
409 
410 		SetAttrs(ctxmenu_item_image[id],
411 						BITMAP_Width, 16,
412 						BITMAP_Height, 16,
413 						TAG_DONE);
414 	}
415 
416 	ctxmenu_item_hook[id].h_Entry = func;
417 	ctxmenu_item_hook[id].h_Data = 0;
418 }
419 
420 /** Exported interface documented in ctxmenu.h **/
ami_ctxmenu_get_hook(APTR data)421 struct Hook *ami_ctxmenu_get_hook(APTR data)
422 {
423 	return AllocSysObjectTags(ASOT_HOOK,
424 		ASOHOOK_Entry, (HOOKFUNC)ami_ctxmenu_hook_func,
425 		ASOHOOK_Data, data,
426 		TAG_DONE);
427 }
428 
429 /** Exported interface documented in ctxmenu.h **/
ami_ctxmenu_release_hook(struct Hook * hook)430 void ami_ctxmenu_release_hook(struct Hook *hook)
431 {
432 	FreeSysObject(ASOT_HOOK, hook);
433 }
434 
435 /** Exported interface documented in ctxmenu.h **/
ami_ctxmenu_free(void)436 void ami_ctxmenu_free(void)
437 {
438 	for(int i = 1; i < AMI_CTX_ID_MAX; i++) {
439 		if((ctxmenu_item_label[i] != NULL) && (ctxmenu_item_label[i] != ML_SEPARATOR)) {
440 			ami_utf8_free(ctxmenu_item_label[i]);
441 		}
442 		ctxmenu_item_label[i] = NULL;
443 
444 		if(ctxmenu_item_shortcut[i] != NULL) {
445 			free(ctxmenu_item_shortcut[i]);
446 			ctxmenu_item_shortcut[i] = NULL;
447 		}
448 
449 		if(ctxmenu_item_image[i] != NULL) {
450 			DisposeObject(ctxmenu_item_image[i]);
451 			ctxmenu_item_image[i] = NULL;
452 		}
453 	}
454 
455 	if(ctxmenu_obj != NULL) DisposeObject(ctxmenu_obj);
456 	ctxmenu_obj = NULL;
457 }
458 
459 /** Exported interface documented in ctxmenu.h **/
ami_ctxmenu_init(void)460 void ami_ctxmenu_init(void)
461 {
462 	ami_ctxmenu_alloc_item(AMI_CTX_ID_NONE, 		ML_SEPARATOR, NULL, NULL, NULL);
463 
464 	ami_ctxmenu_alloc_item(AMI_CTX_ID_SELCOPY, 		"CopyNS",		"C",	"TBImages:list_copy",
465 		ami_ctxmenu_item_selcopy);
466 	ami_ctxmenu_alloc_item(AMI_CTX_ID_WEBSEARCH, 	"SearchWeb",	NULL,	"TBImages:list_search",
467 		ami_ctxmenu_item_websearch);
468 
469 	ami_ctxmenu_alloc_item(AMI_CTX_ID_URLOPENTAB, 	"LinkNewTab",	NULL,	"TBImages:list_tab",
470 		ami_ctxmenu_item_urlopentab);
471 	ami_ctxmenu_alloc_item(AMI_CTX_ID_URLOPENWIN, 	"LinkNewWin",	NULL,	"TBImages:list_app",
472 		ami_ctxmenu_item_urlopenwin);
473 	ami_ctxmenu_alloc_item(AMI_CTX_ID_URLDOWNLOAD, 	"LinkDload",	NULL,	"TBImages:list_save",
474 		ami_ctxmenu_item_urldownload);
475 	ami_ctxmenu_alloc_item(AMI_CTX_ID_URLCOPY, 		"CopyURL",		NULL,	"TBImages:list_copy",
476 		ami_ctxmenu_item_urlcopy);
477 
478 	ami_ctxmenu_alloc_item(AMI_CTX_ID_OBJSHOW, 		"ObjShow",		NULL,	"TBImages:list_preview",
479 		ami_ctxmenu_item_objshow);
480 	ami_ctxmenu_alloc_item(AMI_CTX_ID_OBJCOPY, 		"CopyClip",		NULL,	"TBImages:list_copy",
481 		ami_ctxmenu_item_objcopy);
482 	ami_ctxmenu_alloc_item(AMI_CTX_ID_OBJCMD, 		"ExternalApp",	NULL,	"TBImages:list_tool",
483 		ami_ctxmenu_item_objcmd);
484 
485 	ami_ctxmenu_alloc_item(AMI_CTX_ID_FRAMESHOW, 	"FrameOnly",	NULL,	"TBImages:list_preview",
486 		ami_ctxmenu_item_frameshow);
487 
488 	ami_ctxmenu_alloc_item(AMI_CTX_ID_TABNEW, "NewTab", "T", "TBImages:list_tab",
489 		ami_ctxmenu_item_tabnew);
490 	ami_ctxmenu_alloc_item(AMI_CTX_ID_TABCLOSE_OTHER, "CloseInactive", "K", "TBImages:list_cancel",
491 		ami_ctxmenu_item_tabclose_other);
492 }
493 
494 /********************************
495  * History button context menus *
496  ********************************/
497 
498 /** Create menu entries from browser history **/
ami_ctxmenu_history(int direction,struct gui_window_2 * gwin,const struct history_entry * entry)499 static bool ami_ctxmenu_history(int direction, struct gui_window_2 *gwin, const struct history_entry *entry)
500 {
501 	Object *history_root;
502 	int id = AMI_CTX_ID_HISTORY0 + ami_gui2_get_ctxmenu_history_tmp(gwin);
503 	if(direction == AMI_CTXMENU_HISTORY_FORWARD) id += 10;
504 
505 	if(ami_gui2_get_ctxmenu_history_tmp(gwin) >= 10) return false;
506 
507 	ctxmenu_item_hook[id].h_Entry = (HOOKFUNC)ami_ctxmenu_item_history;
508 	ctxmenu_item_hook[id].h_Data = (APTR)entry;
509 
510 	history_root = (Object *)IDoMethod(ami_gui2_get_ctxmenu_history(gwin, direction), MM_FINDID, 0, AMI_CTX_ID_HISTORY);
511 
512 	IDoMethod(history_root, OM_ADDMEMBER, MStrip,
513 							MA_Type, T_ITEM,
514 							/* TODO: MA_Label should be in local charset */
515 							MA_Label, browser_window_history_entry_get_title(entry),
516 							MA_ID, id,
517 							MA_Image, NULL,
518 							MA_UserData, &ctxmenu_item_hook[id],
519 						MEnd);
520 
521 	ami_gui2_set_ctxmenu_history_tmp(gwin, ami_gui2_get_ctxmenu_history_tmp(gwin) + 1);
522 
523 	return true;
524 }
525 
526 /** Callback for browser_window_history_enumerate **/
ami_ctxmenu_history_back(const struct browser_window * bw,int x0,int y0,int x1,int y1,const struct history_entry * entry,void * user_data)527 static bool ami_ctxmenu_history_back(const struct browser_window *bw,
528 		int x0, int y0, int x1, int y1,
529 		const struct history_entry *entry, void *user_data)
530 {
531 	return ami_ctxmenu_history(AMI_CTXMENU_HISTORY_BACK, (struct gui_window_2 *)user_data, entry);
532 }
533 
534 /** Callback for browser_window_history_enumerate **/
ami_ctxmenu_history_forward(const struct browser_window * bw,int x0,int y0,int x1,int y1,const struct history_entry * entry,void * user_data)535 static bool ami_ctxmenu_history_forward(const struct browser_window *bw,
536 		int x0, int y0, int x1, int y1,
537 		const struct history_entry *entry, void *user_data)
538 {
539 	return ami_ctxmenu_history(AMI_CTXMENU_HISTORY_FORWARD, (struct gui_window_2 *)user_data, entry);
540 }
541 
542 /** Exported interface documented in ctxmenu.h **/
ami_ctxmenu_history_create(int direction,struct gui_window_2 * gwin)543 struct Menu *ami_ctxmenu_history_create(int direction, struct gui_window_2 *gwin)
544 {
545 	Object *obj;
546 
547 	if(ami_gui2_get_ctxmenu_history(gwin, direction) == NULL) {
548 		if(ctxmenu_item_label[AMI_CTX_ID_HISTORY] == NULL)
549 			ctxmenu_item_label[AMI_CTX_ID_HISTORY] = ami_utf8_easy(messages_get("History"));
550 
551 		obj = MStrip,
552 						MA_Type, T_ROOT,
553 						MA_AddChild, MStrip,
554 							MA_Type, T_MENU,
555 							MA_ID, AMI_CTX_ID_HISTORY,
556 							MA_Label, ctxmenu_item_label[AMI_CTX_ID_HISTORY],
557 							MA_EmbeddedKey, FALSE,
558 							//MA_FreeImage, FALSE,
559 						MEnd,
560 					MEnd;
561 
562 		ami_gui2_set_ctxmenu_history(gwin, direction, obj);
563 
564 	} else {
565 		for (int i = 0; i < 20; i++) {
566 			obj = (Object *)IDoMethod(ami_gui2_get_ctxmenu_history(gwin, direction),
567 					MM_FINDID, 0, AMI_CTX_ID_HISTORY0 + i);
568 			if(obj != NULL) IDoMethod(ami_gui2_get_ctxmenu_history(gwin, direction), OM_REMMEMBER, obj);
569 		}
570 
571 		ami_gui2_set_ctxmenu_history_tmp(gwin, 0);
572 
573 		if(direction == AMI_CTXMENU_HISTORY_BACK) {
574 			browser_window_history_enumerate_back(ami_gui2_get_browser_window(gwin), ami_ctxmenu_history_back, gwin);
575 		} else {
576 			browser_window_history_enumerate_forward(ami_gui2_get_browser_window(gwin), ami_ctxmenu_history_forward, gwin);
577 		}
578 	}
579 
580 	return (struct Menu *)ami_gui2_get_ctxmenu_history(gwin, direction);
581 }
582 
583 
584 /**************************
585  * ClickTab context menus *
586  **************************/
587 
588 /** Exported interface documented in ctxmenu.h **/
ami_ctxmenu_clicktab_create(struct gui_window_2 * gwin,Object ** clicktab_obj)589 struct Menu *ami_ctxmenu_clicktab_create(struct gui_window_2 *gwin, Object **clicktab_obj)
590 {
591 	Object *root_menu;
592 	Object *clicktab;
593 
594 	if(*clicktab_obj != NULL) {
595 		return (struct Menu *)*clicktab_obj;
596 	}
597 
598 	clicktab = MStrip,
599 					MA_Type, T_ROOT,
600 					MA_AddChild, root_menu = MStrip,
601 						MA_Type, T_MENU,
602 						MA_Label, NULL,
603 						MA_EmbeddedKey, FALSE,
604 					MEnd,
605 				MEnd;
606 
607 	*clicktab_obj = clicktab;
608 
609 	ami_ctxmenu_add_item(root_menu, AMI_CTX_ID_TABNEW, gwin);
610 	ami_ctxmenu_add_item(root_menu, AMI_CTX_ID_TABCLOSE_OTHER, gwin);
611 
612 	return (struct Menu *)clicktab;
613 }
614 
615 
616 #endif
617 
618