diff --git a/src/scripting/see/core.c b/src/scripting/see/core.c index 8d54750d6..947407135 100644 --- a/src/scripting/see/core.c +++ b/src/scripting/see/core.c @@ -9,12 +9,16 @@ #include "elinks.h" #include "bfu/dialog.h" +#include "config/conf.h" #include "config/home.h" +#include "config/options.h" +#include "config/opttypes.h" #include "intl/gettext/libintl.h" #include "main/module.h" #include "scripting/scripting.h" #include "scripting/see/core.h" #include "scripting/see/see.h" +#include "session/session.h" #include "util/error.h" #include "util/file.h" #include "util/string.h" @@ -23,6 +27,7 @@ #define SEE_HOOKS_FILENAME "hooks.js" struct SEE_interpreter see_interpreter; +struct session *see_ses; struct string * @@ -52,29 +57,125 @@ alert_see_error(struct session *ses, unsigned char *msg) /* The ELinks module: */ +static void +navigator_preference(struct SEE_interpreter *see, struct SEE_object *self, + struct SEE_object *thisobj, int argc, struct SEE_value **argv, + struct SEE_value *res) +{ + struct SEE_value v; + struct string opt_name; + struct option *opt; + + SEE_SET_UNDEFINED(res); + + if (argc != 1 && argc != 2) return; + + SEE_ToString(see, argv[0], &v); + if (!convert_see_string(&opt_name, v.u.string)) + return; + + opt = get_opt_rec(config_options, opt_name.source); + done_string(&opt_name); + /* FIXME: Alert? */ + if (!opt) return; + + /* Set option */ + switch (opt->type) { + case OPT_BOOL: + { + long value = opt->value.number; + + if (argc == 1) { + SEE_SET_BOOLEAN(res, value); + return; + } + + SEE_ToBoolean(see, argv[1], &v); + value = !!v.u.boolean; + opt->value.number = value; + break; + } + case OPT_INT: + case OPT_LONG: + { + long value; + + if (argc == 1) { + SEE_SET_NUMBER(res, opt->value.number); + return; + } + + SEE_ToInteger(see, argv[1], &v); + value = SEE_ToInt32(see, &v); + if (opt->min <= value && value <= opt->max) + option_types[opt->type].set(opt, (unsigned char *) (&value)); + break; + } + case OPT_STRING: + case OPT_CODEPAGE: + case OPT_LANGUAGE: + case OPT_COLOR: + { + struct string opt_value; + + if (argc == 1) { + SEE_SET_STRING(res, SEE_string_sprintf(see, opt->value.string)); + return; + } + + SEE_ToString(see, argv[1], &v); + if (!convert_see_string(&opt_value, v.u.string)) + return; + + option_types[opt->type].set(opt, opt_value.source); + done_string(&opt_value); + break; + } + default: + return; + } + + if (argc == 2) { + opt->flags |= OPT_TOUCHED; + call_change_hooks(see_ses, opt, opt); + } +} + +static void +navigator_save_preferences(struct SEE_interpreter *see, struct SEE_object *self, + struct SEE_object *thisobj, int argc, struct SEE_value **argv, + struct SEE_value *res) +{ + if (see_ses) + write_config(see_ses->tab->term); +} + static void navigator_alert(struct SEE_interpreter *see, struct SEE_object *self, struct SEE_object *thisobj, int argc, struct SEE_value **argv, struct SEE_value *res) { - struct SEE_value v; + struct SEE_value v; struct string string; + struct terminal *term; - SEE_SET_UNDEFINED(res); + SEE_SET_UNDEFINED(res); - if (!argc) return; + if (!argc) return; SEE_ToString(see, argv[0], &v); if (!convert_see_string(&string, v.u.string)) return; - if (list_empty(terminals)) { + if (!see_ses && list_empty(terminals)) { usrerror("[SEE] %s", string.source); done_string(&string); return; } - info_box(terminals.next, MSGBOX_NO_TEXT_INTL | MSGBOX_FREE_TEXT, + term = see_ses ? see_ses->tab->term : terminals.next; + + info_box(term, MSGBOX_NO_TEXT_INTL | MSGBOX_FREE_TEXT, N_("SEE Message"), ALIGN_LEFT, string.source); } @@ -124,12 +225,23 @@ init_see_environment(struct SEE_interpreter *see) name = SEE_string_sprintf(see, "appHome"); SEE_OBJECT_PUT(see, navigator, name, &value, SEE_ATTR_READONLY); - /* Create a 'write' method and attach to the browser object. */ + /* Create an 'alert' method and attach to the browser object. */ + /* FIXME: The browser object and the Global object should be identical. */ name = SEE_string_sprintf(see, "alert"); obj = SEE_cfunction_make(see, navigator_alert, name, 1); SEE_SET_OBJECT(&value, obj); SEE_OBJECT_PUT(see, navigator, name, &value, 0); SEE_OBJECT_PUT(see, see->Global, name, &value, 0); + + name = SEE_string_sprintf(see, "preference"); + obj = SEE_cfunction_make(see, navigator_preference, name, 1); + SEE_SET_OBJECT(&value, obj); + SEE_OBJECT_PUT(see, navigator, name, &value, 0); + + name = SEE_string_sprintf(see, "savePreferences"); + obj = SEE_cfunction_make(see, navigator_save_preferences, name, 1); + SEE_SET_OBJECT(&value, obj); + SEE_OBJECT_PUT(see, navigator, name, &value, 0); } static void diff --git a/src/scripting/see/core.h b/src/scripting/see/core.h index bf108e439..a3ee58b08 100644 --- a/src/scripting/see/core.h +++ b/src/scripting/see/core.h @@ -9,6 +9,7 @@ struct session; struct string; extern struct SEE_interpreter see_interpreter; +extern struct session *see_ses; struct string *convert_see_string(struct string *string, struct SEE_string *source); void alert_see_error(struct session *ses, unsigned char *msg); diff --git a/src/scripting/see/hooks.c b/src/scripting/see/hooks.c index 7ae890a72..e22c4e4af 100644 --- a/src/scripting/see/hooks.c +++ b/src/scripting/see/hooks.c @@ -21,7 +21,8 @@ * to do is explained in doc/events.txt */ static struct SEE_value * -call_see_hook(struct SEE_interpreter *see, unsigned char *name, +call_see_hook(struct SEE_interpreter *see, struct session *ses, + unsigned char *name, struct SEE_value *args[], int argc, struct SEE_value *result) { @@ -36,6 +37,8 @@ call_see_hook(struct SEE_interpreter *see, unsigned char *name, || !SEE_OBJECT_HAS_CALL(hook.u.object)) return NULL; + see_ses = ses; + SEE_TRY(see, try_context) { SEE_OBJECT_CALL(see, hook.u.object, NULL, argc, args, result); } @@ -52,18 +55,20 @@ call_see_hook(struct SEE_interpreter *see, unsigned char *name, if (init_string(&error_msg)) { convert_see_string(&error_msg, value.u.string); - alert_see_error(NULL, error_msg.source); + alert_see_error(ses, error_msg.source); done_string(&error_msg); } } if (SEE_CAUGHT(try_context2)) { - WDBG("exception thrown while printing exception"); + alert_see_error(ses, "exception thrown while printing exception"); } + see_ses = NULL; return NULL; } + see_ses = NULL; return result; } @@ -80,6 +85,7 @@ script_hook_goto_url(va_list ap, void *data) if (*url == NULL) return EVENT_HOOK_STATUS_NEXT; + see_ses = ses; SEE_SET_STRING(args[0], SEE_string_sprintf(see, "%s", *url)); if (!ses || !have_location(ses)) { @@ -89,7 +95,7 @@ script_hook_goto_url(va_list ap, void *data) SEE_string_sprintf(see, "%s", struri(cur_loc(ses)->vs.uri))); } - if (!call_see_hook(see, "goto_url", args, sizeof_array(args), &result)) + if (!call_see_hook(see, ses, "goto_url", args, sizeof_array(args), &result)) return EVENT_HOOK_STATUS_NEXT; switch (SEE_VALUE_GET_TYPE(&result)) { @@ -120,14 +126,12 @@ script_hook_follow_url(va_list ap, void *data) struct SEE_value args_[1], *args[1] = { &args_[0] }; struct SEE_value result; - evhook_use_params(url && ses); - if (*url == NULL) return EVENT_HOOK_STATUS_NEXT; SEE_SET_STRING(args[0], SEE_string_sprintf(see, "%s", *url)); - if (!call_see_hook(see, "follow_url", args, sizeof_array(args), &result)) + if (!call_see_hook(see, ses, "follow_url", args, sizeof_array(args), &result)) return EVENT_HOOK_STATUS_NEXT; switch (SEE_VALUE_GET_TYPE(&result)) { @@ -168,7 +172,7 @@ script_hook_pre_format_html(va_list ap, void *data) SEE_SET_STRING(args[0], SEE_string_sprintf(see, "%s", url)); SEE_SET_STRING(args[1], SEE_string_sprintf(see, "%s", *html)); - if (!call_see_hook(see, "pre_format_html", args, sizeof_array(args), &result)) + if (!call_see_hook(see, ses, "pre_format_html", args, sizeof_array(args), &result)) return EVENT_HOOK_STATUS_NEXT; switch (SEE_VALUE_GET_TYPE(&result)) { @@ -209,7 +213,7 @@ script_hook_get_proxy(va_list ap, void *data) SEE_SET_STRING(args[0], SEE_string_sprintf(see, "%s", url)); - if (!call_see_hook(see, "get_proxy", args, sizeof_array(args), &result)) + if (!call_see_hook(see, NULL, "get_proxy", args, sizeof_array(args), &result)) return EVENT_HOOK_STATUS_NEXT; switch (SEE_VALUE_GET_TYPE(&result)) { @@ -237,7 +241,7 @@ script_hook_quit(va_list ap, void *data) struct SEE_interpreter *see = &see_interpreter; struct SEE_value result; - call_see_hook(see, "quit", NULL, 0, &result); + call_see_hook(see, NULL, "quit", NULL, 0, &result); return EVENT_HOOK_STATUS_NEXT; }