From a94ae7a80a9d96c4aa88995412ea26feafa69f3b Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Sun, 21 Jun 2015 23:24:31 +0100 Subject: Allow translation messages to be compiled in as GTK resources --- gtk/Makefile.target | 45 ++++++++++----- gtk/gui.c | 21 +++++-- gtk/res/messages.gresource.xml | 10 ++++ gtk/resources.c | 22 +++++++- utils/messages.c | 121 ++++++++++++++++++++++++++++++++++++++--- utils/messages.h | 4 +- 6 files changed, 192 insertions(+), 31 deletions(-) create mode 100644 gtk/res/messages.gresource.xml diff --git a/gtk/Makefile.target b/gtk/Makefile.target index cc8516264..fbc1ecb1a 100644 --- a/gtk/Makefile.target +++ b/gtk/Makefile.target @@ -69,6 +69,17 @@ $(eval $(call pkg_config_find_and_add,gmodule-2.0,GModule2)) CFLAGS += $(GTKCFLAGS) LDFLAGS += -lm +# --------------------------------------------------------------------------- +# Target setup +# --------------------------------------------------------------------------- + +# The gtk binary target +EXETARGET := nsgtk + +# The filter and target for split messages +MESSAGES_FILTER=gtk +MESSAGES_TARGET=gtk/res + # --------------------------------------------------------------------------- # Windows flag setup # --------------------------------------------------------------------------- @@ -84,6 +95,9 @@ endif # builtin resource sources S_RESOURCE := +# Path to GTK resources +NSGTK_RESOURCES_DIR := gtk/res + # Glib prior to 2.32 does not have GResource handling. # # This uses pkg-config to check for the minimum required version for @@ -106,16 +120,24 @@ NETSURF_FEATURE_GRESOURCE_ENABLED := yes GLIB_COMPILE_RESOURCES := glib-compile-resources CFLAGS += -DWITH_GRESOURCE -S_RESOURCE += $(OBJROOT)/netsurf_gresource.c +NETSURF_GRESOURCE_XML := $(NSGTK_RESOURCES_DIR)/netsurf.gresource.xml +MESSAGES_GRESOURCE_XML := $(NSGTK_RESOURCES_DIR)/messages.gresource.xml -NSGTK_RESOURCES_DIR := gtk/res -GRESOURCE_XML := $(NSGTK_RESOURCES_DIR)/netsurf.gresource.xml +# generate the netsurf gresource source files +$(OBJROOT)/netsurf_gresource.c: $(NETSURF_GRESOURCE_XML) $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir $(NSGTK_RESOURCES_DIR) --generate-dependencies $(NETSURF_GRESOURCE_XML)) + $(VQ)echo "GRESORCE: $<" + $(Q)$(GLIB_COMPILE_RESOURCES) --generate-source --sourcedir $(NSGTK_RESOURCES_DIR) --target=$@ $< + +S_RESOURCE += $(OBJROOT)/netsurf_gresource.c -# generate the gresource source file -$(OBJROOT)/netsurf_gresource.c: $(GRESOURCE_XML) $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir $(NSGTK_RESOURCES_DIR) --generate-dependencies $(GRESOURCE_XML)) +# generate the messages gresource source file +$(OBJROOT)/messages_gresource.c: $(MESSAGES_GRESOURCE_XML) $(addsuffix /Messages,$(addprefix $(MESSAGES_TARGET)/,$(MESSAGES_LANGUAGES))) $(VQ)echo "GRESORCE: $<" $(Q)$(GLIB_COMPILE_RESOURCES) --generate-source --sourcedir $(NSGTK_RESOURCES_DIR) --target=$@ $< +S_RESOURCE += $(OBJROOT)/messages_gresource.c + + endif endif @@ -125,7 +147,9 @@ ifneq ($(NETSURF_FEATURE_GRESOURCE_ENABLED),yes) CFLAGS += -DWITH_BUILTIN_PIXBUF -GTK_IMAGE_menu_cursor := gtk/res/menu_cursor.png +GTK_IMAGE_favicon := favicon.png +GTK_IMAGE_netsurf := netsurf.xpm +GTK_IMAGE_menu_cursor := menu_cursor.png # 1: input file # 2: output file @@ -143,7 +167,7 @@ $(2): $(1) endef -$(eval $(foreach V,$(filter GTK_IMAGE_%,$(.VARIABLES)),$(call convert_image,$($(V)),$(OBJROOT)/$(patsubst GTK_IMAGE_%,%,$(V)).c,$(patsubst GTK_IMAGE_%,%,$(V))_pixdata))) +$(eval $(foreach V,$(filter GTK_IMAGE_%,$(.VARIABLES)),$(call convert_image,$(addprefix $(NSGTK_RESOURCES_DIR)/,$($(V))),$(OBJROOT)/$(patsubst GTK_IMAGE_%,%,$(V)).c,$(patsubst GTK_IMAGE_%,%,$(V))_pixdata))) endif endif @@ -167,13 +191,6 @@ S_GTK := $(addprefix gtk/,$(S_GTK)) $(addprefix utils/,container.c) # are not yet available SOURCES = $(S_COMMON) $(S_IMAGE) $(S_BROWSER) $(S_RESOURCE) $(S_GTK) -# The gtk binary target -EXETARGET := nsgtk - -# The filter and target for split messages -MESSAGES_FILTER=gtk -MESSAGES_TARGET=gtk/res - # ---------------------------------------------------------------------------- # Install target # ---------------------------------------------------------------------------- diff --git a/gtk/gui.c b/gtk/gui.c index 15348b9af..3a41b605e 100644 --- a/gtk/gui.c +++ b/gtk/gui.c @@ -1047,13 +1047,22 @@ static struct gui_browser_table nsgtk_browser_table = { static nserror nsgtk_messages_init(char **respaths) { char *messages; - nserror ret = NSERROR_NOT_FOUND; + nserror ret; + const uint8_t *data; + size_t data_size; - /* Obtain path to messages */ - messages = filepath_find(respaths, "Messages"); - if (messages != NULL) { - ret = messages_add_from_file(messages); - free(messages); + ret = nsgtk_data_from_resname("Messages", &data, &data_size); + if (ret == NSERROR_OK) { + ret = messages_add_from_inline(data, data_size); + } else { + /* Obtain path to messages */ + messages = filepath_find(respaths, "Messages"); + if (messages != NULL) { + ret = messages_add_from_file(messages); + free(messages); + } else { + ret = NSERROR_NOT_FOUND; + } } return ret; } diff --git a/gtk/res/messages.gresource.xml b/gtk/res/messages.gresource.xml new file mode 100644 index 000000000..684a10862 --- /dev/null +++ b/gtk/res/messages.gresource.xml @@ -0,0 +1,10 @@ + + + + Messages + nl/Messages + de/Messages + fr/Messages + it/Messages + + diff --git a/gtk/resources.c b/gtk/resources.c index 1998034ff..c9f08f4b7 100644 --- a/gtk/resources.c +++ b/gtk/resources.c @@ -45,8 +45,12 @@ #ifdef WITH_BUILTIN_PIXBUF #ifdef __GNUC__ extern const guint8 menu_cursor_pixdata[] __attribute__ ((__aligned__ (4))); +const guint8 favicon_pixdata[] __attribute__ ((__aligned__ (4))); +const guint8 netsurf_pixdata[] __attribute__ ((__aligned__ (4))); #else extern const guint8 menu_cursor_pixdata[]; +const guint8 favicon_pixdata[]; +const guint8 netsurf_pixdata[]; #endif #endif @@ -119,6 +123,7 @@ static struct nsgtk_resource_s direct_resource[] = { RES_ENTRY("icons/hotlist-add.png"), RES_ENTRY("icons/hotlist-rmv.png"), RES_ENTRY("icons/search.png"), + RES_ENTRY("Messages"), { NULL, 0, NSGTK_RESOURCE_FILE, NULL }, }; @@ -129,9 +134,8 @@ GdkCursor *nsgtk_create_menu_cursor(void) GdkCursor *cursor = NULL; GdkPixbuf *pixbuf; nserror res; - const char *resname = "menu_cursor.png"; - res = nsgdk_pixbuf_new_from_resname(resname, &pixbuf); + res = nsgdk_pixbuf_new_from_resname("menu_cursor.png", &pixbuf); if (res == NSERROR_OK) { cursor = gdk_cursor_new_from_pixbuf(gdk_display_get_default(), pixbuf, 0, 3); @@ -284,6 +288,20 @@ init_pixbuf_resource(char **respath, struct nsgtk_resource_s *resource) LOG("Found builtin for %s", resource->name); return NSERROR_OK; } + + if (strncmp(resource->name, "netsurf.xpm", resource->len) == 0) { + resource->path = (char *)&netsurf_pixdata[0]; + resource->type = NSGTK_RESOURCE_INLINE; + LOG("Found builtin for %s", resource->name); + return NSERROR_OK; + } + + if (strncmp(resource->name, "favicon.png", resource->len) == 0) { + resource->path = (char *)&favicon_pixdata[0]; + resource->type = NSGTK_RESOURCE_INLINE; + LOG("Found builtin for %s", resource->name); + return NSERROR_OK; + } #endif return init_resource(respath, resource); } diff --git a/utils/messages.c b/utils/messages.c index 91b41cbc8..d652fefae 100644 --- a/utils/messages.c +++ b/utils/messages.c @@ -44,6 +44,41 @@ /** The hash table used to store the standard Messages file for the old API */ static struct hash_table *messages_hash = NULL; +/** + * process a line of input. + */ +static nserror +message_process_line(struct hash_table *hash, uint8_t *ln, int lnlen) +{ + uint8_t *value; + uint8_t *colon; + + /* empty or comment lines */ + if (ln[0] == 0 || ln[0] == '#') { + return NSERROR_OK; + } + + /* find first colon as key/value separator */ + for (colon = ln; colon < (ln + lnlen); colon++) { + if (*colon == ':') { + break; + } + } + if (colon == (ln + lnlen)) { + /* no colon found */ + return NSERROR_INVALID; + } + + *colon = 0; /* terminate key */ + value = colon + 1; + + if (hash_add(hash, (char *)ln, (char *)value) == false) { + LOG("Unable to add %s:%s to hash table", ln, value); + return NSERROR_INVALID; + } + return NSERROR_OK; +} + /** * Read keys and values from messages file. * @@ -147,19 +182,89 @@ nserror messages_add_from_file(const char *path) nserror err; if (path == NULL) { - err = NSERROR_BAD_PARAMETER; - } else { - LOG("Loading Messages from '%s'", path); - - err = messages_load_ctx(path, &messages_hash); + return NSERROR_BAD_PARAMETER; } + LOG("Loading Messages from '%s'", path); + + err = messages_load_ctx(path, &messages_hash); + + return err; } + /* exported interface documented in messages.h */ -nserror messages_add_from_inline(const char *data) +nserror messages_add_from_inline(const uint8_t *data, size_t data_size) { + z_stream strm; + int ret; + uint8_t s[512]; /* line buffer */ + size_t used = 0; /* number of bytes in buffer in use */ + uint8_t *nl; + + /* ensure the hash table is initialised */ + if (messages_hash == NULL) { + messages_hash = hash_create(HASH_SIZE); + } + if (messages_hash == NULL) { + LOG("Unable to create hash table"); + return NSERROR_NOMEM; + } + + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + + strm.next_in = (uint8_t *)data; + strm.avail_in = data_size; + + ret = inflateInit2(&strm, 32 + MAX_WBITS); + if (ret != Z_OK) { + LOG("inflateInit returned %d", ret); + return NSERROR_INVALID; + } + + do { + strm.next_out = s + used; + strm.avail_out = sizeof(s) - used; + + ret = inflate(&strm, Z_NO_FLUSH); + if ((ret != Z_OK) && (ret != Z_STREAM_END)) { + break; + } + + used = sizeof(s) - strm.avail_out; + while (used > 0) { + /* find nl */ + for (nl = &s[0]; nl < &s[used]; nl++) { + if (*nl == '\n') { + break; + } + } + if (nl == &s[used]) { + /* no nl found */ + break; + } + /* found newline */ + *nl = 0; /* null terminate line */ + message_process_line(messages_hash, &s[0], nl - &s[0]); + memmove(&s[0], nl + 1, used - ((nl + 1) - &s[0]) ); + used -= ((nl +1) - &s[0]); + } + if (used == sizeof(s)) { + /* entire buffer used and no newline */ + LOG("Overlength line"); + used = 0; + } + } while (ret != Z_STREAM_END); + + inflateEnd(&strm); + + if (ret != Z_STREAM_END) { + LOG("inflate returned %d", ret); + return NSERROR_INVALID; + } return NSERROR_OK; } @@ -181,7 +286,7 @@ char *messages_get_buff(const char *key, ...) if (buff == NULL) { LOG("malloc failed"); - warn_user("NoMemory", 0); + warn_user("NoMemory", 0); } else { va_start(ap, key); vsnprintf(buff, buff_len + 1, msg_fmt, ap); @@ -268,7 +373,7 @@ const char *messages_get_errorcode(nserror code) return messages_get_ctx("ParsingFail", messages_hash); case NSERROR_CSS: - /* CSS call returned error */ + /* CSS call returned error */ return messages_get_ctx("CSSGeneric", messages_hash); case NSERROR_CSS_BASE: diff --git a/utils/messages.h b/utils/messages.h index 4d04cd52b..ac1ea985d 100644 --- a/utils/messages.h +++ b/utils/messages.h @@ -33,6 +33,8 @@ #ifndef _NETSURF_UTILS_MESSAGES_H_ #define _NETSURF_UTILS_MESSAGES_H_ +#include + #include "utils/errors.h" /** @@ -57,7 +59,7 @@ nserror messages_add_from_file(const char *path); * \param data The inline message data. * \return NSERROR_OK on success or error code on faliure. */ -nserror messages_add_from_inline(const char *data); +nserror messages_add_from_inline(const uint8_t *data, size_t data_size); /** * Fast lookup of a message by key from the standard Messages hash. -- cgit v1.2.3