1
0
mirror of https://github.com/rkd77/elinks.git synced 2025-01-03 14:57:44 -05:00
elinks/src/scripting/python/dialogs.c
2022-01-30 18:48:53 +01:00

243 lines
5.8 KiB
C

/* Dialog boxes for Python. */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "scripting/python/pythoninc.h"
#include "elinks.h"
#include "bfu/inpfield.h"
#include "bfu/msgbox.h"
#include "intl/libintl.h"
#include "scripting/python/core.h"
#include "scripting/python/dialogs.h"
#include "session/session.h"
#include "util/error.h"
#include "util/memlist.h"
#include "util/memory.h"
#include "util/string.h"
/* Python interface for displaying information to the user. */
char python_info_box_doc[] =
PYTHON_DOCSTRING("info_box(text[, title]) -> None\n\
\n\
Display information to the user in a dialog box.\n\
\n\
Arguments:\n\
\n\
text -- The text to be displayed in the dialog box. This argument can\n\
be a string or any object that has a string representation as\n\
returned by str(object).\n\
\n\
Optional arguments:\n\
\n\
title -- A string containing a title for the dialog box. By default\n\
the string \"Info\" is used.\n");
PyObject *
python_info_box(PyObject *self, PyObject *args, PyObject *kwargs)
{
/* [gettext_accelerator_context(python_info_box)] */
char *title = N_("Info");
PyObject *object, *string_object;
char *text;
static char s_text[] = "text";
static char s_title[] = "title";
static char *kwlist[] = {s_text, s_title, NULL};
if (!python_ses) {
PyErr_SetString(python_elinks_err, "No session");
return NULL;
}
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|s:info_box", kwlist,
&object, &title))
return NULL;
assert(object);
if_assert_failed {
PyErr_SetString(python_elinks_err, N_("Internal error"));
return NULL;
}
/*
* Get a string representation of the object, then copy that string's
* contents.
*/
string_object = PyObject_Str(object);
if (!string_object) return NULL;
text = (char *) PyUnicode_AsUTF8(string_object);
if (!text) {
Py_DECREF(string_object);
return NULL;
}
text = stracpy(text);
Py_DECREF(string_object);
if (!text) goto mem_error;
title = stracpy(title);
if (!title) goto free_text;
(void) msg_box(python_ses->tab->term, getml(title, (void *) NULL),
MSGBOX_NO_INTL | MSGBOX_SCROLLABLE | MSGBOX_FREE_TEXT,
title, ALIGN_LEFT,
text,
NULL, 1,
MSG_BOX_BUTTON(N_("~OK"), NULL, B_ENTER | B_ESC));
Py_INCREF(Py_None);
return Py_None;
free_text:
mem_free(text);
mem_error:
return PyErr_NoMemory();
}
struct python_input_callback_hop {
struct session *ses;
PyObject *callback;
};
/*
* C wrapper that invokes Python callbacks for input_dialog() OK button.
*
* This is also used indirectly for the Cancel button, with a NULL @text
* argument. See invoke_input_cancel_callback() below.
*/
static void
invoke_input_ok_callback(void *data, char *text)
{
struct python_input_callback_hop *hop = (struct python_input_callback_hop *)data;
struct session *saved_python_ses = python_ses;
PyObject *result;
assert(hop && hop->callback);
if_assert_failed return;
python_ses = hop->ses;
/* If @text is NULL, the "s" format will create a None reference. */
result = PyObject_CallFunction(hop->callback, "s", text);
if (result)
Py_DECREF(result);
else
alert_python_error();
Py_DECREF(hop->callback);
mem_free(hop);
python_ses = saved_python_ses;
}
/* C wrapper that invokes Python callbacks for input_dialog() cancel button. */
static void
invoke_input_cancel_callback(void *data)
{
invoke_input_ok_callback(data, NULL);
}
/* Python interface for getting input from the user. */
char python_input_box_doc[] =
PYTHON_DOCSTRING(
"input_box(prompt, callback, title=\"User dialog\", initial=\"\") -> None\n\
\n\
Display a dialog box to prompt for user input.\n\
\n\
Arguments:\n\
\n\
prompt -- A string containing a prompt for the dialog box.\n\
callback -- A callable object to be called after the dialog is\n\
finished. It will be called with a single argument, which\n\
will be either a string provided by the user or else None\n\
if the user canceled the dialog.\n\
\n\
Optional keyword arguments:\n\
\n\
title -- A string containing a title for the dialog box. By default\n\
the string \"User dialog\" is used.\n\
initial -- A string containing an initial value for the text entry\n\
field. By default the entry field is initially empty.\n");
PyObject *
python_input_box(PyObject *self, PyObject *args, PyObject *kwargs)
{
char *prompt;
PyObject *callback;
char *title = N_("User dialog");
char *initial = NULL;
struct python_input_callback_hop *hop;
static char s_prompt[] = "prompt";
static char s_callback[] = "callback";
static char s_title[] = "title";
static char s_initial[] = "initial";
static char *kwlist[] = {s_prompt, s_callback, s_title, s_initial, NULL};
if (!python_ses) {
PyErr_SetString(python_elinks_err, "No session");
return NULL;
}
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sO|ss:input_box",
kwlist, &prompt, &callback, &title,
&initial))
return NULL;
assert(prompt && callback && title);
if_assert_failed {
PyErr_SetString(python_elinks_err, N_("Internal error"));
return NULL;
}
prompt = stracpy(prompt);
if (!prompt) goto mem_error;
title = stracpy(title);
if (!title) goto free_prompt;
if (initial) {
initial = stracpy(initial);
if (!initial) goto free_title;
}
hop = (struct python_input_callback_hop *)mem_alloc(sizeof(*hop));
if (!hop) goto free_initial;
hop->ses = python_ses;
hop->callback = callback;
Py_INCREF(callback);
input_dialog(python_ses->tab->term,
getml(prompt, (void *) title, (void *) initial, (void *) NULL),
title, prompt,
hop, NULL,
MAX_STR_LEN, initial, 0, 0, NULL,
invoke_input_ok_callback,
invoke_input_cancel_callback);
Py_INCREF(Py_None);
return Py_None;
free_initial:
mem_free_if(initial);
free_title:
mem_free(title);
free_prompt:
mem_free(prompt);
mem_error:
return PyErr_NoMemory();
}