netsurf/riscos/dialog.c

801 lines
20 KiB
C

/*
* 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 2003 Phil Mellor <monkeyson@users.sourceforge.net>
* Copyright 2004 James Bursa <bursa@users.sourceforge.net>
* Copyright 2003 John M Bell <jmb202@ecs.soton.ac.uk>
* Copyright 2004 Richard Wilson <not_ginger_matt@users.sourceforge.net>
*/
#include <assert.h>
#include <stddef.h>
#include <string.h>
#include "oslib/colourtrans.h"
#include "oslib/osfile.h"
#include "oslib/osgbpb.h"
#include "oslib/osspriteop.h"
#include "oslib/wimp.h"
#include "netsurf/utils/config.h"
#include "netsurf/desktop/netsurf.h"
#include "netsurf/riscos/constdata.h"
#include "netsurf/riscos/gui.h"
#include "netsurf/riscos/options.h"
#include "netsurf/utils/log.h"
#include "netsurf/utils/messages.h"
#include "netsurf/utils/utils.h"
wimp_w dialog_info, dialog_saveas, dialog_config, dialog_config_br,
dialog_config_prox, dialog_config_th, download_template,
#ifdef WITH_AUTH
dialog_401li,
#endif
dialog_zoom, dialog_pageinfo, dialog_tooltip;
;
wimp_menu* theme_menu = NULL;
static int font_size;
static int font_min_size;
static void ro_gui_dialog_click_config(wimp_pointer *pointer);
static void ro_gui_dialog_click_config_br(wimp_pointer *pointer);
static void ro_gui_dialog_update_config_br(void);
static void ro_gui_dialog_click_config_prox(wimp_pointer *pointer);
static void ro_gui_dialog_click_config_th(wimp_pointer *pointer);
static void ro_gui_dialog_click_zoom(wimp_pointer *pointer);
static void ro_gui_dialog_reset_zoom(void);
static void set_browser_choices(void);
static void get_browser_choices(void);
static void set_proxy_choices(void);
static void get_proxy_choices(void);
static void set_theme_choices(void);
static void get_theme_choices(void);
static void load_theme_preview(char* thname);
/*static void ro_gui_destroy_theme_menu(void);*/
static void ro_gui_build_theme_menu(void);
static int file_exists(const char* base, const char* dir, const char* leaf, bits ftype);
static void set_icon_state(wimp_w w, wimp_i i, int state);
static int get_icon_state(wimp_w w, wimp_i i);
static void set_icon_string_i(wimp_w w, wimp_i i, int num);
static const char *language_name(const char *code);
/**
* Load and create dialogs from template file.
*/
void ro_gui_dialog_init(void)
{
dialog_info = ro_gui_dialog_create("info");
/* fill in about box version info */
ro_gui_set_icon_string(dialog_info, 4, netsurf_version);
dialog_saveas = ro_gui_dialog_create("saveas");
dialog_config = ro_gui_dialog_create("config");
dialog_config_br = ro_gui_dialog_create("config_br");
dialog_config_prox = ro_gui_dialog_create("config_prox");
dialog_config_th = ro_gui_dialog_create("config_th");
dialog_zoom = ro_gui_dialog_create("zoom");
dialog_pageinfo = ro_gui_dialog_create("pageinfo");
dialog_tooltip = ro_gui_dialog_create("tooltip");
set_browser_choices();
set_proxy_choices();
set_theme_choices();
}
/**
* Create a window from a template.
*/
wimp_w ro_gui_dialog_create(const char *template_name)
{
char name[20];
int context, window_size, data_size;
char *data;
wimp_window *window;
wimp_w w;
/* wimp_load_template won't accept a const char * */
strncpy(name, template_name, 20);
/* find required buffer sizes */
context = wimp_load_template(wimp_GET_SIZE, 0, 0, wimp_NO_FONTS,
name, 0, &window_size, &data_size);
assert(context != 0);
window = xcalloc((unsigned int) window_size, 1);
data = xcalloc((unsigned int) data_size, 1);
/* load and create */
wimp_load_template(window, data, data + data_size, wimp_NO_FONTS,
name, 0, 0, 0);
w = wimp_create_window(window);
/* the window definition is copied by the wimp and may be freed */
xfree(window);
return w;
}
/**
* Open a dialog box, centered on the screen.
*/
void ro_gui_dialog_open(wimp_w w)
{
int screen_x, screen_y, dx, dy;
wimp_window_state open;
/* find screen centre in os units */
ro_gui_screen_size(&screen_x, &screen_y);
screen_x /= 2;
screen_y /= 2;
/* centre and open */
open.w = w;
wimp_get_window_state(&open);
dx = (open.visible.x1 - open.visible.x0) / 2;
dy = (open.visible.y1 - open.visible.y0) / 2;
open.visible.x0 = screen_x - dx;
open.visible.x1 = screen_x + dx;
open.visible.y0 = screen_y - dy;
open.visible.y1 = screen_y + dy;
open.next = wimp_TOP;
wimp_open_window((wimp_open *) &open);
}
/**
* Handle key presses in one of the dialog boxes.
*/
bool ro_gui_dialog_keypress(wimp_key *key)
{
#ifdef WITH_AUTH
if (key->w == dialog_401li)
return ro_gui_401login_keypress(key);
#endif
return false;
}
/**
* Handle clicks in one of the dialog boxes.
*/
void ro_gui_dialog_click(wimp_pointer *pointer)
{
if (pointer->buttons == wimp_CLICK_MENU)
return;
if (pointer->w == dialog_config)
ro_gui_dialog_click_config(pointer);
else if (pointer->w == dialog_config_br)
ro_gui_dialog_click_config_br(pointer);
else if (pointer->w == dialog_config_prox)
ro_gui_dialog_click_config_prox(pointer);
else if (pointer->w == dialog_config_th)
ro_gui_dialog_click_config_th(pointer);
#ifdef WITH_AUTH
else if (pointer->w == dialog_401li)
ro_gui_401login_click(pointer);
#endif
else if (pointer->w == dialog_zoom)
ro_gui_dialog_click_zoom(pointer);
}
/**
* Handle clicks in the main Choices dialog.
*/
void ro_gui_dialog_click_config(wimp_pointer *pointer)
{
switch (pointer->i) {
case ICON_CONFIG_SAVE:
get_browser_choices();
get_proxy_choices();
get_theme_choices();
xosfile_create_dir("<Choices$Write>.WWW", 0);
xosfile_create_dir("<Choices$Write>.WWW.NetSurf", 0);
options_write("<Choices$Write>.WWW.NetSurf.Choices");
if (pointer->buttons == wimp_CLICK_SELECT) {
ro_gui_dialog_close(dialog_config_br);
ro_gui_dialog_close(dialog_config_prox);
ro_gui_dialog_close(dialog_config_th);
ro_gui_dialog_close(dialog_config);
}
break;
case ICON_CONFIG_CANCEL:
if (pointer->buttons == wimp_CLICK_SELECT) {
ro_gui_dialog_close(dialog_config_br);
ro_gui_dialog_close(dialog_config_prox);
ro_gui_dialog_close(dialog_config_th);
ro_gui_dialog_close(dialog_config);
}
set_browser_choices();
set_proxy_choices();
set_theme_choices();
break;
case ICON_CONFIG_BROWSER:
ro_gui_dialog_open(dialog_config_br);
break;
case ICON_CONFIG_PROXY:
ro_gui_dialog_open(dialog_config_prox);
break;
case ICON_CONFIG_THEME:
ro_gui_dialog_open(dialog_config_th);
break;
}
}
/**
* Handle clicks in the Browser Choices dialog.
*/
void ro_gui_dialog_click_config_br(wimp_pointer *pointer)
{
switch (pointer->i) {
case ICON_CONFIG_BR_OK:
if (pointer->buttons == wimp_CLICK_SELECT)
ro_gui_dialog_close(dialog_config_br);
break;
case ICON_CONFIG_BR_CANCEL:
if (pointer->buttons == wimp_CLICK_SELECT)
ro_gui_dialog_close(dialog_config_br);
set_browser_choices();
break;
case ICON_CONFIG_BR_FONTSIZE_DEC:
if (font_size == 50)
break;
font_size--;
if (font_size < font_min_size)
font_min_size = font_size;
ro_gui_dialog_update_config_br();
break;
case ICON_CONFIG_BR_FONTSIZE_INC:
if (font_size == 1000)
break;
font_size++;
ro_gui_dialog_update_config_br();
break;
case ICON_CONFIG_BR_MINSIZE_DEC:
if (font_min_size == 10)
break;
font_min_size--;
ro_gui_dialog_update_config_br();
break;
case ICON_CONFIG_BR_MINSIZE_INC:
if (font_min_size == 500)
break;
font_min_size++;
if (font_size < font_min_size)
font_size = font_min_size;
ro_gui_dialog_update_config_br();
break;
}
}
/**
* Update font size icons in browser choices dialog.
*/
void ro_gui_dialog_update_config_br(void)
{
char s[10];
sprintf(s, "%i.%ipt", font_size / 10, font_size % 10);
ro_gui_set_icon_string(dialog_config_br, ICON_CONFIG_BR_FONTSIZE, s);
sprintf(s, "%i.%ipt", font_min_size / 10, font_min_size % 10);
ro_gui_set_icon_string(dialog_config_br, ICON_CONFIG_BR_MINSIZE, s);
}
/**
* Handle clicks in the Proxy Choices dialog.
*/
void ro_gui_dialog_click_config_prox(wimp_pointer *pointer)
{
switch (pointer->i) {
case ICON_CONFIG_PROX_OK:
if (pointer->buttons == wimp_CLICK_SELECT)
ro_gui_dialog_close(dialog_config_prox);
break;
case ICON_CONFIG_PROX_CANCEL:
if (pointer->buttons == wimp_CLICK_SELECT)
ro_gui_dialog_close(dialog_config_prox);
set_proxy_choices();
break;
}
}
/**
* Handle clicks in the Theme Choices dialog.
*/
void ro_gui_dialog_click_config_th(wimp_pointer *pointer)
{
switch (pointer->i) {
case ICON_CONFIG_TH_OK:
if (pointer->buttons == wimp_CLICK_SELECT)
ro_gui_dialog_close(dialog_config_th);
break;
case ICON_CONFIG_TH_CANCEL:
if (pointer->buttons == wimp_CLICK_SELECT)
ro_gui_dialog_close(dialog_config_th);
set_theme_choices();
break;
case ICON_CONFIG_TH_NAME:
case ICON_CONFIG_TH_PICK:
ro_gui_build_theme_menu();
ro_gui_popup_menu(theme_menu, dialog_config_th,
ICON_CONFIG_TH_PICK);
break;
case ICON_CONFIG_TH_MANAGE:
os_cli("Filer_OpenDir " THEMES_DIR);
break;
case ICON_CONFIG_TH_GET:
browser_window_create(THEMES_URL);
break;
}
}
/**
* Handle clicks in the Scale view dialog.
*/
void ro_gui_dialog_click_zoom(wimp_pointer *pointer)
{
unsigned int scale;
int stepping = 10;
scale = atoi(ro_gui_get_icon_string(dialog_zoom, ICON_ZOOM_VALUE));
/* Adjust moves values the opposite direction
*/
if (pointer->buttons == wimp_CLICK_ADJUST) stepping = -stepping;
switch (pointer->i) {
case ICON_ZOOM_DEC: scale -= stepping; break;
case ICON_ZOOM_INC: scale += stepping; break;
case ICON_ZOOM_50: scale = 50; break;
case ICON_ZOOM_80: scale = 80; break;
case ICON_ZOOM_100: scale = 100; break;
case ICON_ZOOM_120: scale = 120; break;
}
if (scale < 10)
scale = 10;
else if (500 < scale)
scale = 500;
set_icon_string_i(dialog_zoom, ICON_ZOOM_VALUE, scale);
if (pointer->i == ICON_ZOOM_OK) {
current_gui->scale = scale * 0.01;
current_gui->data.browser.reformat_pending = true;
gui_reformat_pending = true;
}
if ((pointer->buttons == wimp_CLICK_ADJUST) && (pointer->i == ICON_ZOOM_CANCEL)) {
ro_gui_dialog_reset_zoom();
}
if (pointer->buttons == wimp_CLICK_SELECT &&
(pointer->i == ICON_ZOOM_CANCEL ||
pointer->i == ICON_ZOOM_OK))
wimp_create_menu(wimp_CLOSE_MENU, 0, 0);
}
/*
* Resets the Scale view dialog
*/
void ro_gui_dialog_reset_zoom(void) {
char scale_buffer[8];
sprintf(scale_buffer, "%.0f", current_gui->scale * 100);
ro_gui_set_icon_string(dialog_zoom, ICON_ZOOM_VALUE, scale_buffer);
}
/**
* Close a dialog box.
*/
void ro_gui_dialog_close(wimp_w close)
{
wimp_close_window(close);
}
/**
* Update the browser choices dialog with the current options.
*/
void set_browser_choices(void)
{
font_size = option_font_size;
font_min_size = option_font_min_size;
ro_gui_dialog_update_config_br();
ro_gui_set_icon_string(dialog_config_br, ICON_CONFIG_BR_LANG,
language_name(option_language ?
option_language : "en"));
ro_gui_set_icon_string(dialog_config_br, ICON_CONFIG_BR_ALANG,
language_name(option_accept_language ?
option_accept_language : "en"));
}
/**
* Set the current options to the settings in the browser choices dialog.
*/
void get_browser_choices(void)
{
option_font_size = font_size;
option_font_min_size = font_min_size;
}
/**
* Update the proxy choices dialog with the current options.
*/
void set_proxy_choices(void)
{
set_icon_state(dialog_config_prox, ICON_CONFIG_PROX_HTTP,
option_http_proxy);
ro_gui_set_icon_string(dialog_config_prox, ICON_CONFIG_PROX_HTTPHOST,
option_http_proxy_host ? option_http_proxy_host : "");
set_icon_string_i(dialog_config_prox, ICON_CONFIG_PROX_HTTPPORT,
option_http_proxy_port);
}
/**
* Set the current options to the settings in the proxy choices dialog.
*/
void get_proxy_choices(void)
{
option_http_proxy = get_icon_state(dialog_config_prox,
ICON_CONFIG_PROX_HTTP);
free(option_http_proxy_host);
option_http_proxy_host = strdup(ro_gui_get_icon_string(dialog_config_prox,
ICON_CONFIG_PROX_HTTPHOST));
option_http_proxy_port = atoi(ro_gui_get_icon_string(dialog_config_prox,
ICON_CONFIG_PROX_HTTPPORT));
}
/**
* Update the theme choices dialog with the current options.
*/
void set_theme_choices(void)
{
ro_gui_set_icon_string(dialog_config_th, ICON_CONFIG_TH_NAME,
option_theme ? option_theme : "Default");
load_theme_preview(option_theme ? option_theme : "Default");
}
/**
* Set the current options to the settings in the theme choices dialog.
*/
void get_theme_choices(void)
{
free(option_theme);
option_theme = strdup(ro_gui_get_icon_string(dialog_config_th,
ICON_CONFIG_TH_NAME));
}
osspriteop_area* theme_preview = NULL;
void load_theme_preview(char* thname)
{
if (theme_preview != NULL)
xfree(theme_preview);
theme_preview = NULL;
if (file_exists(THEMES_DIR, thname, "Preview", 0xff9))
{
char filename[256];
FILE* fp;
int size;
sprintf(filename, "%s.%s.Preview", THEMES_DIR, thname);
fp = fopen(filename, "rb");
if (fp == 0) return;
if (fseek(fp, 0, SEEK_END) != 0) die("fseek() failed");
if ((size = (int) ftell(fp)) == -1) die("ftell() failed");
fclose(fp);
theme_preview = xcalloc((unsigned int)(size + 16), 1);
if (theme_preview == NULL)
return;
theme_preview->size = size + 16;
theme_preview->sprite_count = 0;
theme_preview->first = 16;
theme_preview->used = 16;
osspriteop_clear_sprites(osspriteop_USER_AREA, theme_preview);
osspriteop_load_sprite_file(osspriteop_USER_AREA, theme_preview, filename);
}
}
void ro_gui_redraw_config_th(wimp_draw* redraw)
{
int x, y, size;
osbool more;
wimp_icon_state preview;
wimp_window_state win;
osspriteop_trans_tab* trans_tab;
win.w = dialog_config_th;
wimp_get_window_state(&win);
preview.w = dialog_config_th;
preview.i = ICON_CONFIG_TH_PREVIEW;
wimp_get_icon_state(&preview);
if (theme_preview != NULL)
{
x = preview.icon.extent.x0 + win.visible.x0 + 4;
y = preview.icon.extent.y0 + win.visible.y1 + 4;
xcolourtrans_generate_table_for_sprite(theme_preview,
(osspriteop_id)"preview",
(os_mode)-1,
(os_palette const*)-1,
0, 0, 0, 0, &size);
trans_tab = malloc((unsigned int)(size + 32));
xcolourtrans_generate_table_for_sprite(theme_preview,
(osspriteop_id)"preview",
(os_mode)-1,
(os_palette const*)-1,
trans_tab, 0, 0, 0, &size);
more = wimp_redraw_window(redraw);
while (more)
{
xosspriteop_put_sprite_scaled(osspriteop_NAME, theme_preview,
(osspriteop_id)"preview", x, y,
(osspriteop_action)osspriteop_USE_MASK |
osspriteop_USE_PALETTE,
0, trans_tab);
more = wimp_get_rectangle(redraw);
}
xfree(trans_tab);
}
else
{
preview.icon.flags = wimp_ICON_TEXT | wimp_ICON_INDIRECTED | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) | (wimp_COLOUR_VERY_LIGHT_GREY << wimp_ICON_BG_COLOUR_SHIFT);
preview.icon.data.indirected_text.text = "No preview available";
preview.icon.data.indirected_text.size = 21;
more = wimp_redraw_window(redraw);
while (more)
{
wimp_plot_icon(&preview.icon);
more = wimp_get_rectangle(redraw);
}
}
return;
}
/**
* Construct or update theme_menu by scanning THEMES_DIR.
*/
void ro_gui_build_theme_menu(void)
{
unsigned int i;
static unsigned int entries = 0;
int context = 0;
int read_count;
osgbpb_INFO(100) info;
if (theme_menu) {
/* free entry text buffers */
for (i = 0; i != entries; i++)
free(theme_menu->entries[i].data.indirected_text.text);
} else {
theme_menu = xcalloc(1, wimp_SIZEOF_MENU(1));
theme_menu->title_data.indirected_text.text =
messages_get("Themes");
theme_menu->title_fg = wimp_COLOUR_BLACK;
theme_menu->title_bg = wimp_COLOUR_LIGHT_GREY;
theme_menu->work_fg = wimp_COLOUR_BLACK;
theme_menu->work_bg = wimp_COLOUR_WHITE;
theme_menu->width = 256;
theme_menu->height = 44;
theme_menu->gap = 0;
}
i = 0;
while (context != -1) {
context = osgbpb_dir_entries_info(THEMES_DIR,
(osgbpb_info_list *) &info, 1, context,
sizeof(info), 0, &read_count);
if (read_count == 0)
continue;
if (info.obj_type != fileswitch_IS_DIR)
continue;
if (!(file_exists(THEMES_DIR, info.name, "Templates", 0xfec) &&
file_exists(THEMES_DIR, info.name, "Sprites", 0xff9)))
continue;
theme_menu = xrealloc(theme_menu, wimp_SIZEOF_MENU(i + 1));
theme_menu->entries[i].menu_flags = 0;
if (option_theme && strcmp(info.name, option_theme) == 0)
theme_menu->entries[i].menu_flags |= wimp_MENU_TICKED;
theme_menu->entries[i].sub_menu = wimp_NO_SUB_MENU;
theme_menu->entries[i].icon_flags = wimp_ICON_TEXT |
wimp_ICON_FILLED | wimp_ICON_INDIRECTED |
(wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) |
(wimp_COLOUR_WHITE << wimp_ICON_BG_COLOUR_SHIFT);
theme_menu->entries[i].data.indirected_text.text =
xstrdup(info.name);
theme_menu->entries[i].data.indirected_text.validation = (char*)-1;
theme_menu->entries[i].data.indirected_text.size =
strlen(info.name) + 1;
i++;
}
assert(i != 0);
entries = i;
theme_menu->entries[0].menu_flags |= wimp_MENU_TITLE_INDIRECTED;
theme_menu->entries[i - 1].menu_flags |= wimp_MENU_LAST;
}
void ro_gui_theme_menu_selection(char *theme)
{
ro_gui_set_icon_string(dialog_config_th, ICON_CONFIG_TH_NAME, theme);
load_theme_preview(theme);
wimp_set_icon_state(dialog_config_th, ICON_CONFIG_TH_PREVIEW, 0, 0);
}
int file_exists(const char* base, const char* dir, const char* leaf, bits ftype)
{
char buffer[256];
fileswitch_object_type type;
bits load, exec;
int size;
fileswitch_attr attr;
bits file_type;
snprintf(buffer, 255, "%s.%s.%s", base, dir, leaf);
LOG(("checking %s", buffer));
if (xosfile_read_stamped_no_path(buffer, &type, &load, &exec, &size, &attr, &file_type) == NULL)
{
return (type == 1 && ftype == file_type);
}
return 0;
}
void set_icon_state(wimp_w w, wimp_i i, int state)
{
if (state)
wimp_set_icon_state(w,i, wimp_ICON_SELECTED, wimp_ICON_SELECTED);
else
wimp_set_icon_state(w,i, 0, wimp_ICON_SELECTED);
}
int get_icon_state(wimp_w w, wimp_i i)
{
wimp_icon_state ic;
ic.w = w;
ic.i = i;
wimp_get_icon_state(&ic);
return (ic.icon.flags & wimp_ICON_SELECTED) != 0;
}
/**
* Set the contents of an icon to a string.
*
* \param w window handle
* \param i icon handle
* \param text string (copied)
*/
void ro_gui_set_icon_string(wimp_w w, wimp_i i, const char *text) {
wimp_caret caret;
wimp_icon_state ic;
unsigned int old_len, len;
/* Get the icon data
*/
ic.w = w;
ic.i = i;
wimp_get_icon_state(&ic);
/* Check that the existing text is not the same as the updated text
to stop flicker
*/
if (!strncmp(ic.icon.data.indirected_text.text, text,
(unsigned int)ic.icon.data.indirected_text.size)) return;
/* Copy the text across
*/
old_len = strlen(ic.icon.data.indirected_text.text);
strncpy(ic.icon.data.indirected_text.text, text,
(unsigned int)ic.icon.data.indirected_text.size);
/* Handle the caret being in the icon
*/
if (!xwimp_get_caret_position(&caret)) {
if ((caret.w == w) && (caret.i == i)) {
len = strlen(text);
if ((caret.index > len) || (caret.index == old_len)) caret.index = len;
xwimp_set_caret_position(w, i, caret.pos.x, caret.pos.y, -1, caret.index);
}
}
/* Redraw the icon
*/
wimp_set_icon_state(w, i, 0, 0);
}
/**
* Read the contents of an icon.
*
* \param w window handle
* \param i icon handle
* \return string in icon
*/
char *ro_gui_get_icon_string(wimp_w w, wimp_i i)
{
wimp_icon_state ic;
ic.w = w;
ic.i = i;
wimp_get_icon_state(&ic);
return ic.icon.data.indirected_text.text;
}
void set_icon_string_i(wimp_w w, wimp_i i, int num)
{
char buffer[255];
sprintf(buffer, "%d", num);
ro_gui_set_icon_string(w, i, buffer);
}
/**
* Convert a 2-letter ISO language code to the language name.
*
* \param code 2-letter ISO language code
* \return language name, or code if unknown
*/
const char *language_name(const char *code)
{
char key[] = "lang_xx";
key[5] = code[0];
key[6] = code[1];
return messages_get(key);
}