24#include "gdbsupport/intrusive_list.h"
45struct gdbpy_tui_window
50 tui_py_window *window;
53 bool is_valid ()
const;
56extern PyTypeObject gdbpy_tui_window_object_type
67 m_wrapper (
std::move (wrapper))
69 m_wrapper->window =
this;
81 m_window = std::move (user_window);
84 const char *
name ()
const override
86 return m_name.c_str ();
95 if (m_inner_window !=
nullptr)
97 wnoutrefresh (handle.get ());
98 touchwin (m_inner_window.get ());
105 void click (
int mouse_x,
int mouse_y,
int mouse_button)
override;
110 if (is_visible () && m_inner_window !=
nullptr)
112 werase (m_inner_window.get ());
119 void output (
const char *str,
bool full_window);
122 int viewport_width ()
const
124 return std::max (0, width - 2);
128 int viewport_height ()
const
130 return std::max (0, height - 2);
140 std::unique_ptr<WINDOW, curses_deleter> m_inner_window;
152gdbpy_tui_window::is_valid ()
const
157tui_py_window::~tui_py_window ()
163 if (m_window !=
nullptr
164 && PyObject_HasAttrString (m_window.get (),
"close"))
168 if (result ==
nullptr)
173 m_wrapper->window =
nullptr;
176 m_wrapper.reset (
nullptr);
177 m_window.reset (
nullptr);
181tui_py_window::rerender ()
187 int h = viewport_height ();
188 int w = viewport_width ();
189 if (h == 0 || w == 0)
193 m_inner_window.reset (
nullptr);
196 m_inner_window.reset (newwin (h, w, y + 1, x + 1));
198 if (PyObject_HasAttrString (m_window.get (),
"render"))
202 if (result ==
nullptr)
208tui_py_window::do_scroll_horizontal (
int num_to_scroll)
212 if (PyObject_HasAttrString (m_window.get (),
"hscroll"))
215 "i", num_to_scroll,
nullptr));
216 if (result ==
nullptr)
222tui_py_window::do_scroll_vertical (
int num_to_scroll)
226 if (PyObject_HasAttrString (m_window.get (),
"vscroll"))
229 "i", num_to_scroll,
nullptr));
230 if (result ==
nullptr)
236tui_py_window::click (
int mouse_x,
int mouse_y,
int mouse_button)
240 if (PyObject_HasAttrString (m_window.get (),
"click"))
243 "iii", mouse_x, mouse_y,
245 if (result ==
nullptr)
251tui_py_window::output (
const char *text,
bool full_window)
253 if (m_inner_window !=
nullptr)
256 werase (m_inner_window.get ());
258 tui_puts (text, m_inner_window.get ());
260 check_and_display_highlight_if_needed ();
271class gdbpy_tui_window_maker
272 :
public intrusive_list_node<gdbpy_tui_window_maker>
276 explicit gdbpy_tui_window_maker (
gdbpy_ref<> &&constr)
277 : m_constr (
std::move (constr))
279 m_window_maker_list.push_back (*
this);
282 ~gdbpy_tui_window_maker ();
284 gdbpy_tui_window_maker (gdbpy_tui_window_maker &&other) noexcept
285 : m_constr (std::move (other.m_constr))
287 m_window_maker_list.push_back (*
this);
290 gdbpy_tui_window_maker (
const gdbpy_tui_window_maker &other)
293 m_constr = other.m_constr;
294 m_window_maker_list.push_back (*
this);
297 gdbpy_tui_window_maker &operator= (gdbpy_tui_window_maker &&other)
299 m_constr = std::move (other.m_constr);
303 gdbpy_tui_window_maker &operator= (
const gdbpy_tui_window_maker &other)
306 m_constr = other.m_constr;
321 for (gdbpy_tui_window_maker &
f : m_window_maker_list)
331 static intrusive_list<gdbpy_tui_window_maker> m_window_maker_list;
336intrusive_list<gdbpy_tui_window_maker>
337 gdbpy_tui_window_maker::m_window_maker_list;
339gdbpy_tui_window_maker::~gdbpy_tui_window_maker ()
343 m_window_maker_list.erase (m_window_maker_list.iterator_to (*
this));
345 if (m_constr !=
nullptr)
348 m_constr.reset (
nullptr);
353gdbpy_tui_window_maker::operator() (
const char *win_name)
358 (PyObject_New (gdbpy_tui_window, &gdbpy_tui_window_object_type));
359 if (wrapper ==
nullptr)
365 std::unique_ptr<tui_py_window> window
366 (
new tui_py_window (win_name, wrapper));
374 gdb_assert (m_constr !=
nullptr);
377 (PyObject_CallFunctionObjArgs (m_constr.get (),
380 if (user_window ==
nullptr)
386 window->set_user_window (std::move (user_window));
388 return window.release ();
396 static const char *keywords[] = {
"name",
"constructor",
nullptr };
410 catch (
const gdb_exception &except)
423#define REQUIRE_WINDOW(Window) \
425 if (!(Window)->is_valid ()) \
426 return PyErr_Format (PyExc_RuntimeError, \
427 _("TUI window is invalid.")); \
432#define REQUIRE_WINDOW_FOR_SETTER(Window) \
434 if (!(Window)->is_valid ()) \
436 PyErr_Format (PyExc_RuntimeError, \
437 _("TUI window is invalid.")); \
447 gdbpy_tui_window *win = (gdbpy_tui_window *) self;
449 if (win->is_valid ())
458 gdbpy_tui_window *win = (gdbpy_tui_window *) self;
460 REQUIRE_WINDOW (win);
462 win->window->erase ();
471 gdbpy_tui_window *win = (gdbpy_tui_window *) self;
475 if (!PyArg_ParseTuple (args,
"s|i", &text, &full_window))
478 REQUIRE_WINDOW (win);
480 win->window->output (text, full_window);
487gdbpy_tui_width (
PyObject *self,
void *closure)
489 gdbpy_tui_window *win = (gdbpy_tui_window *) self;
490 REQUIRE_WINDOW (win);
493 return result.release ();
498gdbpy_tui_height (
PyObject *self,
void *closure)
500 gdbpy_tui_window *win = (gdbpy_tui_window *) self;
501 REQUIRE_WINDOW (win);
504 return result.release ();
509gdbpy_tui_title (
PyObject *self,
void *closure)
511 gdbpy_tui_window *win = (gdbpy_tui_window *) self;
512 REQUIRE_WINDOW (win);
520 gdbpy_tui_window *win = (gdbpy_tui_window *) self;
522 REQUIRE_WINDOW_FOR_SETTER (win);
524 if (newvalue ==
nullptr)
526 PyErr_Format (PyExc_TypeError, _(
"Cannot delete \"title\" attribute."));
530 gdb::unique_xmalloc_ptr<char>
value
532 if (
value ==
nullptr)
535 win->window->set_title (
value.get ());
541 {
"width", gdbpy_tui_width, NULL,
"Width of the window.", NULL },
542 {
"height", gdbpy_tui_height, NULL,
"Height of the window.", NULL },
543 {
"title", gdbpy_tui_title, gdbpy_tui_set_title,
"Title of the window.",
548static PyMethodDef tui_object_methods[] =
550 {
"is_valid", gdbpy_tui_is_valid, METH_NOARGS,
551 "is_valid () -> Boolean\n\
552Return true if this TUI window is valid, false if not." },
553 {
"erase", gdbpy_tui_erase, METH_NOARGS,
554 "Erase the TUI window." },
555 {
"write", (PyCFunction) gdbpy_tui_write, METH_VARARGS,
556 "Append a string to the TUI window." },
560PyTypeObject gdbpy_tui_window_object_type =
562 PyVarObject_HEAD_INIT (NULL, 0)
564 sizeof (gdbpy_tui_window),
581 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
582 "GDB TUI window object",
609 gdbpy_tui_window_object_type.tp_new = PyType_GenericNew;
610 if (PyType_Ready (&gdbpy_tui_window_object_type) < 0)
623 gdbpy_tui_window_maker::invalidate_all ();
gdb::ref_ptr< T, gdbpy_ref_policy< T > > gdbpy_ref
static void gdbpy_finalize_tui()
static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION gdbpy_initialize_tui()
gdbpy_ref host_string_to_python_string(const char *str)
gdbpy_ref gdb_py_object_from_longest(LONGEST l)
void gdbpy_convert_exception(const struct gdb_exception &exception)
gdb::unique_xmalloc_ptr< char > python_string_to_host_string(PyObject *obj)
void gdbpy_print_stack(void)
#define PyObject_CallMethod
PyObject * gdbpy_register_tui_window(PyObject *self, PyObject *args, PyObject *kw)
#define CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF(ARG)
#define CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
#define GDBPY_INITIALIZE_FILE(INIT,...)
static int gdb_PyArg_ParseTupleAndKeywords(PyObject *args, PyObject *kw, const char *format, const char **keywords,...)
void check_and_display_highlight_if_needed()
DISABLE_COPY_AND_ASSIGN(tui_win_info)
virtual void do_scroll_horizontal(int num_to_scroll)=0
virtual const char * name() const =0
virtual void click(int mouse_x, int mouse_y, int mouse_button)
virtual void do_scroll_vertical(int num_to_scroll)=0
virtual void refresh_window()
void tui_puts(const char *string, WINDOW *w)
void tui_register_window(const char *name, window_factory &&factory)
void tui_wrefresh(WINDOW *win)