big dialogs: dlg_format_text: no need to pass the term.
[elinks.git] / src / scripting / python / dialogs.c
blobc34826238cc62fb14a6eef5597a5e842202514bd
1 /* Dialog boxes for Python. */
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif
7 #include <Python.h>
9 #include "elinks.h"
11 #include "bfu/inpfield.h"
12 #include "bfu/msgbox.h"
13 #include "intl/gettext/libintl.h"
14 #include "scripting/python/core.h"
15 #include "session/session.h"
16 #include "util/error.h"
17 #include "util/memlist.h"
18 #include "util/memory.h"
19 #include "util/string.h"
21 /* Python interface for displaying information to the user. */
23 static char python_info_box_doc[] =
24 PYTHON_DOCSTRING("info_box(text[, title]) -> None\n\
25 \n\
26 Display information to the user in a dialog box.\n\
27 \n\
28 Arguments:\n\
29 \n\
30 text -- The text to be displayed in the dialog box. This argument can\n\
31 be a string or any object that has a string representation as\n\
32 returned by str(object).\n\
33 \n\
34 Optional arguments:\n\
35 \n\
36 title -- A string containing a title for the dialog box. By default\n\
37 the string \"Info\" is used.\n");
39 static PyObject *
40 python_info_box(PyObject *self, PyObject *args, PyObject *kwargs)
42 /* [gettext_accelerator_context(python_info_box)] */
43 unsigned char *title = N_("Info");
44 PyObject *object, *string_object;
45 unsigned char *text;
46 static char *kwlist[] = {"text", "title", NULL};
48 if (!python_ses) {
49 PyErr_SetString(python_elinks_err, "No session");
50 return NULL;
53 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|s:info_box", kwlist,
54 &object, &title))
55 return NULL;
57 assert(object);
58 if_assert_failed {
59 PyErr_SetString(python_elinks_err, N_("Internal error"));
60 return NULL;
64 * Get a string representation of the object, then copy that string's
65 * contents.
67 string_object = PyObject_Str(object);
68 if (!string_object) return NULL;
69 text = (unsigned char *) PyString_AS_STRING(string_object);
70 if (!text) {
71 Py_DECREF(string_object);
72 return NULL;
74 text = stracpy(text);
75 Py_DECREF(string_object);
76 if (!text) goto mem_error;
78 title = stracpy(title);
79 if (!title) goto free_text;
81 (void) msg_box(python_ses->tab->term, getml(title, (void *) NULL),
82 MSGBOX_NO_INTL | MSGBOX_SCROLLABLE | MSGBOX_FREE_TEXT,
83 title, ALIGN_LEFT,
84 text,
85 NULL, 1,
86 MSG_BOX_BUTTON(N_("~OK"), NULL, B_ENTER | B_ESC));
88 Py_INCREF(Py_None);
89 return Py_None;
91 free_text:
92 mem_free(text);
94 mem_error:
95 return PyErr_NoMemory();
98 struct python_input_callback_hop {
99 struct session *ses;
100 PyObject *callback;
104 * C wrapper that invokes Python callbacks for input_dialog() OK button.
106 * This is also used indirectly for the Cancel button, with a NULL @text
107 * argument. See invoke_input_cancel_callback() below.
110 static void
111 invoke_input_ok_callback(void *data, unsigned char *text)
113 struct python_input_callback_hop *hop = data;
114 struct session *saved_python_ses = python_ses;
115 PyObject *result;
117 assert(hop && hop->callback);
118 if_assert_failed return;
120 python_ses = hop->ses;
122 /* If @text is NULL, the "s" format will create a None reference. */
123 result = PyObject_CallFunction(hop->callback, "s", text);
124 if (result)
125 Py_DECREF(result);
126 else
127 alert_python_error();
129 Py_DECREF(hop->callback);
130 mem_free(hop);
132 python_ses = saved_python_ses;
135 /* C wrapper that invokes Python callbacks for input_dialog() cancel button. */
137 static void
138 invoke_input_cancel_callback(void *data)
140 invoke_input_ok_callback(data, NULL);
143 /* Python interface for getting input from the user. */
145 static char python_input_box_doc[] =
146 PYTHON_DOCSTRING(
147 "input_box(prompt, callback, title=\"User dialog\", initial=\"\") -> None\n\
149 Display a dialog box to prompt for user input.\n\
151 Arguments:\n\
153 prompt -- A string containing a prompt for the dialog box.\n\
154 callback -- A callable object to be called after the dialog is\n\
155 finished. It will be called with a single argument, which\n\
156 will be either a string provided by the user or else None\n\
157 if the user canceled the dialog.\n\
159 Optional keyword arguments:\n\
161 title -- A string containing a title for the dialog box. By default\n\
162 the string \"User dialog\" is used.\n\
163 initial -- A string containing an initial value for the text entry\n\
164 field. By default the entry field is initially empty.\n");
166 static PyObject *
167 python_input_box(PyObject *self, PyObject *args, PyObject *kwargs)
169 unsigned char *prompt;
170 PyObject *callback;
171 unsigned char *title = N_("User dialog");
172 unsigned char *initial = NULL;
173 struct python_input_callback_hop *hop;
174 static char *kwlist[] = {"prompt", "callback", "title", "initial", NULL};
176 if (!python_ses) {
177 PyErr_SetString(python_elinks_err, "No session");
178 return NULL;
181 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sO|ss:input_box",
182 kwlist, &prompt, &callback, &title,
183 &initial))
184 return NULL;
186 assert(prompt && callback && title);
187 if_assert_failed {
188 PyErr_SetString(python_elinks_err, N_("Internal error"));
189 return NULL;
192 prompt = stracpy(prompt);
193 if (!prompt) goto mem_error;
195 title = stracpy(title);
196 if (!title) goto free_prompt;
198 if (initial) {
199 initial = stracpy(initial);
200 if (!initial) goto free_title;
203 hop = mem_alloc(sizeof(*hop));
204 if (!hop) goto free_initial;
205 hop->ses = python_ses;
206 hop->callback = callback;
207 Py_INCREF(callback);
209 input_dialog(python_ses->tab->term,
210 getml(prompt, (void *) title, (void *) initial, (void *) NULL),
211 title, prompt,
212 hop, NULL,
213 MAX_STR_LEN, initial, 0, 0, NULL,
214 invoke_input_ok_callback,
215 invoke_input_cancel_callback);
217 Py_INCREF(Py_None);
218 return Py_None;
220 free_initial:
221 mem_free_if(initial);
223 free_title:
224 mem_free(title);
226 free_prompt:
227 mem_free(prompt);
229 mem_error:
230 return PyErr_NoMemory();
233 static PyMethodDef dialogs_methods[] = {
234 {"info_box", (PyCFunction) python_info_box,
235 METH_VARARGS | METH_KEYWORDS,
236 python_info_box_doc},
238 {"input_box", (PyCFunction) python_input_box,
239 METH_VARARGS | METH_KEYWORDS,
240 python_input_box_doc},
242 {NULL, NULL, 0, NULL}
246 python_init_dialogs_interface(PyObject *dict, PyObject *name)
248 return add_python_methods(dict, name, dialogs_methods);