1 /*
2 * Copyright 2016 Vincent Sanders <vince@netsurf-browser.org>
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 /**
20 * \file
21 * Implementation of RISC OS cookie manager.
22 */
23
24 #include <stdint.h>
25 #include <stdlib.h>
26 #include <oslib/wimp.h>
27
28 #include "utils/log.h"
29 #include "utils/nsoption.h"
30 #include "utils/messages.h"
31 #include "netsurf/plotters.h"
32 #include "netsurf/keypress.h"
33 #include "desktop/cookie_manager.h"
34
35 #include "riscos/gui.h"
36 #include "riscos/wimp.h"
37 #include "riscos/wimp_event.h"
38 #include "riscos/dialog.h"
39 #include "riscos/toolbar.h"
40 #include "riscos/corewindow.h"
41 #include "riscos/cookies.h"
42
43 struct ro_cookie_window {
44 struct ro_corewindow core;
45 wimp_menu *menu;
46 };
47
48 /** cookie window is a singleton */
49 static struct ro_cookie_window *cookie_window = NULL;
50
51 /** riscos template for cookie window */
52 static wimp_window *dialog_cookie_template;
53
54
55 /**
56 * callback to draw on drawable area of ro cookie window
57 *
58 * \param ro_cw The riscos core window structure.
59 * \param r The rectangle of the window that needs updating.
60 * \param originx The risc os plotter x origin.
61 * \param originy The risc os plotter y origin.
62 * \return NSERROR_OK on success otherwise apropriate error code
63 */
64 static nserror
cookie_draw(struct ro_corewindow * ro_cw,int originx,int originy,struct rect * r)65 cookie_draw(struct ro_corewindow *ro_cw,
66 int originx,
67 int originy,
68 struct rect *r)
69 {
70 struct redraw_context ctx = {
71 .interactive = true,
72 .background_images = true,
73 .plot = &ro_plotters
74 };
75
76 ro_plot_origin_x = originx;
77 ro_plot_origin_y = originy;
78 no_font_blending = true;
79 cookie_manager_redraw(0, 0, r, &ctx);
80 no_font_blending = false;
81
82 return NSERROR_OK;
83 }
84
85
86 /**
87 * callback for keypress on ro cookie window
88 *
89 * \param ro_cw The ro core window structure.
90 * \param nskey The netsurf key code.
91 * \return NSERROR_OK if key processed,
92 * NSERROR_NOT_IMPLEMENTED if key not processed
93 * otherwise apropriate error code
94 */
cookie_key(struct ro_corewindow * ro_cw,uint32_t nskey)95 static nserror cookie_key(struct ro_corewindow *ro_cw, uint32_t nskey)
96 {
97 if (cookie_manager_keypress(nskey)) {
98 return NSERROR_OK;
99 }
100 return NSERROR_NOT_IMPLEMENTED;
101 }
102
103
104 /**
105 * callback for mouse event on ro cookie window
106 *
107 * \param ro_cw The ro core window structure.
108 * \param mouse_state mouse state
109 * \param x location of event
110 * \param y location of event
111 * \return NSERROR_OK on sucess otherwise apropriate error code.
112 */
113 static nserror
cookie_mouse(struct ro_corewindow * ro_cw,browser_mouse_state mouse_state,int x,int y)114 cookie_mouse(struct ro_corewindow *ro_cw,
115 browser_mouse_state mouse_state,
116 int x, int y)
117 {
118 cookie_manager_mouse_action(mouse_state, x, y);
119
120 return NSERROR_OK;
121 }
122
123
124 /**
125 * handle clicks in ro core window toolbar.
126 *
127 * \param ro_cw The ro core window structure.
128 * \param action The button bar action.
129 * \return NSERROR_OK if config saved, otherwise apropriate error code
130 */
131 static nserror
cookie_toolbar_click(struct ro_corewindow * ro_cw,button_bar_action action)132 cookie_toolbar_click(struct ro_corewindow *ro_cw, button_bar_action action)
133 {
134 switch (action) {
135 case TOOLBAR_BUTTON_DELETE:
136 cookie_manager_keypress(NS_KEY_DELETE_LEFT);
137 break;
138
139 case TOOLBAR_BUTTON_EXPAND:
140 cookie_manager_expand(false);
141 break;
142
143 case TOOLBAR_BUTTON_COLLAPSE:
144 cookie_manager_contract(false);
145 break;
146
147 case TOOLBAR_BUTTON_OPEN:
148 cookie_manager_expand(true);
149 break;
150
151 case TOOLBAR_BUTTON_CLOSE:
152 cookie_manager_contract(true);
153 break;
154
155 default:
156 break;
157 }
158
159 return NSERROR_OK;
160 }
161
162
163 /**
164 * Handle updating state of buttons in ro core window toolbar.
165 *
166 * \param ro_cw The ro core window structure.
167 * \return NSERROR_OK if config saved, otherwise apropriate error code
168 */
cookie_toolbar_update(struct ro_corewindow * ro_cw)169 static nserror cookie_toolbar_update(struct ro_corewindow *ro_cw)
170 {
171 ro_toolbar_set_button_shaded_state(ro_cw->toolbar,
172 TOOLBAR_BUTTON_DELETE,
173 !cookie_manager_has_selection());
174 return NSERROR_OK;
175 }
176
177
178 /**
179 * callback for saving of toolbar state in ro cookie window
180 *
181 * \param ro_cw The ro core window structure.
182 * \param config The new toolbar configuration.
183 * \return NSERROR_OK if config saved, otherwise apropriate error code
184 */
cookie_toolbar_save(struct ro_corewindow * ro_cw,char * config)185 static nserror cookie_toolbar_save(struct ro_corewindow *ro_cw, char *config)
186 {
187 nsoption_set_charp(toolbar_cookies, config);
188 ro_gui_save_options();
189
190 return NSERROR_OK;
191 }
192
193
194 /**
195 * Prepare the cookie meu for display
196 *
197 * \param w The window owning the menu.
198 * \param i The icon owning the menu.
199 * \param menu The menu from which the selection was made.
200 * \param pointer The pointer shape
201 * \return true if action accepted; else false.
202 */
203 static bool
cookie_menu_prepare(wimp_w w,wimp_i i,wimp_menu * menu,wimp_pointer * pointer)204 cookie_menu_prepare(wimp_w w,
205 wimp_i i,
206 wimp_menu *menu,
207 wimp_pointer *pointer)
208 {
209 bool selection;
210 struct ro_cookie_window *cookiew;
211
212 cookiew = (struct ro_cookie_window *)ro_gui_wimp_event_get_user_data(w);
213
214 if ((cookiew == NULL) ||
215 (menu != cookiew->menu)) {
216 return false;
217 }
218
219 selection = cookie_manager_has_selection();
220
221 ro_gui_menu_set_entry_shaded(menu, TREE_SELECTION, !selection);
222 ro_gui_menu_set_entry_shaded(menu, TREE_CLEAR_SELECTION, !selection);
223
224 ro_gui_menu_set_entry_shaded(menu, TOOLBAR_BUTTONS,
225 ro_toolbar_menu_option_shade(cookiew->core.toolbar));
226 ro_gui_menu_set_entry_ticked(menu, TOOLBAR_BUTTONS,
227 ro_toolbar_menu_buttons_tick(cookiew->core.toolbar));
228
229 ro_gui_menu_set_entry_shaded(menu, TOOLBAR_EDIT,
230 ro_toolbar_menu_edit_shade(cookiew->core.toolbar));
231 ro_gui_menu_set_entry_ticked(menu, TOOLBAR_EDIT,
232 ro_toolbar_menu_edit_tick(cookiew->core.toolbar));
233
234 return true;
235 }
236
237
238 /**
239 * Handle submenu warnings for the cookies menu
240 *
241 * \param w The window owning the menu.
242 * \param i The icon owning the menu.
243 * \param menu The menu to which the warning applies.
244 * \param selection The wimp menu selection data.
245 * \param action The selected menu action.
246 */
247 static void
cookie_menu_warning(wimp_w w,wimp_i i,wimp_menu * menu,wimp_selection * selection,menu_action action)248 cookie_menu_warning(wimp_w w,
249 wimp_i i,
250 wimp_menu *menu,
251 wimp_selection *selection,
252 menu_action action)
253 {
254 /* Do nothing */
255 }
256
257
258 /**
259 * Handle selections from the cookies menu
260 *
261 * \param w The window owning the menu.
262 * \param i The icon owning the menu.
263 * \param menu The menu from which the selection was made.
264 * \param selection The wimp menu selection data.
265 * \param action The selected menu action.
266 * \return true if action accepted; else false.
267 */
268 static bool
cookie_menu_select(wimp_w w,wimp_i i,wimp_menu * menu,wimp_selection * selection,menu_action action)269 cookie_menu_select(wimp_w w,
270 wimp_i i,
271 wimp_menu *menu,
272 wimp_selection *selection,
273 menu_action action)
274 {
275 struct ro_cookie_window *cookiew;
276
277 cookiew = (struct ro_cookie_window *)ro_gui_wimp_event_get_user_data(w);
278
279 if ((cookiew == NULL) ||
280 (menu != cookiew->menu)) {
281 return false;
282 }
283
284 switch (action) {
285 case TREE_EXPAND_ALL:
286 cookie_manager_expand(false);
287 return true;
288
289 case TREE_EXPAND_FOLDERS:
290 cookie_manager_expand(true);
291 return true;
292
293 case TREE_EXPAND_LINKS:
294 cookie_manager_expand(false);
295 return true;
296
297 case TREE_COLLAPSE_ALL:
298 cookie_manager_contract(true);
299 return true;
300
301 case TREE_COLLAPSE_FOLDERS:
302 cookie_manager_contract(true);
303 return true;
304
305 case TREE_COLLAPSE_LINKS:
306 cookie_manager_contract(false);
307 return true;
308
309 case TREE_SELECTION_DELETE:
310 cookie_manager_keypress(NS_KEY_DELETE_LEFT);
311 return true;
312
313 case TREE_SELECT_ALL:
314 cookie_manager_keypress(NS_KEY_SELECT_ALL);
315 return true;
316
317 case TREE_CLEAR_SELECTION:
318 cookie_manager_keypress(NS_KEY_CLEAR_SELECTION);
319 return true;
320
321 case TOOLBAR_BUTTONS:
322 ro_toolbar_set_display_buttons(cookiew->core.toolbar,
323 !ro_toolbar_get_display_buttons(cookiew->core.toolbar));
324 return true;
325
326 case TOOLBAR_EDIT:
327 ro_toolbar_toggle_edit(cookiew->core.toolbar);
328 return true;
329
330 default:
331 return false;
332 }
333
334 return false;
335 }
336
337
338 /**
339 * Creates the window for the cookie tree.
340 *
341 * \return NSERROR_OK on success else appropriate error code on faliure.
342 */
ro_cookie_init(void)343 static nserror ro_cookie_init(void)
344 {
345 os_error *error;
346 struct ro_cookie_window *ncwin;
347 nserror res;
348 static const struct ns_menu cookie_menu_def = {
349 "Cookies", {
350 { "Cookies", NO_ACTION, 0 },
351 { "Cookies.Expand", TREE_EXPAND_ALL, 0 },
352 { "Cookies.Expand.All", TREE_EXPAND_ALL, 0 },
353 { "Cookies.Expand.Folders", TREE_EXPAND_FOLDERS, 0 },
354 { "Cookies.Expand.Links", TREE_EXPAND_LINKS, 0 },
355 { "Cookies.Collapse", TREE_COLLAPSE_ALL, 0 },
356 { "Cookies.Collapse.All", TREE_COLLAPSE_ALL, 0 },
357 { "Cookies.Collapse.Folders", TREE_COLLAPSE_FOLDERS, 0 },
358 { "Cookies.Collapse.Links", TREE_COLLAPSE_LINKS, 0 },
359 { "Cookies.Toolbars", NO_ACTION, 0 },
360 { "_Cookies.Toolbars.ToolButtons", TOOLBAR_BUTTONS, 0 },
361 { "Cookies.Toolbars.EditToolbar",TOOLBAR_EDIT, 0 },
362 { "Selection", TREE_SELECTION, 0 },
363 { "Selection.Delete", TREE_SELECTION_DELETE, 0 },
364 { "SelectAll", TREE_SELECT_ALL, 0 },
365 { "Clear", TREE_CLEAR_SELECTION, 0 },
366 { NULL, 0, 0}
367 }
368 };
369
370 static const struct button_bar_buttons cookies_toolbar_buttons[] = {
371 { "delete", TOOLBAR_BUTTON_DELETE, TOOLBAR_BUTTON_NONE, '0', "0"},
372 { "expand", TOOLBAR_BUTTON_EXPAND, TOOLBAR_BUTTON_COLLAPSE, '1', "1"},
373 { "open", TOOLBAR_BUTTON_OPEN, TOOLBAR_BUTTON_CLOSE, '2', "2"},
374 { NULL, TOOLBAR_BUTTON_NONE, TOOLBAR_BUTTON_NONE, '\0', ""}
375 };
376
377 if (cookie_window != NULL) {
378 return NSERROR_OK;
379 }
380
381 ncwin = calloc(1, sizeof(*ncwin));
382 if (ncwin == NULL) {
383 return NSERROR_NOMEM;
384 }
385
386 /* create window from template */
387 error = xwimp_create_window(dialog_cookie_template, &ncwin->core.wh);
388 if (error) {
389 NSLOG(netsurf, INFO, "xwimp_create_window: 0x%x: %s",
390 error->errnum, error->errmess);
391 ro_warn_user("WimpError", error->errmess);
392 free(ncwin);
393 return NSERROR_NOMEM;
394 }
395
396 ro_gui_set_window_title(ncwin->core.wh, messages_get("Cookies"));
397
398 ncwin->core.draw = cookie_draw;
399 ncwin->core.key = cookie_key;
400 ncwin->core.mouse = cookie_mouse;
401 ncwin->core.toolbar_click = cookie_toolbar_click;
402 ncwin->core.toolbar_save = cookie_toolbar_save;
403 /* update is not valid untill cookie manager is initialised */
404 ncwin->core.toolbar_update = NULL;
405
406 /* initialise core window */
407 res = ro_corewindow_init(&ncwin->core,
408 cookies_toolbar_buttons,
409 nsoption_charp(toolbar_cookies),
410 THEME_STYLE_COOKIES_TOOLBAR,
411 "HelpCookiesToolbar");
412 if (res != NSERROR_OK) {
413 free(ncwin);
414 return res;
415 }
416
417 res = cookie_manager_init(ncwin->core.cb_table,
418 (struct core_window *)ncwin);
419 if (res != NSERROR_OK) {
420 free(ncwin);
421 return res;
422 }
423
424 /* setup toolbar update post cookie manager initialisation */
425 ncwin->core.toolbar_update = cookie_toolbar_update;
426 cookie_toolbar_update(&ncwin->core);
427
428 /* Build the cookies window menu. */
429 ncwin->menu = ro_gui_menu_define_menu(&cookie_menu_def);
430
431 ro_gui_wimp_event_register_menu(ncwin->core.wh,
432 ncwin->menu, false, false);
433 ro_gui_wimp_event_register_menu_prepare(ncwin->core.wh,
434 cookie_menu_prepare);
435 ro_gui_wimp_event_register_menu_selection(ncwin->core.wh,
436 cookie_menu_select);
437 ro_gui_wimp_event_register_menu_warning(ncwin->core.wh,
438 cookie_menu_warning);
439
440 /* memoise window so it can be represented when necessary
441 * instead of recreating every time.
442 */
443 cookie_window = ncwin;
444
445 return NSERROR_OK;
446 }
447
448
449 /* exported interface documented in riscos/cookies.h */
ro_gui_cookies_present(const char * search_term)450 nserror ro_gui_cookies_present(const char *search_term)
451 {
452 nserror res;
453
454 res = ro_cookie_init();
455 if (res == NSERROR_OK) {
456 NSLOG(netsurf, INFO, "Presenting");
457 ro_gui_dialog_open_top(cookie_window->core.wh,
458 cookie_window->core.toolbar,
459 600, 800);
460 if (search_term != NULL) {
461 res = cookie_manager_set_search_string(search_term);
462 }
463 } else {
464 NSLOG(netsurf, INFO, "Failed presenting code %d", res);
465 }
466
467 return res;
468 }
469
470
471 /* exported interface documented in riscos/cookies.h */
ro_gui_cookies_initialise(void)472 void ro_gui_cookies_initialise(void)
473 {
474 dialog_cookie_template = ro_gui_dialog_load_template("tree");
475 }
476
477
478 /* exported interface documented in riscos/cookies.h */
ro_gui_cookies_finalise(void)479 nserror ro_gui_cookies_finalise(void)
480 {
481 nserror res;
482
483 if (cookie_window == NULL) {
484 return NSERROR_OK;
485 }
486
487 res = cookie_manager_fini();
488 if (res == NSERROR_OK) {
489 res = ro_corewindow_fini(&cookie_window->core);
490
491 free(cookie_window);
492 cookie_window = NULL;
493 }
494
495 return res;
496 }
497
498
499 /* exported interface documented in riscos/cookies.h */
ro_gui_cookies_check_window(wimp_w wh)500 bool ro_gui_cookies_check_window(wimp_w wh)
501 {
502 if ((cookie_window != NULL) &&
503 (cookie_window->core.wh == wh)) {
504 return true;
505 }
506 return false;
507 }
508
509
510 /* exported interface documented in riscos/cookies.h */
ro_gui_cookies_check_menu(wimp_menu * menu)511 bool ro_gui_cookies_check_menu(wimp_menu *menu)
512 {
513 if ((cookie_window != NULL) &&
514 (cookie_window->menu == menu)) {
515 return true;
516 }
517 return false;
518 }
519