75
77
#define UIM_CUSTOM_EXPERIMENTAL_MTIME_SENSING
80
#define MAX_LENGTH_OF_INT_AS_STR (((sizeof(int) == 4) ? sizeof("-2147483648") : sizeof("-9223372036854775808")) - sizeof((char)'\0'))
82
#define UGETTEXT(str) (dgettext(GETTEXT_PACKAGE, (str)))
84
/* we cannot use the variadic macro (i.e. __VA_ARGS__) because we
85
should also support C89 compilers
87
#define UIM_EVAL_STRING_INTERNAL(uc, sexp_str) \
88
(uim_scm_last_val = uim_scm_eval_c_string(sexp_str))
90
#define UIM_EVAL_STRING(uc, sexp_str) \
92
UIM_EVAL_STRING_INTERNAL(uc, sexp_str); \
95
#define UIM_EVAL_FSTRING1(uc, sexp_tmpl, arg1) \
99
form_size = uim_sizeof_sexp_str(sexp_tmpl, arg1); \
100
if (form_size != -1) { \
101
buf = malloc(form_size); \
102
snprintf(buf, form_size, sexp_tmpl, arg1); \
103
UIM_EVAL_STRING_INTERNAL(uc, buf); \
108
#define UIM_EVAL_FSTRING2(uc, sexp_tmpl, arg1, arg2) \
112
form_size = uim_sizeof_sexp_str(sexp_tmpl, arg1, arg2); \
113
if (form_size != -1) { \
114
buf = malloc(form_size); \
115
snprintf(buf, form_size, sexp_tmpl, arg1, arg2); \
116
UIM_EVAL_STRING_INTERNAL(uc, buf); \
121
#define UIM_EVAL_FSTRING3(uc, sexp_tmpl, arg1, arg2, arg3) \
125
form_size = uim_sizeof_sexp_str(sexp_tmpl, arg1, arg2, arg3); \
126
if (form_size != -1) { \
127
buf = malloc(form_size); \
128
snprintf(buf, form_size, sexp_tmpl, arg1, arg2, arg3); \
129
UIM_EVAL_STRING_INTERNAL(uc, buf); \
134
#define UIM_EVAL_FSTRING4(uc, sexp_tmpl, arg1, arg2, arg3, arg4) \
138
form_size = uim_sizeof_sexp_str(sexp_tmpl, arg1, arg2, arg3, arg4); \
139
if (form_size != -1) { \
140
buf = malloc(form_size); \
141
snprintf(buf, form_size, sexp_tmpl, arg1, arg2, arg3, arg4); \
142
UIM_EVAL_STRING_INTERNAL(uc, buf); \
147
#define UIM_EVAL_FSTRING5(uc, sexp_tmpl, arg1, arg2, arg3, arg4, arg5) \
151
form_size = uim_sizeof_sexp_str(sexp_tmpl, arg1, arg2, arg3, arg4, arg5); \
152
if (form_size != -1) { \
153
buf = malloc(form_size); \
154
snprintf(buf, form_size, sexp_tmpl, arg1, arg2, arg3, arg4, arg5); \
155
UIM_EVAL_STRING_INTERNAL(uc, buf); \
78
160
typedef void (*uim_custom_cb_update_cb_t)(void *ptr, const char *custom_sym);
79
161
typedef void (*uim_custom_global_cb_update_cb_t)(void *ptr);
163
typedef void *(*uim_scm_c_list_conv_func)(uim_lisp elem);
164
typedef void (*uim_scm_c_list_free_func)(void *elem);
81
166
/* exported for internal use */
82
167
uim_bool uim_custom_init(void);
83
168
uim_bool uim_custom_quit(void);
170
/* uim_scm_return_value() can only be used to retrieve result of
171
* UIM_EVAL_FSTRINGn() or UIM_EVAL_STRING(). */
172
static uim_lisp uim_scm_return_value(void);
173
static int uim_sizeof_sexp_str(const char *tmpl, ...);
175
static void **uim_scm_c_list(const char *list_repl, const char *mapper_proc,
176
uim_scm_c_list_conv_func conv_func);
177
static char *uim_scm_c_str_failsafe(uim_lisp str);
178
static char **uim_scm_c_str_list(const char *list_repl,
179
const char *mapper_proc);
180
static void uim_scm_c_list_free(void **list,
181
uim_scm_c_list_free_func free_func);
85
183
static char *literalize_string(const char *str);
184
static char *literalize_string_internal(const char *str);
87
186
static char *c_list_to_str(const void *const *list, char *(*mapper)(const void *elem), const char *sep);
89
188
static int uim_custom_type_eq(const char *custom_sym, const char *custom_type);
90
189
static int uim_custom_type(const char *custom_sym);
91
190
static int uim_custom_is_active(const char *custom_sym);
92
static char *uim_custom_get_str(const char *custom_sym, const char *proc);
191
static const char *uim_custom_get_str(const char *custom_sym,
93
193
static char *uim_custom_label(const char *custom_sym);
94
194
static char *uim_custom_desc(const char *custom_sym);
120
220
static void uim_custom_range_free(int custom_type, union uim_custom_range *custom_range);
121
221
static uim_lisp uim_custom_cb_update_cb_gate(uim_lisp cb, uim_lisp ptr, uim_lisp custom_sym);
122
222
static uim_lisp uim_custom_global_cb_update_cb_gate(uim_lisp cb, uim_lisp ptr);
223
static uim_bool custom_cb_remove(const char *key_sym, const char *hook);
123
224
static uim_bool custom_cb_add(const char *hook, const char *validator,
124
225
const char *custom_sym, void *ptr,
125
226
const char *gate_func, void (*cb)(void));
126
static uim_bool custom_cb_remove(const char *key_sym, const char *hook);
227
struct custom_cb_add_args {
229
const char *validator;
230
const char *custom_sym;
232
const char *gate_func;
235
static void *custom_cb_add_internal(struct custom_cb_add_args *args);
128
237
static void helper_disconnect_cb(void);
129
238
static char *uim_conf_path(const char *subpath);
134
243
static uim_bool uim_custom_load_group(const char *group);
135
244
static uim_bool uim_custom_save_group(const char *group);
137
#if UIM_SCM_GCC4_READY_GC
138
static char *literalize_string_internal(const char *str);
139
static uim_bool custom_cb_add_internal(const char *hook, const char *validator,
140
const char *custom_sym, void *ptr,
141
const char *gate_func, void (*cb)(void));
144
246
static const char str_list_arg[] = "uim-custom-c-str-list-arg";
145
247
static const char custom_subdir[] = "customs";
146
248
static const char custom_msg_tmpl[] = "prop_update_custom\n%s\n%s\n";
147
249
static int helper_fd = -1;
148
250
static uim_lisp return_val;
251
static uim_lisp uim_scm_last_val;
255
uim_scm_return_value(void)
257
return uim_scm_last_val;
260
/** Calculate actual sexp string size from printf-style args.
261
* This function calculates actual sexp string size from printf-style
262
* args. Format string \a sexp_tmpl only accepts %d and %s.
265
uim_sizeof_sexp_str(const char *sexp_tmpl, ...)
270
const char *sexp_tmpl_end, *escp = sexp_tmpl, *strarg;
273
va_start(ap, sexp_tmpl);
274
len = strlen(sexp_tmpl);
275
sexp_tmpl_end = sexp_tmpl + len - 1;
276
while ((escp = strchr(escp, '%'))) {
277
if (escp < sexp_tmpl_end) {
278
escp += sizeof((char)'%');
282
tmp = va_arg(ap, int);
283
len += MAX_LENGTH_OF_INT_AS_STR;
286
strarg = va_arg(ap, const char *);
287
len += strlen(strarg);
290
/* unexpected format string */
295
/* invalid format string */
300
size = len + sizeof((char)'\0');
309
- list_repl must always returns same list for each evaluation
310
- returns NULL terminated array. NULL will not appeared except terminator
311
- non-string element such as #f is converted to ""
314
uim_scm_c_list(const char *list_repl, const char *mapper_proc,
315
uim_scm_c_list_conv_func conv_func)
320
UIM_EVAL_FSTRING1(NULL, "(length %s)", list_repl);
321
list_len = uim_scm_c_int(uim_scm_return_value());
323
result = (void **)malloc(sizeof(void *) * (list_len + 1));
327
result[list_len] = NULL;
328
for (i = 0; i < list_len; i++) {
329
UIM_EVAL_FSTRING3(NULL, "(%s (nth %d %s))", mapper_proc, i, list_repl);
330
result[i] = (*conv_func)(uim_scm_return_value());
337
uim_scm_c_str_failsafe(uim_lisp str)
339
return (uim_scm_truep(str)) ? uim_scm_c_str(str) : strdup("");
343
uim_scm_c_str_list(const char *list_repl, const char *mapper_proc)
347
list = uim_scm_c_list(list_repl, mapper_proc,
348
(uim_scm_c_list_conv_func)uim_scm_c_str_failsafe);
350
return (char **)list;
354
uim_scm_c_list_free(void **list, uim_scm_c_list_free_func free_func)
362
for (p = list; *p; p++) {
152
370
literalize_string(const char *str)
153
#if UIM_SCM_GCC4_READY_GC
157
UIM_SCM_GC_PROTECTED_CALL(ret, char *, literalize_string_internal, (str));
372
return uim_scm_call_with_gc_ready_stack((uim_gc_gate_func_ptr)literalize_string_internal, (void *)str);
163
376
literalize_string_internal(const char *str)
166
#if !UIM_SCM_GCC4_READY_GC
167
uim_lisp stack_start;
172
#if !UIM_SCM_GCC4_READY_GC
173
uim_scm_gc_protect_stack(&stack_start);
176
381
form = uim_scm_list2(uim_scm_make_symbol("string-escape"),
177
382
uim_scm_make_str(str));
178
383
escaped = uim_scm_c_str(uim_scm_eval(form));
180
#if !UIM_SCM_GCC4_READY_GC
181
uim_scm_gc_unprotect_stack(&stack_start);
256
457
return uim_scm_c_bool(return_val);
260
461
uim_custom_get_str(const char *custom_sym, const char *proc)
262
463
UIM_EVAL_FSTRING2(NULL, "(%s '%s)", proc, custom_sym);
263
464
return_val = uim_scm_return_value();
266
The arg must be assigned to return_val to be proteced from GC
269
return uim_scm_c_str(return_val);
466
return uim_scm_refer_c_str(return_val);
273
470
uim_custom_label(const char *custom_sym)
275
return uim_custom_get_str(custom_sym, "custom-label");
474
str = uim_custom_get_str(custom_sym, "custom-label");
475
return strdup(UGETTEXT(str));
279
479
uim_custom_desc(const char *custom_sym)
281
return uim_custom_get_str(custom_sym, "custom-desc");
483
str = uim_custom_get_str(custom_sym, "custom-desc");
484
return strdup(UGETTEXT(str));
782
985
uim_custom_init(void)
987
const char *client_codeset;
784
989
return_val = uim_scm_f();
990
uim_scm_last_val = uim_scm_f();
786
991
uim_scm_gc_protect(&return_val);
992
uim_scm_gc_protect(&uim_scm_last_val);
788
uim_scm_init_subr_3("custom-update-cb-gate", uim_custom_cb_update_cb_gate);
789
uim_scm_init_subr_2("custom-global-update-cb-gate",
790
uim_custom_global_cb_update_cb_gate);
994
uim_scm_init_proc3("custom-update-cb-gate", uim_custom_cb_update_cb_gate);
995
uim_scm_init_proc2("custom-global-update-cb-gate",
996
uim_custom_global_cb_update_cb_gate);
792
998
uim_scm_require_file("custom.scm");
794
1000
/* temporary solution to control key definition expantion */
795
1001
UIM_EVAL_STRING(NULL, "(define uim-custom-expand-key? #t)");
1003
/* Assumes that bind_textdomain_codeset() is already called in client
1005
client_codeset = bind_textdomain_codeset(textdomain(NULL), NULL);
1006
bind_textdomain_codeset(GETTEXT_PACKAGE, client_codeset);
797
1008
return UIM_TRUE;
1461
1676
custom_cb_add(const char *hook, const char *validator,
1462
1677
const char *custom_sym, void *ptr,
1463
1678
const char *gate_func, void (*cb)(void))
1464
#if UIM_SCM_GCC4_READY_GC
1468
UIM_SCM_GC_PROTECTED_CALL(ret, uim_bool, custom_cb_add_internal,
1469
(hook, validator, custom_sym, ptr, gate_func, cb));
1680
struct custom_cb_add_args args;
1683
args.validator = validator;
1684
args.custom_sym = custom_sym;
1686
args.gate_func = gate_func;
1688
return (uim_bool)(uintptr_t)uim_scm_call_with_gc_ready_stack((uim_gc_gate_func_ptr)custom_cb_add_internal, &args);
1475
custom_cb_add_internal(const char *hook, const char *validator,
1476
const char *custom_sym, void *ptr,
1477
const char *gate_func, void (*cb)(void))
1692
custom_cb_add_internal(struct custom_cb_add_args *args)
1480
1694
uim_bool succeeded;
1481
#if !UIM_SCM_GCC4_READY_GC
1482
uim_lisp stack_start;
1696
const char *validator;
1697
const char *custom_sym;
1699
const char *gate_func;
1486
#if !UIM_SCM_GCC4_READY_GC
1487
uim_scm_gc_protect_stack(&stack_start);
1704
validator = args->validator;
1705
custom_sym = args->custom_sym;
1707
gate_func = args->gate_func;
1490
1710
form = uim_scm_list5(uim_scm_make_symbol(validator),
1491
1711
uim_scm_quote(uim_scm_make_symbol(custom_sym)),