summaryrefslogtreecommitdiff
path: root/riscos
diff options
context:
space:
mode:
Diffstat (limited to 'riscos')
-rw-r--r--riscos/dialog.c62
-rw-r--r--riscos/download.c51
-rw-r--r--riscos/gui.h2
-rw-r--r--riscos/help.c24
-rw-r--r--riscos/menus.c751
-rw-r--r--riscos/save.c33
-rw-r--r--riscos/ucstables.c281
-rw-r--r--riscos/wimp.c78
-rw-r--r--riscos/wimp.h2
-rw-r--r--riscos/window.c23
10 files changed, 989 insertions, 318 deletions
diff --git a/riscos/dialog.c b/riscos/dialog.c
index 4baea65d0..505c09b4e 100644
--- a/riscos/dialog.c
+++ b/riscos/dialog.c
@@ -430,14 +430,14 @@ bool ro_gui_dialog_keypress(wimp_key *key)
pointer.w = key->w;
pointer.i = ICON_OPENURL_OPEN;
pointer.buttons = wimp_CLICK_SELECT;
- ro_gui_dialog_click_open_url(&pointer);
+ ro_gui_dialog_click_open_url(&pointer);
}
}
#ifdef WITH_AUTH
if (key->w == dialog_401li)
return ro_gui_401login_keypress(key);
#endif
-
+
return false;
}
@@ -838,46 +838,44 @@ void ro_gui_save_options(void)
void ro_gui_dialog_click_config_br(wimp_pointer *pointer)
{
switch (pointer->i) {
- case ICON_CONFIG_BR_LANG_PICK:
- /* drop through */
- case ICON_CONFIG_BR_ALANG_PICK:
- config_br_icon = pointer->i;
- ro_gui_popup_menu(languages_menu, dialog_config_br,
- pointer->i);
- break;
+ case ICON_CONFIG_BR_LANG_PICK:
+ ro_gui_menu_prepare_languages(false, ro_gui_choices_lang);
+ config_br_icon = pointer->i;
+ ro_gui_popup_menu(languages_menu, dialog_config_br,
+ pointer->i);
+ break;
+ case ICON_CONFIG_BR_ALANG_PICK:
+ ro_gui_menu_prepare_languages(true, ro_gui_choices_alang);
+ config_br_icon = pointer->i;
+ ro_gui_popup_menu(languages_menu, dialog_config_br,
+ pointer->i);
+ break;
}
}
/**
* Handle a selection from the language selection popup menu.
*
- * \param lang The language name (as returned by messages_get)
+ * \param lang The language messages key
*/
-void ro_gui_dialog_languages_menu_selection(char *lang)
+void ro_gui_dialog_languages_menu_selection(const char *lang)
{
int offset = strlen("lang_");
- const char *temp = messages_get_key(lang);
- if (temp == NULL) {
- warn_user("MiscError", "Failed to retrieve message key");
- config_br_icon = -1;
- return;
- }
-
switch (config_br_icon) {
- case ICON_CONFIG_BR_LANG_PICK:
- ro_gui_choices_lang = temp + offset;
- ro_gui_set_icon_string(dialog_config_br,
- ICON_CONFIG_BR_LANG,
- lang);
- break;
- case ICON_CONFIG_BR_ALANG_PICK:
- ro_gui_choices_alang = temp + offset;
- ro_gui_set_icon_string(dialog_config_br,
- ICON_CONFIG_BR_ALANG,
- lang);
- break;
+ case ICON_CONFIG_BR_LANG_PICK:
+ ro_gui_choices_lang = lang + offset;
+ ro_gui_set_icon_string(dialog_config_br, ICON_CONFIG_BR_LANG,
+ messages_get(lang));
+ ro_gui_menu_prepare_languages(false, ro_gui_choices_lang);
+ break;
+ case ICON_CONFIG_BR_ALANG_PICK:
+ ro_gui_choices_alang = lang + offset;
+ ro_gui_set_icon_string(dialog_config_br,
+ ICON_CONFIG_BR_ALANG, messages_get(lang));
+ ro_gui_menu_prepare_languages(true, ro_gui_choices_alang);
+ break;
}
}
@@ -1266,7 +1264,7 @@ void ro_gui_dialog_click_open_url(wimp_pointer *pointer)
bool reopen_window = false;
wimp_caret caret;
os_error *error;
-
+
if (pointer->i == ICON_OPENURL_MENU) {
/* we can't have two open menus, so we close the iconbar menu
* and detach our window from it */
@@ -1315,7 +1313,7 @@ void ro_gui_dialog_click_open_url(wimp_pointer *pointer)
ro_gui_popup_menu(url_suggest_menu,
dialog_openurl,
ICON_OPENURL_MENU);
- return;
+ return;
}
if ((pointer->i != ICON_OPENURL_OPEN) &&
diff --git a/riscos/download.c b/riscos/download.c
index 3f64cd315..02c226c05 100644
--- a/riscos/download.c
+++ b/riscos/download.c
@@ -38,6 +38,7 @@
#include "netsurf/utils/log.h"
#include "netsurf/utils/messages.h"
#include "netsurf/utils/url.h"
+#include "netsurf/utils/utf8.h"
#include "netsurf/utils/utils.h"
@@ -385,6 +386,8 @@ void ro_gui_download_update_status(struct gui_download_window *dw)
float rate;
os_error *error;
int width;
+ char *local_status;
+ utf8_convert_ret err;
gettimeofday(&t, 0);
dt = (t.tv_sec + 0.000001 * t.tv_usec) - (dw->last_time.tv_sec +
@@ -405,18 +408,47 @@ void ro_gui_download_update_status(struct gui_download_window *dw)
left = (dw->total_size - dw->received) / rate;
sprintf(time, "%u:%.2u", left / 60, left % 60);
}
- snprintf(dw->status, sizeof dw->status,
+
+ /* convert to local encoding */
+ err = utf8_to_local_encoding(
+ messages_get("Download"), 0, &local_status);
+ if (err != UTF8_CONVERT_OK) {
+ /* badenc should never happen */
+ assert(err != UTF8_CONVERT_BADENC);
+ /* hide nomem error */
+ snprintf(dw->status, sizeof dw->status,
messages_get("Download"),
received, total_size, speed, time);
+ }
+ else {
+ snprintf(dw->status, sizeof dw->status,
+ local_status,
+ received, total_size, speed, time);
+ free(local_status);
+ }
f = (float) dw->received / (float) dw->total_size;
width = download_progress_width * f;
} else {
left = t.tv_sec - dw->start_time.tv_sec;
sprintf(time, "%u:%.2u", left / 60, left % 60);
- snprintf(dw->status, sizeof dw->status,
+
+ err = utf8_to_local_encoding(
+ messages_get("DownloadU"), 0, &local_status);
+ if (err != UTF8_CONVERT_OK) {
+ /* badenc should never happen */
+ assert(err != UTF8_CONVERT_BADENC);
+ /* hide nomem error */
+ snprintf(dw->status, sizeof dw->status,
messages_get("DownloadU"),
received, speed, time);
+ }
+ else {
+ snprintf(dw->status, sizeof dw->status,
+ local_status,
+ received, speed, time);
+ free(local_status);
+ }
/* length unknown, stay at 0 til finished */
width = 0;
@@ -428,9 +460,22 @@ void ro_gui_download_update_status(struct gui_download_window *dw)
rate = (float) dw->received / (float) left;
sprintf(time, "%u:%.2u", left / 60, left % 60);
speed = human_friendly_bytesize(rate);
- snprintf(dw->status, sizeof dw->status,
+
+ err = utf8_to_local_encoding(messages_get("DownloadU"), 0,
+ &local_status);
+ if (err != UTF8_CONVERT_OK) {
+ /* badenc should never happen */
+ assert(err != UTF8_CONVERT_BADENC);
+ /* hide nomem error */
+ snprintf(dw->status, sizeof dw->status,
messages_get("Downloaded"),
total_size, speed, time);
+ }
+ else {
+ snprintf(dw->status, sizeof dw->status, local_status,
+ total_size, speed, time);
+ free(local_status);
+ }
/* all done */
width = download_progress_width;
diff --git a/riscos/gui.h b/riscos/gui.h
index 2ab7f7084..3b24d0738 100644
--- a/riscos/gui.h
+++ b/riscos/gui.h
@@ -115,7 +115,7 @@ void ro_gui_dialog_close(wimp_w close);
void ro_gui_dialog_open_config(void);
void ro_gui_dialog_proxyauth_menu_selection(int item);
void ro_gui_dialog_image_menu_selection(int item);
-void ro_gui_dialog_languages_menu_selection(char *lang);
+void ro_gui_dialog_languages_menu_selection(const char *lang);
void ro_gui_dialog_font_menu_selection(int item);
void ro_gui_dialog_redraw(wimp_draw *redraw);
diff --git a/riscos/help.c b/riscos/help.c
index bc5494c45..50f6912ce 100644
--- a/riscos/help.c
+++ b/riscos/help.c
@@ -9,6 +9,7 @@
* Interactive help (implementation).
*/
+#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#include "oslib/help.h"
@@ -24,6 +25,7 @@
#include "netsurf/riscos/wimp.h"
#include "netsurf/utils/messages.h"
#include "netsurf/utils/log.h"
+#include "netsurf/utils/utf8.h"
#include "netsurf/utils/utils.h"
@@ -158,7 +160,7 @@ void ro_gui_interactive_help_request(wimp_message *message) {
sprintf(message_token, "HelpToolbar%i", (int)icon);
} else if ((g = ro_gui_status_lookup(window)) != NULL)
sprintf(message_token, "HelpStatus%i", (int)icon);
-
+
/* change toolbars to editors where appropriate */
if ((toolbar) && (toolbar->editor))
sprintf(message_token, "HelpEditToolbar%i", (int)icon);
@@ -233,7 +235,9 @@ static void ro_gui_interactive_help_broadcast(wimp_message *message,
const char *translated_token;
help_full_message_reply *reply;
char *base_token;
+ char *local_token;
os_error *error;
+ utf8_convert_ret err;
/* start off with an empty reply */
reply = (help_full_message_reply *)message;
@@ -260,8 +264,20 @@ static void ro_gui_interactive_help_broadcast(wimp_message *message,
/* copy our message string */
if (translated_token != token) {
- reply->reply[235] = 0;
- strncpy(reply->reply, translated_token, 235);
+ /* convert to local encoding */
+ err = utf8_to_local_encoding(translated_token, 0,
+ &local_token);
+ if (err != UTF8_CONVERT_OK) {
+ /* badenc should never happen */
+ assert(err != UTF8_CONVERT_BADENC);
+ /* simply use UTF-8 string */
+ strncpy(reply->reply, translated_token, 235);
+ }
+ else {
+ strncpy(reply->reply, local_token, 235);
+ free(local_token);
+ }
+ reply->reply[235] = '\0';
}
/* broadcast the help reply */
@@ -303,7 +319,7 @@ bool ro_gui_interactive_help_available(void) {
error->errnum, error->errmess));
warn_user("MiscError", error->errmess);
}
-
+
/* we can't just use strcmp due to string termination issues */
if (!strncmp(task.name, "Help", 4) &&
(task.name[4] < 32))
diff --git a/riscos/menus.c b/riscos/menus.c
index 86272a112..c294b9869 100644
--- a/riscos/menus.c
+++ b/riscos/menus.c
@@ -12,10 +12,13 @@
* Menu creation and handling (implementation).
*/
+#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include "oslib/os.h"
+#include "oslib/osbyte.h"
#include "oslib/osgbpb.h"
+#include "oslib/territory.h"
#include "oslib/wimp.h"
#include "netsurf/desktop/gui.h"
#include "netsurf/render/box.h"
@@ -56,11 +59,14 @@ struct ns_menu {
struct menu_definition_entry {
menu_action action; /**< menu action */
wimp_menu_entry *menu_entry; /**< corresponding menu entry */
+ const char *entry_key; /**< Messages key for entry text */
struct menu_definition_entry *next; /**< next menu entry */
};
struct menu_definition {
wimp_menu *menu; /**< corresponding menu */
+ const char *title_key; /**< Messages key for title text */
+ int current_encoding; /**< Identifier for current text encoding of menu text (as per OS_Byte,71,127) */
struct menu_definition_entry *entries; /**< menu entries */
struct menu_definition *next; /**< next menu */
};
@@ -68,7 +74,8 @@ struct menu_definition {
static wimp_menu *ro_gui_menu_define_menu(struct ns_menu *menu);
static void ro_gui_menu_define_menu_add(struct menu_definition *definition,
- struct ns_menu *menu, int depth, wimp_menu_entry *link,
+ struct ns_menu *menu, int depth,
+ wimp_menu_entry *parent_entry,
int first, int last, const char *prefix, int prefix_length);
static struct menu_definition *ro_gui_menu_find_menu(wimp_menu *menu);
static struct menu_definition_entry *ro_gui_menu_find_entry(wimp_menu *menu,
@@ -87,6 +94,7 @@ static bool ro_gui_menu_prepare_url_suggest(void);
static void ro_gui_menu_prepare_pageinfo(struct gui_window *g);
static void ro_gui_menu_prepare_objectinfo(struct box *box);
static void ro_gui_menu_refresh_toolbar(struct toolbar *toolbar);
+static bool ro_gui_menu_translate(struct menu_definition *menu);
/* default menu item flags */
@@ -119,18 +127,16 @@ wimp_menu *iconbar_menu, *browser_menu, *hotlist_menu, *global_history_menu,
static wimp_MENU(GLOBAL_HISTORY_RECENT_URLS) url_suggest;
wimp_menu *url_suggest_menu = (wimp_menu *)&url_suggest;
+/* the values given in PRM 3-157 for how to check menus/windows are
+ * incorrect so we use a hack of checking if the sub-menu is within
+ * 256KB of its parent */
+#define IS_MENU(menu, submenu) (abs((int)(submenu) - (int)(menu)) < 0x40000)
/**
* Create menu structures.
*/
-void ro_gui_menu_init(void) {
- int context = 0, read_count, entries = 0;
- os_error *error;
- osgbpb_INFO(100) info;
- char lang[8] = {0};
- char *lang_name;
- void *temp;
-
+void ro_gui_menu_init(void)
+{
/* iconbar menu */
NS_MENU(9) iconbar_definition = {
"NetSurf", {
@@ -162,7 +168,7 @@ void ro_gui_menu_init(void) {
{ "Page.SaveURL.URI", BROWSER_SAVE_URL_URI, dialog_saveas },
{ "Page.SaveURL.URL", BROWSER_SAVE_URL_URL, dialog_saveas },
{ "Page.SaveURL.LinkText", BROWSER_SAVE_URL_TEXT, dialog_saveas },
- { "Page.Print_", BROWSER_PRINT, dialog_print },
+ { "_Page.Print", BROWSER_PRINT, dialog_print },
{ "Page.NewWindow", BROWSER_NEW_WINDOW, 0 },
{ "Page.ViewSrc", BROWSER_VIEW_SOURCE, 0 },
{ "Object", BROWSER_OBJECT, 0 },
@@ -170,7 +176,7 @@ void ro_gui_menu_init(void) {
{ "Object.ObjSave", BROWSER_OBJECT_SAVE, dialog_saveas },
{ "Object.Export", NO_ACTION, 0 },
{ "Object.Export.Sprite", BROWSER_OBJECT_EXPORT_SPRITE, dialog_saveas },
- { "Object.SaveURL_", NO_ACTION, 0 },
+ { "_Object.SaveURL", NO_ACTION, 0 },
{ "Object.SaveURL.URI", BROWSER_OBJECT_SAVE_URL_URI, dialog_saveas },
{ "Object.SaveURL.URL", BROWSER_OBJECT_SAVE_URL_URL, dialog_saveas },
{ "Object.SaveURL.LinkText", BROWSER_OBJECT_SAVE_URL_TEXT, dialog_saveas },
@@ -178,7 +184,7 @@ void ro_gui_menu_init(void) {
{ "Navigate", NO_ACTION, 0 },
{ "Navigate.Home", BROWSER_NAVIGATE_HOME, 0 },
{ "Navigate.Back", BROWSER_NAVIGATE_BACK, 0 },
- { "Navigate.Forward_", BROWSER_NAVIGATE_FORWARD, 0 },
+ { "_Navigate.Forward", BROWSER_NAVIGATE_FORWARD, 0 },
{ "Navigate.Reload", BROWSER_NAVIGATE_RELOAD_ALL, 0 },
{ "Navigate.Stop", BROWSER_NAVIGATE_STOP, 0 },
{ "View", NO_ACTION, 0 },
@@ -190,9 +196,9 @@ void ro_gui_menu_init(void) {
{ "View.Toolbars.ToolButtons", TOOLBAR_BUTTONS, 0 },
{ "View.Toolbars.ToolAddress", TOOLBAR_ADDRESS_BAR, 0 },
{ "View.Toolbars.ToolThrob", TOOLBAR_THROBBER, 0 },
- { "View.Toolbars.ToolStatus_", TOOLBAR_STATUS_BAR, 0 },
+ { "_View.Toolbars.ToolStatus", TOOLBAR_STATUS_BAR, 0 },
{ "View.Toolbars.EditToolbar", TOOLBAR_EDIT, 0 },
- { "View.Render_", NO_ACTION, 0 },
+ { "_View.Render", NO_ACTION, 0 },
{ "View.Render.RenderAnims", BROWSER_BUFFER_ANIMS, 0 },
{ "View.Render.RenderAll", BROWSER_BUFFER_ALL, 0 },
{ "View.OptDefault", BROWSER_SAVE_VIEW, 0 },
@@ -207,13 +213,13 @@ void ro_gui_menu_init(void) {
{ "Utilities.Window", NO_ACTION, 0 },
{ "Utilities.Window.WindowSave", BROWSER_WINDOW_DEFAULT, 0 },
{ "Utilities.Window.WindowStagr", BROWSER_WINDOW_STAGGER, 0 },
- { "Utilities.Window.WindowSize_", BROWSER_WINDOW_COPY, 0 },
+ { "_Utilities.Window.WindowSize", BROWSER_WINDOW_COPY, 0 },
{ "Utilities.Window.WindowReset", BROWSER_WINDOW_RESET, 0 },
{ "Help", HELP_OPEN_CONTENTS, 0 },
{ "Help.HelpContent", HELP_OPEN_CONTENTS, 0 },
{ "Help.HelpGuide", HELP_OPEN_GUIDE, 0 },
- { "Help.HelpInfo_", HELP_OPEN_INFORMATION, 0 },
- { "Help.HelpAbout_", HELP_OPEN_ABOUT, 0 },
+ { "_Help.HelpInfo", HELP_OPEN_INFORMATION, 0 },
+ { "_Help.HelpAbout", HELP_OPEN_ABOUT, 0 },
{ "Help.HelpInter", HELP_LAUNCH_INTERACTIVE, 0 },
{NULL, 0, 0}
}
@@ -228,7 +234,7 @@ void ro_gui_menu_init(void) {
{ "Hotlist.New", NO_ACTION, 0 },
{ "Hotlist.New.Folder", TREE_NEW_FOLDER, dialog_folder },
{ "Hotlist.New.Link", TREE_NEW_LINK, dialog_entry },
- { "Hotlist.Export_", HOTLIST_EXPORT, dialog_saveas },
+ { "_Hotlist.Export", HOTLIST_EXPORT, dialog_saveas },
{ "Hotlist.Expand", TREE_EXPAND_ALL, 0 },
{ "Hotlist.Expand.All", TREE_EXPAND_ALL, 0 },
{ "Hotlist.Expand.Folders", TREE_EXPAND_FOLDERS, 0 },
@@ -238,7 +244,7 @@ void ro_gui_menu_init(void) {
{ "Hotlist.Collapse.Folders", TREE_COLLAPSE_FOLDERS, 0 },
{ "Hotlist.Collapse.Links", TREE_COLLAPSE_LINKS, 0 },
{ "Hotlist.Toolbars", NO_ACTION, 0 },
- { "Hotlist.Toolbars.ToolButtons_", TOOLBAR_BUTTONS, 0 },
+ { "_Hotlist.Toolbars.ToolButtons", TOOLBAR_BUTTONS, 0 },
{ "Hotlist.Toolbars.EditToolbar", TOOLBAR_EDIT, 0 },
{ "Selection", TREE_SELECTION, 0 },
{ "Selection.Edit", TREE_SELECTION_EDIT, (wimp_w)1 },
@@ -257,7 +263,7 @@ void ro_gui_menu_init(void) {
NS_MENU(19) global_history_definition = {
"History", {
{ "History", NO_ACTION, 0 },
- { "History.Export_", HISTORY_EXPORT, dialog_saveas },
+ { "_History.Export", HISTORY_EXPORT, dialog_saveas },
{ "History.Expand", TREE_EXPAND_ALL, 0 },
{ "History.Expand.All", TREE_EXPAND_ALL, 0 },
{ "History.Expand.Folders", TREE_EXPAND_FOLDERS, 0 },
@@ -267,7 +273,7 @@ void ro_gui_menu_init(void) {
{ "History.Collapse.Folders", TREE_COLLAPSE_FOLDERS, 0 },
{ "History.Collapse.Links", TREE_COLLAPSE_LINKS, 0 },
{ "History.Toolbars", NO_ACTION, 0 },
- { "History.Toolbars.ToolButtons_", TOOLBAR_BUTTONS, 0 },
+ { "_History.Toolbars.ToolButtons", TOOLBAR_BUTTONS, 0 },
{ "History.Toolbars.EditToolbar",TOOLBAR_EDIT, 0 },
{ "Selection", TREE_SELECTION, 0 },
{ "Selection.Launch", TREE_SELECTION_LAUNCH, 0 },
@@ -343,56 +349,62 @@ void ro_gui_menu_init(void) {
url_suggest_menu->height = wimp_MENU_ITEM_HEIGHT;
url_suggest_menu->gap = wimp_MENU_ITEM_GAP;
- /* language menu */
- languages_menu = calloc(1, wimp_SIZEOF_MENU(1));
- if (!languages_menu)
- die("Insufficient memory for languages menu.");
- languages_menu->title_data.indirected_text.text =
- messages_get("Languages");
- languages_menu->title_fg = wimp_COLOUR_BLACK;
- languages_menu->title_bg = wimp_COLOUR_LIGHT_GREY;
- languages_menu->work_fg = wimp_COLOUR_BLACK;
- languages_menu->work_bg = wimp_COLOUR_WHITE;
- languages_menu->width = 200;
- languages_menu->height = wimp_MENU_ITEM_HEIGHT;
- languages_menu->gap = wimp_MENU_ITEM_GAP;
-
- while (context != -1) {
- error = xosgbpb_dir_entries_info("<NetSurf$Dir>.Resources",
- (osgbpb_info_list*)&info, 1, context,
- sizeof(info), 0, &read_count, &context);
- if (error)
- die(error->errmess);
- if ((read_count == 0) || (info.obj_type != fileswitch_IS_DIR))
- continue;
-
- snprintf(lang, sizeof lang, "lang_%2s", info.name);
- /* we can't duplicate the string returned from our messages as
- * it causes value->key lookups to fail */
- lang_name = messages_get(lang);
- if ((lang_name == lang) || (strlen(info.name) != 2))
- continue;
-
- temp = realloc(languages_menu, wimp_SIZEOF_MENU(entries + 1));
- if (!temp)
- die("Insufficient memory for languages menu");
-
- languages_menu = temp;
- languages_menu->entries[entries].menu_flags = 0;
- languages_menu->entries[entries].sub_menu = wimp_NO_SUB_MENU;
- languages_menu->entries[entries].icon_flags = DEFAULT_FLAGS |
- wimp_ICON_INDIRECTED;
- languages_menu->entries[entries].data.indirected_text.text =
- lang_name;
- languages_menu->entries[entries].data.indirected_text.
- validation = (char *)-1;
- languages_menu->entries[entries].data.indirected_text.size =
- strlen(lang_name) + 1;
- entries++;
- }
+ /* Note: This table *must* be kept in sync with the LangNames file */
+ NS_MENU(48) lang_definition = {
+ "Languages", {
+ { "lang_af", NO_ACTION, 0 },
+ { "lang_bm", NO_ACTION, 0 },
+ { "lang_ca", NO_ACTION, 0 },
+ { "lang_cs", NO_ACTION, 0 },
+ { "lang_cy", NO_ACTION, 0 },
+ { "lang_da", NO_ACTION, 0 },
+ { "lang_de", NO_ACTION, 0 },
+ { "lang_en", NO_ACTION, 0 },
+ { "lang_es", NO_ACTION, 0 },
+ { "lang_et", NO_ACTION, 0 },
+ { "lang_eu", NO_ACTION, 0 },
+ { "lang_ff", NO_ACTION, 0 },
+ { "lang_fi", NO_ACTION, 0 },
+ { "lang_fr", NO_ACTION, 0 },
+ { "lang_ga", NO_ACTION, 0 },
+ { "lang_gl", NO_ACTION, 0 },
+ { "lang_ha", NO_ACTION, 0 },
+ { "lang_hr", NO_ACTION, 0 },
+ { "lang_hu", NO_ACTION, 0 },
+ { "lang_id", NO_ACTION, 0 },
+ { "lang_is", NO_ACTION, 0 },
+ { "lang_it", NO_ACTION, 0 },
+ { "lang_lt", NO_ACTION, 0 },
+ { "lang_lv", NO_ACTION, 0 },
+ { "lang_ms", NO_ACTION, 0 },
+ { "lang_mt", NO_ACTION, 0 },
+ { "lang_nl", NO_ACTION, 0 },
+ { "lang_no", NO_ACTION, 0 },
+ { "lang_pl", NO_ACTION, 0 },
+ { "lang_pt", NO_ACTION, 0 },
+ { "lang_rn", NO_ACTION, 0 },
+ { "lang_ro", NO_ACTION, 0 },
+ { "lang_rw", NO_ACTION, 0 },
+ { "lang_sk", NO_ACTION, 0 },
+ { "lang_sl", NO_ACTION, 0 },
+ { "lang_so", NO_ACTION, 0 },
+ { "lang_sq", NO_ACTION, 0 },
+ { "lang_sr", NO_ACTION, 0 },
+ { "lang_sv", NO_ACTION, 0 },
+ { "lang_sw", NO_ACTION, 0 },
+ { "lang_tr", NO_ACTION, 0 },
+ { "lang_uz", NO_ACTION, 0 },
+ { "lang_vi", NO_ACTION, 0 },
+ { "lang_wo", NO_ACTION, 0 },
+ { "lang_xs", NO_ACTION, 0 },
+ { "lang_yo", NO_ACTION, 0 },
+ { "lang_zu", NO_ACTION, 0 },
+ { NULL, 0, 0 }
+ }
+ };
- languages_menu->entries[0].menu_flags |= wimp_MENU_TITLE_INDIRECTED;
- languages_menu->entries[entries-1].menu_flags |= wimp_MENU_LAST;
+ languages_menu = ro_gui_menu_define_menu(
+ (struct ns_menu *)&lang_definition);
}
@@ -406,6 +418,17 @@ void ro_gui_menu_create(wimp_menu *menu, int x, int y, wimp_w w) {
os_error *error;
int i;
menu_action action;
+ struct menu_definition *definition;
+
+ /* translate menu, if necessary (this returns quickly
+ * if there's nothing to be done) */
+ definition = ro_gui_menu_find_menu(menu);
+ if (definition) {
+ if (!ro_gui_menu_translate(definition)) {
+ warn_user("NoMemory", 0);
+ return;
+ }
+ }
/* read the object under the pointer for a new gui_window menu */
if ((!current_menu) && (menu == browser_menu)) {
@@ -555,8 +578,9 @@ void ro_gui_menu_selection(wimp_selection *selection) {
wimp_menu *menu;
os_error *error;
- /* if we are using gui_multitask then menu selection events may be delivered
- * after the menu has been closed. As such, we simply ignore these events. */
+ /* if we are using gui_multitask then menu selection events
+ * may be delivered after the menu has been closed. As such,
+ * we simply ignore these events. */
if (!current_menu)
return
assert(current_menu_window);
@@ -595,9 +619,18 @@ void ro_gui_menu_selection(wimp_selection *selection) {
} else if (current_menu == image_quality_menu) {
ro_gui_dialog_image_menu_selection(selection->items[0]);
} else if (current_menu == languages_menu) {
- ro_gui_dialog_languages_menu_selection(languages_menu->
- entries[selection->items[0]].
- data.indirected_text.text);
+ struct menu_definition *desc;
+ struct menu_definition_entry *entry;
+
+ /* find the relevant menu definition entry */
+ desc = ro_gui_menu_find_menu(current_menu);
+ for (entry = desc->entries; entry; entry = entry->next)
+ if (entry->menu_entry == menu_entry)
+ break;
+ if (entry)
+ /* found it, so handle the seletion */
+ ro_gui_dialog_languages_menu_selection(
+ entry->entry_key);
} else if (current_menu == font_menu) {
ro_gui_dialog_font_menu_selection(selection->items[0]);
} else if ((current_menu == gui_form_select_menu) &&
@@ -660,7 +693,6 @@ void ro_gui_menu_warning(wimp_message_menu_warning *warning) {
wimp_menu_entry *menu_entry;
wimp_menu *sub_menu;
os_error *error;
- int menu_check;
assert(current_menu);
assert(current_menu_window);
@@ -673,11 +705,7 @@ void ro_gui_menu_warning(wimp_message_menu_warning *warning) {
menu_entry = &menu_entry->sub_menu->
entries[warning->selection.items[i]];
- /* the values given in PRM 3-157 for how to check menus/windows are
- * incorrect so we use a hack of checking if the sub-menu is within
- * 256KB of its parent */
- menu_check = abs((int)menu_entry->sub_menu - (int)menu_entry);
- if (menu_check < 0x40000) {
+ if (IS_MENU(menu_entry, menu_entry->sub_menu)) {
sub_menu = menu_entry->sub_menu;
i = 0;
do {
@@ -778,9 +806,11 @@ void ro_gui_prepare_navigate(struct gui_window *gui) {
ro_gui_menu_prepare_action(gui->window, HOTLIST_SHOW, false);
ro_gui_menu_prepare_action(gui->window, BROWSER_NAVIGATE_STOP, false);
- ro_gui_menu_prepare_action(gui->window, BROWSER_NAVIGATE_RELOAD_ALL, false);
+ ro_gui_menu_prepare_action(gui->window, BROWSER_NAVIGATE_RELOAD_ALL,
+ false);
ro_gui_menu_prepare_action(gui->window, BROWSER_NAVIGATE_BACK, false);
- ro_gui_menu_prepare_action(gui->window, BROWSER_NAVIGATE_FORWARD, false);
+ ro_gui_menu_prepare_action(gui->window, BROWSER_NAVIGATE_FORWARD,
+ false);
ro_gui_menu_prepare_action(gui->window, HOTLIST_SHOW, false);
ro_gui_menu_prepare_action(gui->window, BROWSER_SAVE, false);
ro_gui_menu_prepare_action(gui->window, BROWSER_PRINT, false);
@@ -894,6 +924,40 @@ void ro_gui_menu_prepare_objectinfo(struct box *box) {
/**
+ * Prepare languages menu for use
+ *
+ * \param accept For Accept-Languages selection
+ * \param lang Currently selected language
+ */
+void ro_gui_menu_prepare_languages(bool accept, const char *lang)
+{
+ struct menu_definition *menu;
+ struct menu_definition_entry *entry;
+ char path_buf[40];
+ int offset = strlen("lang_");
+
+ menu = ro_gui_menu_find_menu(languages_menu);
+ for (entry = menu->entries; entry; entry = entry->next) {
+ if (!accept) {
+ snprintf(path_buf, sizeof path_buf,
+ "<NetSurf$Dir>.Resources.%.2s",
+ entry->entry_key + offset);
+
+ entry->menu_entry->icon_flags |= is_dir(path_buf) ?
+ 0 : wimp_ICON_SHADED;
+ }
+ else
+ entry->menu_entry->icon_flags &= ~wimp_ICON_SHADED;
+
+ /* set ticked status */
+ if (strncmp(lang, entry->entry_key + offset, 2) == 0)
+ entry->menu_entry->menu_flags |= wimp_MENU_TICKED;
+ else
+ entry->menu_entry->menu_flags &= ~wimp_MENU_TICKED;
+ }
+}
+
+/**
* Display a menu of options for a form select control.
*
* \param bw browser window containing form control
@@ -902,7 +966,7 @@ void ro_gui_menu_prepare_objectinfo(struct box *box) {
void gui_create_form_select_menu(struct browser_window *bw,
struct form_control *control) {
unsigned int i = 0, j;
- char *text_convert;
+ char *text_convert, *temp, *s;
struct form_option *option;
wimp_pointer pointer;
os_error *error;
@@ -911,7 +975,8 @@ void gui_create_form_select_menu(struct browser_window *bw,
assert(control);
- for (option = control->data.select.items; option; option = option->next)
+ for (option = control->data.select.items; option;
+ option = option->next)
i++;
if (i == 0) {
ro_gui_menu_closed();
@@ -926,6 +991,7 @@ void gui_create_form_select_menu(struct browser_window *bw,
wimp_MENU_LAST)
break;
}
+ free(gui_form_select_menu->title_data.indirected_text.text);
free(gui_form_select_menu);
gui_form_select_menu = 0;
}
@@ -938,8 +1004,18 @@ void gui_create_form_select_menu(struct browser_window *bw,
ro_gui_menu_closed();
return;
}
+ err = utf8_to_local_encoding(messages_get("SelectMenu"), 0,
+ &text_convert);
+ if (err != UTF8_CONVERT_OK) {
+ /* badenc should never happen */
+ assert(err != UTF8_CONVERT_BADENC);
+ LOG(("utf8_to_local_encoding failed"));
+ warn_user("NoMemory", 0);
+ ro_gui_menu_closed();
+ return;
+ }
gui_form_select_menu->title_data.indirected_text.text =
- messages_get("SelectMenu");
+ text_convert;
gui_form_select_menu->title_fg = wimp_COLOUR_BLACK;
gui_form_select_menu->title_bg = wimp_COLOUR_LIGHT_GREY;
gui_form_select_menu->work_fg = wimp_COLOUR_BLACK;
@@ -963,8 +1039,24 @@ void gui_create_form_select_menu(struct browser_window *bw,
wimp_ICON_FG_COLOUR_SHIFT) |
(wimp_COLOUR_WHITE <<
wimp_ICON_BG_COLOUR_SHIFT);
- err = utf8_to_enc(option->text,
- local_encoding_name(), 0, &text_convert);
+ temp = cnv_space2nbsp(option->text);
+ if (!temp) {
+ LOG(("cnv_space2nbsp failed"));
+ warn_user("NoMemory", 0);
+ ro_gui_menu_closed();
+ return;
+ }
+
+ /* convert spaces to hard spaces to stop things
+ * like 'Go Home' being treated as if 'Home' is a
+ * keyboard shortcut and right aligned in the menu.
+ */
+ for (s = temp; *s != '\0'; s++)
+ if (*s == 0x20)
+ *s = 0xa0;
+
+ err = utf8_to_local_encoding(option->text,
+ 0, &text_convert);
if (err != UTF8_CONVERT_OK) {
/* A bad encoding should never happen,
* so assert this */
@@ -975,15 +1067,11 @@ void gui_create_form_select_menu(struct browser_window *bw,
return;
}
+ free(temp);
+
gui_form_select_menu->entries[i].data.indirected_text.text =
text_convert;
- /* convert spaces to hard spaces to stop things like 'Go Home'
- * being treated as if 'Home' is a keyboard shortcut and right
- * aligned in the menu. */
- text_convert -= 1;
- while (*++text_convert != '\0')
- if (*text_convert == 0x20)
- *text_convert = 0xa0;
+
gui_form_select_menu->entries[i].data.indirected_text.
validation = (char *)-1;
gui_form_select_menu->entries[i].data.indirected_text.size =
@@ -1029,22 +1117,45 @@ wimp_menu *ro_gui_menu_define_menu(struct ns_menu *menu) {
definition->next = ro_gui_menu_definitions;
ro_gui_menu_definitions = definition;
+ /* count number of menu entries */
+ for (entry = 0; menu->entries[entry].text; entry++)
+ /* do nothing */;
+
/* create our definitions */
- for (entry = 0; menu->entries[entry].text; entry++);
ro_gui_menu_define_menu_add(definition, menu, 0, NULL,
0, entry, NULL, 0);
+
+ /* and translate menu into current encoding */
+ if (!ro_gui_menu_translate(definition))
+ die("No memory to translate menu.");
+
return definition->menu;
}
+/**
+ * Create a wimp menu tree from ns_menu data.
+ * This function does *not* deal with the menu textual content - it simply
+ * creates and populates the appropriate structures. Textual content is
+ * generated by ro_gui_menu_translate_menu()
+ *
+ * \param definition Top level menu definition
+ * \param menu Menu declaration data
+ * \param depth Depth of menu we're currently building
+ * \param parent_entry Entry in parent menu, or NULL if root menu
+ * \param first First index in declaration data that is used by this menu
+ * \param last Last index in declaration data that is used by this menu
+ * \param prefix Prefix pf menu declaration string already seen
+ * \param prefix_length Length of prefix
+ */
void ro_gui_menu_define_menu_add(struct menu_definition *definition,
- struct ns_menu *menu, int depth, wimp_menu_entry *link,
- int first, int last, const char *prefix, int prefix_length) {
- int entry, id, cur_depth, new_prefix_length;
+ struct ns_menu *menu, int depth,
+ wimp_menu_entry *parent_entry, int first, int last,
+ const char *prefix, int prefix_length) {
+ int entry, id, cur_depth;
int entries = 0;
int matches[last - first + 1];
const char *match;
- char *text, *menu_text, *search;
- char *title, *translated;
+ const char *text, *menu_text;
wimp_menu *new_menu;
struct menu_definition_entry *definition_entry;
@@ -1052,33 +1163,49 @@ void ro_gui_menu_define_menu_add(struct menu_definition *definition,
for (entry = first; entry < last; entry++) {
cur_depth = 0;
match = menu->entries[entry].text;
+
+ /* skip specials at start of string */
+ while (!isalnum(*match))
+ match++;
+
+ /* attempt prefix match */
if ((prefix) && (strncmp(match, prefix, prefix_length)))
continue;
+
+ /* Find depth of this entry */
while (*match)
if (*match++ == '.')
cur_depth++;
+
if (depth == cur_depth)
matches[entries++] = entry;
}
matches[entries] = last;
- /* step 2: build and link the menu. we must use realloc to stop
- * our memory fragmenting so we can test for sub-menus easily */
+ /* no entries, so exit */
if (entries == 0)
return;
+
+ /* step 2: build and link the menu. we must use realloc to stop
+ * our memory fragmenting so we can test for sub-menus easily */
new_menu = (wimp_menu *)malloc(wimp_SIZEOF_MENU(entries));
if (!new_menu)
die("No memory to create menu.");
- if (link) {
- title = link->data.indirected_text.text;
- link->sub_menu = new_menu;
+
+ if (parent_entry) {
+ /* Fix up sub menu pointer */
+ parent_entry->sub_menu = new_menu;
} else {
- title = messages_get(menu->title);
- if (!title)
- die("No memory to translate root menu title");
+ /* Root menu => fill in definition struct */
+ definition->title_key = menu->title;
+ definition->current_encoding = 0;
definition->menu = new_menu;
}
- new_menu->title_data.indirected_text.text = title;
+
+ /* this is fixed up in ro_gui_menu_translate() */
+ new_menu->title_data.indirected_text.text = NULL;
+
+ /* fill in menu flags */
new_menu->title_fg = wimp_COLOUR_BLACK;
new_menu->title_bg = wimp_COLOUR_LIGHT_GREY;
new_menu->work_fg = wimp_COLOUR_BLACK;
@@ -1086,71 +1213,70 @@ void ro_gui_menu_define_menu_add(struct menu_definition *definition,
new_menu->width = 200;
new_menu->height = wimp_MENU_ITEM_HEIGHT;
new_menu->gap = wimp_MENU_ITEM_GAP;
+
+ /* and then create the entries */
for (entry = 0; entry < entries; entry++) {
/* add the entry */
id = matches[entry];
- text = strdup(menu->entries[id].text);
- if (!text)
- die("No memory to examine menu text");
- search = menu_text = text;
- while (*search)
- if (*search++ == '.')
- menu_text = search;
+
+ text = menu->entries[id].text;
+
+ /* fill in menu flags from specials at start of string */
new_menu->entries[entry].menu_flags = 0;
- search = menu_text;
- while (*search)
- if (*search++ == '_') {
+ while (!isalnum(*text)) {
+ if (*text == '_')
new_menu->entries[entry].menu_flags |=
- wimp_MENU_SEPARATE;
- search[-1] = 0;
- break;
- }
+ wimp_MENU_SEPARATE;
+ text++;
+ }
+
+ /* get messages key for menu entry */
+ menu_text = strrchr(text, '.');
+ if (!menu_text)
+ /* no '.' => top-level entry */
+ menu_text = text;
+ else
+ menu_text++; /* and move past the '.' */
+
+ /* fill in submenu data */
if (menu->entries[id].sub_window)
- new_menu->entries[entry].sub_menu = (wimp_menu *)menu->
- entries[id].sub_window;
+ new_menu->entries[entry].sub_menu =
+ (wimp_menu *)menu->entries[id].sub_window;
else
new_menu->entries[entry].sub_menu = wimp_NO_SUB_MENU;
+
+ /* icon flags */
new_menu->entries[entry].icon_flags = DEFAULT_FLAGS |
wimp_ICON_INDIRECTED;
- translated = messages_get(menu_text);
- if (translated != menu_text)
- free(text);
- new_menu->entries[entry].data.indirected_text.text = translated;
- new_menu->entries[entry].data.indirected_text.validation =
- (char *)-1;
- new_menu->entries[entry].data.indirected_text.size =
- strlen(translated);
- /* store action */
- if (menu->entries[id].action != NO_ACTION) {
- definition_entry = malloc(
- sizeof(struct menu_definition_entry));
- if (!definition_entry)
- die("Unable to create menu definition entry");
- definition_entry->action = menu->entries[id].action;
- definition_entry->menu_entry =
- &new_menu->entries[entry];
- definition_entry->next = definition->entries;
- definition->entries = definition_entry;
- }
+ /* this is fixed up in ro_gui_menu_translate() */
+ new_menu->entries[entry].data.indirected_text.text = NULL;
+
+ /* create definition entry */
+ definition_entry =
+ malloc(sizeof(struct menu_definition_entry));
+ if (!definition_entry)
+ die("Unable to create menu definition entry");
+ definition_entry->action = menu->entries[id].action;
+ definition_entry->menu_entry = &new_menu->entries[entry];
+ definition_entry->entry_key = menu_text;
+ definition_entry->next = definition->entries;
+ definition->entries = definition_entry;
/* recurse */
if (new_menu->entries[entry].sub_menu == wimp_NO_SUB_MENU) {
- new_prefix_length = strlen(menu->entries[id].text);
- if (menu->entries[id].text[new_prefix_length - 1] == '_')
- new_prefix_length--;
- ro_gui_menu_define_menu_add(definition, menu, depth + 1,
- &new_menu->entries[entry],
+ ro_gui_menu_define_menu_add(definition, menu,
+ depth + 1, &new_menu->entries[entry],
matches[entry], matches[entry + 1],
- menu->entries[id].text,
- new_prefix_length);
+ text, strlen(text));
}
/* give menu warnings */
if (new_menu->entries[entry].sub_menu != wimp_NO_SUB_MENU)
new_menu->entries[entry].menu_flags |=
- wimp_MENU_GIVE_WARNING;
+ wimp_MENU_GIVE_WARNING;
}
+
new_menu->entries[0].menu_flags |= wimp_MENU_TITLE_INDIRECTED;
new_menu->entries[entries - 1].menu_flags |= wimp_MENU_LAST;
}
@@ -1268,7 +1394,8 @@ void ro_gui_menu_set_entry_ticked(wimp_menu *menu, menu_action action,
* \param windows_at_pointer whether to open any windows at the pointer location
*/
bool ro_gui_menu_handle_action(wimp_w owner, menu_action action,
- bool windows_at_pointer) {
+ bool windows_at_pointer)
+{
wimp_window_state state;
struct gui_window *g = NULL;
struct browser_window *bw = NULL;
@@ -1296,7 +1423,8 @@ bool ro_gui_menu_handle_action(wimp_w owner, menu_action action,
ro_gui_open_help_page("info");
return true;
case HELP_OPEN_ABOUT:
- browser_window_create("file:/<NetSurf$Dir>/Docs/about",
+ browser_window_create(
+ "file:/<NetSurf$Dir>/Docs/about",
0, 0);
return true;
case HELP_LAUNCH_INTERACTIVE:
@@ -1307,7 +1435,8 @@ bool ro_gui_menu_handle_action(wimp_w owner, menu_action action,
case HISTORY_SHOW_LOCAL:
if ((!bw) || (!bw->history))
return false;
- ro_gui_history_open(bw, bw->history, windows_at_pointer);
+ ro_gui_history_open(bw, bw->history,
+ windows_at_pointer);
return true;
case HISTORY_SHOW_GLOBAL:
ro_gui_tree_show(global_history_tree);
@@ -1323,7 +1452,8 @@ bool ro_gui_menu_handle_action(wimp_w owner, menu_action action,
return false;
}
node = tree_create_URL_node(hotlist_tree->root,
- c->title, norm_url, ro_content_filetype(c),
+ c->title, norm_url,
+ ro_content_filetype(c),
time(NULL), -1, 0);
free(norm_url);
if (node) {
@@ -1346,15 +1476,15 @@ bool ro_gui_menu_handle_action(wimp_w owner, menu_action action,
if (!c)
return false;
ro_gui_menu_prepare_action(owner, action, true);
- ro_gui_dialog_open_persistent(g->window, dialog_pageinfo,
- windows_at_pointer);
+ ro_gui_dialog_open_persistent(g->window,
+ dialog_pageinfo, windows_at_pointer);
return true;
case BROWSER_PRINT:
if (!c)
return false;
ro_gui_menu_prepare_action(owner, action, true);
- ro_gui_dialog_open_persistent(g->window, dialog_print,
- windows_at_pointer);
+ ro_gui_dialog_open_persistent(g->window,
+ dialog_print, windows_at_pointer);
return true;
case BROWSER_NEW_WINDOW:
if (!c)
@@ -1372,8 +1502,8 @@ bool ro_gui_menu_handle_action(wimp_w owner, menu_action action,
if (!current_menu_object_box)
return false;
ro_gui_menu_prepare_action(owner, action, true);
- ro_gui_dialog_open_persistent(g->window, dialog_objinfo,
- windows_at_pointer);
+ ro_gui_dialog_open_persistent(g->window,
+ dialog_objinfo, windows_at_pointer);
return true;
case BROWSER_OBJECT_RELOAD:
if (!current_menu_object_box)
@@ -1410,8 +1540,10 @@ bool ro_gui_menu_handle_action(wimp_w owner, menu_action action,
case BROWSER_NAVIGATE_HOME:
if (!bw)
return false;
- if ((option_homepage_url) && (option_homepage_url[0])) {
- browser_window_go(g->bw, option_homepage_url, 0);
+ if ((option_homepage_url) &&
+ (option_homepage_url[0])) {
+ browser_window_go(g->bw,
+ option_homepage_url, 0);
} else {
snprintf(url, sizeof url,
"file:/<NetSurf$Dir>/Docs/intro_%s",
@@ -1459,24 +1591,27 @@ bool ro_gui_menu_handle_action(wimp_w owner, menu_action action,
if (!c || c->type != CONTENT_HTML)
return false;
ro_gui_menu_prepare_action(owner, action, true);
- ro_gui_dialog_open_persistent(g->window, dialog_search,
- windows_at_pointer);
+ ro_gui_dialog_open_persistent(g->window,
+ dialog_search, windows_at_pointer);
return true;
case BROWSER_IMAGES_BACKGROUND:
if (!g)
return false;
- g->option.background_images = !g->option.background_images;
+ g->option.background_images =
+ !g->option.background_images;
gui_window_redraw_window(g);
return true;
case BROWSER_BUFFER_ANIMS:
if (!g)
return false;
- g->option.buffer_animations = !g->option.buffer_animations;
+ g->option.buffer_animations =
+ !g->option.buffer_animations;
break;
case BROWSER_BUFFER_ALL:
if (!g)
return false;
- g->option.buffer_everything = !g->option.buffer_everything;
+ g->option.buffer_everything =
+ !g->option.buffer_everything;
break;
case BROWSER_SAVE_VIEW:
if (!bw)
@@ -1493,13 +1628,16 @@ bool ro_gui_menu_handle_action(wimp_w owner, menu_action action,
error = xwimp_get_window_state(&state);
if (error) {
LOG(("xwimp_get_window_state: 0x%x: %s",
- error->errnum, error->errmess));
+ error->errnum,
+ error->errmess));
warn_user("WimpError", error->errmess);
}
option_window_x = state.visible.x0;
option_window_y = state.visible.y0;
- option_window_width = state.visible.x1 - state.visible.x0;
- option_window_height = state.visible.y1 - state.visible.y0;
+ option_window_width =
+ state.visible.x1 - state.visible.x0;
+ option_window_height =
+ state.visible.y1 - state.visible.y0;
return true;
case BROWSER_WINDOW_STAGGER:
option_window_stagger = !option_window_stagger;
@@ -1610,7 +1748,9 @@ bool ro_gui_menu_handle_action(wimp_w owner, menu_action action,
* \param action the action to prepare
* \param windows whether to update sub-windows
*/
-void ro_gui_menu_prepare_action(wimp_w owner, menu_action action, bool windows) {
+void ro_gui_menu_prepare_action(wimp_w owner, menu_action action,
+ bool windows)
+{
struct menu_definition_entry *entry;
struct gui_window *g;
struct browser_window *bw;
@@ -1631,8 +1771,10 @@ void ro_gui_menu_prepare_action(wimp_w owner, menu_action action, bool windows)
/* help actions */
case HELP_LAUNCH_INTERACTIVE:
result = ro_gui_interactive_help_available();
- ro_gui_menu_set_entry_shaded(current_menu, action, result);
- ro_gui_menu_set_entry_ticked(current_menu, action, result);
+ ro_gui_menu_set_entry_shaded(current_menu,
+ action, result);
+ ro_gui_menu_set_entry_ticked(current_menu,
+ action, result);
break;
/* history actions */
@@ -1655,39 +1797,49 @@ void ro_gui_menu_prepare_action(wimp_w owner, menu_action action, bool windows)
case HOTLIST_SHOW:
ro_gui_menu_set_entry_shaded(current_menu, action,
!hotlist_tree);
- if ((t) && (!t->editor) && (t->type == THEME_BROWSER_TOOLBAR))
- ro_gui_set_icon_shaded_state(t->toolbar_handle,
- ICON_TOOLBAR_BOOKMARK, !hotlist_tree);
+ if ((t) && (!t->editor) &&
+ (t->type == THEME_BROWSER_TOOLBAR))
+ ro_gui_set_icon_shaded_state(
+ t->toolbar_handle,
+ ICON_TOOLBAR_BOOKMARK,
+ !hotlist_tree);
break;
/* page actions */
case BROWSER_PAGE_INFO:
- ro_gui_menu_set_entry_shaded(current_menu, action, !c);
+ ro_gui_menu_set_entry_shaded(current_menu,
+ action, !c);
if ((windows) && (c))
ro_gui_menu_prepare_pageinfo(g);
break;
case BROWSER_PRINT:
- ro_gui_menu_set_entry_shaded(current_menu, action, !c);
+ ro_gui_menu_set_entry_shaded(current_menu,
+ action, !c);
if ((t) && (t->type == THEME_BROWSER_TOOLBAR))
- ro_gui_set_icon_shaded_state(t->toolbar_handle,
+ ro_gui_set_icon_shaded_state(
+ t->toolbar_handle,
ICON_TOOLBAR_PRINT, !c);
if ((windows) && (c))
ro_gui_print_prepare(g);
- if ((t) && (!t->editor) && (t->type == THEME_BROWSER_TOOLBAR))
- ro_gui_set_icon_shaded_state(t->toolbar_handle,
+ if ((t) && (!t->editor) &&
+ (t->type == THEME_BROWSER_TOOLBAR))
+ ro_gui_set_icon_shaded_state(
+ t->toolbar_handle,
ICON_TOOLBAR_PRINT, !c);
break;
case BROWSER_PAGE:
case BROWSER_NEW_WINDOW:
case BROWSER_VIEW_SOURCE:
- ro_gui_menu_set_entry_shaded(current_menu, action, !c);
+ ro_gui_menu_set_entry_shaded(current_menu,
+ action, !c);
break;
/* object actions */
case BROWSER_OBJECT:
c = current_menu_object_box ?
current_menu_object_box->object : NULL;
- ro_gui_menu_set_entry_shaded(current_menu, action, !c);
+ ro_gui_menu_set_entry_shaded(current_menu,
+ action, !c);
break;
case BROWSER_OBJECT_INFO:
if ((windows) && (current_menu_object_box))
@@ -1702,37 +1854,45 @@ void ro_gui_menu_prepare_action(wimp_w owner, menu_action action, bool windows)
case BROWSER_OBJECT_SAVE:
c = current_menu_object_box ?
current_menu_object_box->object : NULL;
- ro_gui_menu_set_entry_shaded(current_menu, action, !c);
+ ro_gui_menu_set_entry_shaded(current_menu,
+ action, !c);
if ((c) && (windows))
ro_gui_save_prepare(GUI_SAVE_OBJECT_ORIG, c);
break;
case BROWSER_OBJECT_EXPORT_SPRITE:
c = current_menu_object_box ?
current_menu_object_box->object : NULL;
- ro_gui_menu_set_entry_shaded(current_menu, action, !c);
+ ro_gui_menu_set_entry_shaded(current_menu,
+ action, !c);
if ((c) && (windows))
ro_gui_save_prepare(GUI_SAVE_OBJECT_NATIVE, c);
break;
case BROWSER_SAVE:
- ro_gui_menu_set_entry_shaded(current_menu, action, !c);
+ ro_gui_menu_set_entry_shaded(current_menu,
+ action, !c);
if ((c) && (windows))
ro_gui_save_prepare(GUI_SAVE_SOURCE, c);
- if ((t) && (!t->editor) && (t->type == THEME_BROWSER_TOOLBAR))
- ro_gui_set_icon_shaded_state(t->toolbar_handle,
+ if ((t) && (!t->editor) &&
+ (t->type == THEME_BROWSER_TOOLBAR))
+ ro_gui_set_icon_shaded_state(
+ t->toolbar_handle,
ICON_TOOLBAR_SAVE, !c);
break;
case BROWSER_SAVE_COMPLETE:
- ro_gui_menu_set_entry_shaded(current_menu, action, !c);
+ ro_gui_menu_set_entry_shaded(current_menu,
+ action, !c);
if ((c) && (windows))
ro_gui_save_prepare(GUI_SAVE_COMPLETE, c);
break;
case BROWSER_EXPORT_DRAW:
- ro_gui_menu_set_entry_shaded(current_menu, action, !c);
+ ro_gui_menu_set_entry_shaded(current_menu,
+ action, !c);
if ((c) && (windows))
ro_gui_save_prepare(GUI_SAVE_DRAW, c);
break;
case BROWSER_EXPORT_TEXT:
- ro_gui_menu_set_entry_shaded(current_menu, action, !c);
+ ro_gui_menu_set_entry_shaded(current_menu,
+ action, !c);
if ((c) && (windows))
ro_gui_save_prepare(GUI_SAVE_TEXT, c);
break;
@@ -1740,7 +1900,8 @@ void ro_gui_menu_prepare_action(wimp_w owner, menu_action action, bool windows)
c = current_menu_object_box ?
current_menu_object_box->object : NULL;
case BROWSER_SAVE_URL_URI:
- ro_gui_menu_set_entry_shaded(current_menu, action, !c);
+ ro_gui_menu_set_entry_shaded(current_menu,
+ action, !c);
if ((c) && (windows))
ro_gui_save_prepare(GUI_SAVE_LINK_URI, c);
break;
@@ -1748,7 +1909,8 @@ void ro_gui_menu_prepare_action(wimp_w owner, menu_action action, bool windows)
c = current_menu_object_box ?
current_menu_object_box->object : NULL;
case BROWSER_SAVE_URL_URL:
- ro_gui_menu_set_entry_shaded(current_menu, action, !c);
+ ro_gui_menu_set_entry_shaded(current_menu,
+ action, !c);
if ((c) && (windows))
ro_gui_save_prepare(GUI_SAVE_LINK_URL, c);
break;
@@ -1756,7 +1918,8 @@ void ro_gui_menu_prepare_action(wimp_w owner, menu_action action, bool windows)
c = current_menu_object_box ?
current_menu_object_box->object : NULL;
case BROWSER_SAVE_URL_TEXT:
- ro_gui_menu_set_entry_shaded(current_menu, action, !c);
+ ro_gui_menu_set_entry_shaded(current_menu,
+ action, !c);
if ((c) && (windows))
ro_gui_save_prepare(GUI_SAVE_LINK_TEXT, c);
break;
@@ -1775,34 +1938,46 @@ void ro_gui_menu_prepare_action(wimp_w owner, menu_action action, bool windows)
case BROWSER_NAVIGATE_BACK:
result = (!bw || !bw->history ||
!history_back_available(bw->history));
- ro_gui_menu_set_entry_shaded(current_menu, action, result);
- if ((t) && (!t->editor) && (t->type == THEME_BROWSER_TOOLBAR))
- ro_gui_set_icon_shaded_state(t->toolbar_handle,
+ ro_gui_menu_set_entry_shaded(current_menu,
+ action, result);
+ if ((t) && (!t->editor) &&
+ (t->type == THEME_BROWSER_TOOLBAR))
+ ro_gui_set_icon_shaded_state(
+ t->toolbar_handle,
ICON_TOOLBAR_BACK, result);
break;
case BROWSER_NAVIGATE_FORWARD:
result = (!bw || !bw->history ||
!history_forward_available(bw->history));
- ro_gui_menu_set_entry_shaded(current_menu, action, result);
- if ((t) && (!t->editor) && (t->type == THEME_BROWSER_TOOLBAR))
- ro_gui_set_icon_shaded_state(t->toolbar_handle,
+ ro_gui_menu_set_entry_shaded(current_menu,
+ action, result);
+ if ((t) && (!t->editor) &&
+ (t->type == THEME_BROWSER_TOOLBAR))
+ ro_gui_set_icon_shaded_state(
+ t->toolbar_handle,
ICON_TOOLBAR_FORWARD, result);
break;
case BROWSER_NAVIGATE_RELOAD:
case BROWSER_NAVIGATE_RELOAD_ALL:
result = (bw->current_content && !bw->loading_content);
- ro_gui_menu_set_entry_shaded(current_menu, action, !result);
- if ((t) && (!t->editor) && (t->type == THEME_BROWSER_TOOLBAR))
- ro_gui_set_icon_shaded_state(t->toolbar_handle,
+ ro_gui_menu_set_entry_shaded(current_menu,
+ action, !result);
+ if ((t) && (!t->editor) &&
+ (t->type == THEME_BROWSER_TOOLBAR))
+ ro_gui_set_icon_shaded_state(
+ t->toolbar_handle,
ICON_TOOLBAR_RELOAD, !result);
break;
case BROWSER_NAVIGATE_STOP:
result = (bw->loading_content || (bw->current_content &&
(bw->current_content->status !=
CONTENT_STATUS_DONE)));
- ro_gui_menu_set_entry_shaded(current_menu, action, !result);
- if ((t) && (!t->editor) && (t->type == THEME_BROWSER_TOOLBAR))
- ro_gui_set_icon_shaded_state(t->toolbar_handle,
+ ro_gui_menu_set_entry_shaded(current_menu,
+ action, !result);
+ if ((t) && (!t->editor) &&
+ (t->type == THEME_BROWSER_TOOLBAR))
+ ro_gui_set_icon_shaded_state(
+ t->toolbar_handle,
ICON_TOOLBAR_STOP, !result);
break;
case BROWSER_NAVIGATE_URL:
@@ -1812,44 +1987,53 @@ void ro_gui_menu_prepare_action(wimp_w owner, menu_action action, bool windows)
/* display actions */
case BROWSER_SCALE_VIEW:
- ro_gui_menu_set_entry_shaded(current_menu, action, !c);
+ ro_gui_menu_set_entry_shaded(current_menu,
+ action, !c);
if ((c) && (windows))
ro_gui_dialog_prepare_zoom(g);
- if ((t) && (!t->editor) && (t->type == THEME_BROWSER_TOOLBAR))
- ro_gui_set_icon_shaded_state(t->toolbar_handle,
+ if ((t) && (!t->editor) &&
+ (t->type == THEME_BROWSER_TOOLBAR))
+ ro_gui_set_icon_shaded_state(
+ t->toolbar_handle,
ICON_TOOLBAR_SCALE, !c);
break;
case BROWSER_FIND_TEXT:
result = !c || c->type != CONTENT_HTML;
- ro_gui_menu_set_entry_shaded(current_menu, action, result);
+ ro_gui_menu_set_entry_shaded(current_menu,
+ action, result);
if ((c) && (windows))
ro_gui_search_prepare(g);
- if ((t) && (!t->editor) && (t->type == THEME_BROWSER_TOOLBAR))
- ro_gui_set_icon_shaded_state(t->toolbar_handle,
+ if ((t) && (!t->editor) &&
+ (t->type == THEME_BROWSER_TOOLBAR))
+ ro_gui_set_icon_shaded_state(
+ t->toolbar_handle,
ICON_TOOLBAR_SEARCH, result);
break;
case BROWSER_IMAGES_FOREGROUND:
- ro_gui_menu_set_entry_shaded(current_menu, action, true);
- ro_gui_menu_set_entry_ticked(current_menu, action, true);
+ ro_gui_menu_set_entry_shaded(current_menu,
+ action, true);
+ ro_gui_menu_set_entry_ticked(current_menu,
+ action, true);
break;
case BROWSER_IMAGES_BACKGROUND:
if (g)
- ro_gui_menu_set_entry_ticked(current_menu, action,
- g->option.background_images);
+ ro_gui_menu_set_entry_ticked(current_menu,
+ action, g->option.background_images);
break;
case BROWSER_BUFFER_ANIMS:
if (g) {
- ro_gui_menu_set_entry_shaded(current_menu, action,
- g->option.buffer_everything);
- ro_gui_menu_set_entry_ticked(current_menu, action,
+ ro_gui_menu_set_entry_shaded(current_menu,
+ action, g->option.buffer_everything);
+ ro_gui_menu_set_entry_ticked(current_menu,
+ action,
g->option.buffer_animations ||
g->option.buffer_everything);
}
break;
case BROWSER_BUFFER_ALL:
if (g)
- ro_gui_menu_set_entry_ticked(current_menu, action,
- g->option.buffer_everything);
+ ro_gui_menu_set_entry_ticked(current_menu,
+ action, g->option.buffer_everything);
break;
case BROWSER_WINDOW_STAGGER:
ro_gui_menu_set_entry_shaded(current_menu, action,
@@ -1881,19 +2065,23 @@ void ro_gui_menu_prepare_action(wimp_w owner, menu_action action, bool windows)
case TREE_COLLAPSE_FOLDERS:
case TREE_COLLAPSE_LINKS:
if ((tree) && (tree->root))
- ro_gui_menu_set_entry_shaded(current_menu, action,
- !tree->root->child);
+ ro_gui_menu_set_entry_shaded(current_menu,
+ action, !tree->root->child);
break;
case TREE_SELECTION:
if ((!tree) || (!tree->root))
break;
if (tree->root->child)
result = tree_has_selection(tree->root->child);
- ro_gui_menu_set_entry_shaded(current_menu, action, !result);
- if ((t) && (!t->editor) && (t->type != THEME_BROWSER_TOOLBAR)) {
- ro_gui_set_icon_shaded_state(t->toolbar_handle,
+ ro_gui_menu_set_entry_shaded(current_menu,
+ action, !result);
+ if ((t) && (!t->editor) &&
+ (t->type != THEME_BROWSER_TOOLBAR)) {
+ ro_gui_set_icon_shaded_state(
+ t->toolbar_handle,
ICON_TOOLBAR_DELETE, !result);
- ro_gui_set_icon_shaded_state(t->toolbar_handle,
+ ro_gui_set_icon_shaded_state(
+ t->toolbar_handle,
ICON_TOOLBAR_LAUNCH, !result);
}
break;
@@ -1921,7 +2109,8 @@ void ro_gui_menu_prepare_action(wimp_w owner, menu_action action, bool windows)
break;
if (tree->root->child)
result = tree_has_selection(tree->root->child);
- ro_gui_menu_set_entry_shaded(current_menu, action, !result);
+ ro_gui_menu_set_entry_shaded(current_menu,
+ action, !result);
break;
case TREE_SELECT_ALL:
ro_gui_menu_set_entry_shaded(current_menu, action,
@@ -1932,33 +2121,39 @@ void ro_gui_menu_prepare_action(wimp_w owner, menu_action action, bool windows)
break;
if (tree->root->child)
result = tree_has_selection(tree->root->child);
- ro_gui_menu_set_entry_shaded(current_menu, action, !result);
+ ro_gui_menu_set_entry_shaded(current_menu,
+ action, !result);
break;
/* toolbar actions */
case TOOLBAR_BUTTONS:
- ro_gui_menu_set_entry_shaded(current_menu, action, (!t ||
- (t->editor)));
- ro_gui_menu_set_entry_ticked(current_menu, action, (t &&
+ ro_gui_menu_set_entry_shaded(current_menu,
+ action, (!t || (t->editor)));
+ ro_gui_menu_set_entry_ticked(current_menu,
+ action, (t &&
((t->display_buttons) || (t->editor))));
break;
case TOOLBAR_ADDRESS_BAR:
- ro_gui_menu_set_entry_shaded(current_menu, action, !t);
+ ro_gui_menu_set_entry_shaded(current_menu,
+ action, !t);
ro_gui_menu_set_entry_ticked(current_menu, action,
(t && t->display_url));
break;
case TOOLBAR_THROBBER:
- ro_gui_menu_set_entry_shaded(current_menu, action, !t);
+ ro_gui_menu_set_entry_shaded(current_menu,
+ action, !t);
ro_gui_menu_set_entry_ticked(current_menu, action,
(t && t->display_throbber));
break;
case TOOLBAR_STATUS_BAR:
- ro_gui_menu_set_entry_shaded(current_menu, action, !t);
+ ro_gui_menu_set_entry_shaded(current_menu,
+ action, !t);
ro_gui_menu_set_entry_ticked(current_menu, action,
(t && t->display_status));
break;
case TOOLBAR_EDIT:
- ro_gui_menu_set_entry_shaded(current_menu, action, !t);
+ ro_gui_menu_set_entry_shaded(current_menu,
+ action, !t);
ro_gui_menu_set_entry_ticked(current_menu, action,
(t && t->editor));
break;
@@ -2053,3 +2248,79 @@ int ro_gui_menu_get_checksum(void) {
return checksum;
}
+
+/**
+ * Translate a menu's textual content into the system local encoding
+ *
+ * \param menu The menu to translate
+ * \return false if out of memory, true otherwise
+ */
+bool ro_gui_menu_translate(struct menu_definition *menu)
+{
+ os_error *error;
+ int alphabet;
+ struct menu_definition_entry *entry;
+ char *translated;
+ utf8_convert_ret err;
+
+ /* 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 (menu->current_encoding == alphabet)
+ /* menu text is already in the correct encoding */
+ return true;
+
+ /* translate root menu title text */
+ free(menu->menu->title_data.indirected_text.text);
+ err = utf8_to_local_encoding(messages_get(menu->title_key),
+ 0, &translated);
+ if (err != UTF8_CONVERT_OK) {
+ assert(err != UTF8_CONVERT_BADENC);
+ LOG(("utf8_to_enc failed"));
+ return false;
+ }
+
+ /* and fill in WIMP menu field */
+ menu->menu->title_data.indirected_text.text = translated;
+
+ /* now the menu entries */
+ for (entry = menu->entries; entry; entry = entry->next) {
+ wimp_menu *submenu = entry->menu_entry->sub_menu;
+
+ /* tranlate menu entry text */
+ free(entry->menu_entry->data.indirected_text.text);
+ err = utf8_to_local_encoding(messages_get(entry->entry_key),
+ 0, &translated);
+ if (err != UTF8_CONVERT_OK) {
+ assert(err != UTF8_CONVERT_BADENC);
+ LOG(("utf8_to_enc failed"));
+ return false;
+ }
+
+ /* fill in WIMP menu fields */
+ entry->menu_entry->data.indirected_text.text = translated;
+ entry->menu_entry->data.indirected_text.validation =
+ (char *) -1;
+ entry->menu_entry->data.indirected_text.size =
+ strlen(translated);
+
+ /* child menu title - this is the same as the text of
+ * the parent menu entry, so just copy the pointer */
+ if (submenu != wimp_NO_SUB_MENU &&
+ IS_MENU(entry->menu_entry, submenu)) {
+ submenu->title_data.indirected_text.text =
+ translated;
+ }
+ }
+
+ /* finally, set the current encoding of the menu */
+ menu->current_encoding = alphabet;
+
+ return true;
+}
diff --git a/riscos/save.c b/riscos/save.c
index 0c4f8ea0b..807b45549 100644
--- a/riscos/save.c
+++ b/riscos/save.c
@@ -37,6 +37,7 @@
#include "netsurf/utils/log.h"
#include "netsurf/utils/messages.h"
#include "netsurf/utils/url.h"
+#include "netsurf/utils/utf8.h"
#include "netsurf/utils/utils.h"
@@ -192,7 +193,8 @@ void ro_gui_save_prepare(gui_save_type save_type, struct content *c)
ro_gui_save_set_state(c, save_type, name_buf, icon_buf);
- ro_gui_set_icon_string(dialog_saveas, ICON_SAVE_ICON, icon_buf);
+ ro_gui_set_icon_sprite(dialog_saveas, ICON_SAVE_ICON, saveas_area,
+ icon_buf);
ro_gui_set_icon_string(dialog_saveas, ICON_SAVE_PATH, name_buf);
}
@@ -435,6 +437,8 @@ void ro_gui_save_drag_end(wimp_dragged *drag)
wimp_message message;
os_error *error;
char *dp, *ep;
+ char *local_name = NULL;
+ utf8_convert_ret err;
if (using_dragasprite) {
error = xdragasprite_stop();
@@ -466,8 +470,15 @@ void ro_gui_save_drag_end(wimp_dragged *drag)
return;
if (!saving_from_dialog) {
- /* saving directly from browser window, choose a name based upon the URL */
- name = save_leafname;
+ /* saving directly from browser window, choose a
+ * name based upon the URL */
+ err = utf8_to_local_encoding(save_leafname, 0, &local_name);
+ if (err != UTF8_CONVERT_OK) {
+ /* badenc should never happen */
+ assert(err != UTF8_CONVERT_BADENC);
+ local_name = NULL;
+ }
+ name = local_name ? local_name : save_leafname;
}
else {
char *dot;
@@ -502,6 +513,8 @@ void ro_gui_save_drag_end(wimp_dragged *drag)
wimp_send_message_to_window(wimp_USER_MESSAGE, &message,
pointer.w, pointer.i);
+
+ free(local_name);
}
@@ -871,6 +884,8 @@ void ro_gui_save_set_state(struct content *c, gui_save_type save_type, char *lea
url_func_result res;
bool done = false;
char *nice = NULL;
+ utf8_convert_ret err;
+ char *local_name;
/* parameters that we need to remember */
gui_save_current_type = save_type;
@@ -886,8 +901,19 @@ void ro_gui_save_set_state(struct content *c, gui_save_type save_type, char *lea
name = nice;
else
name = messages_get(name);
+
+ /* filename is utf8 */
strcpy(leaf_buf, name);
+ err = utf8_to_local_encoding(name, 0, &local_name);
+ if (err != UTF8_CONVERT_OK) {
+ /* badenc should never happen */
+ assert(err != UTF8_CONVERT_BADENC);
+ local_name = NULL;
+ }
+
+ name = local_name ? local_name : name;
+
/* sprite name used for icon and dragging */
if (save_type == GUI_SAVE_COMPLETE) {
int index;
@@ -933,6 +959,7 @@ void ro_gui_save_set_state(struct content *c, gui_save_type save_type, char *lea
}
}
+ free(local_name);
free(nice);
}
diff --git a/riscos/ucstables.c b/riscos/ucstables.c
index b744e9c6a..ef103f367 100644
--- a/riscos/ucstables.c
+++ b/riscos/ucstables.c
@@ -6,12 +6,17 @@
*/
/** \file
- * UCS conversion tables
+ * UCS conversion tables and RISC OS-specific UTF-8 text handling
*/
+#include <assert.h>
+#include <limits.h>
+#include <string.h>
#include "oslib/osbyte.h"
#include "oslib/territory.h"
+
#include "netsurf/riscos/ucstables.h"
+#include "netsurf/utils/utf8.h"
#include "netsurf/utils/utils.h"
/* Common values (ASCII) */
@@ -334,15 +339,16 @@ int *ucstable_from_alphabet(int alphabet)
return ucstable;
}
+
static const char *localencodings[] = {
"ISO-8859-1", /* BFont - 100 - just use Latin1, instead */
- "ISO-8859-1", /* do we want to use Acorn Latin1, instead? */
+ "ISO-8859-1",
"ISO-8859-2",
"ISO-8859-3",
"ISO-8859-4",
"ISO-8859-5",
"ISO-8859-6",
- "ISO-8869-7",
+ "ISO-8859-7",
"ISO-8859-8",
"ISO-8859-9",
"ISO-IR-182",
@@ -354,21 +360,272 @@ static const char *localencodings[] = {
"CP866" /* Cyrillic2 - 120 */
};
+static const struct special {
+ char local; /**< Local 8bit representation */
+ char len; /**< Length (in bytes) of UTF-8 character */
+ const char *utf; /**< UTF-8 representation */
+} special_chars[] = {
+ { 0x80, 3, "\xE2\x82\xAC" }, /* EURO SIGN */
+ { 0x81, 2, "\xC5\xB4" }, /* LATIN CAPITAL LETTER W WITH CIRCUMFLEX */
+ { 0x82, 2, "\xC5\xB5" }, /* LATIN SMALL LETTER W WITH CIRCUMFLEX */
+ { 0x84, 3, "\xE2\x9C\x98" }, /* HEAVY BALLOT X */
+ { 0x85, 2, "\xC5\xB6" }, /* LATIN CAPITAL LETTER Y WITH CIRCUMFLEX */
+ { 0x86, 2, "\xC5\xB7" }, /* LATIN SMALL LETTER Y WITH CIRCUMFLEX */
+ { 0x88, 3, "\xE2\x87\x90" }, /* LEFTWARDS DOUBLE ARROW */
+ { 0x89, 3, "\xE2\x87\x92" }, /* RIGHTWARDS DOUBLE ARROW */
+ { 0x8a, 3, "\xE2\x87\x93" }, /* DOWNWARDS DOUBLE ARROW */
+ { 0x8b, 3, "\xE2\x87\x91" }, /* UPWARDS DOUBLE ARROW */
+ { 0x8c, 3, "\xE2\x80\xA6" }, /* HORIZONTAL ELLIPSIS */
+ { 0x8d, 3, "\xE2\x84\xA2" }, /* TRADE MARK SIGN */
+ { 0x8e, 3, "\xE2\x80\xB0" }, /* PER MILLE SIGN */
+ { 0x8f, 3, "\xE2\x80\xA2" }, /* BULLET */
+ { 0x90, 3, "\xE2\x80\x98" }, /* LEFT SINGLE QUOTATION MARK */
+ { 0x91, 3, "\xE2\x80\x99" }, /* RIGHT SINGLE QUOTATION MARK */
+ { 0x92, 3, "\xE2\x80\xB9" }, /* SINGLE LEFT-POINTING ANGLE QUOTATION MARK */
+ { 0x93, 3, "\xE2\x80\xBA" }, /* SINGLE RIGHT-POINTING ANGLE QUOTATION MARK */
+ { 0x94, 3, "\xE2\x80\x9C" }, /* LEFT DOUBLE QUOTATION MARK */
+ { 0x95, 3, "\xE2\x80\x9D" }, /* RIGHT DOUBLE QUOTATION MARK */
+ { 0x96, 3, "\xE2\x80\x9E" }, /* DOUBLE LOW-9 QUOTATION MARK */
+ { 0x97, 3, "\xE2\x80\x93" }, /* EN DASH */
+ { 0x98, 3, "\xE2\x80\x94" }, /* EM DASH */
+ { 0x99, 3, "\xE2\x88\x92" }, /* MINUS SIGN */
+ { 0x9a, 2, "\xC5\x92" }, /* LATIN CAPITAL LIGATURE OE */
+ { 0x9b, 2, "\xC5\x93" }, /* LATIN SMALL LIGATURE OE */
+ { 0x9c, 3, "\xE2\x80\xA0" }, /* DAGGER */
+ { 0x9d, 3, "\xE2\x80\xA1" }, /* DOUBLE DAGGER */
+ { 0x9e, 3, "\xEF\xAC\x81" }, /* LATIN SMALL LIGATURE FI */
+ { 0x9f, 3, "\xEF\xAC\x82" } /* LATIN SMALL LIGATURE FL */
+};
+
+
/**
- * Retrieve local encoding name, suitable for passing to iconv
+ * Convert a UTF-8 encoded string into the system local encoding
+ *
+ * \param string The string to convert
+ * \param len The length (in bytes) of the string, or 0
+ * \param result Pointer to location in which to store result
+ * \return The appropriate utf8_convert_ret value
*/
-const char *local_encoding_name(void)
+utf8_convert_ret utf8_to_local_encoding(const char *string, size_t len,
+ char **result)
{
os_error *error;
- int alphabet;
+ int alphabet, i, offset_count = 0;
+ struct {
+ const struct special *local; /* local character */
+ size_t offset; /* byte offset into string */
+ } offsets[CHAR_MAX];
+ size_t off;
+ char *temp;
+ const char *enc;
+ utf8_convert_ret err;
+
+ assert(string && result);
+
+ /* get length, if necessary */
+ if (len == 0)
+ len = strlen(string);
+ /* read system alphabet */
error = xosbyte1(osbyte_ALPHABET_NUMBER, 127, 0, &alphabet);
- if (!error) {
- if (alphabet < 116)
- return localencodings[alphabet - 100];
- else if (alphabet == 120)
- return localencodings[16];
+ if (error)
+ alphabet = territory_ALPHABET_LATIN1;
+
+ /* UTF-8 -> simply copy string */
+ if (alphabet == 111 /* UTF-8 */) {
+ *result = strndup(string, len);
+ return UTF8_CONVERT_OK;
+ }
+
+ /* get encoding name */
+ enc = (alphabet < 116 ? localencodings[alphabet - 100]
+ : (alphabet == 120 ? localencodings[16]
+ : localencodings[0]));
+
+ /* populate offsets array with details of characters that
+ * will be stripped by iconv */
+ for (off = 0; off < len; off = utf8_next(string, len, off)) {
+ if (string[off] != 0xE2 &&
+ string[off] != 0xC5 && string[off] != 0xEF)
+ continue;
+
+ for (i = 0; i != NOF_ELEMENTS(special_chars); i++) {
+ if (strncmp(string + off, special_chars[i].utf,
+ special_chars[i].len) == 0) {
+ /* ensure we don't overflow our buffer */
+ assert(offset_count < CHAR_MAX - 1);
+ offsets[offset_count].local =
+ &special_chars[i];
+ offsets[offset_count].offset = off;
+ offset_count++;
+ break;
+ }
+ }
+ }
+
+ if (offset_count == 0) {
+ /* No substitutions are required, so exit here */
+ return utf8_to_enc(string, enc, len, result);
+ }
+
+ /* create output buffer */
+ *(result) = malloc(len + 1);
+ if (!(*result))
+ return UTF8_CONVERT_NOMEM;
+ *(*result) = '\0';
+
+ /* convert the chunks between offsets, then copy stripped
+ * character into output string */
+ for (i = 0; i != offset_count; i++) {
+ off = (i > 0 ? offsets[i-1].offset + offsets[i-1].local->len
+ : 0);
+
+ err = utf8_to_enc(string + off, enc,
+ offsets[i].offset - off, &temp);
+ if (err != UTF8_CONVERT_OK) {
+ assert(err != UTF8_CONVERT_BADENC);
+ free(*result);
+ return UTF8_CONVERT_NOMEM;
+ }
+
+ strcat((*result), temp);
+ off = strlen(*result);
+ (*result)[off] = offsets[i].local->local;
+ (*result)[off+1] = '\0';
+
+ free(temp);
+ }
+
+ /* handle last chunk */
+ if (offsets[offset_count - 1].offset < len) {
+ off = offsets[offset_count - 1].offset +
+ offsets[offset_count - 1].local->len;
+
+ err = utf8_to_enc(string + off, enc, len - off, &temp);
+ if (err != UTF8_CONVERT_OK) {
+ assert(err != UTF8_CONVERT_BADENC);
+ free(*result);
+ return UTF8_CONVERT_NOMEM;
+ }
+
+ strcat((*result), temp);
+
+ free(temp);
+ }
+
+ return UTF8_CONVERT_OK;
+}
+
+/**
+ * Convert a string encoded in the system local encoding to UTF-8
+ *
+ * \param string The string to convert
+ * \param len The length (in bytes) of the string, or 0
+ * \param result Pointer to location in which to store result
+ * \return The appropriate utf8_convert_ret value
+ */
+utf8_convert_ret utf8_from_local_encoding(const char *string, size_t len,
+ char **result)
+{
+ os_error *error;
+ int alphabet, i, offset_count = 0;
+ struct {
+ const struct special *local; /* utf character */
+ size_t offset; /* byte offset into string */
+ } offsets[CHAR_MAX];
+ size_t off;
+ char *temp;
+ const char *enc;
+ utf8_convert_ret err;
+
+ assert(string && result);
+
+ /* get length, if necessary */
+ if (len == 0)
+ len = strlen(string);
+
+ /* read system alphabet */
+ error = xosbyte1(osbyte_ALPHABET_NUMBER, 127, 0, &alphabet);
+ if (error)
+ alphabet = territory_ALPHABET_LATIN1;
+
+ /* UTF-8 -> simply copy string */
+ if (alphabet == 111 /* UTF-8 */) {
+ *result = strndup(string, len);
+ return UTF8_CONVERT_OK;
+ }
+
+ /* get encoding name */
+ enc = (alphabet < 116 ? localencodings[alphabet - 100]
+ : (alphabet == 120 ? localencodings[16]
+ : localencodings[0]));
+
+ /* populate offsets array with details of characters that
+ * will be stripped by iconv */
+ for (off = 0; off < len; off++) {
+ if (string[off] < 0x80 || string[off] > 0x9f)
+ continue;
+
+ for (i = 0; i != NOF_ELEMENTS(special_chars); i++) {
+ if (string[off] == special_chars[i].local) {
+ /* ensure we don't overflow our buffer */
+ assert(offset_count < CHAR_MAX - 1);
+ offsets[offset_count].local =
+ &special_chars[i];
+ offsets[offset_count].offset = off;
+ offset_count++;
+ break;
+ }
+ }
+ }
+
+ if (offset_count == 0) {
+ /* No substitutions are required, so exit here */
+ return utf8_from_enc(string, enc, len, result);
+ }
+
+ /* create output buffer (oversized, but not by much) */
+ *(result) = malloc(len + (3 * offset_count) + 1);
+ if (!(*result))
+ return UTF8_CONVERT_NOMEM;
+ *(*result) = '\0';
+
+ /* convert the chunks between offsets, then copy stripped
+ * UTF-8 character into output string */
+ for (i = 0; i != offset_count; i++) {
+ off = (i > 0 ? offsets[i-1].offset + offsets[i-1].local->len
+ : 0);
+
+ err = utf8_from_enc(string + off, enc,
+ offsets[i].offset - off, &temp);
+ if (err != UTF8_CONVERT_OK) {
+ assert(err != UTF8_CONVERT_BADENC);
+ free(*result);
+ return UTF8_CONVERT_NOMEM;
+ }
+
+ strcat((*result), temp);
+ strcat((*result), offsets[i].local->utf);
+
+ free(temp);
+ }
+
+ /* handle last chunk */
+ if (offsets[offset_count - 1].offset < len) {
+ off = offsets[offset_count - 1].offset +
+ offsets[offset_count - 1].local->len;
+
+ err = utf8_from_enc(string + off, enc, len - off, &temp);
+ if (err != UTF8_CONVERT_OK) {
+ assert(err != UTF8_CONVERT_BADENC);
+ free(*result);
+ return UTF8_CONVERT_NOMEM;
+ }
+
+ strcat((*result), temp);
+
+ free(temp);
}
- return localencodings[0];
+ return UTF8_CONVERT_OK;
}
diff --git a/riscos/wimp.c b/riscos/wimp.c
index ec12545df..8d1c641d3 100644
--- a/riscos/wimp.c
+++ b/riscos/wimp.c
@@ -25,6 +25,7 @@
#include "netsurf/riscos/gui.h"
#include "netsurf/riscos/wimp.h"
#include "netsurf/utils/log.h"
+#include "netsurf/utils/utf8.h"
#include "netsurf/utils/utils.h"
static void ro_gui_wimp_cache_furniture_sizes(wimp_w w);
@@ -205,13 +206,15 @@ char *ro_gui_get_icon_string(wimp_w w, wimp_i i) {
*
* \param w window handle
* \param i icon handle
- * \param text string (copied)
+ * \param text string (UTF-8 encoded) (copied)
*/
void ro_gui_set_icon_string(wimp_w w, wimp_i i, const char *text) {
wimp_caret caret;
wimp_icon_state ic;
os_error *error;
int old_len, len;
+ char *local_text;
+ utf8_convert_ret err;
/* get the icon data */
ic.w = w;
@@ -224,17 +227,27 @@ void ro_gui_set_icon_string(wimp_w w, wimp_i i, const char *text) {
return;
}
+ /* convert text to local encoding */
+ err = utf8_to_local_encoding(text, 0, &local_text);
+ if (err != UTF8_CONVERT_OK) {
+ /* A bad encoding should never happen, so assert this */
+ assert(err != UTF8_CONVERT_BADENC);
+ LOG(("utf8_to_enc failed"));
+ return;
+ }
+
/* check that the existing text is not the same as the updated text
* to stop flicker */
if (ic.icon.data.indirected_text.size &&
- !strncmp(ic.icon.data.indirected_text.text, text,
+ !strncmp(ic.icon.data.indirected_text.text,
+ local_text,
(unsigned int)ic.icon.data.indirected_text.size - 1))
return;
/* copy the text across */
old_len = strlen(ic.icon.data.indirected_text.text);
if (ic.icon.data.indirected_text.size) {
- strncpy(ic.icon.data.indirected_text.text, text,
+ strncpy(ic.icon.data.indirected_text.text, local_text,
(unsigned int)ic.icon.data.indirected_text.size - 1);
ic.icon.data.indirected_text.text[
ic.icon.data.indirected_text.size - 1] = '\0';
@@ -249,7 +262,7 @@ void ro_gui_set_icon_string(wimp_w w, wimp_i i, const char *text) {
return;
}
if ((caret.w == w) && (caret.i == i)) {
- len = strlen(text);
+ len = strlen(local_text);
if ((caret.index > len) || (caret.index == old_len))
caret.index = len;
error = xwimp_set_caret_position(w, i, caret.pos.x, caret.pos.y,
@@ -261,6 +274,8 @@ void ro_gui_set_icon_string(wimp_w w, wimp_i i, const char *text) {
}
}
ro_gui_redraw_icon(w, i);
+
+ free(local_text);
}
@@ -374,6 +389,45 @@ void ro_gui_set_icon_button_type(wimp_w w, wimp_i i, int type) {
/**
+ * Set an icon's sprite
+ *
+ * \param w window handle
+ * \param i icon handle
+ * \param area sprite area containing sprite
+ * \param name name of sprite in area (in local encoding)
+ */
+void ro_gui_set_icon_sprite(wimp_w w, wimp_i i, osspriteop_area *area,
+ const char *name)
+{
+ wimp_icon_state ic;
+ os_error *error;
+
+ /* get the icon data */
+ ic.w = w;
+ ic.i = i;
+ error = xwimp_get_icon_state(&ic);
+ if (error) {
+ LOG(("xwimp_get_icon_state: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ /* copy the name across */
+ if (ic.icon.data.indirected_text.size) {
+ strncpy(ic.icon.data.indirected_text.text, name,
+ (unsigned int)ic.icon.data.indirected_text.size - 1);
+ ic.icon.data.indirected_text.text[
+ ic.icon.data.indirected_text.size - 1] = '\0';
+ }
+
+ ic.icon.data.indirected_sprite.area = area;
+
+ ro_gui_redraw_icon(w, i);
+}
+
+
+/**
* Set a window title (does *not* redraw the title)
*
* \param w window handle
@@ -382,6 +436,8 @@ void ro_gui_set_icon_button_type(wimp_w w, wimp_i i, int type) {
void ro_gui_set_window_title(wimp_w w, const char *text) {
wimp_window_info_base window;
os_error *error;
+ char *title_local_enc;
+ utf8_convert_ret err;
/* Get the window details
*/
@@ -394,9 +450,19 @@ void ro_gui_set_window_title(wimp_w w, const char *text) {
return;
}
+ /* convert text to local encoding */
+ err = utf8_to_local_encoding(text, 0, &title_local_enc);
+ if (err != UTF8_CONVERT_OK) {
+ /* A bad encoding should never happen,
+ * so assert this */
+ assert(err != UTF8_CONVERT_BADENC);
+ LOG(("utf8_to_enc failed"));
+ return;
+ }
+
/* Set the title string
*/
- strncpy(window.title_data.indirected_text.text, text,
+ strncpy(window.title_data.indirected_text.text, title_local_enc,
(unsigned int)window.title_data.indirected_text.size
- 1);
window.title_data.indirected_text.text[
@@ -411,6 +477,8 @@ void ro_gui_set_window_title(wimp_w w, const char *text) {
warn_user("WimpError", error->errmess);
return;
}
+
+ free(title_local_enc);
}
diff --git a/riscos/wimp.h b/riscos/wimp.h
index b26f8dc72..cc587c39b 100644
--- a/riscos/wimp.h
+++ b/riscos/wimp.h
@@ -37,6 +37,8 @@ bool ro_gui_get_icon_selected_state(wimp_w w, wimp_i i);
void ro_gui_set_icon_shaded_state(wimp_w w, wimp_i i, bool state);
bool ro_gui_get_icon_shaded_state(wimp_w w, wimp_i i);
void ro_gui_set_icon_button_type(wimp_w w, wimp_i i, int type);
+void ro_gui_set_icon_sprite(wimp_w w, wimp_i i, osspriteop_area *area,
+ const char *name);
void ro_gui_set_window_title(wimp_w w, const char *title);
void ro_gui_set_caret_first(wimp_w w);
void ro_gui_open_window_centre(wimp_w parent, wimp_w child);
diff --git a/riscos/window.c b/riscos/window.c
index 8abc6c9ed..867382565 100644
--- a/riscos/window.c
+++ b/riscos/window.c
@@ -909,24 +909,11 @@ void gui_window_set_extent(struct gui_window *g, int width, int height)
void gui_window_set_status(struct gui_window *g, const char *text)
{
- char *local_text;
- utf8_convert_ret err;
-
if ((!g->toolbar) || (!g->toolbar->status_handle))
return;
- /* convert text to local encoding */
- err = utf8_to_enc(text, local_encoding_name(), 0, &local_text);
- if (err != UTF8_CONVERT_OK) {
- /* A bad encoding should never happen, so assert this */
- assert(err != UTF8_CONVERT_BADENC);
- LOG(("utf8_to_enc failed"));
- return;
- }
-
ro_gui_set_icon_string(g->toolbar->status_handle,
- ICON_STATUS_TEXT, local_text);
- free(local_text);
+ ICON_STATUS_TEXT, text);
}
@@ -1904,14 +1891,14 @@ bool ro_gui_window_keypress(struct gui_window *g, int key, bool toolbar)
}
return true;
- case wimp_KEY_CONTROL + wimp_KEY_SHIFT + wimp_KEY_F9:
- talloc_report_full(0, stderr);
- return true;
-
case wimp_KEY_CONTROL + wimp_KEY_F9: /* Dump url_store. */
url_store_dump();
return true;
+ case wimp_KEY_CONTROL + wimp_KEY_SHIFT + wimp_KEY_F9:
+ talloc_report_full(0, stderr);
+ return true;
+
case wimp_KEY_F11: /* Zoom */
return ro_gui_menu_handle_action(g->window,
BROWSER_SCALE_VIEW, false);