summaryrefslogtreecommitdiff
path: root/riscos
diff options
context:
space:
mode:
authorRichard Wilson <rjw@netsurf-browser.org>2006-10-11 23:25:02 +0000
committerRichard Wilson <rjw@netsurf-browser.org>2006-10-11 23:25:02 +0000
commita6d038c543ba9ee197e844399bf5ffa582b1e7a8 (patch)
tree03d4ec40f5c2418b162ecabbed2b8e07c2bc7d1a /riscos
parentab03c6736098f4123ff6865ec6a12fe8ba4b3feb (diff)
downloadnetsurf-a6d038c543ba9ee197e844399bf5ffa582b1e7a8.tar.gz
netsurf-a6d038c543ba9ee197e844399bf5ffa582b1e7a8.tar.bz2
UTF-8 status bar component.
svn path=/trunk/netsurf/; revision=2995
Diffstat (limited to 'riscos')
-rw-r--r--riscos/gui/status_bar.c608
-rw-r--r--riscos/gui/status_bar.h34
2 files changed, 642 insertions, 0 deletions
diff --git a/riscos/gui/status_bar.c b/riscos/gui/status_bar.c
new file mode 100644
index 000000000..68971d161
--- /dev/null
+++ b/riscos/gui/status_bar.c
@@ -0,0 +1,608 @@
+/*
+ * This file is part of NetSurf, http://netsurf.sourceforge.net/
+ * Licensed under the GNU General Public License,
+ * http://www.opensource.org/licenses/gpl-license
+ * Copyright 2006 Richard Wilson <info@tinct.net>
+ */
+
+/** \file
+ * UTF8 status bar (implementation).
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+#include <string.h>
+#include <swis.h>
+#include "oslib/colourtrans.h"
+#include "oslib/os.h"
+#include "oslib/wimp.h"
+#include "oslib/wimpspriteop.h"
+#include "netsurf/desktop/plotters.h"
+#include "netsurf/utils/log.h"
+#include "netsurf/utils/utf8.h"
+#include "netsurf/utils/utils.h"
+#include "netsurf/riscos/gui.h"
+#include "netsurf/riscos/wimp.h"
+#include "netsurf/riscos/wimp_event.h"
+#include "netsurf/riscos/gui/progress_bar.h"
+#include "netsurf/riscos/gui/status_bar.h"
+
+#define ICON_WIDGET 0
+#define WIDGET_WIDTH 12
+#define PROGRESS_WIDTH 160
+
+struct status_bar {
+ wimp_w w; /**< status bar window handle */
+ wimp_w parent; /**< parent window handle */
+ char *text; /**< status bar text */
+ char *local; /**< status bar text (local encoding) */
+ struct progress_bar *pb; /**< progress bar */
+ unsigned int scale; /**< current status bar scale */
+ int width; /**< current status bar width */
+ bool visible; /**< status bar is visible? */
+};
+
+static char status_widget_text[] = "\0";
+static char status_widget_validation[] = "R5;Pptr_lr,8,6\0";
+
+wimp_WINDOW(1) status_bar_definition = {
+ {0, 0, 1, 1},
+ 0,
+ 0,
+ wimp_TOP,
+ wimp_WINDOW_NEW_FORMAT | wimp_WINDOW_MOVEABLE |
+ wimp_WINDOW_FURNITURE_WINDOW |
+ wimp_WINDOW_IGNORE_XEXTENT,
+ wimp_COLOUR_BLACK,
+ wimp_COLOUR_LIGHT_GREY,
+ wimp_COLOUR_LIGHT_GREY,
+ wimp_COLOUR_VERY_LIGHT_GREY,
+ wimp_COLOUR_DARK_GREY,
+ wimp_COLOUR_MID_LIGHT_GREY,
+ wimp_COLOUR_CREAM,
+ wimp_WINDOW_NEVER3D | 0x16u /* RISC OS 5.03+ */,
+ {0, 0, 65535, 65535},
+ 0,
+ 0,
+ wimpspriteop_AREA,
+ 1,
+ 1,
+ {""},
+ 1,
+ {
+ {
+ {0, 0, 1, 1},
+ wimp_ICON_TEXT | wimp_ICON_INDIRECTED |
+ wimp_ICON_BORDER | wimp_ICON_FILLED |
+ (wimp_COLOUR_LIGHT_GREY <<
+ wimp_ICON_BG_COLOUR_SHIFT) |
+ (wimp_BUTTON_CLICK_DRAG <<
+ wimp_ICON_BUTTON_TYPE_SHIFT),
+ {
+ .indirected_text = {
+ status_widget_text,
+ status_widget_validation,
+ 1
+ }
+ }
+ }
+ }
+};
+
+static void ro_gui_status_bar_open(wimp_open *open);
+static bool ro_gui_status_bar_click(wimp_pointer *pointer);
+static void ro_gui_status_bar_redraw(wimp_draw *redraw);
+static void ro_gui_status_position_progress_bar(struct status_bar *sb);
+
+
+/**
+ * Create a new status bar
+ *
+ * \param parent the window to contain the status bar
+ * \param width the proportional width to use (0...10,000)
+ */
+struct status_bar *ro_gui_status_bar_create(wimp_w parent, unsigned int width) {
+ struct status_bar *sb;
+ os_error *error;
+
+ sb = calloc(1, sizeof(*sb));
+ if (!sb)
+ return NULL;
+
+ sb->pb = ro_gui_progress_bar_create();
+ if (!sb->pb)
+ return NULL;
+
+ error = xwimp_create_window((wimp_window *)&status_bar_definition,
+ &sb->w);
+ if (error) {
+ LOG(("xwimp_create_window: 0x%x: %s",
+ error->errnum, error->errmess));
+ free(sb);
+ return NULL;
+ }
+ sb->parent = parent;
+ sb->scale = width;
+ sb->visible = true;
+
+ ro_gui_wimp_event_set_user_data(sb->w, sb);
+ ro_gui_wimp_event_register_open_window(sb->w,
+ ro_gui_status_bar_open);
+ ro_gui_wimp_event_register_mouse_click(sb->w,
+ ro_gui_status_bar_click);
+ ro_gui_wimp_event_register_redraw_window(sb->w,
+ ro_gui_status_bar_redraw);
+ ro_gui_wimp_event_set_user_data(sb->w, sb);
+ ro_gui_wimp_event_set_help_prefix(sb->w, "HelpStatus");
+ ro_gui_status_bar_resize(sb);
+ return sb;
+}
+
+
+/**
+ * Destroy a status bar and free all associated resources
+ *
+ * \param sb the status bar to destroy
+ */
+void ro_gui_status_bar_destroy(struct status_bar *sb) {
+ os_error *error;
+ assert(sb);
+
+ ro_gui_wimp_event_finalise(sb->w);
+ error = xwimp_delete_window(sb->w);
+ if (error) {
+ LOG(("xwimp_delete_window: 0x%x:%s",
+ error->errnum, error->errmess));
+ }
+
+ free(sb);
+}
+
+
+/**
+ * Get the handle of the window that represents a status bar
+ *
+ * \param sb the status bar to get the window handle of
+ * \return the status bar's window handle
+ */
+wimp_w ro_gui_status_bar_get_window(struct status_bar *sb) {
+ assert(sb);
+
+ return sb->w;
+}
+
+
+/**
+ * Get the proportional width the status bar is currently using
+ *
+ * \param sb the status bar to get the width of
+ * \return the status bar's width (0...10,000)
+ */
+unsigned int ro_gui_status_bar_get_width(struct status_bar *sb) {
+ assert(sb);
+
+ return sb->scale;
+}
+
+
+/**
+ * Get the visibility status of the status bar
+ *
+ * \param sb the status bar to check the visiblity of
+ * \return whether the status bar is visible
+ */
+void ro_gui_status_bar_set_visible(struct status_bar *sb, bool visible) {
+ os_error *error;
+
+ assert(sb);
+
+ sb->visible = visible;
+ if (visible) {
+ ro_gui_status_bar_resize(sb);
+ } else {
+ error = xwimp_close_window(sb->w);
+ if (error) {
+ LOG(("xwimp_close_window: 0x%x:%s",
+ error->errnum, error->errmess));
+ }
+ }
+}
+
+
+/**
+ * Get the visibility status of the status bar
+ *
+ * \param sb the status bar to check the visiblity of
+ * \return whether the status bar is visible
+ */
+bool ro_gui_status_bar_get_visible(struct status_bar *sb) {
+ assert(sb);
+
+ return sb->visible;
+}
+
+
+/**
+ * Set the value of the progress bar
+ *
+ * \param pb the status bar to set the progress of
+ * \param value the value to use
+ */
+void ro_gui_status_bar_set_progress_value(struct status_bar *sb,
+ unsigned int value) {
+
+ assert(sb);
+
+ ro_gui_status_bar_set_progress_range(sb,
+ max(value, ro_gui_progress_bar_get_range(sb->pb)));
+ ro_gui_progress_bar_set_value(sb->pb, value);
+}
+
+
+/**
+ * Set the range of the progress bar
+ *
+ * \param pb the status bar to set the range of
+ * \param value the value to use, or 0 to turn off the progress bar
+ */
+void ro_gui_status_bar_set_progress_range(struct status_bar *sb,
+ unsigned int range) {
+ unsigned int old_range;
+ os_error *error;
+
+ assert(sb);
+
+ old_range = ro_gui_progress_bar_get_range(sb->pb);
+ ro_gui_progress_bar_set_range(sb->pb, range);
+
+ LOG(("Ranges are %i vs %i", old_range, range));
+ if ((old_range == 0) && (range != 0)) {
+ ro_gui_status_position_progress_bar(sb);
+ } else if ((old_range != 0) && (range == 0)) {
+ error = xwimp_close_window(
+ ro_gui_progress_bar_get_window(sb->pb));
+ if (error) {
+ LOG(("xwimp_close_window: 0x%x:%s",
+ error->errnum, error->errmess));
+ }
+ }
+}
+
+
+/**
+ * Set the icon for the progress bar
+ *
+ * \param pb the status bar to set the icon for
+ * \param icon the icon to use, or NULL for no icon
+ */
+void ro_gui_status_bar_set_progress_icon(struct status_bar *sb,
+ const char *icon) {
+ assert(sb);
+
+ ro_gui_progress_bar_set_icon(sb->pb, icon);
+}
+
+
+/**
+ * Set the text to display in the status bar
+ *
+ * \param text the UTF8 text to display, or NULL for none
+ */
+void ro_gui_status_bar_set_text(struct status_bar *sb, const char *text) {
+ utf8_convert_ret ret;
+
+ assert(sb);
+
+ /* check for no change */
+ if ((sb->text) && (!strcmp(text, sb->text)))
+ return;
+
+ /* release the old text */
+ if (sb->text)
+ free(sb->text);
+ sb->text = NULL;
+ if (sb->local)
+ free(sb->local);
+ sb->local = NULL;
+
+ /* copy the text */
+ sb->text = strdup(text);
+ if (!sb->text)
+ return;
+
+ /* get local encoding */
+ ret = utf8_to_local_encoding(text, 0, &(sb->local));
+ if (ret != UTF8_CONVERT_OK) {
+ assert(ret != UTF8_CONVERT_BADENC);
+ LOG(("utf8_to_enc failed"));
+ free(sb->text);
+ sb->text = NULL;
+ return;
+ }
+
+ /* redraw the window */
+ xwimp_force_redraw(sb->w, 0, 0, sb->width - WIDGET_WIDTH, 65536);
+}
+
+
+/**
+ * Resize a status bar following a change in the dimensions of the
+ * parent window.
+ *
+ * \param sb the status bar to resize
+ */
+void ro_gui_status_bar_resize(struct status_bar *sb) {
+ int window_width, window_height;
+ int status_width, status_height;
+ int redraw_left, redraw_right;
+ wimp_window_state state;
+ os_error *error;
+ os_box extent;
+
+ if (!sb)
+ return;
+
+ /* get the window work area dimensions */
+ state.w = sb->parent;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG(("xwimp_get_window_state: 0x%x: %s",
+ error->errnum, error->errmess));
+ return;
+ }
+ window_width = state.visible.x1 - state.visible.x0;
+ window_height = state.visible.y1 - state.visible.y0;
+
+
+ /* recalculate the scaled width */
+ status_width = (window_width * sb->scale) / 10000;
+ if (status_width < WIDGET_WIDTH)
+ status_width = WIDGET_WIDTH;
+ status_height = ro_get_hscroll_height(sb->parent);
+
+ /* resize the status/resize icons */
+ if (status_width != sb->width) {
+ /* update the window extent */
+ extent.x0 = 0;
+ extent.y0 = 0;
+ extent.x1 = status_width;
+ extent.y1 = status_height - 4;
+ error = xwimp_set_extent(sb->w, &extent);
+ if (error) {
+ LOG(("xwimp_set_extent: 0x%x: %s",
+ error->errnum, error->errmess));
+ return;
+ }
+
+ /* re-open the nested window */
+ state.w = sb->w;
+ state.xscroll = 0;
+ state.yscroll = 0;
+ state.next = wimp_TOP;
+ state.visible.x0 = state.visible.x0;
+ state.visible.y1 = state.visible.y0 - 2;
+ state.visible.x1 = state.visible.x0 + status_width;
+ state.visible.y0 = state.visible.y1 - status_height + 4;
+ error = xwimp_open_window_nested((wimp_open *)&state,
+ sb->parent,
+ wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
+ << wimp_CHILD_XORIGIN_SHIFT |
+ wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
+ << wimp_CHILD_YORIGIN_SHIFT |
+ wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
+ << wimp_CHILD_LS_EDGE_SHIFT |
+ wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
+ << wimp_CHILD_BS_EDGE_SHIFT |
+ wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
+ << wimp_CHILD_RS_EDGE_SHIFT |
+ wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
+ << wimp_CHILD_TS_EDGE_SHIFT);
+ if (error) {
+ LOG(("xwimp_open_window_nested: 0x%x: %s",
+ error->errnum, error->errmess));
+ return;
+ }
+ ro_gui_status_position_progress_bar(sb);
+ error = xwimp_resize_icon(sb->w, ICON_WIDGET,
+ status_width - WIDGET_WIDTH, 0,
+ status_width, status_height - 4);
+ if (error) {
+ LOG(("xwimp_resize_icon: 0x%x: %s",
+ error->errnum, error->errmess));
+ return;
+ }
+
+ redraw_left = min(status_width, sb->width) - WIDGET_WIDTH - 2;
+ redraw_right = max(status_width, sb->width);
+ xwimp_force_redraw(sb->w, redraw_left, 0,
+ redraw_right, status_height);
+ sb->width = status_width;
+ }
+}
+
+
+/**
+ * Process a WIMP redraw request
+ *
+ * \param redraw the redraw request to process
+ */
+void ro_gui_status_bar_redraw(wimp_draw *redraw) {
+
+ struct status_bar *sb;
+ os_error *error;
+ osbool more;
+ rufl_code code;
+
+ sb = (struct status_bar *)ro_gui_wimp_event_get_user_data(redraw->w);
+ assert(sb);
+
+ /* initialise the plotters */
+ plot = ro_plotters;
+ ro_plot_set_scale(1.0);
+ ro_plot_origin_x = 0;
+ ro_plot_origin_y = 0;
+
+ /* redraw the window */
+ error = xwimp_redraw_window(redraw, &more);
+ if (error) {
+ LOG(("xwimp_redraw_window: 0x%x: %s",
+ error->errnum, error->errmess));
+ return;
+ }
+ while (more) {
+ /* redraw the status text */
+ if (sb->local) {
+ error = xcolourtrans_set_font_colours(font_CURRENT,
+ 0xeeeeee00, 0x00000000, 14, 0, 0, 0);
+ if (error) {
+ LOG(("xcolourtrans_set_font_colours: 0x%x: %s",
+ error->errnum, error->errmess));
+ return;
+ }
+ code = rufl_paint(ro_gui_desktop_font_family,
+ ro_gui_desktop_font_style,
+ ro_gui_desktop_font_size,
+ sb->local, strlen(sb->local),
+ redraw->box.x0 + 6, redraw->box.y0 + 8,
+ rufl_BLEND_FONT);
+ if (code != rufl_OK) {
+ if (code == rufl_FONT_MANAGER_ERROR)
+ LOG(("rufl_FONT_MANAGER_ERROR: 0x%x: %s",
+ rufl_fm_error->errnum,
+ rufl_fm_error->errmess));
+ else
+ LOG(("rufl_paint: 0x%x", code));
+ }
+ }
+
+ /* separate the widget from the text with a line */
+ plot.fill((redraw->box.x0 + sb->width - WIDGET_WIDTH - 2) >> 1,
+ -redraw->box.y0 >> 1,
+ (redraw->box.x0 + sb->width - WIDGET_WIDTH) >> 1,
+ -redraw->box.y1 >> 1,
+ 0x00000000);
+
+ error = xwimp_get_rectangle(redraw, &more);
+ if (error) {
+ LOG(("xwimp_get_rectangle: 0x%x: %s",
+ error->errnum, error->errmess));
+ return;
+ }
+ }
+}
+
+
+/**
+ * Process an mouse_click event for a status window.
+ *
+ * \param pointer details of the mouse click
+ */
+bool ro_gui_status_bar_click(wimp_pointer *pointer) {
+ wimp_drag drag;
+ os_error *error;
+
+ switch (pointer->i) {
+ case ICON_WIDGET:
+ gui_current_drag_type = GUI_DRAG_STATUS_RESIZE;
+ drag.w = pointer->w;
+ drag.type = wimp_DRAG_SYSTEM_SIZE;
+ drag.initial.x0 = pointer->pos.x;
+ drag.initial.x1 = pointer->pos.x;
+ drag.initial.y0 = pointer->pos.y;
+ drag.initial.y1 = pointer->pos.y;
+ error = xwimp_drag_box(&drag);
+ if (error) {
+ LOG(("xwimp_drag_box: 0x%x: %s",
+ error->errnum, error->errmess));
+ }
+ break;
+ }
+ return true;
+}
+
+
+/**
+ * Process an open_window request for a status window.
+ *
+ * \param open the request to process
+ */
+void ro_gui_status_bar_open(wimp_open *open) {
+ struct status_bar *sb;
+ int window_width, status_width;
+ wimp_window_state state;
+ os_error *error;
+
+ /* get the parent width for scaling */
+ sb = (struct status_bar *)ro_gui_wimp_event_get_user_data(open->w);
+ state.w = sb->parent;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG(("xwimp_get_window_state: 0x%x: %s",
+ error->errnum, error->errmess));
+ return;
+ }
+ window_width = state.visible.x1 - state.visible.x0;
+ if (window_width == 0)
+ window_width = 1;
+ status_width = open->visible.x1 - open->visible.x0;
+ if (status_width <= 12)
+ status_width = 0;
+
+ /* store the new size */
+ sb->scale = (10000 * status_width) / window_width;
+ if (sb->scale > 10000)
+ sb->scale = 10000;
+ ro_gui_status_bar_resize(sb);
+}
+
+
+/**
+ * Reposition the progress component following a change in the
+ * dimension of the status window.
+ *
+ * \param sb the status bar to update
+ */
+void ro_gui_status_position_progress_bar(struct status_bar *sb) {
+ wimp_window_state state;
+ os_error *error;
+
+ if (!sb)
+ return;
+ if (ro_gui_progress_bar_get_range(sb->pb) == 0)
+ return;
+
+ /* get the window work area dimensions */
+ state.w = sb->w;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG(("xwimp_get_window_state: 0x%x: %s",
+ error->errnum, error->errmess));
+ return;
+ }
+
+ /* re-open the nested window */
+ state.w = ro_gui_progress_bar_get_window(sb->pb);
+ state.xscroll = 0;
+ state.yscroll = 0;
+ state.next = wimp_TOP;
+ state.visible.x0 = state.visible.x1 - PROGRESS_WIDTH;
+ state.visible.x1 -= WIDGET_WIDTH + 2;
+ error = xwimp_open_window_nested((wimp_open *)&state,
+ sb->w,
+ wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
+ << wimp_CHILD_XORIGIN_SHIFT |
+ wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
+ << wimp_CHILD_YORIGIN_SHIFT |
+ wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
+ << wimp_CHILD_LS_EDGE_SHIFT |
+ wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
+ << wimp_CHILD_BS_EDGE_SHIFT |
+ wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
+ << wimp_CHILD_RS_EDGE_SHIFT |
+ wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
+ << wimp_CHILD_TS_EDGE_SHIFT);
+ if (error) {
+ LOG(("xwimp_open_window: 0x%x: %s",
+ error->errnum, error->errmess));
+ }
+}
diff --git a/riscos/gui/status_bar.h b/riscos/gui/status_bar.h
new file mode 100644
index 000000000..b1c5baca4
--- /dev/null
+++ b/riscos/gui/status_bar.h
@@ -0,0 +1,34 @@
+/*
+ * This file is part of NetSurf, http://netsurf.sourceforge.net/
+ * Licensed under the GNU General Public License,
+ * http://www.opensource.org/licenses/gpl-license
+ * Copyright 2006 Richard Wilson <info@tinct.net>
+ */
+
+/** \file
+ * UTF8 status bar (interface).
+ */
+
+#include <stdbool.h>
+
+#ifndef _NETSURF_RISCOS_STATUS_BAR_H_
+#define _NETSURF_RISCOS_STATUS_BAR_H_
+
+struct status_bar;
+
+struct status_bar *ro_gui_status_bar_create(wimp_w parent, unsigned int width);
+void ro_gui_status_bar_destroy(struct status_bar *sb);
+
+wimp_w ro_gui_status_bar_get_window(struct status_bar *sb);
+unsigned int ro_gui_status_bar_get_width(struct status_bar *sb);
+void ro_gui_status_bar_resize(struct status_bar *sb);
+void ro_gui_status_bar_set_visible(struct status_bar *pb, bool visible);
+bool ro_gui_status_bar_get_visible(struct status_bar *pb);
+void ro_gui_status_bar_set_text(struct status_bar *pb, const char *text);
+void ro_gui_status_bar_set_progress_value(struct status_bar *sb,
+ unsigned int value);
+void ro_gui_status_bar_set_progress_range(struct status_bar *sb,
+ unsigned int range);
+void ro_gui_status_bar_set_progress_icon(struct status_bar *sb,
+ const char *icon);
+#endif