netsurf/riscos/configure.c
2009-05-29 22:56:09 +00:00

418 lines
12 KiB
C

/*
* Copyright 2005 Richard Wilson <info@tinct.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/** \file
* RISC OS option setting (implementation).
*/
#include <assert.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "oslib/os.h"
#include "oslib/osbyte.h"
#include "oslib/territory.h"
#include "oslib/wimp.h"
#include "riscos/dialog.h"
#include "riscos/configure.h"
#include "riscos/wimp.h"
#include "riscos/wimp_event.h"
#include "riscos/configure/configure.h"
#include "utils/log.h"
#include "utils/utils.h"
#include "utils/messages.h"
#define CONFIGURE_ICON_PADDING_H 32
#define CONFIGURE_ICON_PADDING_V 32
#define CONFIGURE_DEFAULT_ICON_WIDTH (68 + CONFIGURE_ICON_PADDING_H)
#define CONFIGURE_DEFAULT_ICON_HEIGHT (128 + CONFIGURE_ICON_PADDING_V)
struct configure_tool {
const char *name;
#define CONFIGURE_TOOL_TRANSLATED_SIZE 64
char translated[CONFIGURE_TOOL_TRANSLATED_SIZE];
char *validation;
bool (*initialise)(wimp_w w);
void (*finalise)(wimp_w w);
wimp_w w;
wimp_i i;
bool open;
struct configure_tool *next;
};
static wimp_w configure_window;
static int configure_current_encoding;
static int configure_icons = 0;
static struct configure_tool *configure_tools = NULL;
static int configure_icon_width = CONFIGURE_DEFAULT_ICON_WIDTH;
static int configure_icon_height = CONFIGURE_DEFAULT_ICON_HEIGHT;
static int configure_icons_per_line = 0;
static int configure_width;
static int configure_height;
static bool ro_gui_configure_click(wimp_pointer *pointer);
static void ro_gui_configure_open_window(wimp_open *open);
static void ro_gui_configure_close(wimp_w w);
static bool ro_gui_configure_translate(void);
static void ro_gui_configure_register(const char *window,
bool (*initialise)(wimp_w w), void (*finalise)(wimp_w w));
void ro_gui_configure_initialise(void)
{
/* create our window */
configure_window = ro_gui_dialog_create("configure");
ro_gui_wimp_event_register_open_window(configure_window,
ro_gui_configure_open_window);
ro_gui_wimp_event_register_mouse_click(configure_window,
ro_gui_configure_click);
ro_gui_wimp_event_set_help_prefix(configure_window, "HelpConfigure");
/* add in our option windows */
ro_gui_configure_register("con_cache",
ro_gui_options_cache_initialise,
ro_gui_wimp_event_finalise);
ro_gui_configure_register("con_connect",
ro_gui_options_connection_initialise,
ro_gui_wimp_event_finalise);
ro_gui_configure_register("con_content",
ro_gui_options_content_initialise,
ro_gui_wimp_event_finalise);
ro_gui_configure_register("con_fonts",
ro_gui_options_fonts_initialise,
ro_gui_wimp_event_finalise);
ro_gui_configure_register("con_home",
ro_gui_options_home_initialise,
ro_gui_wimp_event_finalise);
ro_gui_configure_register("con_image",
ro_gui_options_image_initialise,
ro_gui_options_image_finalise);
ro_gui_configure_register("con_inter",
ro_gui_options_interface_initialise,
ro_gui_wimp_event_finalise);
ro_gui_configure_register("con_lang",
ro_gui_options_language_initialise,
ro_gui_wimp_event_finalise);
ro_gui_configure_register("con_memory",
ro_gui_options_memory_initialise,
ro_gui_wimp_event_finalise);
ro_gui_configure_register("con_theme",
ro_gui_options_theme_initialise,
ro_gui_options_theme_finalise);
ro_gui_configure_register("con_secure",
ro_gui_options_security_initialise,
ro_gui_wimp_event_finalise);
/* translate the icons */
if (!ro_gui_configure_translate())
die("ro_gui_configure_translate failed");
}
void ro_gui_configure_show(void)
{
int width, height;
width = configure_icon_width << 2;
height = ((configure_icons + 3) >> 2) * configure_icon_height;
ro_gui_dialog_open_top(configure_window, NULL, width, height);
}
bool ro_gui_configure_click(wimp_pointer *pointer)
{
struct configure_tool *tool;
if (pointer->buttons == wimp_CLICK_MENU)
return true;
for (tool = configure_tools; tool; tool = tool->next) {
if (tool->i == pointer->i) {
if (!tool->open) {
tool->open = true;
if (!tool->initialise(tool->w))
return false;
ro_gui_dialog_open_persistent(
configure_window,
tool->w, true);
ro_gui_wimp_event_register_close_window(
tool->w,
ro_gui_configure_close);
} else {
ro_gui_dialog_open_top(tool->w, NULL, 0, 0);
}
break;
}
}
return true;
}
void ro_gui_configure_close(wimp_w w)
{
struct configure_tool *tool;
for (tool = configure_tools; tool; tool = tool->next) {
if (tool->w == w) {
tool->open = false;
if (tool->finalise)
tool->finalise(w);
break;
}
}
}
void ro_gui_configure_open_window(wimp_open *open)
{
os_error *error;
int screen_width, screen_height;
int height, width;
int icons_per_line, icon_lines;
int max_icons_per_line, max_height;
os_box extent = { 0, 0, 0, 0 };
int x, y, l;
struct configure_tool *tool;
if (!ro_gui_configure_translate()) {
warn_user("ro_gui_configure_translate failed", 0);
return;
}
width = open->visible.x1 - open->visible.x0;
height = open->visible.y1 - open->visible.y0;
icons_per_line = width / configure_icon_width;
if (icons_per_line < 1)
icons_per_line = 1;
/* move our icons */
if (icons_per_line != configure_icons_per_line) {
configure_icons_per_line = icons_per_line;
x = CONFIGURE_ICON_PADDING_H / 2;
y = -configure_icon_height + (CONFIGURE_ICON_PADDING_V / 2);
l = 0;
for (tool = configure_tools; tool; tool = tool->next) {
error = xwimp_resize_icon(configure_window,
tool->i,
x,
y,
x + configure_icon_width -
CONFIGURE_ICON_PADDING_H,
y + configure_icon_height -
CONFIGURE_ICON_PADDING_V);
if (error) {
LOG(("xwimp_resize_icon: 0x%x: %s",
error->errnum, error->errmess));
}
x += configure_icon_width;
l++;
if (l >= icons_per_line) {
x = CONFIGURE_ICON_PADDING_H / 2;
l = 0;
y -= configure_icon_height;
}
}
error = xwimp_force_redraw(configure_window,
0, -16384, 16384, 0);
if (error) {
LOG(("xwimp_force_redraw: 0x%x: %s",
error->errnum, error->errmess));
warn_user("WimpError", error->errmess);
}
}
/* restrict our height */
icon_lines = (configure_icons + icons_per_line - 1) /
icons_per_line;
max_height = (icon_lines * configure_icon_height);
if (height > max_height)
open->visible.y0 = open->visible.y1 - max_height;
/* set the extent */
if ((configure_height != height) || (configure_width != width)) {
ro_gui_screen_size(&screen_width, &screen_height);
max_icons_per_line = screen_width / configure_icon_width;
if (max_icons_per_line > configure_icons)
max_icons_per_line = configure_icons;
extent.x1 = configure_icon_width * max_icons_per_line;
extent.y0 = -max_height;
error = xwimp_set_extent(open->w, &extent);
if (error) {
LOG(("xwimp_set_extent: 0x%x: %s",
error->errnum, error->errmess));
warn_user("WimpError", error->errmess);
return;
}
configure_height = height;
configure_width = width;
}
/* open the window */
error = xwimp_open_window(open);
if (error) {
LOG(("xwimp_open_window: 0x%x: %s",
error->errnum, error->errmess));
warn_user("WimpError", error->errmess);
return;
}
}
void ro_gui_configure_register(const char *window,
bool (*initialise)(wimp_w w), void (*finalise)(wimp_w w))
{
wimp_icon_create new_icon;
struct configure_tool *tool;
struct configure_tool *link;
os_error *error;
/* create our tool */
tool = calloc(sizeof(struct configure_tool), 1);
if (!tool) {
LOG(("Insufficient memory for calloc()"));
die("Insufficient memory");
return; /* For the benefit of scan-build */
}
tool->name = window;
tool->translated[0] = '\0';
tool->validation = malloc(strlen(window) + 2);
if (!tool->validation) {
LOG(("Insufficient memory for malloc()"));
die("Insufficient memory");
}
sprintf(tool->validation, "S%s", window);
tool->initialise = initialise;
tool->finalise = finalise;
tool->w = ro_gui_dialog_create(tool->name);
/* create the icon */
new_icon.w = configure_window;
new_icon.icon.extent.x0 = 0;
new_icon.icon.extent.x1 = configure_icon_width;
new_icon.icon.extent.y1 = 0;
new_icon.icon.extent.y0 = -configure_icon_height;
new_icon.icon.flags = wimp_ICON_TEXT | wimp_ICON_SPRITE |
wimp_ICON_INDIRECTED | wimp_ICON_HCENTRED |
(wimp_COLOUR_VERY_LIGHT_GREY << wimp_ICON_BG_COLOUR_SHIFT) |
(wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) |
(wimp_BUTTON_CLICK << wimp_ICON_BUTTON_TYPE_SHIFT);
new_icon.icon.data.indirected_text_and_sprite.text =
tool->translated;
new_icon.icon.data.indirected_text_and_sprite.validation =
tool->validation;
new_icon.icon.data.indirected_text_and_sprite.size =
CONFIGURE_TOOL_TRANSLATED_SIZE;
error = xwimp_create_icon(&new_icon, &tool->i);
if (error) {
LOG(("xwimp_create_icon: 0x%x: %s",
error->errnum, error->errmess));
die(error->errmess);
}
/* Set the icon's text in current local encoding */
ro_gui_set_icon_string(configure_window, tool->i,
messages_get(tool->name), true);
/* link into our list alphabetically */
if ((!configure_tools) ||
(strcmp(configure_tools->translated,
tool->translated) > 0)) {
tool->next = configure_tools;
configure_tools = tool;
} else {
for (link = configure_tools; link; link = link->next) {
if (link->next) {
if (strcmp(link->next->translated,
tool->translated) > 0) {
tool->next = link->next;
link->next = tool;
break;
}
} else {
link->next = tool;
break;
}
}
}
configure_icons++;
}
/**
* Translate tool icons into the system local encoding.
* This will also recalculate the minimum required icon width.
*
* \return true on success, false on memory exhaustion
*/
bool ro_gui_configure_translate(void)
{
int alphabet;
struct configure_tool *tool;
int icon_width;
os_error *error;
/* read current alphabet */
error = xosbyte1(osbyte_ALPHABET_NUMBER, 127, 0,
&alphabet);
if (error) {
LOG(("failed reading alphabet: 0x%x: %s",
error->errnum, error->errmess));
/* assume Latin1 */
alphabet = territory_ALPHABET_LATIN1;
}
if (alphabet == configure_current_encoding)
/* text is already in the correct encoding */
return true;
/* reset icon width */
configure_icon_width = CONFIGURE_DEFAULT_ICON_WIDTH;
for (tool = configure_tools; tool; tool = tool->next) {
/* re-translate the text */
ro_gui_set_icon_string(configure_window, tool->i,
messages_get(tool->name), true);
/* update the width */
error = xwimptextop_string_width(tool->translated,
strlen(tool->translated), &icon_width);
if (error) {
LOG(("xwimptextop_string_width: 0x%x: %s",
error->errnum, error->errmess));
return false;
}
icon_width += CONFIGURE_ICON_PADDING_H;
if (icon_width > configure_icon_width)
configure_icon_width = icon_width;
error = xwimp_resize_icon(configure_window,
tool->i,
0,
-configure_icon_height,
configure_icon_width,
0);
if (error) {
LOG(("xwimp_resize_icon: 0x%x: %s",
error->errnum, error->errmess));
}
}
/* invalidate our global icons_per_line setting
* so the icons get reflowed */
configure_icons_per_line = 0;
/* finally, set the current encoding */
configure_current_encoding = alphabet;
return true;
}