Cast to (const char *) in strrchr calls
[elinks.git] / src / scripting / guile / hooks.c
blob5e7a4ac9f1cbe7f2a35880c523fd82443f26dcf9
1 /* Guile scripting hooks */
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif
7 #include <libguile.h>
9 #include "elinks.h"
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"
19 static SCM
20 internal_module(void)
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 */
30 static SCM
31 error_handler(void *data, SCM tag, SCM throw_args)
33 return SCM_BOOL_F;
36 static SCM
37 get_guile_hook_do(void *data)
39 unsigned char *hook = data;
41 return scm_c_module_lookup(internal_module(), hook);
44 static SCM
45 get_guile_hook(unsigned char *hook)
47 return scm_internal_catch(SCM_BOOL_T, get_guile_hook_do, hook,
48 error_handler, NULL);
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 *);
60 SCM proc;
61 SCM x;
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));
72 if (SCM_STRINGP(x)) {
73 unsigned char *new_url;
75 new_url = stracpy(SCM_STRING_UCHARS(x));
76 if (new_url) {
77 mem_free_set(url, new_url);
79 } else {
80 (*url)[0] = 0;
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 *);
91 SCM proc;
92 SCM x;
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);
108 if (new_url) {
109 mem_free_set(url, new_url);
111 } else {
112 (*url)[0] = 0;
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);
125 int len;
126 SCM proc;
127 SCM x;
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");
158 SCM x;
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,