Bug 885: Proper charset support in xterm window title
[elinks.git] / src / scripting / python / hooks.c
blobc25eb47efd424510400efae444658dbc280e2bc6
1 /* Python scripting hooks */
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif
7 #include <Python.h>
9 #include <stdarg.h>
10 #include <string.h>
12 #include "elinks.h"
14 #include "cache/cache.h"
15 #include "main/event.h"
16 #include "protocol/uri.h"
17 #include "scripting/python/core.h"
18 #include "session/session.h"
19 #include "util/memory.h"
20 #include "util/string.h"
22 extern PyObject *python_hooks;
25 * A utility function for script_hook_url() and script_hook_get_proxy():
26 * Free a char * and replace it with the contents of a Python string.
27 * (Py_None is ignored.)
30 static PyObject *
31 replace_with_python_string(unsigned char **dest, PyObject *object)
33 unsigned char *str;
35 if (object == Py_None) return object;
37 str = (unsigned char *) PyString_AsString(object);
38 if (!str) return NULL;
40 str = stracpy(str);
41 if (!str) return PyErr_NoMemory();
43 mem_free_set(dest, str);
44 return object;
47 /* Call a Python hook for a goto-url or follow-url event. */
49 static enum evhook_status
50 script_hook_url(va_list ap, void *data)
52 unsigned char **url = va_arg(ap, unsigned char **);
53 struct session *ses = va_arg(ap, struct session *);
54 char *method = data;
55 struct session *saved_python_ses = python_ses;
56 PyObject *result;
58 evhook_use_params(url && ses);
60 if (!python_hooks || !url || !*url
61 || !PyObject_HasAttrString(python_hooks, method))
62 return EVENT_HOOK_STATUS_NEXT;
64 python_ses = ses;
66 result = PyObject_CallMethod(python_hooks, method, "s", *url);
68 if (!result || !replace_with_python_string(url, result))
69 alert_python_error();
71 Py_XDECREF(result);
73 python_ses = saved_python_ses;
75 return EVENT_HOOK_STATUS_NEXT;
78 /* Call a Python hook for a pre-format-html event. */
80 static enum evhook_status
81 script_hook_pre_format_html(va_list ap, void *data)
83 struct session *ses = va_arg(ap, struct session *);
84 struct cache_entry *cached = va_arg(ap, struct cache_entry *);
85 struct fragment *fragment = get_cache_fragment(cached);
86 unsigned char *url = struri(cached->uri);
87 char *method = "pre_format_html_hook";
88 struct session *saved_python_ses = python_ses;
89 PyObject *result;
90 int success = 0;
92 evhook_use_params(ses && cached);
94 if (!python_hooks || !cached->length || !*fragment->data
95 || !PyObject_HasAttrString(python_hooks, method))
96 return EVENT_HOOK_STATUS_NEXT;
98 python_ses = ses;
100 result = PyObject_CallMethod(python_hooks, method, "ss#", url,
101 fragment->data, fragment->length);
102 if (!result) goto error;
104 if (result != Py_None) {
105 unsigned char *str;
106 Py_ssize_t len;
108 if (PyString_AsStringAndSize(result, (char **) &str, &len) != 0)
109 goto error;
111 /* This assumes the Py_ssize_t len is not too large to
112 * fit in the off_t parameter of normalize_cache_entry().
113 * add_fragment() itself seems to assume the same thing,
114 * and there is no standard OFF_MAX macro against which
115 * ELinks could check the value. */
116 (void) add_fragment(cached, 0, str, len);
117 normalize_cache_entry(cached, len);
120 success = 1;
122 error:
123 if (!success) alert_python_error();
125 Py_XDECREF(result);
127 python_ses = saved_python_ses;
129 return EVENT_HOOK_STATUS_NEXT;
132 /* Call a Python hook for a get-proxy event. */
134 static enum evhook_status
135 script_hook_get_proxy(va_list ap, void *data)
137 unsigned char **proxy = va_arg(ap, unsigned char **);
138 unsigned char *url = va_arg(ap, unsigned char *);
139 char *method = "proxy_for_hook";
140 PyObject *result;
142 evhook_use_params(proxy && url);
144 if (!python_hooks || !proxy || !url
145 || !PyObject_HasAttrString(python_hooks, method))
146 return EVENT_HOOK_STATUS_NEXT;
148 result = PyObject_CallMethod(python_hooks, method, "s", url);
150 if (!result || !replace_with_python_string(proxy, result))
151 alert_python_error();
153 Py_XDECREF(result);
155 return EVENT_HOOK_STATUS_NEXT;
158 /* Call a Python hook for a quit event. */
160 static enum evhook_status
161 script_hook_quit(va_list ap, void *data)
163 char *method = "quit_hook";
164 PyObject *result;
166 if (!python_hooks || !PyObject_HasAttrString(python_hooks, method))
167 return EVENT_HOOK_STATUS_NEXT;
169 result = PyObject_CallMethod(python_hooks, method, NULL);
170 if (!result) alert_python_error();
172 Py_XDECREF(result);
174 return EVENT_HOOK_STATUS_NEXT;
177 struct event_hook_info python_scripting_hooks[] = {
178 { "goto-url", 0, script_hook_url, "goto_url_hook" },
179 { "follow-url", 0, script_hook_url, "follow_url_hook" },
180 { "pre-format-html", 0, script_hook_pre_format_html, NULL },
181 { "get-proxy", 0, script_hook_get_proxy, NULL },
182 { "quit", 0, script_hook_quit, NULL },
183 NULL_EVENT_HOOK_INFO,