1 /* Guile scripting hooks */
11 #include "cache/cache.h"
12 #include "main/event.h"
13 #include "protocol/uri.h"
14 #include "scripting/guile/hooks.h"
15 #include "session/session.h"
16 #include "util/string.h"
22 /* XXX: should use internal_module from core.c instead of referring to
23 * the module by name, once I figure out how... --pw */
24 return scm_c_resolve_module("elinks internal");
28 /* We need to catch and handle errors because, otherwise, Guile will kill us.
29 * Unfortunately, I do not know Guile, but this seems to work... -- Miciah */
31 error_handler(void *data
, SCM tag
, SCM throw_args
)
37 get_guile_hook_do(void *data
)
39 unsigned char *hook
= data
;
41 return scm_c_module_lookup(internal_module(), hook
);
45 get_guile_hook(unsigned char *hook
)
47 return scm_internal_catch(SCM_BOOL_T
, get_guile_hook_do
, hook
,
52 /* The events that will trigger the functions below and what they are expected
53 * to do is explained in doc/events.txt */
55 static enum evhook_status
56 script_hook_goto_url(va_list ap
, void *data
)
58 unsigned char **url
= va_arg(ap
, unsigned char **);
59 struct session
*ses
= va_arg(ap
, struct session
*);
63 evhook_use_params(url
&& ses
);
65 if (*url
== NULL
|| !*url
[0]) return EVENT_HOOK_STATUS_NEXT
;
67 proc
= get_guile_hook("%goto-url-hook");
68 if (SCM_FALSEP(proc
)) return EVENT_HOOK_STATUS_NEXT
;
70 x
= scm_call_1(SCM_VARIABLE_REF(proc
), scm_makfrom0str(*url
));
73 unsigned char *new_url
;
75 new_url
= stracpy(SCM_STRING_UCHARS(x
));
77 mem_free_set(url
, new_url
);
83 return EVENT_HOOK_STATUS_NEXT
;
86 static enum evhook_status
87 script_hook_follow_url(va_list ap
, void *data
)
89 unsigned char **url
= va_arg(ap
, unsigned char **);
90 struct session
*ses
= va_arg(ap
, struct session
*);
94 evhook_use_params(url
&& ses
);
96 if (*url
== NULL
|| !*url
[0]) return EVENT_HOOK_STATUS_NEXT
;
98 proc
= get_guile_hook("%follow-url-hook");
99 if (SCM_FALSEP(proc
)) return EVENT_HOOK_STATUS_NEXT
;
101 x
= scm_call_1(SCM_VARIABLE_REF(proc
), scm_makfrom0str(*url
));
103 if (SCM_STRINGP(x
)) {
104 unsigned char *new_url
;
106 new_url
= memacpy(SCM_STRING_UCHARS(x
),
107 SCM_STRING_LENGTH(x
) + 1);
109 mem_free_set(url
, new_url
);
115 return EVENT_HOOK_STATUS_NEXT
;
118 static enum evhook_status
119 script_hook_pre_format_html(va_list ap
, void *data
)
121 struct session
*ses
= va_arg(ap
, struct session
*);
122 struct cache_entry
*cached
= va_arg(ap
, struct cache_entry
*);
123 struct fragment
*fragment
= get_cache_fragment(cached
);
124 unsigned char *url
= struri(cached
->uri
);
129 evhook_use_params(ses
&& cached
);
131 if (!cached
->length
|| !*fragment
->data
) return EVENT_HOOK_STATUS_NEXT
;
133 proc
= get_guile_hook("%pre-format-html-hook");
134 if (SCM_FALSEP(proc
)) return EVENT_HOOK_STATUS_NEXT
;
136 x
= scm_call_2(SCM_VARIABLE_REF(proc
), scm_makfrom0str(url
),
137 scm_mem2string(fragment
->data
, fragment
->length
));
139 if (!SCM_STRINGP(x
)) return EVENT_HOOK_STATUS_NEXT
;
141 len
= SCM_STRING_LENGTH(x
);
142 add_fragment(cached
, 0, SCM_STRING_UCHARS(x
), len
);
143 normalize_cache_entry(cached
, len
);
145 return EVENT_HOOK_STATUS_NEXT
;
148 /* The Guile function can return:
149 * - "PROXY:PORT" to use the specified proxy
150 * - "" to not use any proxy
151 * - nil to use the default proxies */
152 static enum evhook_status
153 script_hook_get_proxy(va_list ap
, void *data
)
155 unsigned char **retval
= va_arg(ap
, unsigned char **);
156 unsigned char *url
= va_arg(ap
, unsigned char *);
157 SCM proc
= get_guile_hook("%get-proxy-hook");
160 if (SCM_FALSEP(proc
)) return EVENT_HOOK_STATUS_NEXT
;
162 x
= scm_call_1(SCM_VARIABLE_REF(proc
), scm_makfrom0str(url
));
164 evhook_use_params(retval
&& url
);
166 if (SCM_STRINGP(x
)) {
167 mem_free_set(retval
, memacpy(SCM_STRING_UCHARS(x
), SCM_STRING_LENGTH(x
)+1));
168 } else if (SCM_NULLP(x
)) {
169 mem_free_set(retval
, NULL
);
172 return EVENT_HOOK_STATUS_NEXT
;
175 static enum evhook_status
176 script_hook_quit(va_list ap
, void *data
)
178 SCM proc
= get_guile_hook("%quit-hook");
180 if (SCM_FALSEP(proc
)) return EVENT_HOOK_STATUS_NEXT
;
182 scm_call_0(SCM_VARIABLE_REF(proc
));
184 return EVENT_HOOK_STATUS_NEXT
;
187 struct event_hook_info guile_scripting_hooks
[] = {
188 { "goto-url", 0, script_hook_goto_url
, NULL
},
189 { "follow-url", 0, script_hook_follow_url
, NULL
},
190 { "pre-format-html", 0, script_hook_pre_format_html
, NULL
},
191 { "get-proxy", 0, script_hook_get_proxy
, NULL
},
192 { "quit", 0, script_hook_quit
, NULL
},
193 NULL_EVENT_HOOK_INFO
,