NetSurf
wimp.c
Go to the documentation of this file.
1/*
2 * Copyright 2004, 2005 Richard Wilson <info@tinct.net>
3 * Copyright 2008 John Tytgat <joty@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/** \file
21 * General RISC OS WIMP/OS library functions (implementation).
22 */
23
24#include <assert.h>
25#include <locale.h>
26#include <stdbool.h>
27#include <stdlib.h>
28#include <string.h>
29#include <stdio.h>
30#include "oslib/colourtrans.h"
31#include "oslib/os.h"
32#include "oslib/osfile.h"
33#include "oslib/wimp.h"
34#include "oslib/wimpextend.h"
35#include "oslib/wimpspriteop.h"
36
37#include "utils/log.h"
38#include "utils/utf8.h"
39
40#include "riscos/gui.h"
41#include "riscos/oslib_pre7.h"
42#include "riscos/wimp.h"
43#include "riscos/ucstables.h"
44
45
46static void ro_gui_wimp_cache_furniture_sizes(wimp_w w);
47static size_t ro_gui_strlen(const char *str);
48static int ro_gui_strncmp(const char *s1, const char *s2, size_t len);
49
50static wimpextend_furniture_sizes furniture_sizes;
51static wimp_w furniture_window = NULL;
52
53/**
54 * Gets the horizontal scrollbar height
55 *
56 * \param w the window to read (or NULL to read a cached value)
57 */
59{
61 return furniture_sizes.border_widths.y0;
62}
63
64
65/**
66 * Gets the vertical scrollbar width
67 *
68 * \param w the window to read (or NULL to read a cached value)
69 */
71{
73 return furniture_sizes.border_widths.x1;
74}
75
76
77/**
78 * Gets the title bar height
79 *
80 * \param w the window to read (or NULL to read a cached value)
81 */
83{
85 return furniture_sizes.border_widths.y1;
86}
87
88/**
89 * Caches window furniture information
90 *
91 * \param w the window to cache information from
92 * \return true on success, false on error (default values cached)
93 */
95{
96 os_error *error;
97
98 if (furniture_window == w)
99 return;
101 furniture_sizes.w = w;
102 furniture_sizes.border_widths.y0 = 40;
103 furniture_sizes.border_widths.x1 = 40;
104 error = xwimpextend_get_furniture_sizes(&furniture_sizes);
105 if (error) {
106 NSLOG(netsurf, INFO,
107 "xwimpextend_get_furniture_sizes: 0x%x: %s",
108 error->errnum,
109 error->errmess);
110 ro_warn_user("WimpError", error->errmess);
111 }
112}
113
114
115/**
116 * Reads a modes EIG factors.
117 *
118 * \param[in] mode mode to read EIG factors for, or -1 for current
119 * \param[out] xeig The x eig value
120 * \param[out] yeig The y eig value
121 * \return true on success else false.
122 */
123bool ro_gui_wimp_read_eig_factors(os_mode mode, int *xeig, int *yeig)
124{
125 os_error *error;
126
127 error = xos_read_mode_variable(mode, os_MODEVAR_XEIG_FACTOR, xeig, 0);
128 if (error) {
129 NSLOG(netsurf, INFO, "xos_read_mode_variable: 0x%x: %s",
130 error->errnum, error->errmess);
131 ro_warn_user("MiscError", error->errmess);
132 return false;
133 }
134 error = xos_read_mode_variable(mode, os_MODEVAR_YEIG_FACTOR, yeig, 0);
135 if (error) {
136 NSLOG(netsurf, INFO, "xos_read_mode_variable: 0x%x: %s",
137 error->errnum, error->errmess);
138 ro_warn_user("MiscError", error->errmess);
139 return false;
140 }
141 return true;
142}
143
144
145/**
146 * Converts the supplied os_coord from OS units to pixels.
147 *
148 * \param os_units values to convert
149 * \param mode mode to use EIG factors for, or -1 for current
150 */
151void ro_convert_os_units_to_pixels(os_coord *os_units, os_mode mode)
152{
153 int xeig = 1, yeig = 1;
154
155 ro_gui_wimp_read_eig_factors(mode, &xeig, &yeig);
156 os_units->x = ((os_units->x + (1 << xeig) - 1) >> xeig);
157 os_units->y = ((os_units->y + (1 << yeig) - 1) >> yeig);
158}
159
160
161/**
162 * Converts the supplied os_coord from pixels to OS units.
163 *
164 * \param pixels values to convert
165 * \param mode mode to use EIG factors for, or -1 for current
166 */
167void ro_convert_pixels_to_os_units(os_coord *pixels, os_mode mode)
168{
169 int xeig = 1, yeig = 1;
170
171 ro_gui_wimp_read_eig_factors(mode, &xeig, &yeig);
172 pixels->x = (pixels->x << xeig);
173 pixels->y = (pixels->y << yeig);
174}
175
176
177/**
178 * Redraws an icon
179 *
180 * \param w window handle
181 * \param i icon handle
182 */
183
184#define ro_gui_redraw_icon(w, i) xwimp_set_icon_state(w, i, 0, 0)
185
186
187/**
188 * Forces an icon to be redrawn entirely (ie not just updated).
189 *
190 * \param w window handle
191 * \param i icon handle
192 */
193void ro_gui_force_redraw_icon(wimp_w w, wimp_i i)
194{
195 wimp_icon_state ic;
196 os_error *error;
197
198 /* Get the icon data
199 */
200 ic.w = w;
201 ic.i = i;
202 error = xwimp_get_icon_state(&ic);
203 if (error) {
204 NSLOG(netsurf, INFO, "xwimp_get_icon_state: 0x%x: %s",
205 error->errnum, error->errmess);
206 ro_warn_user("WimpError", error->errmess);
207 return;
208 }
209 error = xwimp_force_redraw(w, ic.icon.extent.x0, ic.icon.extent.y0,
210 ic.icon.extent.x1, ic.icon.extent.y1);
211 if (error) {
212 NSLOG(netsurf, INFO, "xwimp_force_redraw: 0x%x: %s",
213 error->errnum, error->errmess);
214 ro_warn_user("WimpError", error->errmess);
215 }
216}
217
218
219/**
220 * Read the contents of a text or sprite icon.
221 *
222 * \param w window handle
223 * \param i icon handle
224 * \return NUL terminated string in icon
225 *
226 * If the icon contains direct text then the returned data will
227 * be invalidated by the next call to this function. Therefore,
228 * all client calls to this function must either copy the string or
229 * ensure that this function is not called again until they are
230 * finished with the string data returned.
231 *
232 * \todo this doesn't do local encoding -> UTF-8 to match what is done in
233 * ro_gui_set_icon_string.
234 */
235const char *ro_gui_get_icon_string(wimp_w w, wimp_i i)
236{
237 static wimp_icon_state ic;
238 os_error *error;
239 char *itext;
240
241 ic.w = w;
242 ic.i = i;
243 error = xwimp_get_icon_state(&ic);
244 if (error) {
245 NSLOG(netsurf, INFO, "xwimp_get_icon_state: 0x%x: %s",
246 error->errnum, error->errmess);
247 ro_warn_user("WimpError", error->errmess);
248 return NULL;
249 }
250 itext = (ic.icon.flags & wimp_ICON_INDIRECTED)
251 ? ic.icon.data.indirected_text.text : ic.icon.data.text;
252 /* Guarantee NUL termination. */
253 itext[ro_gui_strlen(itext)] = '\0';
254
255 return itext;
256}
257
258
259/**
260 * Set the contents of a text or sprite icon to a string.
261 *
262 * \param w window handle
263 * \param i icon handle
264 * \param text NUL terminated string (copied)
265 * \param is_utf8 When true, the given string is UTF-8 encoded and will be
266 * converted to local encoding currently used by the Wimp. When false, the
267 * given string is assumed to be in local encoding in use by the Wimp.
268 */
269void ro_gui_set_icon_string(wimp_w w, wimp_i i, const char *text, bool is_utf8)
270{
271 wimp_caret caret;
272 wimp_icon_state ic;
273 os_error *error;
274 size_t old_len, new_len;
275 char *local_text = NULL;
276 const char *text_for_icon;
277 char *dst_text;
278 size_t dst_max_len;
279 unsigned int button_type;
280
281 if (is_utf8) {
282 nserror err;
283 /* convert text to local encoding */
284 err = utf8_to_local_encoding(text, 0, &local_text);
285 if (err != NSERROR_OK) {
286 /* A bad encoding should never happen, so assert this */
287 assert(err != NSERROR_BAD_ENCODING);
288 NSLOG(netsurf, INFO, "utf8_to_enc failed");
289 /* Paranoia */
290 local_text = NULL;
291 }
292 text_for_icon = local_text ? local_text : text;
293 }
294 else
295 text_for_icon = text;
296 new_len = strlen(text_for_icon);
297
298 /* get the icon data */
299 ic.w = w;
300 ic.i = i;
301 error = xwimp_get_icon_state(&ic);
302 if (error) {
303 NSLOG(netsurf, INFO, "xwimp_get_icon_state: 0x%x: %s",
304 error->errnum, error->errmess);
305 ro_warn_user("WimpError", error->errmess);
306 goto exit;
307 }
308
309 if (ic.icon.flags & wimp_ICON_INDIRECTED) {
310 dst_text = ic.icon.data.indirected_text.text;
311 dst_max_len = ic.icon.data.indirected_text.size;
312 }
313 else {
314 dst_text = ic.icon.data.text;
315 dst_max_len = sizeof(ic.icon.data.text);
316 }
317 old_len = ro_gui_strlen(dst_text);
318 assert(old_len < dst_max_len);
319
320 /* check that the existing text is not the same as the updated text
321 * to stop flicker */
322 if (dst_max_len) {
323 if (!ro_gui_strncmp(dst_text, text_for_icon, dst_max_len))
324 goto exit;
325
326 /* copy the text across */
327 strncpy(dst_text, text_for_icon, dst_max_len - 1);
328 dst_text[dst_max_len - 1] = '\0';
329
330 /* handle the caret being in the icon */
331 button_type = (ic.icon.flags & wimp_ICON_BUTTON_TYPE)
332 >> wimp_ICON_BUTTON_TYPE_SHIFT;
333 if ((button_type == wimp_BUTTON_WRITABLE) ||
334 (button_type == wimp_BUTTON_WRITE_CLICK_DRAG)) {
335 error = xwimp_get_caret_position(&caret);
336 if (error) {
337 NSLOG(netsurf, INFO,
338 "xwimp_get_caret_position: 0x%x: %s",
339 error->errnum,
340 error->errmess);
341 ro_warn_user("WimpError", error->errmess);
342 goto exit;
343 }
344 if ((caret.w == w) && (caret.i == i)) {
345 if ((size_t)caret.index > new_len
346 || (size_t)caret.index == old_len)
347 caret.index = new_len;
348 error = xwimp_set_caret_position(w, i, caret.pos.x,
349 caret.pos.y, -1, caret.index);
350 if (error) {
351 NSLOG(netsurf, INFO,
352 "xwimp_set_caret_position: 0x%x: %s",
353 error->errnum,
354 error->errmess);
355 ro_warn_user("WimpError", error->errmess);
356 }
357 }
358 }
359 ro_gui_redraw_icon(w, i);
360 }
361
362exit:
363 free(local_text);
364}
365
366
367/**
368 * Set the contents of an icon to a number.
369 *
370 * \param w window handle
371 * \param i icon handle
372 * \param value value
373 */
374void ro_gui_set_icon_integer(wimp_w w, wimp_i i, int value)
375{
376 char buffer[20]; // Big enough for 64-bit int
377
378 sprintf(buffer, "%d", value);
379
380 ro_gui_set_icon_string(w, i, buffer, true);
381}
382
383
384/**
385 * Set the contents of an icon to a number.
386 *
387 * \param w window handle
388 * \param i icon handle
389 * \param value value to use in icon.
390 * \param decimal_places The number of decimal places to use.
391 */
392void ro_gui_set_icon_decimal(wimp_w w, wimp_i i, int value, int decimal_places)
393{
394 char buffer[20]; // Big enough for 64-bit int
395
396 switch (decimal_places) {
397 case 0:
398 sprintf(buffer, "%d", value);
399 break;
400 case 1:
401 sprintf(buffer, "%.1f", (float)value / 10);
402 break;
403 case 2:
404 sprintf(buffer, "%.2f", (float)value / 100);
405 break;
406 default:
407 assert(!"Unsupported decimal format");
408 break;
409 }
410
411 ro_gui_set_icon_string(w, i, buffer, true);
412}
413
414
415/**
416 * Get the contents of an icon as a number.
417 *
418 * \param w window handle
419 * \param i icon handle
420 * \param decimal_places number of places to show.
421 * \return value used.
422 */
423int ro_gui_get_icon_decimal(wimp_w w, wimp_i i, int decimal_places)
424{
425 double value;
426 int multiple = 1;
427
428 for (; decimal_places > 0; decimal_places--)
429 multiple *= 10;
430
431 value = atof(ro_gui_get_icon_string(w, i)) * multiple;
432
433 return (int)value;
434}
435
436
437/**
438 * Set the selected state of an icon.
439 *
440 * \param w window handle
441 * \param i icon handle
442 * \param state selected state
443 */
444void ro_gui_set_icon_selected_state(wimp_w w, wimp_i i, bool state)
445{
446 os_error *error;
447 if (ro_gui_get_icon_selected_state(w, i) == state) return;
448 error = xwimp_set_icon_state(w, i,
449 (state ? wimp_ICON_SELECTED : 0), wimp_ICON_SELECTED);
450 if (error) {
451 NSLOG(netsurf, INFO, "xwimp_set_icon_state: 0x%x: %s",
452 error->errnum, error->errmess);
453 ro_warn_user("WimpError", error->errmess);
454 }
455}
456
457/**
458 * Gets the selected state of an icon.
459 *
460 * \param w window handle
461 * \param i icon handle
462 */
463bool ro_gui_get_icon_selected_state(wimp_w w, wimp_i i)
464{
465 os_error *error;
466 wimp_icon_state ic;
467 ic.w = w;
468 ic.i = i;
469 error = xwimp_get_icon_state(&ic);
470 if (error) {
471 NSLOG(netsurf, INFO, "xwimp_get_icon_state: 0x%x: %s",
472 error->errnum, error->errmess);
473 ro_warn_user("WimpError", error->errmess);
474 return false;
475 }
476 return ((ic.icon.flags & wimp_ICON_SELECTED) != 0);
477}
478
479
480/**
481 * Set the shaded state of an icon.
482 *
483 * \param w window handle
484 * \param i icon handle
485 * \param state shaded state
486 */
487void ro_gui_set_icon_shaded_state(wimp_w w, wimp_i i, bool state)
488{
489 wimp_caret caret;
490 os_error *error;
491
492 /* update the state */
493 if (ro_gui_get_icon_shaded_state(w, i) == state)
494 return;
495 error = xwimp_set_icon_state(w, i,
496 (state ? wimp_ICON_SHADED : 0), wimp_ICON_SHADED);
497 if (error) {
498 NSLOG(netsurf, INFO, "xwimp_get_icon_state: 0x%x: %s",
499 error->errnum, error->errmess);
500 ro_warn_user("WimpError", error->errmess);
501 }
502 if (!state)
503 return;
504
505 /* ensure the caret is not in a shaded icon */
506 error = xwimp_get_caret_position(&caret);
507 if (error) {
508 NSLOG(netsurf, INFO, "xwimp_get_caret_position: 0x%x: %s",
509 error->errnum, error->errmess);
510 ro_warn_user("WimpError", error->errmess);
511 return;
512 }
513 if ((caret.w != w) || (caret.i != i))
514 return;
515 /* move the caret to the first avaiable writable */
517 return;
518 /* lose the caret */
519 error = xwimp_set_caret_position((wimp_w)-1, (wimp_i)-1, -1, -1, -1, -1);
520 if (error) {
521 NSLOG(netsurf, INFO, "xwimp_set_caret_position: 0x%x: %s",
522 error->errnum, error->errmess);
523 ro_warn_user("WimpError", error->errmess);
524 return;
525 }
526}
527
528
529/**
530 * Gets the shaded state of an icon.
531 *
532 * \param w window handle
533 * \param i icon handle
534 */
535bool ro_gui_get_icon_shaded_state(wimp_w w, wimp_i i)
536{
537 wimp_icon_state ic;
538 ic.w = w;
539 ic.i = i;
540 xwimp_get_icon_state(&ic);
541 return (ic.icon.flags & wimp_ICON_SHADED) != 0;
542}
543
544
545/**
546 * Set the deleted state of an icon.
547 *
548 * \param w window handle
549 * \param i icon handle
550 * \param state shaded state
551 */
552void ro_gui_set_icon_deleted_state(wimp_w w, wimp_i i, bool state)
553{
554 wimp_caret caret;
555 os_error *error;
556
557 /* update the state */
558 if (ro_gui_get_icon_deleted_state(w, i) == state)
559 return;
560 error = xwimp_set_icon_state(w, i,
561 (state ? wimp_ICON_DELETED : 0), wimp_ICON_DELETED);
562 if (error) {
563 NSLOG(netsurf, INFO, "xwimp_get_icon_state: 0x%x: %s",
564 error->errnum, error->errmess);
565 ro_warn_user("WimpError", error->errmess);
566 }
567 if (!state)
568 return;
569
570 /* ensure the caret is not in a shaded icon */
571 error = xwimp_get_caret_position(&caret);
572 if (error) {
573 NSLOG(netsurf, INFO, "xwimp_get_caret_position: 0x%x: %s",
574 error->errnum, error->errmess);
575 ro_warn_user("WimpError", error->errmess);
576 return;
577 }
578 if ((caret.w != w) || (caret.i != i))
579 return;
580 /* move the caret to the first avaiable writable */
582 return;
583 /* lose the caret */
584 error = xwimp_set_caret_position((wimp_w)-1, (wimp_i)-1, -1, -1, -1, -1);
585 if (error) {
586 NSLOG(netsurf, INFO, "xwimp_set_caret_position: 0x%x: %s",
587 error->errnum, error->errmess);
588 ro_warn_user("WimpError", error->errmess);
589 return;
590 }
591}
592
593
594/**
595 * Gets the deleted state of an icon.
596 *
597 * \param w window handle
598 * \param i icon handle
599 */
600bool ro_gui_get_icon_deleted_state(wimp_w w, wimp_i i)
601{
602 wimp_icon_state ic;
603 ic.w = w;
604 ic.i = i;
605 xwimp_get_icon_state(&ic);
606 return (ic.icon.flags & wimp_ICON_DELETED) != 0;
607}
608
609
610/**
611 * Set the button type of an icon.
612 *
613 * \param w window handle
614 * \param i icon handle
615 * \param type button type
616 */
617void ro_gui_set_icon_button_type(wimp_w w, wimp_i i, int type)
618{
619 os_error *error;
620 error = xwimp_set_icon_state(w, i, wimp_ICON_BUTTON_TYPE,
621 (type << wimp_ICON_BUTTON_TYPE_SHIFT));
622 if (error) {
623 NSLOG(netsurf, INFO, "xwimp_set_icon_state: 0x%x: %s",
624 error->errnum, error->errmess);
625 ro_warn_user("WimpError", error->errmess);
626 }
627}
628
629
630/**
631 * Set an icon's sprite
632 *
633 * \param w window handle
634 * \param i icon handle
635 * \param area sprite area containing sprite
636 * \param name name of sprite in area (in local encoding)
637 */
638void ro_gui_set_icon_sprite(wimp_w w, wimp_i i, osspriteop_area *area,
639 const char *name)
640{
641 wimp_icon_state ic;
642 os_error *error;
643
644 /* get the icon data */
645 ic.w = w;
646 ic.i = i;
647 error = xwimp_get_icon_state(&ic);
648 if (error) {
649 NSLOG(netsurf, INFO, "xwimp_get_icon_state: 0x%x: %s",
650 error->errnum, error->errmess);
651 ro_warn_user("WimpError", error->errmess);
652 return;
653 }
654
655 /* copy the name across */
656 if (ic.icon.data.indirected_text.size) {
657 strncpy(ic.icon.data.indirected_text.text, name,
658 (unsigned int)ic.icon.data.indirected_text.size - 1);
659 ic.icon.data.indirected_text.text[
660 ic.icon.data.indirected_text.size - 1] = '\0';
661 }
662
663 ic.icon.data.indirected_sprite.area = area;
664
665 ro_gui_redraw_icon(w, i);
666}
667
668
669/**
670 * Set a window title
671 *
672 * \param w window handle
673 * \param text new title (copied)
674 */
675void ro_gui_set_window_title(wimp_w w, const char *text)
676{
677 wimp_window_info_base window;
678 os_error *error;
679 char *title_local_enc;
680 nserror err;
681
682 /* Get the window details
683 */
684 window.w = w;
685 error = xwimp_get_window_info_header_only((wimp_window_info *)&window);
686 if (error) {
687 NSLOG(netsurf, INFO, "xwimp_get_window_info: 0x%x: %s",
688 error->errnum, error->errmess);
689 ro_warn_user("WimpError", error->errmess);
690 return;
691 }
692
693 /* convert text to local encoding */
694 err = utf8_to_local_encoding(text, 0, &title_local_enc);
695 if (err != NSERROR_OK) {
696 /* A bad encoding should never happen,
697 * so assert this */
698 assert(err != NSERROR_BAD_ENCODING);
699 NSLOG(netsurf, INFO, "utf8_to_enc failed");
700 return;
701 }
702
703 /* Set the title string
704 */
705 strncpy(window.title_data.indirected_text.text, title_local_enc,
706 (unsigned int)window.title_data.indirected_text.size
707 - 1);
708 window.title_data.indirected_text.text[
709 window.title_data.indirected_text.size - 1] = '\0';
710
711 /* Redraw accordingly
712 */
713 error = xwimp_force_redraw_title(w);
714 if (error) {
715 NSLOG(netsurf, INFO, "xwimp_force_redraw_title: 0x%x: %s",
716 error->errnum, error->errmess);
717 ro_warn_user("WimpError", error->errmess);
718 return;
719 }
720
721 free(title_local_enc);
722}
723
724
725/**
726 * Places the caret in the first available icon
727 *
728 * \param w the window to place the caret in
729 * \return true if the caret was placed, false otherwise
730 */
732{
733 int icon, b;
734 wimp_window_state win_state;
735 wimp_window_info_base window;
736 wimp_icon_state state;
737 os_error *error;
738
739 /* check the window is open */
740 win_state.w = w;
741 error = xwimp_get_window_state(&win_state);
742 if (error) {
743 NSLOG(netsurf, INFO, "xwimp_get_window_state: 0x%x: %s",
744 error->errnum, error->errmess);
745 ro_warn_user("WimpError", error->errmess);
746 return false;
747 }
748 if (!(win_state.flags & wimp_WINDOW_OPEN))
749 return false;
750
751 /* get the window details for the icon count */
752 window.w = w;
753 error = xwimp_get_window_info_header_only((wimp_window_info *)&window);
754 if (error) {
755 NSLOG(netsurf, INFO, "xwimp_get_window_info: 0x%x: %s",
756 error->errnum, error->errmess);
757 ro_warn_user("WimpError", error->errmess);
758 return false;
759 }
760
761 /* work through all the icons */
762 state.w = w;
763 for (icon = 0; icon < window.icon_count; icon++) {
764 state.i = icon;
765 error = xwimp_get_icon_state(&state);
766 if (error) {
767 NSLOG(netsurf, INFO,
768 "xwimp_get_icon_state: 0x%x: %s",
769 error->errnum,
770 error->errmess);
771 ro_warn_user("WimpError", error->errmess);
772 return false;
773 }
774
775 /* ignore if it's shaded or not writable */
776 if (state.icon.flags & wimp_ICON_SHADED)
777 continue;
778 b = (state.icon.flags >> wimp_ICON_BUTTON_TYPE_SHIFT) & 0xf;
779 if ((b != wimp_BUTTON_WRITE_CLICK_DRAG) &&
780 (b != wimp_BUTTON_WRITABLE))
781 continue;
782
783 /* move the caret */
784 error = xwimp_set_caret_position(w, icon, 0, 0, -1,
785 strlen(state.icon.data.indirected_text.text));
786 if (error) {
787 NSLOG(netsurf, INFO,
788 "xwimp_set_caret_position: 0x%x: %s",
789 error->errnum,
790 error->errmess);
791 ro_warn_user("WimpError", error->errmess);
792 }
793 return true;
794 }
795 return false;
796}
797
798
799/**
800 * Load a sprite file into memory.
801 *
802 * \param pathname file to load
803 * \return sprite area, or 0 on memory exhaustion or error and error reported
804 */
805
806osspriteop_area *ro_gui_load_sprite_file(const char *pathname)
807{
808 int len;
809 fileswitch_object_type obj_type;
810 osspriteop_area *area;
811 os_error *error;
812
813 error = xosfile_read_stamped_no_path(pathname,
814 &obj_type, 0, 0, &len, 0, 0);
815 if (error) {
816 NSLOG(netsurf, INFO,
817 "xosfile_read_stamped_no_path: 0x%x: %s",
818 error->errnum,
819 error->errmess);
820 ro_warn_user("MiscError", error->errmess);
821 return 0;
822 }
823 if (obj_type != fileswitch_IS_FILE) {
824 ro_warn_user("FileError", pathname);
825 return 0;
826 }
827
828 area = malloc(len + 4);
829 if (!area) {
830 ro_warn_user("NoMemory", 0);
831 return 0;
832 }
833
834 area->size = len + 4;
835 area->sprite_count = 0;
836 area->first = 16;
837 area->used = 16;
838
839 error = xosspriteop_load_sprite_file(osspriteop_USER_AREA,
840 area, pathname);
841 if (error) {
842 NSLOG(netsurf, INFO,
843 "xosspriteop_load_sprite_file: 0x%x: %s",
844 error->errnum,
845 error->errmess);
846 ro_warn_user("MiscError", error->errmess);
847 free(area);
848 return 0;
849 }
850
851 return area;
852}
853
854
855/**
856 * Check if a sprite is present in the Wimp sprite pool.
857 *
858 * \param sprite name of sprite
859 * \return true if the sprite is present
860 */
861
862bool ro_gui_wimp_sprite_exists(const char *sprite)
863{
864 static char last_sprite_found[16];
865 os_error *error;
866
867 /* make repeated calls fast */
868 if (!strncmp(sprite, last_sprite_found, sizeof(last_sprite_found)))
869 return true;
870
871 /* fallback if not known to exist */
872 error = xwimpspriteop_select_sprite(sprite, 0);
873 if (error) {
874 if (error->errnum != error_SPRITE_OP_DOESNT_EXIST) {
875 NSLOG(netsurf, INFO,
876 "xwimpspriteop_select_sprite: 0x%x: %s",
877 error->errnum,
878 error->errmess);
879 ro_warn_user("MiscError", error->errmess);
880 }
881 return false;
882 }
883 snprintf(last_sprite_found, sizeof(last_sprite_found), sprite);
884 return true;
885}
886
887
888/**
889 * Locate a sprite in the Wimp sprite pool, returning a pointer to it.
890 *
891 * \param name sprite name
892 * \param sprite receives pointer to sprite if found
893 * \return error ptr iff not found
894 */
895
896os_error *ro_gui_wimp_get_sprite(const char *name, osspriteop_header **sprite)
897{
898 osspriteop_area *rom_base, *ram_base;
899 os_error *error;
900
901 error = xwimp_base_of_sprites(&rom_base, &ram_base);
902 if (error) return error;
903
904 error = xosspriteop_select_sprite(osspriteop_USER_AREA,
905 ram_base, (osspriteop_id)name, sprite);
906
907 if (error && error->errnum == error_SPRITE_OP_DOESNT_EXIST)
908 error = xosspriteop_select_sprite(osspriteop_USER_AREA,
909 rom_base, (osspriteop_id)name, sprite);
910
911 return error;
912}
913
914
915/**
916 * Get the dimensions of a sprite
917 *
918 * \param *area The sprite area to use.
919 * \param *sprite Pointer to the sprite name.
920 * \param *width Return the sprite width.
921 * \param *height Return the sprite height.
922 * \return true if successful; else false.
923 */
924
925bool ro_gui_wimp_get_sprite_dimensions(osspriteop_area *area, char *sprite,
926 int *width, int *height)
927{
928 os_error *error = NULL;
929 os_mode mode;
930 os_coord dimensions;
931
932 dimensions.x = 0;
933 dimensions.y = 0;
934
935 if (area != (osspriteop_area *) -1)
936 error = xosspriteop_read_sprite_info(osspriteop_USER_AREA,
937 area, (osspriteop_id) sprite,
938 &dimensions.x, &dimensions.y, 0, &mode);
939
940 if (error != NULL || area == (osspriteop_area *) -1)
941 error = xwimpspriteop_read_sprite_info(sprite,
942 &dimensions.x, &dimensions.y, 0, &mode);
943
944 if (error == NULL) {
946 if (width != NULL)
947 *width = dimensions.x;
948 if (height != NULL)
949 *height = dimensions.y;
950 } else if (error->errnum != error_SPRITE_OP_DOESNT_EXIST) {
951 NSLOG(netsurf, INFO,
952 "xosspriteop_read_sprite_info: 0x%x: %s",
953 error->errnum,
954 error->errmess);
955 ro_warn_user("MiscError", error->errmess);
956 return false;
957 }
958
959 return true;
960}
961
962
963/**
964 * Performs simple user redraw for a window.
965 *
966 * \param redraw wimp draw
967 * \param user_fill whether to fill the redraw area
968 * \param user_colour the colour to use when filling
969 */
970
971void ro_gui_user_redraw(wimp_draw *redraw, bool user_fill,
972 os_colour user_colour)
973{
974 os_error *error;
975 osbool more;
976
977 error = xwimp_redraw_window(redraw, &more);
978 if (error) {
979 NSLOG(netsurf, INFO, "xwimp_redraw_window: 0x%x: %s",
980 error->errnum, error->errmess);
981 ro_warn_user("WimpError", error->errmess);
982 return;
983 }
984 while (more) {
985 if (user_fill) {
986 error = xcolourtrans_set_gcol(user_colour,
988 os_ACTION_OVERWRITE, 0, 0);
989 if (error) {
990 NSLOG(netsurf, INFO,
991 "xcolourtrans_set_gcol: 0x%x: %s",
992 error->errnum,
993 error->errmess);
994 ro_warn_user("MiscError", error->errmess);
995 }
996 os_clg();
997 }
998 error = xwimp_get_rectangle(redraw, &more);
999 if (error) {
1000 NSLOG(netsurf, INFO, "xwimp_get_rectangle: 0x%x: %s",
1001 error->errnum, error->errmess);
1002 ro_warn_user("WimpError", error->errmess);
1003 return;
1004 }
1005 }
1006}
1007
1008
1009/**
1010 * Sets whether a piece of window furniture is present for a window.
1011 *
1012 * \param w the window to modify
1013 * \param bic_mask the furniture flags to clear
1014 * \param xor_mask the furniture flags to toggle
1015 */
1016void ro_gui_wimp_update_window_furniture(wimp_w w, wimp_window_flags bic_mask,
1017 wimp_window_flags xor_mask)
1018{
1019 wimp_window_state state;
1020 wimp_w parent;
1021 bits linkage;
1022 os_error *error;
1023 bool open;
1024
1025 state.w = w;
1026 error = xwimp_get_window_state_and_nesting(&state, &parent, &linkage);
1027 if (error) {
1028 NSLOG(netsurf, INFO, "xwimp_get_window_state: 0x%x: %s",
1029 error->errnum, error->errmess);
1030 ro_warn_user("WimpError", error->errmess);
1031 return;
1032 }
1033
1034 open = state.flags & wimp_WINDOW_OPEN;
1035 state.flags &= ~(63 << 16); /* clear bits 16-21 */
1036 state.flags &= ~bic_mask;
1037 state.flags ^= xor_mask;
1038 if (!open)
1039 state.next = wimp_HIDDEN;
1040 error = xwimp_open_window_nested_with_flags(&state, parent, linkage);
1041 if (error) {
1042 NSLOG(netsurf, INFO, "xwimp_open_window: 0x%x: %s",
1043 error->errnum, error->errmess);
1044 ro_warn_user("WimpError", error->errmess);
1045 return;
1046 }
1047
1048 if (!open) {
1049 error = xwimp_close_window(w);
1050 if (error) {
1051 NSLOG(netsurf, INFO, "xwimp_close_window: 0x%x: %s",
1052 error->errnum, error->errmess);
1053 ro_warn_user("WimpError", error->errmess);
1054 return;
1055 }
1056 }
1057}
1058
1059
1060/**
1061 * Checks whether a piece of window furniture is present for a window.
1062 *
1063 * \param w the window to modify
1064 * \param mask the furniture flags to check
1065 */
1066bool ro_gui_wimp_check_window_furniture(wimp_w w, wimp_window_flags mask)
1067{
1068 wimp_window_state state;
1069 os_error *error;
1070
1071 state.w = w;
1072 error = xwimp_get_window_state(&state);
1073 if (error) {
1074 NSLOG(netsurf, INFO, "xwimp_get_window_state: 0x%x: %s",
1075 error->errnum, error->errmess);
1076 ro_warn_user("WimpError", error->errmess);
1077 return false;
1078 }
1079 return state.flags & mask;
1080}
1081
1082/**
1083 * RO GUI-specific strlen, for control character terminated strings
1084 *
1085 * \param str The string to measure the length of
1086 * \return The length of the string
1087 */
1088size_t ro_gui_strlen(const char *str)
1089{
1090 const char *str_begin;
1091
1092 if (str == NULL)
1093 return 0;
1094
1095 for (str_begin = str; *str++ >= ' '; /* */)
1096 /* */;
1097
1098 return str - str_begin - 1;
1099}
1100
1101/**
1102 * RO GUI-specific strncmp, for control character terminated strings
1103 *
1104 * \param s1 The first string for comparison
1105 * \param s2 The second string for comparison
1106 * \param len Maximum number of bytes to be checked
1107 * \return 0 for equal strings up to len bytes; pos for s1 being bigger than
1108 * s2; neg for s1 being smaller than s2.
1109 */
1110int ro_gui_strncmp(const char *s1, const char *s2, size_t len)
1111{
1112 while (len--) {
1113 char c1 = *s1++;
1114 char c2 = *s2++;
1115 if (c1 < ' ' || c2 < ' ')
1116 return (c1 < ' ' ? 0 : c1) - (c2 < ' ' ? 0 : c2);
1117 int diff = c1 - c2;
1118 if (diff)
1119 return diff;
1120 }
1121 return 0;
1122}
1123
1124
1125/**
1126 * Generic window scroll event handler.
1127 *
1128 * \param *scroll Pointer to Scroll Event block.
1129 */
1130
1131void ro_gui_scroll(wimp_scroll *scroll)
1132{
1133 os_error *error;
1134 int x = scroll->visible.x1 - scroll->visible.x0 - 32;
1135 int y = scroll->visible.y1 - scroll->visible.y0 - 32;
1136
1137 switch (scroll->xmin) {
1138 case wimp_SCROLL_PAGE_LEFT:
1139 scroll->xscroll -= x;
1140 break;
1141 case wimp_SCROLL_COLUMN_LEFT:
1142 scroll->xscroll -= 100;
1143 break;
1144 case wimp_SCROLL_COLUMN_RIGHT:
1145 scroll->xscroll += 100;
1146 break;
1147 case wimp_SCROLL_PAGE_RIGHT:
1148 scroll->xscroll += x;
1149 break;
1150 default:
1151 scroll->xscroll += (x * (scroll->xmin>>2)) >> 2;
1152 break;
1153 }
1154
1155 switch (scroll->ymin) {
1156 case wimp_SCROLL_PAGE_UP:
1157 scroll->yscroll += y;
1158 break;
1159 case wimp_SCROLL_LINE_UP:
1160 scroll->yscroll += 100;
1161 break;
1162 case wimp_SCROLL_LINE_DOWN:
1163 scroll->yscroll -= 100;
1164 break;
1165 case wimp_SCROLL_PAGE_DOWN:
1166 scroll->yscroll -= y;
1167 break;
1168 default:
1169 scroll->yscroll += (y * (scroll->ymin>>2)) >> 2;
1170 break;
1171 }
1172
1173 error = xwimp_open_window((wimp_open *) scroll);
1174 if (error) {
1175 NSLOG(netsurf, INFO, "xwimp_open_window: 0x%x: %s",
1176 error->errnum, error->errmess);
1177 }
1178}
1179
static os_mode mode
The current sprite mode.
Definition: buffer.c:72
static osspriteop_area * buffer
The buffer characteristics.
Definition: buffer.c:55
wimp_w parent
Definition: dialog.c:88
nserror
Enumeration of error codes.
Definition: errors.h:29
@ NSERROR_BAD_ENCODING
The character set is unknown.
Definition: errors.h:45
@ NSERROR_OK
No error.
Definition: errors.h:30
const char * type
Definition: filetype.cpp:44
nserror utf8_to_local_encoding(const char *string, size_t len, char **result)
Definition: utf8.c:89
#define NSLOG(catname, level, logmsg, args...)
Definition: log.h:116
Backward compatible defines to make NetSurf buildable with pre-OSLib 7 releases.
#define colourtrans_SET_BG_GCOL
After OSLib 6.90, there was a rename of colourtrans defines in order to avoid namespace clashes: svn ...
Definition: oslib_pre7.h:36
int width
Definition: gui.c:159
nserror ro_warn_user(const char *warning, const char *detail)
Display a warning for a serious problem (eg memory exhaustion).
Definition: gui.c:2076
int height
Definition: gui.c:160
Interface to utility string handling.
UCS conversion tables (interface) This is only used if nothing claims Service_International,...
UTF-8 manipulation functions (interface).
os_error * ro_gui_wimp_get_sprite(const char *name, osspriteop_header **sprite)
Locate a sprite in the Wimp sprite pool, returning a pointer to it.
Definition: wimp.c:896
static wimp_w furniture_window
Definition: wimp.c:51
void ro_gui_set_icon_string(wimp_w w, wimp_i i, const char *text, bool is_utf8)
Set the contents of a text or sprite icon to a string.
Definition: wimp.c:269
void ro_gui_set_icon_deleted_state(wimp_w w, wimp_i i, bool state)
Set the deleted state of an icon.
Definition: wimp.c:552
void ro_gui_wimp_update_window_furniture(wimp_w w, wimp_window_flags bic_mask, wimp_window_flags xor_mask)
Sets whether a piece of window furniture is present for a window.
Definition: wimp.c:1016
int ro_get_hscroll_height(wimp_w w)
Gets the horizontal scrollbar height.
Definition: wimp.c:58
int ro_gui_get_icon_decimal(wimp_w w, wimp_i i, int decimal_places)
Get the contents of an icon as a number.
Definition: wimp.c:423
void ro_convert_os_units_to_pixels(os_coord *os_units, os_mode mode)
Converts the supplied os_coord from OS units to pixels.
Definition: wimp.c:151
static void ro_gui_wimp_cache_furniture_sizes(wimp_w w)
Caches window furniture information.
Definition: wimp.c:94
void ro_gui_set_icon_button_type(wimp_w w, wimp_i i, int type)
Set the button type of an icon.
Definition: wimp.c:617
void ro_gui_force_redraw_icon(wimp_w w, wimp_i i)
Forces an icon to be redrawn entirely (ie not just updated).
Definition: wimp.c:193
bool ro_gui_wimp_get_sprite_dimensions(osspriteop_area *area, char *sprite, int *width, int *height)
Get the dimensions of a sprite.
Definition: wimp.c:925
bool ro_gui_get_icon_deleted_state(wimp_w w, wimp_i i)
Gets the deleted state of an icon.
Definition: wimp.c:600
void ro_gui_set_window_title(wimp_w w, const char *text)
Set a window title.
Definition: wimp.c:675
int ro_get_title_height(wimp_w w)
Gets the title bar height.
Definition: wimp.c:82
osspriteop_area * ro_gui_load_sprite_file(const char *pathname)
Load a sprite file into memory.
Definition: wimp.c:806
void ro_gui_set_icon_shaded_state(wimp_w w, wimp_i i, bool state)
Set the shaded state of an icon.
Definition: wimp.c:487
bool ro_gui_wimp_sprite_exists(const char *sprite)
Check if a sprite is present in the Wimp sprite pool.
Definition: wimp.c:862
const char * ro_gui_get_icon_string(wimp_w w, wimp_i i)
Read the contents of a text or sprite icon.
Definition: wimp.c:235
static int ro_gui_strncmp(const char *s1, const char *s2, size_t len)
RO GUI-specific strncmp, for control character terminated strings.
Definition: wimp.c:1110
bool ro_gui_wimp_read_eig_factors(os_mode mode, int *xeig, int *yeig)
Reads a modes EIG factors.
Definition: wimp.c:123
void ro_gui_set_icon_selected_state(wimp_w w, wimp_i i, bool state)
Set the selected state of an icon.
Definition: wimp.c:444
bool ro_gui_wimp_check_window_furniture(wimp_w w, wimp_window_flags mask)
Checks whether a piece of window furniture is present for a window.
Definition: wimp.c:1066
bool ro_gui_get_icon_shaded_state(wimp_w w, wimp_i i)
Gets the shaded state of an icon.
Definition: wimp.c:535
void ro_gui_set_icon_sprite(wimp_w w, wimp_i i, osspriteop_area *area, const char *name)
Set an icon's sprite.
Definition: wimp.c:638
bool ro_gui_set_caret_first(wimp_w w)
Places the caret in the first available icon.
Definition: wimp.c:731
void ro_convert_pixels_to_os_units(os_coord *pixels, os_mode mode)
Converts the supplied os_coord from pixels to OS units.
Definition: wimp.c:167
static wimpextend_furniture_sizes furniture_sizes
Definition: wimp.c:50
static size_t ro_gui_strlen(const char *str)
RO GUI-specific strlen, for control character terminated strings.
Definition: wimp.c:1088
#define ro_gui_redraw_icon(w, i)
Redraws an icon.
Definition: wimp.c:184
void ro_gui_set_icon_integer(wimp_w w, wimp_i i, int value)
Set the contents of an icon to a number.
Definition: wimp.c:374
void ro_gui_user_redraw(wimp_draw *redraw, bool user_fill, os_colour user_colour)
Performs simple user redraw for a window.
Definition: wimp.c:971
void ro_gui_set_icon_decimal(wimp_w w, wimp_i i, int value, int decimal_places)
Set the contents of an icon to a number.
Definition: wimp.c:392
bool ro_gui_get_icon_selected_state(wimp_w w, wimp_i i)
Gets the selected state of an icon.
Definition: wimp.c:463
void ro_gui_scroll(wimp_scroll *scroll)
Generic window scroll event handler.
Definition: wimp.c:1131
int ro_get_vscroll_width(wimp_w w)
Gets the vertical scrollbar width.
Definition: wimp.c:70
General RISC OS WIMP/OS library functions (interface).
static nserror text(const struct redraw_context *ctx, const struct plot_font_style *fstyle, int x, int y, const char *text, size_t length)
Text plotting.
Definition: plot.c:978