1 /*
2 * Copyright 2004, 2005 Richard Wilson <info@tinct.net>
3 * Copyright 2011-2014 Stephen Fryatt <stevef@netsurf-browser.org>
4 *
5 * This file is part of NetSurf, http://www.netsurf-browser.org/
6 *
7 * NetSurf is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * NetSurf is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 /**
21 * \file
22 * RISC OS URL bar implementation.
23 *
24 * The treeview resources are retrieved from resource url necessitating
25 * the use of the hlcache content interface.
26 */
27
28 #include <stddef.h>
29 #include "oslib/wimp.h"
30
31 #include "utils/log.h"
32 #include "utils/messages.h"
33 #include "netsurf/browser_window.h"
34 #include "netsurf/plotters.h"
35 #include "netsurf/content.h"
36 #include "content/hlcache.h"
37
38 #include "riscos/gui.h"
39 #include "riscos/hotlist.h"
40 #include "riscos/url_suggest.h"
41 #include "riscos/wimp.h"
42 #include "riscos/wimp_event.h"
43 #include "riscos/window.h"
44 #include "riscos/ucstables.h"
45 #include "riscos/filetype.h"
46 #include "riscos/gui/url_bar.h"
47
48 #define URLBAR_HEIGHT 52
49 #define URLBAR_FAVICON_SIZE 16
50 #define URLBAR_HOTLIST_SIZE 17
51 #define URLBAR_PGINFO_WIDTH ((26) * 2)
52 #define URLBAR_FAVICON_WIDTH ((5 + URLBAR_FAVICON_SIZE + 5) * 2)
53 #define URLBAR_HOTLIST_WIDTH ((5 + URLBAR_HOTLIST_SIZE + 5) * 2)
54 #define URLBAR_MIN_WIDTH 52
55 #define URLBAR_GRIGHT_GUTTER 8
56
57 #define URLBAR_PGINFO_NAME_LENGTH 12
58 #define URLBAR_FAVICON_NAME_LENGTH 12
59
60 struct url_bar {
61 /** The applied theme (or NULL to use the default) */
62 struct theme_descriptor *theme;
63
64 /** The widget dimensions. */
65 int x_min, y_min;
66
67 /** The window and icon details. */
68 wimp_w window;
69 os_box extent;
70 osspriteop_area *sprites;
71
72 wimp_i container_icon;
73
74 bool hidden;
75 bool display;
76 bool shaded;
77
78 struct {
79 char sprite[URLBAR_PGINFO_NAME_LENGTH];
80 os_box extent;
81 } pginfo;
82
83 struct {
84 char sprite[URLBAR_FAVICON_NAME_LENGTH];
85 int type;
86 struct hlcache_handle *content;
87 os_box extent;
88 os_coord offset;
89 int width;
90 int height;
91 } favicon;
92
93 struct {
94 wimp_i icon;
95 char *buffer;
96 size_t size;
97 char *buffer_utf8;
98 } text;
99
100 struct {
101 wimp_i icon;
102 int x;
103 int y;
104 } suggest;
105
106 struct {
107 bool set;
108 os_box extent;
109 os_coord offset;
110 } hotlist;
111 };
112
113 static char text_validation[] = "Pptr_write;KN";
114 static char suggest_icon[] = "gright";
115 static char suggest_validation[] = "R5;Sgright,pgright";
116 static char null_text_string[] = "";
117
118 /** Treeview content resource data */
119 struct url_bar_resource {
120 const char *url;
121 struct hlcache_handle *c;
122 int height;
123 bool ready;
124 };
125
126 enum url_bar_resource_id {
127 URLBAR_RES_HOTLIST_ADD = 0,
128 URLBAR_RES_HOTLIST_REMOVE,
129 URLBAR_RES_LAST
130 };
131
132 /** Treeview content resources */
133 static struct url_bar_resource url_bar_res[URLBAR_RES_LAST] = {
134 { "resource:icons/hotlist-add.png", NULL, 0, false },
135 { "resource:icons/hotlist-rmv.png", NULL, 0, false }
136 };
137
138
139 /**
140 * Position the icons in the URL bar to take account of the currently
141 * configured extent.
142 *
143 * \param *url_bar The URL bar to update.
144 * \param full true to resize everything;
145 * false to move only the right-hand end of the bar.
146 * \return true if successful; else false.
147 */
ro_gui_url_bar_icon_resize(struct url_bar * url_bar,bool full)148 static bool ro_gui_url_bar_icon_resize(struct url_bar *url_bar, bool full)
149 {
150 int x0, y0, x1, y1;
151 int centre;
152 os_error *error;
153 os_coord eig = {1, 1};
154 wimp_caret caret;
155
156 if ((url_bar == NULL) ||
157 (url_bar->window == NULL)) {
158 return false;
159 }
160
161 /* calculate 1px in OS units */
162 ro_convert_pixels_to_os_units(&eig, (os_mode) -1);
163
164 /* The vertical centre line of the widget's extent. */
165 centre = url_bar->extent.y0 +
166 (url_bar->extent.y1 - url_bar->extent.y0) / 2;
167
168 /* Position the container icon. */
169 if (url_bar->container_icon != -1) {
170 x0 = url_bar->extent.x0;
171 x1 = url_bar->extent.x1 -
172 url_bar->suggest.x - URLBAR_GRIGHT_GUTTER;
173
174 y0 = centre - (URLBAR_HEIGHT / 2);
175 y1 = y0 + URLBAR_HEIGHT;
176
177 error = xwimp_resize_icon(url_bar->window,
178 url_bar->container_icon,
179 x0, y0, x1, y1);
180 if (error != NULL) {
181 NSLOG(netsurf, INFO,
182 "xwimp_resize_icon: 0x%x: %s",
183 error->errnum, error->errmess);
184 ro_warn_user("WimpError", error->errmess);
185 url_bar->container_icon = -1;
186 return false;
187 }
188 }
189
190 /* Position the URL Suggest icon. */
191 if (url_bar->suggest.icon != -1) {
192 x0 = url_bar->extent.x1 - url_bar->suggest.x;
193 x1 = url_bar->extent.x1;
194
195 y0 = centre - (url_bar->suggest.y / 2);
196 y1 = y0 + url_bar->suggest.y;
197
198 error = xwimp_resize_icon(url_bar->window,
199 url_bar->suggest.icon,
200 x0, y0, x1, y1);
201 if (error != NULL) {
202 NSLOG(netsurf, INFO,
203 "xwimp_resize_icon: 0x%x: %s",
204 error->errnum, error->errmess);
205 ro_warn_user("WimpError", error->errmess);
206 url_bar->suggest.icon = -1;
207 return false;
208 }
209 }
210
211 /* Position the Text icon. */
212 if (url_bar->text.icon != -1) {
213 x0 = url_bar->extent.x0 + URLBAR_PGINFO_WIDTH + URLBAR_FAVICON_WIDTH;
214 x1 = url_bar->extent.x1 - eig.x - URLBAR_HOTLIST_WIDTH -
215 url_bar->suggest.x - URLBAR_GRIGHT_GUTTER;
216
217 y0 = centre - (URLBAR_HEIGHT / 2) + eig.y;
218 y1 = y0 + URLBAR_HEIGHT - 2 * eig.y;
219
220 error = xwimp_resize_icon(url_bar->window,
221 url_bar->text.icon,
222 x0, y0, x1, y1);
223 if (error != NULL) {
224 NSLOG(netsurf, INFO,
225 "xwimp_resize_icon: 0x%x: %s",
226 error->errnum, error->errmess);
227 ro_warn_user("WimpError", error->errmess);
228 url_bar->text.icon = -1;
229 return false;
230 }
231
232 if (xwimp_get_caret_position(&caret) == NULL) {
233 if ((caret.w == url_bar->window) &&
234 (caret.i == url_bar->text.icon)) {
235 xwimp_set_caret_position(url_bar->window,
236 url_bar->text.icon,
237 caret.pos.x,
238 caret.pos.y,
239 -1,
240 caret.index);
241 }
242 }
243 }
244
245 /* Position the page info icon. */
246 url_bar->pginfo.extent.x0 = url_bar->extent.x0 + eig.x;
247 url_bar->pginfo.extent.x1 = url_bar->extent.x0 + URLBAR_PGINFO_WIDTH;
248 url_bar->pginfo.extent.y0 = centre - (URLBAR_HEIGHT / 2) + eig.y;
249 url_bar->pginfo.extent.y1 = url_bar->pginfo.extent.y0 + URLBAR_HEIGHT
250 - 2 * eig.y;
251
252 /* Position the Favicon icon. */
253 url_bar->favicon.extent.x0 = url_bar->extent.x0 + URLBAR_PGINFO_WIDTH ;
254 url_bar->favicon.extent.x1 = url_bar->extent.x0 + URLBAR_PGINFO_WIDTH + URLBAR_FAVICON_WIDTH;
255 url_bar->favicon.extent.y0 = centre - (URLBAR_HEIGHT / 2) + eig.y;
256 url_bar->favicon.extent.y1 = url_bar->favicon.extent.y0 + URLBAR_HEIGHT
257 - 2 * eig.y;
258
259 /* Position the Hotlist icon. */
260 url_bar->hotlist.extent.x0 = url_bar->extent.x1 - eig.x -
261 URLBAR_HOTLIST_WIDTH - url_bar->suggest.x -
262 URLBAR_GRIGHT_GUTTER;
263 url_bar->hotlist.extent.x1 = url_bar->hotlist.extent.x0 +
264 URLBAR_HOTLIST_WIDTH;
265 url_bar->hotlist.extent.y0 = centre - (URLBAR_HEIGHT / 2) + eig.y;
266 url_bar->hotlist.extent.y1 = url_bar->hotlist.extent.y0 + URLBAR_HEIGHT
267 - 2 * eig.y;
268
269 url_bar->hotlist.offset.x = ((url_bar->hotlist.extent.x1 -
270 url_bar->hotlist.extent.x0) -
271 (URLBAR_HOTLIST_SIZE * 2)) / 2;
272 url_bar->hotlist.offset.y = ((url_bar->hotlist.extent.y1 -
273 url_bar->hotlist.extent.y0) -
274 (URLBAR_HOTLIST_SIZE * 2)) / 2 - 1;
275
276 return true;
277 }
278
279
280 /**
281 * Create or delete a URL bar's icons if required to bring it into sync with
282 * the current hidden setting.
283 *
284 * \param *url_bar The URL bar to update.
285 * \return true if successful; else false.
286 */
ro_gui_url_bar_icon_update(struct url_bar * url_bar)287 static bool ro_gui_url_bar_icon_update(struct url_bar *url_bar)
288 {
289 wimp_icon_create icon;
290 os_error *error;
291 bool resize;
292
293 if ((url_bar == NULL) ||
294 (url_bar->window == NULL)) {
295 return false;
296 }
297
298 icon.w = url_bar->window;
299 icon.icon.extent.x0 = 0;
300 icon.icon.extent.y0 = 0;
301 icon.icon.extent.x1 = 0;
302 icon.icon.extent.y1 = 0;
303
304 resize = false;
305
306 /* Create or delete the container icon. */
307
308 if (!url_bar->hidden && url_bar->container_icon == -1) {
309 icon.icon.flags = wimp_ICON_BORDER |
310 (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) |
311 (wimp_BUTTON_DOUBLE_CLICK_DRAG << wimp_ICON_BUTTON_TYPE_SHIFT);
312 error = xwimp_create_icon(&icon, &url_bar->container_icon);
313 if (error != NULL) {
314 NSLOG(netsurf, INFO,
315 "xwimp_create_icon: 0x%x: %s",
316 error->errnum, error->errmess);
317 ro_warn_user("WimpError", error->errmess);
318 url_bar->container_icon = -1;
319 return false;
320 }
321
322 resize = true;
323 } else if ((url_bar->hidden) &&
324 (url_bar->container_icon != -1)) {
325 error = xwimp_delete_icon(url_bar->window,
326 url_bar->container_icon);
327 if (error != NULL) {
328 NSLOG(netsurf, INFO,
329 "xwimp_delete_icon: 0x%x: %s",
330 error->errnum, error->errmess);
331 ro_warn_user("WimpError", error->errmess);
332 return false;
333 }
334
335 url_bar->container_icon = -1;
336 }
337
338 /* Create or delete the text icon. */
339 if (!url_bar->hidden &&
340 url_bar->text.icon == -1) {
341 icon.icon.data.indirected_text.text = url_bar->text.buffer;
342 icon.icon.data.indirected_text.validation = text_validation;
343 icon.icon.data.indirected_text.size = url_bar->text.size;
344 icon.icon.flags = wimp_ICON_TEXT |
345 wimp_ICON_INDIRECTED |
346 wimp_ICON_VCENTRED |
347 wimp_ICON_FILLED |
348 (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT);
349
350 if (url_bar->display) {
351 icon.icon.flags |= (wimp_BUTTON_NEVER <<
352 wimp_ICON_BUTTON_TYPE_SHIFT);
353 } else {
354 icon.icon.flags |= (wimp_BUTTON_WRITE_CLICK_DRAG <<
355 wimp_ICON_BUTTON_TYPE_SHIFT);
356 }
357 error = xwimp_create_icon(&icon, &url_bar->text.icon);
358 if (error) {
359 NSLOG(netsurf, INFO,
360 "xwimp_create_icon: 0x%x: %s",
361 error->errnum, error->errmess);
362 ro_warn_user("WimpError", error->errmess);
363 url_bar->text.icon = -1;
364 return false;
365 }
366
367 resize = true;
368
369 } else if (url_bar->hidden &&
370 url_bar->text.icon != -1) {
371 error = xwimp_delete_icon(url_bar->window,
372 url_bar->text.icon);
373 if (error != NULL) {
374 NSLOG(netsurf, INFO,
375 "xwimp_delete_icon: 0x%x: %s",
376 error->errnum, error->errmess);
377 ro_warn_user("WimpError", error->errmess);
378 return false;
379 }
380
381 url_bar->text.icon = -1;
382 }
383
384 /* Create or delete the suggest icon. */
385 if (!url_bar->hidden &&
386 url_bar->suggest.icon == -1) {
387 icon.icon.data.indirected_text.text = null_text_string;
388 icon.icon.data.indirected_text.size = 1;
389 icon.icon.data.indirected_text.validation = suggest_validation;
390 icon.icon.flags = wimp_ICON_TEXT |
391 wimp_ICON_SPRITE |
392 wimp_ICON_INDIRECTED |
393 wimp_ICON_HCENTRED |
394 wimp_ICON_VCENTRED |
395 (wimp_BUTTON_CLICK << wimp_ICON_BUTTON_TYPE_SHIFT);
396
397 error = xwimp_create_icon(&icon, &url_bar->suggest.icon);
398 if (error) {
399 NSLOG(netsurf, INFO, "xwimp_create_icon: 0x%x: %s",
400 error->errnum, error->errmess);
401 ro_warn_user("WimpError", error->errmess);
402 return false;
403 }
404
405 if (!url_bar->display)
406 ro_gui_wimp_event_register_menu_gright(url_bar->window,
407 wimp_ICON_WINDOW,
408 url_bar->suggest.icon,
409 ro_gui_url_suggest_menu);
410
411 if (!ro_gui_url_bar_update_urlsuggest(url_bar)) {
412 return false;
413 }
414
415 resize = true;
416
417 } else if (url_bar->hidden &&
418 url_bar->suggest.icon != -1) {
419 ro_gui_wimp_event_deregister(url_bar->window,
420 url_bar->suggest.icon);
421 error = xwimp_delete_icon(url_bar->window,
422 url_bar->suggest.icon);
423 if (error != NULL) {
424 NSLOG(netsurf, INFO,
425 "xwimp_delete_icon: 0x%x: %s",
426 error->errnum, error->errmess);
427 ro_warn_user("WimpError", error->errmess);
428 return false;
429 }
430
431 url_bar->suggest.icon = -1;
432 }
433
434 /* If any icons were created, resize the bar. */
435 if (resize && !ro_gui_url_bar_icon_resize(url_bar, true)) {
436 return false;
437 }
438
439 /* If there are any icons, apply shading as necessary. */
440 if (url_bar->container_icon != -1) {
441 ro_gui_set_icon_shaded_state(url_bar->window,
442 url_bar->container_icon,
443 url_bar->shaded);
444 }
445
446 if (url_bar->text.icon != -1) {
447 ro_gui_set_icon_shaded_state(url_bar->window,
448 url_bar->text.icon,
449 url_bar->shaded);
450 }
451
452 if (url_bar->suggest.icon != -1) {
453 ro_gui_set_icon_shaded_state(url_bar->window,
454 url_bar->suggest.icon,
455 url_bar->shaded);
456 }
457
458 return true;
459 }
460
461
462 /**
463 * Set the state of a URL Bar's hotlist icon.
464 *
465 * \param *url_bar The URL Bar to update.
466 * \param set TRUE to set the hotlist icon; FALSE to clear it.
467 */
ro_gui_url_bar_set_hotlist(struct url_bar * url_bar,bool set)468 static void ro_gui_url_bar_set_hotlist(struct url_bar *url_bar, bool set)
469 {
470 if (url_bar == NULL ||
471 set == url_bar->hotlist.set) {
472 return;
473 }
474
475 url_bar->hotlist.set = set;
476
477 if (!url_bar->hidden) {
478 xwimp_force_redraw(url_bar->window,
479 url_bar->hotlist.extent.x0,
480 url_bar->hotlist.extent.y0,
481 url_bar->hotlist.extent.x1,
482 url_bar->hotlist.extent.y1);
483 }
484 }
485
486
487 /**
488 * Callback for hlcache.
489 */
490 static nserror
ro_gui_url_bar_res_cb(hlcache_handle * handle,const hlcache_event * event,void * pw)491 ro_gui_url_bar_res_cb(hlcache_handle *handle,
492 const hlcache_event *event, void *pw)
493 {
494 struct url_bar_resource *r = pw;
495
496 switch (event->type) {
497 case CONTENT_MSG_READY:
498 case CONTENT_MSG_DONE:
499 r->ready = true;
500 r->height = content_get_height(handle);
501 break;
502
503 default:
504 break;
505 }
506
507 return NSERROR_OK;
508 }
509
510
511 /* This is an exported interface documented in url_bar.h */
ro_gui_url_bar_create(struct theme_descriptor * theme)512 struct url_bar *ro_gui_url_bar_create(struct theme_descriptor *theme)
513 {
514 struct url_bar *url_bar;
515
516 /* Allocate memory. */
517
518 url_bar = malloc(sizeof(struct url_bar));
519 if (url_bar == NULL) {
520 NSLOG(netsurf, INFO, "No memory for malloc()");
521 return NULL;
522 }
523
524 /* Set up default parameters. */
525
526 url_bar->theme = theme;
527 url_bar->sprites = ro_gui_theme_get_sprites(theme);
528
529 url_bar->display = false;
530 url_bar->shaded = false;
531
532 url_bar->x_min = URLBAR_FAVICON_WIDTH + URLBAR_MIN_WIDTH +
533 URLBAR_HOTLIST_WIDTH;
534 url_bar->y_min = URLBAR_HEIGHT;
535
536 url_bar->extent.x0 = 0;
537 url_bar->extent.y0 = 0;
538 url_bar->extent.x1 = 0;
539 url_bar->extent.y1 = 0;
540
541 url_bar->window = NULL;
542 url_bar->container_icon = -1;
543 url_bar->text.icon = -1;
544 url_bar->suggest.icon = -1;
545
546 url_bar->pginfo.extent.x0 = 0;
547 url_bar->pginfo.extent.y0 = 0;
548 url_bar->pginfo.extent.x1 = 0;
549 url_bar->pginfo.extent.y1 = 0;
550 strncpy(url_bar->pginfo.sprite,
551 "pgiinternal",
552 URLBAR_PGINFO_NAME_LENGTH);
553
554 url_bar->favicon.extent.x0 = 0;
555 url_bar->favicon.extent.y0 = 0;
556 url_bar->favicon.extent.x1 = 0;
557 url_bar->favicon.extent.y1 = 0;
558 url_bar->favicon.width = 0;
559 url_bar->favicon.height = 0;
560 url_bar->favicon.content = NULL;
561 url_bar->favicon.type = 0;
562 strncpy(url_bar->favicon.sprite,
563 "Ssmall_xxx",
564 URLBAR_FAVICON_NAME_LENGTH);
565
566 url_bar->hotlist.set = false;
567 url_bar->hotlist.extent.x0 = 0;
568 url_bar->hotlist.extent.y0 = 0;
569 url_bar->hotlist.extent.x1 = 0;
570 url_bar->hotlist.extent.y1 = 0;
571
572 url_bar->text.size = RO_GUI_MAX_URL_SIZE;
573 url_bar->text.buffer = malloc(url_bar->text.size);
574 if (url_bar->text.buffer == NULL) {
575 free(url_bar);
576 return NULL;
577 }
578 url_bar->text.buffer[0] = 0;
579 url_bar->text.buffer_utf8 = NULL;
580
581 url_bar->hidden = false;
582
583 return url_bar;
584 }
585
586
587 /* This is an exported interface documented in url_bar.h */
588 bool
ro_gui_url_bar_rebuild(struct url_bar * url_bar,struct theme_descriptor * theme,theme_style style,wimp_w window,bool display,bool shaded)589 ro_gui_url_bar_rebuild(struct url_bar *url_bar,
590 struct theme_descriptor *theme,
591 theme_style style,
592 wimp_w window,
593 bool display,
594 bool shaded)
595 {
596 if (url_bar == NULL) {
597 return false;
598 }
599
600 url_bar->theme = theme;
601 url_bar->window = window;
602
603 url_bar->display = display;
604 url_bar->shaded = shaded;
605
606 url_bar->container_icon = -1;
607 url_bar->text.icon = -1;
608 url_bar->suggest.icon = -1;
609
610 ro_gui_wimp_get_sprite_dimensions((osspriteop_area *) -1,
611 suggest_icon,
612 &url_bar->suggest.x,
613 &url_bar->suggest.y);
614
615 url_bar->x_min = URLBAR_PGINFO_WIDTH +
616 URLBAR_FAVICON_WIDTH +
617 URLBAR_MIN_WIDTH +
618 URLBAR_HOTLIST_WIDTH +
619 URLBAR_GRIGHT_GUTTER +
620 url_bar->suggest.x;
621
622 url_bar->y_min = (url_bar->suggest.y > URLBAR_HEIGHT) ?
623 url_bar->suggest.y : URLBAR_HEIGHT;
624
625 return ro_gui_url_bar_icon_update(url_bar);
626 }
627
628
629 /* This is an exported interface documented in url_bar.h */
ro_gui_url_bar_destroy(struct url_bar * url_bar)630 void ro_gui_url_bar_destroy(struct url_bar *url_bar)
631 {
632 if (url_bar == NULL) {
633 return;
634 }
635
636 if (url_bar->text.buffer_utf8 != NULL) {
637 free(url_bar->text.buffer_utf8);
638 }
639
640 if (url_bar->text.buffer != NULL) {
641 free(url_bar->text.buffer);
642 }
643
644 free(url_bar);
645 }
646
647
648 /* This is an exported interface documented in url_bar.h */
ro_gui_url_bar_get_dims(struct url_bar * url_bar,int * width,int * height)649 bool ro_gui_url_bar_get_dims(struct url_bar *url_bar, int *width, int *height)
650 {
651 if (url_bar == NULL) {
652 return false;
653 }
654
655 if (url_bar->x_min != -1 &&
656 url_bar->y_min != -1) {
657 if (width != NULL) {
658 *width = url_bar->x_min;
659 }
660 if (height != NULL) {
661 *height = url_bar->y_min;
662 }
663
664 return true;
665 }
666
667 return false;
668 }
669
670
671 /* This is an exported interface documented in url_bar.h */
672 bool
ro_gui_url_bar_set_extent(struct url_bar * url_bar,int x0,int y0,int x1,int y1)673 ro_gui_url_bar_set_extent(struct url_bar *url_bar,
674 int x0, int y0, int x1, int y1)
675 {
676 bool stretch;
677
678 if (url_bar == NULL) {
679 return false;
680 }
681
682 if ((x1 - x0) < url_bar->x_min ||
683 (y1 - y0) < url_bar->y_min) {
684 return false;
685 }
686
687 if (url_bar->extent.x0 == x0 &&
688 url_bar->extent.y0 == y0 &&
689 url_bar->extent.x1 == x1 &&
690 url_bar->extent.y1 == y1) {
691 return true;
692 }
693
694 /* If it's only the length that changes, less needs to be updated. */
695 stretch = (url_bar->extent.x0 == x0 &&
696 url_bar->extent.y0 == y0 &&
697 url_bar->extent.y1 == y1) ? true : false;
698
699 /* Redraw the relevant bits of the toolbar. */
700 if (url_bar->window != NULL &&
701 !url_bar->hidden) {
702 if (stretch) {
703 xwimp_force_redraw(url_bar->window,
704 x0 + URLBAR_PGINFO_WIDTH + URLBAR_FAVICON_WIDTH, y0,
705 (x1 > url_bar->extent.x1) ?
706 x1 : url_bar->extent.x1, y1);
707 } else {
708 xwimp_force_redraw(url_bar->window,
709 url_bar->extent.x0,
710 url_bar->extent.y0,
711 url_bar->extent.x1,
712 url_bar->extent.y1);
713 xwimp_force_redraw(url_bar->window, x0, y0, x1, y1);
714 }
715 }
716
717 /* Reposition the URL bar icons. */
718 url_bar->extent.x0 = x0;
719 url_bar->extent.y0 = y0;
720 url_bar->extent.x1 = x1;
721 url_bar->extent.y1 = y1;
722
723 return ro_gui_url_bar_icon_resize(url_bar, !stretch);
724 }
725
726
727 /* This is an exported interface documented in url_bar.h */
ro_gui_url_bar_hide(struct url_bar * url_bar,bool hide)728 bool ro_gui_url_bar_hide(struct url_bar *url_bar, bool hide)
729 {
730 if (url_bar == NULL || url_bar->hidden == hide)
731 return (url_bar == NULL) ? false : true;
732
733 url_bar->hidden = hide;
734
735 return ro_gui_url_bar_icon_update(url_bar);
736 }
737
738
739 /* This is an exported interface documented in url_bar.h */
ro_gui_url_bar_redraw(struct url_bar * url_bar,wimp_draw * redraw)740 void ro_gui_url_bar_redraw(struct url_bar *url_bar, wimp_draw *redraw)
741 {
742 wimp_icon icon;
743 struct rect clip;
744 bool draw_pginfo = true;
745 bool draw_favicon = true;
746 bool draw_hotlist = true;
747
748 /* Test for a valid URL bar */
749 if (url_bar == NULL || url_bar->hidden)
750 return;
751
752 if ((redraw->clip.x0 - (redraw->box.x0 - redraw->xscroll)) >
753 (url_bar->pginfo.extent.x1) ||
754 (redraw->clip.y0 - (redraw->box.y1 - redraw->yscroll)) >
755 (url_bar->pginfo.extent.y1) ||
756 (redraw->clip.x1 - (redraw->box.x0 - redraw->xscroll)) <
757 (url_bar->pginfo.extent.x0) ||
758 (redraw->clip.y1 - (redraw->box.y1 - redraw->yscroll)) <
759 (url_bar->pginfo.extent.y0)) {
760 /* page info not in redraw area */
761 draw_pginfo = false;
762 }
763
764 if ((redraw->clip.x0 - (redraw->box.x0 - redraw->xscroll)) >
765 (url_bar->favicon.extent.x1) ||
766 (redraw->clip.y0 - (redraw->box.y1 - redraw->yscroll)) >
767 (url_bar->favicon.extent.y1) ||
768 (redraw->clip.x1 - (redraw->box.x0 - redraw->xscroll)) <
769 (url_bar->favicon.extent.x0) ||
770 (redraw->clip.y1 - (redraw->box.y1 - redraw->yscroll)) <
771 (url_bar->favicon.extent.y0)) {
772 /* Favicon not in redraw area */
773 draw_favicon = false;
774 }
775
776 if ((redraw->clip.x0 - (redraw->box.x0 - redraw->xscroll)) >
777 (url_bar->hotlist.extent.x1) ||
778 (redraw->clip.y0 - (redraw->box.y1 - redraw->yscroll)) >
779 (url_bar->hotlist.extent.y1) ||
780 (redraw->clip.x1 - (redraw->box.x0 - redraw->xscroll)) <
781 (url_bar->hotlist.extent.x0) ||
782 (redraw->clip.y1 - (redraw->box.y1 - redraw->yscroll)) <
783 (url_bar->hotlist.extent.y0)) {
784 /* Hotlist icon not in redraw area */
785 draw_hotlist = false;
786 }
787
788 if (draw_pginfo) {
789 icon.flags = wimp_ICON_SPRITE |
790 wimp_ICON_INDIRECTED |
791 wimp_ICON_FILLED |
792 wimp_ICON_HCENTRED |
793 wimp_ICON_VCENTRED |
794 (wimp_COLOUR_WHITE << wimp_ICON_BG_COLOUR_SHIFT);
795 icon.data.indirected_sprite.id = (osspriteop_id)url_bar->pginfo.sprite;
796 icon.data.indirected_sprite.area = url_bar->sprites;
797 icon.data.indirected_sprite.size = 12;
798
799 icon.extent.x0 = url_bar->pginfo.extent.x0;
800 icon.extent.x1 = url_bar->pginfo.extent.x1;
801 icon.extent.y0 = url_bar->pginfo.extent.y0;
802 icon.extent.y1 = url_bar->pginfo.extent.y1;
803
804 xwimp_plot_icon(&icon);
805 }
806
807 if (draw_favicon) {
808 if (url_bar->favicon.content == NULL) {
809 icon.data.indirected_text.text = null_text_string;
810 icon.data.indirected_text.validation =
811 url_bar->favicon.sprite;
812 icon.data.indirected_text.size = 1;
813 icon.flags = wimp_ICON_TEXT | wimp_ICON_SPRITE |
814 wimp_ICON_INDIRECTED |
815 wimp_ICON_FILLED |
816 wimp_ICON_HCENTRED |
817 wimp_ICON_VCENTRED;
818 icon.extent.x0 = url_bar->favicon.extent.x0;
819 icon.extent.x1 = url_bar->favicon.extent.x1;
820 icon.extent.y0 = url_bar->favicon.extent.y0;
821 icon.extent.y1 = url_bar->favicon.extent.y1;
822
823 xwimp_plot_icon(&icon);
824 } else {
825 struct content_redraw_data data;
826 struct redraw_context ctx = {
827 .interactive = true,
828 .background_images = true,
829 .plot = &ro_plotters
830 };
831
832 xwimp_set_colour(wimp_COLOUR_WHITE);
833 xos_plot(os_MOVE_TO,
834 (redraw->box.x0 - redraw->xscroll) +
835 url_bar->favicon.extent.x0,
836 (redraw->box.y1 - redraw->yscroll) +
837 url_bar->favicon.extent.y0);
838 xos_plot(os_PLOT_TO | os_PLOT_RECTANGLE,
839 (redraw->box.x0 - redraw->xscroll) +
840 url_bar->favicon.extent.x1,
841 (redraw->box.y1 - redraw->yscroll) +
842 url_bar->favicon.extent.y1);
843
844 clip.x0 = (redraw->clip.x0 - ro_plot_origin_x) / 2;
845 clip.y0 = (ro_plot_origin_y - redraw->clip.y0) / 2;
846 clip.x1 = (redraw->clip.x1 - ro_plot_origin_x) / 2;
847 clip.y1 = (ro_plot_origin_y - redraw->clip.y1) / 2;
848
849 data.x = (url_bar->favicon.extent.x0 +
850 url_bar->favicon.offset.x) / 2;
851 data.y = (url_bar->favicon.offset.y -
852 url_bar->favicon.extent.y1) / 2;
853 data.width = url_bar->favicon.width;
854 data.height = url_bar->favicon.height;
855 data.background_colour = 0xFFFFFF;
856 data.scale = 1;
857 data.repeat_x = false;
858 data.repeat_y = false;
859
860 content_redraw(url_bar->favicon.content,
861 &data, &clip, &ctx);
862 }
863 }
864
865 if (draw_hotlist) {
866 struct content_redraw_data data;
867 struct redraw_context ctx = {
868 .interactive = true,
869 .background_images = true,
870 .plot = &ro_plotters
871 };
872 struct url_bar_resource *hotlist_icon = url_bar->hotlist.set ?
873 &(url_bar_res[URLBAR_RES_HOTLIST_REMOVE]) :
874 &(url_bar_res[URLBAR_RES_HOTLIST_ADD]);
875
876 xwimp_set_colour(wimp_COLOUR_WHITE);
877 xos_plot(os_MOVE_TO,
878 (redraw->box.x0 - redraw->xscroll) +
879 url_bar->hotlist.extent.x0,
880 (redraw->box.y1 - redraw->yscroll) +
881 url_bar->hotlist.extent.y0);
882 xos_plot(os_PLOT_TO | os_PLOT_RECTANGLE,
883 (redraw->box.x0 - redraw->xscroll) +
884 url_bar->hotlist.extent.x1,
885 (redraw->box.y1 - redraw->yscroll) +
886 url_bar->hotlist.extent.y1);
887
888 if (hotlist_icon->ready == false) {
889 return;
890 }
891
892 clip.x0 = (redraw->clip.x0 - ro_plot_origin_x) / 2;
893 clip.y0 = (ro_plot_origin_y - redraw->clip.y0) / 2;
894 clip.x1 = (redraw->clip.x1 - ro_plot_origin_x) / 2;
895 clip.y1 = (ro_plot_origin_y - redraw->clip.y1) / 2;
896
897 data.x = (url_bar->hotlist.extent.x0 +
898 url_bar->hotlist.offset.x) / 2;
899 data.y = (url_bar->hotlist.offset.y -
900 url_bar->hotlist.extent.y1) / 2;
901 data.width = URLBAR_HOTLIST_SIZE;
902 data.height = URLBAR_HOTLIST_SIZE;
903 data.background_colour = 0xFFFFFF;
904 data.scale = 1;
905 data.repeat_x = false;
906 data.repeat_y = false;
907
908 content_redraw(hotlist_icon->c, &data, &clip, &ctx);
909 }
910 }
911
912 /**
913 * check if os point is inside an os box
914 *
915 * \param pos The coordinate of the point
916 * \param box The box to check against
917 * \return true if point is inside the box else false
918 */
is_point_in_box(os_coord * pos,os_box * box)919 static inline bool is_point_in_box(os_coord *pos, os_box *box)
920 {
921 if (pos->x < box->x0 ||
922 pos->x > box->x1 ||
923 pos->y < box->y0 ||
924 pos->y > box->y1) {
925 return false;
926 }
927 return true;
928 }
929
930 /* This is an exported interface documented in url_bar.h */
931 bool
ro_gui_url_bar_click(struct url_bar * url_bar,wimp_pointer * pointer,wimp_window_state * state,url_bar_action * action)932 ro_gui_url_bar_click(struct url_bar *url_bar,
933 wimp_pointer *pointer,
934 wimp_window_state *state,
935 url_bar_action *action)
936 {
937 os_coord pos;
938
939 if (url_bar == NULL || url_bar->hidden ||
940 url_bar->display || url_bar->shaded) {
941 return false;
942 }
943
944 /* Check that the click was within our part of the window. */
945 pos.x = pointer->pos.x - state->visible.x0 + state->xscroll;
946 pos.y = pointer->pos.y - state->visible.y1 + state->yscroll;
947
948 if (!is_point_in_box(&pos, &url_bar->extent)) {
949 return false;
950 }
951
952 /* If we have a Select or Adjust click, check if it originated on the
953 * hotlist icon; if it did, return an event.
954 */
955 if (pointer->buttons == wimp_SINGLE_SELECT ||
956 pointer->buttons == wimp_SINGLE_ADJUST) {
957 if (is_point_in_box(&pos, &url_bar->hotlist.extent)) {
958 if (pointer->buttons == wimp_SINGLE_SELECT &&
959 action != NULL) {
960 *action = TOOLBAR_URL_SELECT_HOTLIST;
961 } else if (pointer->buttons == wimp_SINGLE_ADJUST &&
962 action != NULL) {
963 *action = TOOLBAR_URL_ADJUST_HOTLIST;
964 }
965 return true;
966 }
967
968 if (is_point_in_box(&pos, &url_bar->pginfo.extent)) {
969 if (pointer->buttons == wimp_SINGLE_SELECT &&
970 action != NULL) {
971 *action = TOOLBAR_URL_SELECT_PGINFO;
972 } else if (pointer->buttons == wimp_SINGLE_ADJUST &&
973 action != NULL) {
974 *action = TOOLBAR_URL_ADJUST_PGINFO;
975 }
976 return true;
977 }
978
979 }
980
981 /* If we find a Select or Adjust drag, check if it originated on the
982 * URL bar or over the favicon. If either, then return an event.
983 */
984 if (pointer->buttons == wimp_DRAG_SELECT ||
985 pointer->buttons == wimp_DRAG_ADJUST) {
986 if (pointer->i == url_bar->text.icon) {
987 if (action != NULL) {
988 *action = TOOLBAR_URL_DRAG_URL;
989 }
990 return true;
991 }
992
993 if (is_point_in_box(&pos, &url_bar->favicon.extent)) {
994 if (action != NULL) {
995 *action = TOOLBAR_URL_DRAG_FAVICON;
996 }
997 return true;
998 }
999 }
1000
1001 return false;
1002 }
1003
1004
1005 /* This is an exported interface documented in url_bar.h */
1006 bool
ro_gui_url_bar_menu_prepare(struct url_bar * url_bar,wimp_i i,wimp_menu * menu,wimp_pointer * pointer)1007 ro_gui_url_bar_menu_prepare(struct url_bar *url_bar,
1008 wimp_i i,
1009 wimp_menu *menu,
1010 wimp_pointer *pointer)
1011 {
1012 if (url_bar == NULL ||
1013 url_bar->suggest.icon != i ||
1014 menu != ro_gui_url_suggest_menu) {
1015 return false;
1016 }
1017
1018 if (pointer != NULL) {
1019 return ro_gui_url_suggest_prepare_menu();
1020 }
1021
1022 return true;
1023 }
1024
1025
1026 /* This is an exported interface documented in url_bar.h */
1027 bool
ro_gui_url_bar_menu_select(struct url_bar * url_bar,wimp_i i,wimp_menu * menu,wimp_selection * selection,menu_action action)1028 ro_gui_url_bar_menu_select(struct url_bar *url_bar,
1029 wimp_i i,
1030 wimp_menu *menu,
1031 wimp_selection *selection,
1032 menu_action action)
1033 {
1034 const char *urltxt;
1035 struct gui_window *g;
1036
1037 if (url_bar == NULL ||
1038 url_bar->suggest.icon != i ||
1039 menu != ro_gui_url_suggest_menu) {
1040 return false;
1041 }
1042
1043 urltxt = ro_gui_url_suggest_get_selection(selection);
1044 g = ro_gui_toolbar_lookup(url_bar->window);
1045
1046 if (urltxt != NULL &&
1047 g != NULL &&
1048 g->bw != NULL) {
1049 nsurl *url;
1050 nserror error;
1051
1052 error = nsurl_create(urltxt, &url);
1053 if (error != NSERROR_OK) {
1054 ro_warn_user(messages_get_errorcode(error), 0);
1055 } else {
1056 ro_gui_window_set_url(g, url);
1057
1058 browser_window_navigate(g->bw,
1059 url,
1060 NULL,
1061 BW_NAVIGATE_HISTORY,
1062 NULL,
1063 NULL,
1064 NULL);
1065 nsurl_unref(url);
1066 }
1067 }
1068
1069 return true;
1070 }
1071
1072
1073 /* This is an exported interface documented in url_bar.h */
1074 bool
ro_gui_url_bar_help_suffix(struct url_bar * url_bar,wimp_i i,os_coord * mouse,wimp_window_state * state,wimp_mouse_state buttons,const char ** suffix)1075 ro_gui_url_bar_help_suffix(struct url_bar *url_bar,
1076 wimp_i i,
1077 os_coord *mouse,
1078 wimp_window_state *state,
1079 wimp_mouse_state buttons,
1080 const char **suffix)
1081 {
1082 os_coord pos;
1083
1084 if (url_bar == NULL || url_bar->hidden) {
1085 return false;
1086 }
1087
1088 /* Check that the click was within our part of the window. */
1089
1090 pos.x = mouse->x - state->visible.x0 + state->xscroll;
1091 pos.y = mouse->y - state->visible.y1 + state->yscroll;
1092
1093 if (pos.x < url_bar->extent.x0 ||
1094 pos.x > url_bar->extent.x1 ||
1095 pos.y < url_bar->extent.y0 ||
1096 pos.y > url_bar->extent.y1) {
1097 return false;
1098 }
1099
1100 /* Return hard-coded icon numbers that match the ones that were
1101 * always allocated to the URL bar in a previous implementation.
1102 * If Messages can be updated, this could be changed.
1103 */
1104
1105 if (i == url_bar->text.icon) {
1106 *suffix = "14";
1107 } else if (i == url_bar->suggest.icon) {
1108 *suffix = "15";
1109 } else if (pos.x >= url_bar->hotlist.extent.x0 &&
1110 pos.x <= url_bar->hotlist.extent.x1 &&
1111 pos.y >= url_bar->hotlist.extent.y0 &&
1112 pos.y <= url_bar->hotlist.extent.y1) {
1113 *suffix = "Hot";
1114 } else if (pos.x >= url_bar->favicon.extent.x0 &&
1115 pos.x <= url_bar->favicon.extent.x1 &&
1116 pos.y >= url_bar->favicon.extent.y0 &&
1117 pos.y <= url_bar->favicon.extent.y1) {
1118 *suffix = "Fav";
1119 } else {
1120 *suffix = "";
1121 }
1122
1123 return true;
1124 }
1125
1126
1127 /* This is an exported interface documented in url_bar.h */
ro_gui_url_bar_take_caret(struct url_bar * url_bar)1128 bool ro_gui_url_bar_take_caret(struct url_bar *url_bar)
1129 {
1130 os_error *error;
1131
1132 if (url_bar == NULL || url_bar->hidden) {
1133 return false;
1134 }
1135
1136 error = xwimp_set_caret_position(url_bar->window,
1137 url_bar->text.icon,
1138 -1, -1, -1, 0);
1139 if (error) {
1140 NSLOG(netsurf, INFO,
1141 "xwimp_set_caret_position: 0x%x: %s",
1142 error->errnum, error->errmess);
1143 ro_warn_user("WimpError", error->errmess);
1144
1145 return false;
1146 }
1147
1148 return true;
1149 }
1150
1151
1152 /* This is an exported interface documented in url_bar.h */
1153 void
ro_gui_url_bar_set_url(struct url_bar * url_bar,const char * url,bool is_utf8,bool set_caret)1154 ro_gui_url_bar_set_url(struct url_bar *url_bar,
1155 const char *url,
1156 bool is_utf8,
1157 bool set_caret)
1158 {
1159 wimp_caret caret;
1160 os_error *error;
1161 char *local_text = NULL;
1162 const char *local_url;
1163 nsurl *n;
1164
1165 if (url_bar == NULL ||
1166 url_bar->text.buffer == NULL ||
1167 url == NULL) {
1168 return;
1169 }
1170
1171 /* Before we do anything with the URL, get it into local encoding so
1172 * that behaviour is consistent with the rest of the URL Bar module
1173 * (which will act on the icon's text buffer, which is always in local
1174 * encoding).
1175 */
1176
1177 if (is_utf8) {
1178 nserror err;
1179
1180 err = utf8_to_local_encoding(url, 0, &local_text);
1181 if (err != NSERROR_OK) {
1182 /* A bad encoding should never happen, so assert this */
1183 assert(err != NSERROR_BAD_ENCODING);
1184 NSLOG(netsurf, INFO, "utf8_to_enc failed");
1185 /* Paranoia */
1186 local_text = NULL;
1187 }
1188 local_url = (local_text != NULL) ? local_text : url;
1189 } else {
1190 local_url = url;
1191 }
1192
1193 /* Copy the text into the icon buffer. If the text is too long, truncate
1194 * for URL bar and log the full URL.
1195 */
1196 if (strlen(local_url) >= url_bar->text.size) {
1197 NSLOG(netsurf, WARNING,
1198 "URL too long to show in URL bar (%zu chars): %s",
1199 strlen(url), url);
1200 }
1201
1202 strncpy(url_bar->text.buffer, local_url, url_bar->text.size - 1);
1203 url_bar->text.buffer[url_bar->text.size - 1] = '\0';
1204
1205 if (local_text != NULL) {
1206 free(local_text);
1207 }
1208
1209 /* Set the hotlist flag. */
1210 if (nsurl_create(url, &n) == NSERROR_OK) {
1211 ro_gui_url_bar_set_hotlist(url_bar, ro_gui_hotlist_has_page(n));
1212 nsurl_unref(n);
1213 }
1214
1215 /* If there's no icon, then there's nothing else to do... */
1216 if (url_bar->text.icon == -1) {
1217 return;
1218 }
1219
1220 /* ...if there is, redraw the icon and fix the caret's position. */
1221 ro_gui_redraw_icon(url_bar->window, url_bar->text.icon);
1222
1223 error = xwimp_get_caret_position(&caret);
1224 if (error) {
1225 NSLOG(netsurf, INFO,
1226 "xwimp_get_caret_position: 0x%x: %s",
1227 error->errnum, error->errmess);
1228 ro_warn_user("WimpError", error->errmess);
1229 return;
1230 }
1231
1232 if (set_caret ||
1233 (caret.w == url_bar->window &&
1234 caret.i == url_bar->text.icon)) {
1235 const char *set_url;
1236 set_url = ro_gui_get_icon_string(url_bar->window,
1237 url_bar->text.icon);
1238
1239 error = xwimp_set_caret_position(url_bar->window,
1240 url_bar->text.icon,
1241 0, 0, -1,
1242 strlen(set_url));
1243 if (error) {
1244 NSLOG(netsurf, INFO,
1245 "xwimp_set_caret_position: 0x%x: %s",
1246 error->errnum,
1247 error->errmess);
1248 ro_warn_user("WimpError", error->errmess);
1249 }
1250 }
1251 }
1252
1253
1254 /* This is an exported interface documented in url_bar.h */
ro_gui_url_bar_update_hotlist(struct url_bar * url_bar)1255 void ro_gui_url_bar_update_hotlist(struct url_bar *url_bar)
1256 {
1257 const char *url;
1258 nsurl *n;
1259
1260 if (url_bar == NULL) {
1261 return;
1262 }
1263
1264 url = (const char *) url_bar->text.buffer;
1265 if (url != NULL &&
1266 nsurl_create(url, &n) == NSERROR_OK) {
1267 ro_gui_url_bar_set_hotlist(url_bar, ro_gui_hotlist_has_page(n));
1268 nsurl_unref(n);
1269 }
1270 }
1271
1272
1273 /* This is an exported interface documented in url_bar.h */
ro_gui_url_bar_get_url(struct url_bar * url_bar)1274 const char *ro_gui_url_bar_get_url(struct url_bar *url_bar)
1275 {
1276 nserror res;
1277
1278 if ((url_bar == NULL) ||
1279 (url_bar->text.buffer == NULL)) {
1280 return NULL;
1281 }
1282
1283 if (url_bar->text.buffer_utf8 != NULL) {
1284 free(url_bar->text.buffer_utf8);
1285 url_bar->text.buffer_utf8 = NULL;
1286 }
1287
1288 if (url_bar->text.buffer[0] == '\0') {
1289 return (const char *) url_bar->text.buffer;
1290 }
1291
1292 res = utf8_from_local_encoding(url_bar->text.buffer, 0,
1293 &url_bar->text.buffer_utf8);
1294 if (res == NSERROR_OK) {
1295 return (const char *)url_bar->text.buffer_utf8;
1296 }
1297
1298 return (const char *) url_bar->text.buffer;
1299 }
1300
1301
1302 /* This is an exported interface documented in url_bar.h */
ro_gui_url_bar_get_url_extent(struct url_bar * url_bar,os_box * extent)1303 bool ro_gui_url_bar_get_url_extent(struct url_bar *url_bar, os_box *extent)
1304 {
1305 wimp_icon_state state;
1306 os_error *error;
1307
1308 if (url_bar == NULL || url_bar->hidden) {
1309 return false;
1310 }
1311
1312 if (extent == NULL) {
1313 return true;
1314 }
1315
1316 state.w = url_bar->window;
1317 state.i = url_bar->container_icon;
1318 error = xwimp_get_icon_state(&state);
1319 if (error) {
1320 NSLOG(netsurf, INFO,
1321 "xwimp_get_icon_state: 0x%x: %s",
1322 error->errnum, error->errmess);
1323 ro_warn_user("WimpError", error->errmess);
1324 return false;
1325 }
1326
1327 extent->x0 = state.icon.extent.x0;
1328 extent->y0 = state.icon.extent.y0;
1329 extent->x1 = state.icon.extent.x1;
1330 extent->y1 = state.icon.extent.y1;
1331
1332 return true;
1333 }
1334
1335
1336 /* This is an exported interface documented in url_bar.h */
1337 bool
ro_gui_url_bar_test_for_text_field_click(struct url_bar * url_bar,wimp_pointer * pointer)1338 ro_gui_url_bar_test_for_text_field_click(struct url_bar *url_bar,
1339 wimp_pointer *pointer)
1340 {
1341 if (url_bar == NULL ||
1342 url_bar->hidden ||
1343 pointer == NULL) {
1344 return false;
1345 }
1346
1347 return (pointer->w == url_bar->window &&
1348 pointer->i == url_bar->text.icon) ? true : false;
1349 }
1350
1351
1352 /* This is an exported interface documented in url_bar.h */
1353 bool
ro_gui_url_bar_test_for_text_field_keypress(struct url_bar * url_bar,wimp_key * key)1354 ro_gui_url_bar_test_for_text_field_keypress(struct url_bar *url_bar,
1355 wimp_key *key)
1356 {
1357 const char *url;
1358 nsurl *n;
1359
1360 if (url_bar == NULL ||
1361 url_bar->hidden ||
1362 key == NULL) {
1363 return false;
1364 }
1365
1366 if (key->w != url_bar->window ||
1367 key->i != url_bar->text.icon) {
1368 return false;
1369 }
1370
1371 /* Update hotlist indicator */
1372
1373 url = (const char *) url_bar->text.buffer;
1374 if (url != NULL &&
1375 nsurl_create(url, &n) == NSERROR_OK) {
1376 ro_gui_url_bar_set_hotlist(url_bar, ro_gui_hotlist_has_page(n));
1377 nsurl_unref(n);
1378 } else if (url_bar->hotlist.set) {
1379 ro_gui_url_bar_set_hotlist(url_bar, false);
1380 }
1381
1382 return true;
1383 }
1384
1385
1386 /* This is an exported interface documented in url_bar.h */
1387 bool
ro_gui_url_bar_set_site_favicon(struct url_bar * url_bar,struct hlcache_handle * h)1388 ro_gui_url_bar_set_site_favicon(struct url_bar *url_bar,
1389 struct hlcache_handle *h)
1390 {
1391 content_type type = CONTENT_NONE;
1392
1393 if (url_bar == NULL) {
1394 return false;
1395 }
1396
1397 if (h != NULL) {
1398 type = content_get_type(h);
1399 }
1400
1401 // \TODO -- Maybe test for CONTENT_ICO ???
1402
1403 if (type == CONTENT_IMAGE) {
1404 url_bar->favicon.content = h;
1405 url_bar->favicon.width = content_get_width(h);
1406 url_bar->favicon.height = content_get_height(h);
1407
1408 if (url_bar->favicon.width > URLBAR_FAVICON_SIZE) {
1409 url_bar->favicon.width = URLBAR_FAVICON_SIZE;
1410 }
1411
1412 if (url_bar->favicon.height > URLBAR_FAVICON_SIZE) {
1413 url_bar->favicon.height = URLBAR_FAVICON_SIZE;
1414 }
1415
1416 url_bar->favicon.offset.x = ((url_bar->favicon.extent.x1 -
1417 url_bar->favicon.extent.x0) -
1418 (url_bar->favicon.width * 2)) / 2;
1419 url_bar->favicon.offset.y = ((url_bar->favicon.extent.y1 -
1420 url_bar->favicon.extent.y0) -
1421 (url_bar->favicon.height * 2)) / 2;
1422 } else {
1423 url_bar->favicon.content = NULL;
1424
1425 if (url_bar->favicon.type != 0) {
1426 snprintf(url_bar->favicon.sprite,
1427 URLBAR_FAVICON_NAME_LENGTH,
1428 "Ssmall_%.3x", url_bar->favicon.type);
1429 } else {
1430 snprintf(url_bar->favicon.sprite,
1431 URLBAR_FAVICON_NAME_LENGTH,
1432 "Ssmall_xxx");
1433 }
1434 }
1435
1436 if (!url_bar->hidden) {
1437 xwimp_force_redraw(url_bar->window,
1438 url_bar->favicon.extent.x0,
1439 url_bar->favicon.extent.y0,
1440 url_bar->favicon.extent.x1,
1441 url_bar->favicon.extent.y1);
1442 }
1443
1444 return true;
1445 }
1446
1447
1448 /* This is an exported interface documented in url_bar.h */
ro_gui_url_bar_page_info_change(struct url_bar * url_bar)1449 bool ro_gui_url_bar_page_info_change(struct url_bar *url_bar)
1450 {
1451 browser_window_page_info_state pistate;
1452 const char *icon_name;
1453 struct gui_window *g;
1454
1455 g = ro_gui_toolbar_lookup(url_bar->window);
1456
1457 pistate = browser_window_get_page_info_state(g->bw);
1458
1459 switch (pistate) {
1460 case PAGE_STATE_LOCAL:
1461 icon_name = "pgilocal";
1462 break;
1463
1464 case PAGE_STATE_INSECURE:
1465 icon_name = "pgiinsecure";
1466 break;
1467
1468 case PAGE_STATE_SECURE_OVERRIDE:
1469 icon_name = "pgiwarning";
1470 break;
1471
1472 case PAGE_STATE_SECURE_ISSUES:
1473 icon_name = "pgiwarning";
1474 break;
1475
1476 case PAGE_STATE_SECURE:
1477 icon_name = "pgisecure";
1478 break;
1479
1480 case PAGE_STATE_INTERNAL:
1481 default:
1482 icon_name = "pgiinternal";
1483 break;
1484 }
1485
1486 strncpy(url_bar->pginfo.sprite, icon_name, URLBAR_PGINFO_NAME_LENGTH);
1487
1488 if (!url_bar->hidden) {
1489 xwimp_force_redraw(url_bar->window,
1490 url_bar->pginfo.extent.x0,
1491 url_bar->pginfo.extent.y0,
1492 url_bar->pginfo.extent.x1,
1493 url_bar->pginfo.extent.y1);
1494 }
1495
1496 return true;
1497 }
1498
1499
1500 /* This is an exported interface documented in url_bar.h */
1501 bool
ro_gui_url_bar_set_content_favicon(struct url_bar * url_bar,struct gui_window * g)1502 ro_gui_url_bar_set_content_favicon(struct url_bar *url_bar,
1503 struct gui_window *g)
1504 {
1505 int type = 0;
1506 char sprite[URLBAR_FAVICON_NAME_LENGTH];
1507 struct hlcache_handle *h;
1508
1509 if (url_bar == NULL ||
1510 g == NULL) {
1511 return false;
1512 }
1513
1514 h = browser_window_get_content(g->bw);
1515 if (h != NULL) {
1516 type = ro_content_filetype(h);
1517 }
1518
1519 if (type != 0) {
1520 snprintf(sprite, URLBAR_FAVICON_NAME_LENGTH,
1521 "small_%.3x", type);
1522
1523 if (!ro_gui_wimp_sprite_exists(sprite)) {
1524 type = 0;
1525 }
1526 }
1527
1528 url_bar->favicon.type = type;
1529
1530 if (url_bar->favicon.content == NULL) {
1531 if (type == 0) {
1532 snprintf(url_bar->favicon.sprite,
1533 URLBAR_FAVICON_NAME_LENGTH, "Ssmall_xxx");
1534 } else {
1535 snprintf(url_bar->favicon.sprite,
1536 URLBAR_FAVICON_NAME_LENGTH, "S%s", sprite);
1537 }
1538
1539 if (!url_bar->hidden) {
1540 xwimp_force_redraw(url_bar->window,
1541 url_bar->favicon.extent.x0,
1542 url_bar->favicon.extent.y0,
1543 url_bar->favicon.extent.x1,
1544 url_bar->favicon.extent.y1);
1545 }
1546 }
1547
1548 return true;
1549 }
1550
1551
1552 /* This is an exported interface documented in url_bar.h */
ro_gui_url_bar_update_urlsuggest(struct url_bar * url_bar)1553 bool ro_gui_url_bar_update_urlsuggest(struct url_bar *url_bar)
1554 {
1555 if (url_bar == NULL ||
1556 url_bar->hidden) {
1557 return (url_bar == NULL) ? false : true;
1558 }
1559
1560 if (url_bar->window != NULL &&
1561 url_bar->suggest.icon != -1) {
1562 ro_gui_set_icon_shaded_state(url_bar->window,
1563 url_bar->suggest.icon,
1564 !ro_gui_url_suggest_get_menu_available());
1565 }
1566
1567 return true;
1568 }
1569
1570
1571 /* Exported interface, documented in url_bar.h */
ro_gui_url_bar_init(void)1572 bool ro_gui_url_bar_init(void)
1573 {
1574 int i;
1575
1576 for (i = 0; i < URLBAR_RES_LAST; i++) {
1577 nsurl *url;
1578 if (nsurl_create(url_bar_res[i].url, &url) == NSERROR_OK) {
1579 hlcache_handle_retrieve(url,
1580 0,
1581 NULL,
1582 NULL,
1583 ro_gui_url_bar_res_cb,
1584 &(url_bar_res[i]),
1585 NULL,
1586 CONTENT_IMAGE,
1587 &(url_bar_res[i].c));
1588 nsurl_unref(url);
1589 }
1590 }
1591
1592 return true;
1593 }
1594
1595
1596 /* Exported interface, documented in url_bar.h */
ro_gui_url_bar_fini(void)1597 void ro_gui_url_bar_fini(void)
1598 {
1599 int i;
1600
1601 for (i = 0; i < URLBAR_RES_LAST; i++) {
1602 hlcache_handle_release(url_bar_res[i].c);
1603 }
1604 }
1605