Commit 2f3ebb76 authored by Morten Welinder's avatar Morten Welinder

Function: add hidden option to turn on localized function names.

This isn't ready for prime time yet.  When turned on, function names
ought to be translated in the gui.  That, of course, requires that
translators have translated the function names.  The place to do that
is in the help text.  For example:

msgid "PRODUCT:product  of the given values"
msgstr "PRODUKT:produktet af de givne værdier"

(Does that really have two spaces?)
parent bab1a811
2013-01-09 Morten Welinder <terra@gnome.org>
* src/symbol.c: delete.
* src/func.c: rewrite to use GHashTable instead of symbol.c
(gnm_func_lookup_prefix): Take extra argument indicating whether
to search translated names. Caller changed.
* src/parse-util.c (std_func_map): Lookup translated name as
needed.
(parse_util_init): Add enviroment magic to turn on translated
functions names. This is not ready for prime time and should be
controlled by a user preference eventually.
* src/mathfunc.c (gnm_matrix_eigen): Silence warning. Document a
bit.
......
......@@ -177,7 +177,6 @@ libspreadsheet_la_SOURCES = \
style-border.c \
style-color.c \
style-conditions.c \
symbol.c \
undo.c \
validation.c \
value.c \
......@@ -309,7 +308,6 @@ libspreadsheet_include_HEADERS = \
style-color.h \
style-conditions.h \
style-font.h \
symbol.h \
undo.h \
validation.h \
validation-combo.h \
......
......@@ -21,7 +21,6 @@
#include "expr-impl.h"
#include "expr-name.h"
#include "cell.h"
#include "symbol.h"
#include "workbook-priv.h"
#include "sheet.h"
#include "value.h"
......@@ -39,13 +38,16 @@
#define F2(func,s) dgettext ((func)->textdomain->str, (s))
static GList *categories;
static SymbolTable *global_symbol_table;
static GnmFuncGroup *unknown_cat;
static GHashTable *functions_by_name;
static GHashTable *functions_by_localized_name;
void
functions_init (void)
{
global_symbol_table = symbol_table_new ();
functions_by_name = g_hash_table_new (g_str_hash, g_str_equal);
functions_by_localized_name = g_hash_table_new (g_str_hash, g_str_equal);
func_builtin_init ();
}
......@@ -64,8 +66,11 @@ functions_shutdown (void)
}
func_builtin_shutdown ();
symbol_table_destroy (global_symbol_table);
global_symbol_table = NULL;
g_hash_table_destroy (functions_by_name);
functions_by_name = NULL;
g_hash_table_destroy (functions_by_localized_name);
functions_by_localized_name = NULL;
}
inline void
......@@ -78,11 +83,7 @@ gnm_func_load_if_stub (GnmFunc *func)
static void
copy_hash_table_to_ptr_array (gpointer key, gpointer value, gpointer array)
{
Symbol *sym = value;
GnmFunc *fd = sym->data;
if (sym->type != SYMBOL_FUNCTION)
return;
GnmFunc *fd = value;
if (fd->name == NULL ||
strcmp (fd->name, "perl_adder") == 0 ||
......@@ -93,7 +94,7 @@ copy_hash_table_to_ptr_array (gpointer key, gpointer value, gpointer array)
strcmp (fd->name, "py_bitand") == 0)
return;
gnm_func_load_if_stub ((GnmFunc *) fd);
gnm_func_load_if_stub (fd);
if (fd->help != NULL)
g_ptr_array_add (array, fd);
}
......@@ -118,13 +119,10 @@ func_def_cmp (gconstpointer a, gconstpointer b)
}
static void
cb_dump_usage (gpointer key, Symbol *sym, FILE *out)
cb_dump_usage (gpointer key, GnmFunc const *fd, FILE *out)
{
if (sym != NULL) {
GnmFunc const *fd = sym->data;
if (fd != NULL && fd->usage_count > 0)
fprintf (out, "%d,%s\n", fd->usage_count, fd->name);
}
if (fd->usage_count > 0)
fprintf (out, "%d,%s\n", fd->usage_count, fd->name);
}
static char *
......@@ -242,16 +240,17 @@ function_dump_defs (char const *filename, int dump_type)
}
if (dump_type == 3) {
g_hash_table_foreach (global_symbol_table->hash,
(GHFunc) cb_dump_usage, output_file);
g_hash_table_foreach (functions_by_name,
(GHFunc) cb_dump_usage,
output_file);
fclose (output_file);
return;
}
/* TODO : Use the translated names and split by fn_group. */
ordered = g_ptr_array_new ();
g_hash_table_foreach (global_symbol_table->hash,
copy_hash_table_to_ptr_array, ordered);
g_hash_table_foreach (functions_by_name,
copy_hash_table_to_ptr_array, ordered);
if (ordered->len > 0)
qsort (&g_ptr_array_index (ordered, 0),
......@@ -750,7 +749,7 @@ gnm_func_sanity_check (void)
unsigned ui;
ordered = g_ptr_array_new ();
g_hash_table_foreach (global_symbol_table->hash,
g_hash_table_foreach (functions_by_name,
copy_hash_table_to_ptr_array, ordered);
if (ordered->len > 0)
qsort (&g_ptr_array_index (ordered, 0),
......@@ -965,7 +964,6 @@ gnm_func_load_stub (GnmFunc *func)
void
gnm_func_free (GnmFunc *func)
{
Symbol *sym;
GnmFuncGroup *group;
g_return_if_fail (func != NULL);
......@@ -983,8 +981,10 @@ gnm_func_free (GnmFunc *func)
}
if (!(func->flags & GNM_FUNC_IS_WORKBOOK_LOCAL)) {
sym = symbol_lookup (global_symbol_table, func->name);
symbol_unref (sym);
g_hash_table_remove (functions_by_name, func->name);
if (func->localized_name)
g_hash_table_remove (functions_by_localized_name,
func->localized_name);
}
if (func->fn_type == GNM_FUNC_TYPE_ARGS)
......@@ -1042,9 +1042,31 @@ gnm_func_get_type (void)
GnmFunc *
gnm_func_lookup (char const *name, Workbook *scope)
{
Symbol *sym = symbol_lookup (global_symbol_table, name);
if (sym != NULL)
return sym->data;
GnmFunc *fd = g_hash_table_lookup (functions_by_name, name);
if (fd != NULL)
return fd;
if (scope == NULL || scope->sheet_local_functions == NULL)
return NULL;
return g_hash_table_lookup (scope->sheet_local_functions, (gpointer)name);
}
GnmFunc *
gnm_func_lookup_localized (char const *name, Workbook *scope)
{
GnmFunc *fd;
GHashTableIter hiter;
gpointer value;
/* Must localize all function name. */
g_hash_table_iter_init (&hiter, functions_by_name);
while (g_hash_table_iter_next (&hiter, NULL, &value)) {
GnmFunc *fd = value;
(void)gnm_func_get_name (fd, TRUE);
}
fd = g_hash_table_lookup (functions_by_localized_name, name);
if (fd != NULL)
return fd;
if (scope == NULL || scope->sheet_local_functions == NULL)
return NULL;
return g_hash_table_lookup (scope->sheet_local_functions, (gpointer)name);
......@@ -1052,17 +1074,34 @@ gnm_func_lookup (char const *name, Workbook *scope)
/**
* gnm_func_lookup_prefix:
* @prefix:
* @prefix: prefix to search for
* @scope:
* @trans: whether to search translated function names
*
* Returns: (element-type GnmFunc*) (transfer full):
**/
GSList *
gnm_func_lookup_prefix (char const *prefix, Workbook *scope)
gnm_func_lookup_prefix (char const *prefix, Workbook *scope, gboolean trans)
{
GSList *list = symbol_names (global_symbol_table, NULL, prefix);
GSList *res = NULL;
GHashTableIter hiter;
gpointer value;
/*
* Always iterate over functions_by_name as the localized name
* might not be set yet.
*/
g_hash_table_iter_init (&hiter, functions_by_name);
while (g_hash_table_iter_next (&hiter, NULL, &value)) {
GnmFunc *fd = value;
const char *name = gnm_func_get_name (fd, trans);
if (g_str_has_prefix (name, prefix)) {
gnm_func_ref (fd);
res = g_slist_prepend (res, fd);
}
}
return list;
return res;
}
GnmFunc *
......@@ -1123,7 +1162,8 @@ gnm_func_add (GnmFuncGroup *fn_group,
if (fn_group != NULL)
gnm_func_group_add_func (fn_group, func);
if (!(func->flags & GNM_FUNC_IS_WORKBOOK_LOCAL))
symbol_install (global_symbol_table, func->name, SYMBOL_FUNCTION, func);
g_hash_table_insert (functions_by_name,
(gpointer)(func->name), func);
func->arg_names_p = function_def_create_arg_names (func);
......@@ -1168,7 +1208,9 @@ gnm_func_add_stub (GnmFuncGroup *fn_group,
func->fn_group = fn_group;
if (fn_group != NULL)
gnm_func_group_add_func (fn_group, func);
symbol_install (global_symbol_table, func->name, SYMBOL_FUNCTION, func);
g_hash_table_insert (functions_by_name,
(gpointer)(func->name), func);
return func;
}
......@@ -1264,13 +1306,17 @@ char const *
gnm_func_get_name (GnmFunc const *func, gboolean localized_function_names)
{
int i;
GnmFunc *fd = (GnmFunc *)func;
g_return_val_if_fail (func != NULL, NULL);
if (!localized_function_names)
return func->name;
gnm_func_load_if_stub ((GnmFunc *)func);
if (func->localized_name)
return func->localized_name;
gnm_func_load_if_stub (fd);
for (i = 0;
(func->localized_name == NULL &&
......@@ -1288,12 +1334,15 @@ gnm_func_get_name (GnmFunc const *func, gboolean localized_function_names)
continue;
U = split_at_colon (F2 (func, s), NULL);
((GnmFunc *)func)->localized_name = U ? g_utf8_strdown (U, -1) : NULL;
fd->localized_name = U ? g_utf8_strdown (U, -1) : NULL;
g_free (U);
}
if (!func->localized_name)
((GnmFunc *)func)->localized_name = g_strdup (func->name);
fd->localized_name = g_strdup (func->name);
g_hash_table_insert (functions_by_localized_name,
fd->localized_name, fd);
return func->localized_name;
}
......
......@@ -232,7 +232,9 @@ char const *gnm_func_get_name (GnmFunc const *fn_def,
gpointer gnm_func_get_user_data (GnmFunc const *func);
void gnm_func_set_user_data (GnmFunc *func, gpointer user_data);
GnmFunc *gnm_func_lookup (char const *name, Workbook *scope); /* change scope one day */
GSList *gnm_func_lookup_prefix (char const *prefix, Workbook *scope);
GnmFunc *gnm_func_lookup_localized (char const *name, Workbook *scope);
GSList *gnm_func_lookup_prefix (char const *prefix, Workbook *scope,
gboolean trans);
GnmFunc *gnm_func_add (GnmFuncGroup *group,
GnmFuncDescriptor const *descriptor,
const char *textdomain);
......
......@@ -1389,10 +1389,16 @@ static GnmExpr const *
std_func_map (GnmConventions const *convs, Workbook *scope,
char const *name, GnmExprList *args)
{
GnmFunc *f;
GnmFunc *f = convs->localized_function_names
? gnm_func_lookup_localized (name, scope)
: gnm_func_lookup (name, scope);
if (NULL == (f = gnm_func_lookup (name, scope)))
if (!f) {
/* Ok, great. What do we do if we are supposed to be using
localized function names? */
f = gnm_func_add_placeholder (scope, name, "", TRUE);
}
return gnm_expr_new_funcall (f, args);
}
......@@ -1527,11 +1533,14 @@ parse_util_init (void)
convs = gnm_conventions_new ();
convs->range_sep_colon = TRUE;
convs->r1c1_addresses = FALSE;
/* Not ready for general use yet. */
convs->localized_function_names = g_getenv ("GNM_LOCAL_FUNCS") != NULL;
gnm_conventions_default = convs;
convs = gnm_conventions_new ();
convs->range_sep_colon = TRUE;
convs->r1c1_addresses = TRUE;
convs->localized_function_names = gnm_conventions_default->localized_function_names;
gnm_conventions_xls_r1c1 = convs;
}
......
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Symbol management for the Gnumeric spreadsheet
*
* Author:
* Miguel de Icaza (miguel@kernel.org)
*/
#include <gnumeric-config.h>
#include "gnumeric.h"
#include "symbol.h"
#include "func.h"
#include "gutils.h"
#include <string.h>
#include <goffice/goffice.h>
/**
* symbol_lookup:
* @st: The symbol table where lookup takes place
* @str: string to be looked up in the symbol table
*/
Symbol *
symbol_lookup (SymbolTable *st, char const *str)
{
Symbol *sym;
g_return_val_if_fail (str != NULL, NULL);
g_return_val_if_fail (st != NULL, NULL);
sym = (Symbol *) g_hash_table_lookup (st->hash, str);
return sym;
}
typedef struct {
char const *prefix;
GSList *list;
} symbol_names_cb_t;
static void
symbol_names_cb (char const * key, Symbol *symbol, symbol_names_cb_t *data)
{
if (g_str_has_prefix (key, data->prefix)) {
gnm_func_ref ((GnmFunc*)symbol->data);
data->list = g_slist_prepend (data->list, symbol->data);
}
}
/**
* symbol_names:
* @st: #SymbolTable
* @list: (element-type GnmFunc*) (transfer full): list to which add new
* GnmFunc* from @st.
* @prefix: function name start.
*
* Lists functions whose name start with @prefix and add the mto the list.
* Returns: (element-type GnmFunc*) (transfer full): a list of reffed GnmFunc*.
**/
GSList *
symbol_names (SymbolTable *st, GSList *list, char const *prefix)
{
symbol_names_cb_t data;
data.list = list;
data.prefix = prefix;
g_hash_table_foreach (st->hash,
(GHFunc) symbol_names_cb,
&data);
return data.list;
}
/**
* symbol_install:
* @st: The symbol table
* @str: the string name
* @type: in which hash table we perform the lookup
* @data: information attached to the symbol
*/
Symbol *
symbol_install (SymbolTable *st, char const *str, SymbolType type, void *data)
{
Symbol *sym;
g_return_val_if_fail (str != NULL, NULL);
g_return_val_if_fail (st != NULL, NULL);
sym = (Symbol *) g_hash_table_lookup (st->hash, str);
if (sym) g_warning ("(leak) Symbol [%s] redefined.\n", str);
sym = g_new (Symbol, 1);
sym->ref_count = 1;
sym->type = type;
sym->data = data;
sym->str = g_strdup (str);
sym->st = st;
g_hash_table_replace (st->hash, sym->str, sym);
return sym;
}
/**
* symbol_ref:
* @sym: The symbol to reference
*
* Increments the reference count for the symbol
*/
void
symbol_ref (Symbol *sym)
{
g_return_if_fail (sym != NULL);
sym->ref_count++;
}
/*
* symbol_unref:
* @Sym: The symbol to remove the reference from
*
* Unreferences a symbol. If the count reaches zero, the symbol
* Is deallocated
*/
void
symbol_unref (Symbol *sym)
{
g_return_if_fail (sym != NULL);
g_return_if_fail (sym->ref_count > 0);
if (--(sym->ref_count) == 0) {
g_hash_table_remove (sym->st->hash, sym->str);
g_free (sym->str);
g_free (sym);
}
}
GType
symbol_get_type (void)
{
static GType t = 0;
if (t == 0) {
t = g_boxed_type_register_static ("Symbol",
(GBoxedCopyFunc)symbol_ref,
(GBoxedFreeFunc)symbol_unref);
}
return t;
}
SymbolTable *
symbol_table_new (void)
{
SymbolTable *st = g_new (SymbolTable, 1);
st->hash = g_hash_table_new (go_ascii_strcase_hash,
go_ascii_strcase_equal);
return st;
}
/**
* symbol_table_destroy:
* @st: The symbol table to destroy
*
* This only releases the resources associated with a SymbolTable.
* Note that the symbols on the SymbolTable are not unrefed, it is
* up to the caller to unref them.
*/
void
symbol_table_destroy (SymbolTable *st)
{
g_return_if_fail (st != NULL);
g_hash_table_destroy (st->hash);
g_free (st);
}
static SymbolTable *
symbol_table_copy (SymbolTable *st)
{
return st;
}
/* since there is only one global symbol table, there shouls be no need
* to ref/unref it for introspecion. */
GType
symbol_table_get_type (void)
{
static GType t = 0;
if (t == 0) {
t = g_boxed_type_register_static ("SymbolTable",
(GBoxedCopyFunc)symbol_table_copy,
(GBoxedFreeFunc)symbol_table_copy);
}
return t;
}
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
#ifndef _GNM_SYMBOL_H_
# define _GNM_SYMBOL_H_
G_BEGIN_DECLS
typedef enum {
SYMBOL_FUNCTION
} SymbolType;
typedef struct {
GHashTable *hash;
} SymbolTable;
typedef struct {
int ref_count;
SymbolType type;
char *str;
SymbolTable *st;
void *data;
} Symbol;
GType symbol_table_get_type (void);
SymbolTable *symbol_table_new (void);
void symbol_table_destroy (SymbolTable *st);
Symbol *symbol_lookup (SymbolTable *st, char const *str);
Symbol *symbol_install (SymbolTable *st, char const *str,
SymbolType type, void *data);
GSList *symbol_names (SymbolTable *st, GSList *list, char const *prefix);
GType symbol_get_type (void);
void symbol_ref (Symbol *sym);
void symbol_unref (Symbol *sym);
G_END_DECLS
#endif /* _GNM_SYMBOL_H_ */
......@@ -1161,7 +1161,8 @@ gee_check_tooltip (GnmExprEntry *gee)
end_t = gli->end;
prefix = g_strndup (str + start_t, end_t - start_t);
list = gnm_func_lookup_prefix
(prefix, gee->sheet->workbook);
(prefix, gee->sheet->workbook,
gee_convs (gee)->localized_function_names);
g_free (prefix);
if (list != NULL) {
list = g_slist_sort_with_data
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment