mirror of
https://github.com/idapython/src
synced 2026-06-08 14:47:00 +00:00
887 lines
21 KiB
C++
887 lines
21 KiB
C++
#ifndef __PYWRAPS_CUSTVIEWER__
|
|
#define __PYWRAPS_CUSTVIEWER__
|
|
//<code(py_kernwin_custview)>
|
|
//---------------------------------------------------------------------------
|
|
class cvdata_simpleline_t
|
|
{
|
|
strvec_t lines;
|
|
simpleline_place_t pl_min, pl_max;
|
|
|
|
public:
|
|
void *get_ud() { return &lines; }
|
|
place_t *get_min() { return &pl_min; }
|
|
place_t *get_max() { return &pl_max; }
|
|
strvec_t &get_lines() { return lines; }
|
|
|
|
void clear()
|
|
{
|
|
lines.clear();
|
|
set_minmax();
|
|
}
|
|
|
|
void set_minmax(size_t start=0, size_t end=size_t(-1))
|
|
{
|
|
if ( start == 0 && end == size_t(-1) )
|
|
{
|
|
end = lines.size();
|
|
pl_min.n = 0;
|
|
pl_max.n = end == 0 ? 0 : end - 1;
|
|
}
|
|
else
|
|
{
|
|
pl_min.n = start;
|
|
pl_max.n = end;
|
|
}
|
|
}
|
|
|
|
bool set_line(size_t nline, simpleline_t &sl)
|
|
{
|
|
if ( nline >= lines.size() )
|
|
return false;
|
|
lines[nline] = sl;
|
|
return true;
|
|
}
|
|
|
|
bool del_line(size_t nline)
|
|
{
|
|
if ( nline >= lines.size() )
|
|
return false;
|
|
lines.erase(lines.begin()+nline);
|
|
return true;
|
|
}
|
|
|
|
void add_line(simpleline_t &line)
|
|
{
|
|
lines.push_back(line);
|
|
}
|
|
|
|
void add_line(const char *str)
|
|
{
|
|
lines.push_back(simpleline_t(str));
|
|
}
|
|
|
|
bool insert_line(size_t nline, simpleline_t &line)
|
|
{
|
|
if ( nline >= lines.size() )
|
|
return false;
|
|
lines.insert(lines.begin()+nline, line);
|
|
return true;
|
|
}
|
|
|
|
bool patch_line(size_t nline, size_t offs, int value)
|
|
{
|
|
if ( nline >= lines.size() )
|
|
return false;
|
|
qstring &L = lines[nline].line;
|
|
L[offs] = (uchar) value & 0xFF;
|
|
return true;
|
|
}
|
|
|
|
size_t to_lineno(place_t *pl) const
|
|
{
|
|
return ((simpleline_place_t *)pl)->n;
|
|
}
|
|
|
|
simpleline_t *get_line(size_t nline)
|
|
{
|
|
return nline >= lines.size() ? nullptr : &lines[nline];
|
|
}
|
|
|
|
simpleline_t *get_line(place_t *pl)
|
|
{
|
|
return pl == nullptr ? nullptr : get_line(((simpleline_place_t *)pl)->n);
|
|
}
|
|
|
|
size_t count() const
|
|
{
|
|
return lines.size();
|
|
}
|
|
|
|
void clear_lines()
|
|
{
|
|
lines.clear();
|
|
set_minmax();
|
|
}
|
|
};
|
|
|
|
//---------------------------------------------------------------------------
|
|
// FIXME: This should inherit py_view_base.hpp's py_customidamemo_t,
|
|
// just like py_graph.hpp's py_graph_t does.
|
|
// There should be a way to "merge" the two mechanisms; they are similar.
|
|
class py_simplecustview_t
|
|
{
|
|
qstring title;
|
|
TWidget *widget;
|
|
custom_viewer_handlers_t handlers;
|
|
|
|
cvdata_simpleline_t data;
|
|
PyObject *py_self;
|
|
PyObject *py_this;
|
|
PyObject *py_last_link;
|
|
|
|
int features;
|
|
|
|
enum
|
|
{
|
|
HAVE_HINT = 0x0001,
|
|
HAVE_KEYDOWN = 0x0002,
|
|
HAVE_DBLCLICK = 0x0004,
|
|
HAVE_CURPOS = 0x0008,
|
|
HAVE_CLICK = 0x0010,
|
|
HAVE_CLOSE = 0x0020
|
|
};
|
|
|
|
static bool idaapi s_cv_keydown(
|
|
TWidget * /*cv*/,
|
|
int vk_key,
|
|
int shift,
|
|
void *ud)
|
|
{
|
|
PYW_GIL_GET;
|
|
py_simplecustview_t *_this = (py_simplecustview_t *)ud;
|
|
return _this->on_keydown(vk_key, shift);
|
|
}
|
|
|
|
// The user clicked
|
|
static bool idaapi s_cv_click(TWidget * /*cv*/, int shift, void *ud)
|
|
{
|
|
PYW_GIL_GET;
|
|
py_simplecustview_t *_this = (py_simplecustview_t *)ud;
|
|
return _this->on_click(shift);
|
|
}
|
|
|
|
// The user double clicked
|
|
static bool idaapi s_cv_dblclick(TWidget * /*cv*/, int shift, void *ud)
|
|
{
|
|
PYW_GIL_GET;
|
|
py_simplecustview_t *_this = (py_simplecustview_t *)ud;
|
|
return _this->on_dblclick(shift);
|
|
}
|
|
|
|
// Cursor position has been changed
|
|
static void idaapi s_cv_curpos(TWidget * /*cv*/, void *ud)
|
|
{
|
|
PYW_GIL_GET;
|
|
py_simplecustview_t *_this = (py_simplecustview_t *)ud;
|
|
_this->on_curpos_changed();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
static ssize_t idaapi s_ui_cb(void *ud, int code, va_list va)
|
|
{
|
|
// This hook gets called from the kernel. Ensure we hold the GIL.
|
|
PYW_GIL_GET;
|
|
py_simplecustview_t *_this = (py_simplecustview_t *)ud;
|
|
switch ( code )
|
|
{
|
|
case ui_get_custom_viewer_hint:
|
|
{
|
|
if ( (_this->features & HAVE_HINT) == 0 )
|
|
return 0;
|
|
qstring &hint = *va_arg(va, qstring *);
|
|
TWidget *viewer = va_arg(va, TWidget *);
|
|
if ( _this->widget != viewer )
|
|
return 0;
|
|
place_t *place = va_arg(va, place_t *);
|
|
if ( place == nullptr )
|
|
return 0;
|
|
int *important_lines = va_arg(va, int *);
|
|
return _this->on_hint(place, important_lines, hint) ? 1 : 0;
|
|
}
|
|
|
|
case ui_widget_invisible:
|
|
{
|
|
TWidget *widget = va_arg(va, TWidget *);
|
|
if ( _this->widget != widget )
|
|
break;
|
|
}
|
|
// fallthrough...
|
|
case ui_database_closed:
|
|
idapython_unhook_from_notification_point(HT_UI, s_ui_cb, _this);
|
|
_this->on_close();
|
|
_this->init_vars();
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
static bool get_color(uint32 *out, ref_t obj)
|
|
{
|
|
bool ok = PyLong_Check(obj.o) != 0;
|
|
if ( ok )
|
|
{
|
|
*out = uint32(PyLong_AsUnsignedLong(obj.o));
|
|
}
|
|
else
|
|
{
|
|
ok = PyLong_Check(obj.o) != 0;
|
|
if ( ok )
|
|
*out = uint32(PyLong_AsLong(obj.o));
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Convert a tuple (String, [color, [bgcolor]]) to a simpleline_t
|
|
static bool py_to_simpleline(PyObject *py, simpleline_t &sl)
|
|
{
|
|
PYW_GIL_CHECK_LOCKED_SCOPE();
|
|
|
|
if ( PyUnicode_Check(py) )
|
|
{
|
|
PyUnicode_as_qstring(&sl.line, py);
|
|
return true;
|
|
}
|
|
Py_ssize_t sz;
|
|
if ( !PyTuple_Check(py) || (sz = PyTuple_Size(py)) <= 0 )
|
|
return false;
|
|
|
|
PyObject *py_val = PyTuple_GetItem(py, 0);
|
|
if ( !PyUnicode_Check(py_val) )
|
|
return false;
|
|
|
|
PyUnicode_as_qstring(&sl.line, py_val);
|
|
uint32 col;
|
|
if ( sz > 1 && get_color(&col, borref_t(PyTuple_GetItem(py, 1))) )
|
|
sl.color = color_t(col);
|
|
if ( sz > 2 && get_color(&col, borref_t(PyTuple_GetItem(py, 2))) )
|
|
sl.bgcolor = bgcolor_t(col);
|
|
return true;
|
|
}
|
|
|
|
//
|
|
// Callbacks
|
|
//
|
|
bool on_click(int shift)
|
|
{
|
|
PYW_GIL_CHECK_LOCKED_SCOPE();
|
|
newref_t py_result(PyObject_CallMethod(py_self, (char *)S_ON_CLICK, "i", shift));
|
|
PyW_ShowCbErr(S_ON_CLICK);
|
|
return py_result != nullptr && PyObject_IsTrue(py_result.o);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// OnDblClick
|
|
bool on_dblclick(int shift)
|
|
{
|
|
PYW_GIL_CHECK_LOCKED_SCOPE();
|
|
newref_t py_result(PyObject_CallMethod(py_self, (char *)S_ON_DBL_CLICK, "i", shift));
|
|
PyW_ShowCbErr(S_ON_DBL_CLICK);
|
|
return py_result != nullptr && PyObject_IsTrue(py_result.o);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// OnCurorPositionChanged
|
|
void on_curpos_changed()
|
|
{
|
|
PYW_GIL_CHECK_LOCKED_SCOPE();
|
|
newref_t py_result(PyObject_CallMethod(py_self, (char *)S_ON_CURSOR_POS_CHANGED, nullptr));
|
|
PyW_ShowCbErr(S_ON_CURSOR_POS_CHANGED);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
void on_close()
|
|
{
|
|
if ( py_self != nullptr )
|
|
{
|
|
// Call the close method if it is there and the object is still bound
|
|
if ( (features & HAVE_CLOSE) != 0 )
|
|
{
|
|
PYW_GIL_CHECK_LOCKED_SCOPE();
|
|
newref_t py_result(PyObject_CallMethod(py_self, (char *)S_ON_CLOSE, nullptr));
|
|
PyW_ShowCbErr(S_ON_CLOSE);
|
|
}
|
|
|
|
// Cleanup
|
|
Py_DECREF(py_self);
|
|
py_self = nullptr;
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
bool on_keydown(int vk_key, int shift)
|
|
{
|
|
PYW_GIL_CHECK_LOCKED_SCOPE();
|
|
newref_t py_result(
|
|
PyObject_CallMethod(
|
|
py_self,
|
|
(char *)S_ON_KEYDOWN,
|
|
"ii",
|
|
vk_key,
|
|
shift));
|
|
|
|
PyW_ShowCbErr(S_ON_KEYDOWN);
|
|
return py_result && PyObject_IsTrue(py_result.o);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
bool on_hint(place_t *place, int *important_lines, qstring &hint)
|
|
{
|
|
size_t ln = data.to_lineno(place);
|
|
PYW_GIL_CHECK_LOCKED_SCOPE();
|
|
newref_t py_result(
|
|
PyObject_CallMethod(
|
|
py_self,
|
|
(char *)S_ON_HINT,
|
|
PY_BV_SZ,
|
|
bvsz_t(ln)));
|
|
|
|
PyW_ShowCbErr(S_ON_HINT);
|
|
bool ok = py_result
|
|
&& PyTuple_Check(py_result.o)
|
|
&& PyTuple_Size(py_result.o) == 2;
|
|
if ( ok )
|
|
{
|
|
if ( important_lines != nullptr )
|
|
*important_lines = PyInt_AsLong(PyTuple_GetItem(py_result.o, 0));
|
|
PyUnicode_as_qstring(&hint, PyTuple_GetItem(py_result.o, 1));
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
bool on_popup_menu(size_t menu_id)
|
|
{
|
|
PYW_GIL_CHECK_LOCKED_SCOPE();
|
|
newref_t py_result(
|
|
PyObject_CallMethod(
|
|
py_self,
|
|
(char *)S_ON_POPUP_MENU,
|
|
PY_BV_SZ,
|
|
bvsz_t(menu_id)));
|
|
PyW_ShowCbErr(S_ON_POPUP_MENU);
|
|
return py_result && PyObject_IsTrue(py_result.o);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
void refresh_range()
|
|
{
|
|
data.set_minmax();
|
|
set_range();
|
|
}
|
|
|
|
public:
|
|
py_simplecustview_t()
|
|
{
|
|
py_this = py_self = py_last_link = nullptr;
|
|
init_vars();
|
|
}
|
|
~py_simplecustview_t() {}
|
|
|
|
TWidget *get_widget() { return widget; }
|
|
|
|
void init_vars()
|
|
{
|
|
data.clear();
|
|
features = 0;
|
|
widget = nullptr;
|
|
}
|
|
|
|
void close()
|
|
{
|
|
if ( widget != nullptr )
|
|
close_widget(widget, WCLS_SAVE | WCLS_CLOSE_LATER);
|
|
}
|
|
|
|
bool set_range(
|
|
const place_t *minplace = nullptr,
|
|
const place_t *maxplace = nullptr)
|
|
{
|
|
if ( widget == nullptr )
|
|
return false;
|
|
|
|
set_custom_viewer_range(
|
|
widget,
|
|
minplace == nullptr ? data.get_min() : minplace,
|
|
maxplace == nullptr ? data.get_max() : maxplace);
|
|
return true;
|
|
}
|
|
|
|
place_t *get_place(
|
|
bool mouse = false,
|
|
int *x = 0,
|
|
int *y = 0)
|
|
{
|
|
return widget == nullptr ? nullptr : get_custom_viewer_place(widget, mouse, x, y);
|
|
}
|
|
|
|
bool refresh()
|
|
{
|
|
if ( widget == nullptr )
|
|
return false;
|
|
|
|
refresh_custom_viewer(widget);
|
|
return true;
|
|
}
|
|
|
|
bool get_current_word(bool mouse, qstring &word)
|
|
{
|
|
// query the cursor position
|
|
int x, y;
|
|
if ( get_place(mouse, &x, &y) == nullptr )
|
|
return false;
|
|
|
|
// query the line at the cursor
|
|
qstring qline;
|
|
get_current_line(&qline, mouse, true);
|
|
const char *line = qline.begin();
|
|
if ( line == nullptr )
|
|
return false;
|
|
|
|
if ( x >= (int)qstrlen(line) )
|
|
return false;
|
|
|
|
// find the beginning of the word
|
|
const char *ptr = line + x;
|
|
while ( ptr > line && !qisspace(ptr[-1]) )
|
|
ptr--;
|
|
|
|
// find the end of the word
|
|
const char *begin = ptr;
|
|
ptr = line + x;
|
|
while ( !qisspace(*ptr) && *ptr != '\0' )
|
|
ptr++;
|
|
|
|
word.qclear();
|
|
word.append(begin, ptr-begin);
|
|
return true;
|
|
}
|
|
|
|
void get_current_line(qstring *out, bool mouse, bool notags)
|
|
{
|
|
*out = get_custom_viewer_curline(widget, mouse);
|
|
if ( notags )
|
|
tag_remove(out);
|
|
}
|
|
|
|
bool is_focused()
|
|
{
|
|
return get_current_viewer() == widget;
|
|
}
|
|
|
|
bool create(const char *_title, int _features)
|
|
{
|
|
// Already created? (in the instance)
|
|
if ( widget != nullptr )
|
|
return true;
|
|
|
|
// Already created? (in IDA windows list)
|
|
TWidget *found = find_widget(_title);
|
|
if ( found != nullptr )
|
|
return false;
|
|
|
|
title = _title;
|
|
features = _features;
|
|
|
|
//
|
|
// Prepare handlers
|
|
//
|
|
if ( (features & HAVE_KEYDOWN) != 0 )
|
|
handlers.keyboard = s_cv_keydown;
|
|
|
|
if ( (features & HAVE_CLICK) != 0 )
|
|
handlers.click = s_cv_click;
|
|
|
|
if ( (features & HAVE_DBLCLICK) != 0 )
|
|
handlers.dblclick = s_cv_dblclick;
|
|
|
|
if ( (features & HAVE_CURPOS) != 0 )
|
|
handlers.curpos = s_cv_curpos;
|
|
|
|
// Create the viewer
|
|
widget = create_custom_viewer(
|
|
title.c_str(),
|
|
data.get_min(),
|
|
data.get_max(),
|
|
data.get_min(),
|
|
(const renderer_info_t *) nullptr,
|
|
data.get_ud(),
|
|
&handlers,
|
|
this);
|
|
|
|
// Hook to UI notifications (for TWidget close event)
|
|
idapython_hook_to_notification_point(HT_UI, s_ui_cb, this, /*is_hooks_base=*/ false);
|
|
|
|
return true;
|
|
}
|
|
|
|
// Edits an existing line
|
|
bool edit_line(size_t nline, PyObject *py_sl)
|
|
{
|
|
simpleline_t sl;
|
|
if ( !py_to_simpleline(py_sl, sl) )
|
|
return false;
|
|
|
|
return data.set_line(nline, sl);
|
|
}
|
|
|
|
// Low level: patches a line string directly
|
|
bool patch_line(size_t nline, size_t offs, int value)
|
|
{
|
|
return data.patch_line(nline, offs, value);
|
|
}
|
|
|
|
// Insert a line
|
|
bool insert_line(size_t nline, PyObject *py_sl)
|
|
{
|
|
simpleline_t sl;
|
|
if ( !py_to_simpleline(py_sl, sl) )
|
|
return false;
|
|
return data.insert_line(nline, sl);
|
|
}
|
|
|
|
// Adds a line tuple
|
|
bool add_line(PyObject *py_sl)
|
|
{
|
|
simpleline_t sl;
|
|
if ( !py_to_simpleline(py_sl, sl) )
|
|
return false;
|
|
data.add_line(sl);
|
|
refresh_range();
|
|
return true;
|
|
}
|
|
|
|
bool del_line(size_t nline)
|
|
{
|
|
bool ok = data.del_line(nline);
|
|
if ( ok )
|
|
refresh_range();
|
|
return ok;
|
|
}
|
|
|
|
// Gets the position and returns a tuple (lineno, x, y)
|
|
PyObject *get_pos(bool mouse)
|
|
{
|
|
place_t *pl;
|
|
int x, y;
|
|
pl = get_place(mouse, &x, &y);
|
|
PYW_GIL_CHECK_LOCKED_SCOPE();
|
|
if ( pl == nullptr )
|
|
Py_RETURN_NONE;
|
|
return Py_BuildValue("(" PY_BV_SZ "ii)", bvsz_t(data.to_lineno(pl)), x, y);
|
|
}
|
|
|
|
// Returns the line tuple
|
|
PyObject *get_line(size_t nline)
|
|
{
|
|
simpleline_t *r = data.get_line(nline);
|
|
PYW_GIL_CHECK_LOCKED_SCOPE();
|
|
if ( r == nullptr )
|
|
Py_RETURN_NONE;
|
|
return Py_BuildValue("(sII)", r->line.c_str(), (unsigned int)r->color, (unsigned int)r->bgcolor);
|
|
}
|
|
|
|
// Returns the count of lines
|
|
size_t count() const
|
|
{
|
|
return data.count();
|
|
}
|
|
|
|
// Clears lines
|
|
void clear()
|
|
{
|
|
data.clear_lines();
|
|
refresh_range();
|
|
}
|
|
|
|
bool jumpto(size_t ln, int x, int y)
|
|
{
|
|
simpleline_place_t l(ln);
|
|
return ::jumpto(widget, &l, x, y);
|
|
}
|
|
|
|
// Initializes and links the Python object to this class
|
|
bool init(PyObject *py_link, const char *title)
|
|
{
|
|
// Already created?
|
|
if ( widget != nullptr )
|
|
return true;
|
|
|
|
// Probe callbacks
|
|
int collected_features = 0;
|
|
static struct
|
|
{
|
|
const char *cb_name;
|
|
int feature;
|
|
} const cbtable[] =
|
|
{
|
|
{ S_ON_CLICK, HAVE_CLICK },
|
|
{ S_ON_CLOSE, HAVE_CLOSE },
|
|
{ S_ON_HINT, HAVE_HINT },
|
|
{ S_ON_KEYDOWN, HAVE_KEYDOWN },
|
|
{ S_ON_DBL_CLICK, HAVE_DBLCLICK },
|
|
{ S_ON_CURSOR_POS_CHANGED, HAVE_CURPOS }
|
|
};
|
|
|
|
PYW_GIL_CHECK_LOCKED_SCOPE();
|
|
for ( size_t i=0; i < qnumber(cbtable); i++ )
|
|
if ( PyObject_HasAttrString(py_link, cbtable[i].cb_name) )
|
|
collected_features |= cbtable[i].feature;
|
|
|
|
if ( !create(title, collected_features) )
|
|
return false;
|
|
|
|
// Hold a reference to this object
|
|
py_last_link = py_self = py_link;
|
|
Py_INCREF(py_self);
|
|
|
|
// Return a reference to the C++ instance (only once)
|
|
if ( py_this == nullptr )
|
|
py_this = PyCapsule_New(this, VALID_CAPSULE_NAME, nullptr);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool show()
|
|
{
|
|
if ( widget == nullptr && py_last_link != nullptr )
|
|
{
|
|
// Re-create the view (with same previous parameters)
|
|
if ( !init(py_last_link, title.c_str()) )
|
|
return false;
|
|
}
|
|
|
|
// Closed already?
|
|
if ( widget == nullptr )
|
|
return false;
|
|
|
|
display_widget(widget, WOPN_DP_TAB|WOPN_RESTORE);
|
|
return true;
|
|
}
|
|
|
|
bool get_selection(size_t *x1, size_t *y1, size_t *x2, size_t *y2)
|
|
{
|
|
if ( widget == nullptr )
|
|
return false;
|
|
|
|
twinpos_t p1, p2;
|
|
if ( !::read_selection(widget, &p1, &p2) )
|
|
return false;
|
|
|
|
if ( y1 != nullptr )
|
|
*y1 = data.to_lineno(p1.at);
|
|
if ( y2 != nullptr )
|
|
*y2 = data.to_lineno(p2.at);
|
|
if ( x1 != nullptr )
|
|
*x1 = size_t(p1.x);
|
|
if ( x2 != nullptr )
|
|
*x2 = p2.x;
|
|
return true;
|
|
}
|
|
|
|
PyObject *py_get_selection()
|
|
{
|
|
size_t x1, y1, x2, y2;
|
|
PYW_GIL_CHECK_LOCKED_SCOPE();
|
|
if ( !get_selection(&x1, &y1, &x2, &y2) )
|
|
Py_RETURN_NONE;
|
|
return Py_BuildValue(
|
|
"(" PY_BV_SZ PY_BV_SZ PY_BV_SZ PY_BV_SZ ")",
|
|
bvsz_t(x1), bvsz_t(y1), bvsz_t(x2), bvsz_t(y2));
|
|
}
|
|
|
|
static py_simplecustview_t *get_this(PyObject *py_this)
|
|
{
|
|
PYW_GIL_CHECK_LOCKED_SCOPE();
|
|
return PyCapsule_IsValid(py_this, VALID_CAPSULE_NAME)
|
|
? (py_simplecustview_t *) PyCapsule_GetPointer(py_this, VALID_CAPSULE_NAME)
|
|
: nullptr;
|
|
}
|
|
|
|
PyObject *get_pythis()
|
|
{
|
|
return py_this;
|
|
}
|
|
};
|
|
//</code(py_kernwin_custview)>
|
|
|
|
//---------------------------------------------------------------------------
|
|
//---------------------------------------------------------------------------
|
|
//---------------------------------------------------------------------------
|
|
|
|
//<inline(py_kernwin_custview)>
|
|
//
|
|
// Pywraps Simple Custom Viewer functions
|
|
//
|
|
PyObject *pyscv_init(PyObject *py_link, const char *title)
|
|
{
|
|
PYW_GIL_CHECK_LOCKED_SCOPE();
|
|
if ( py_link == nullptr )
|
|
Py_RETURN_NONE;
|
|
py_simplecustview_t *_this = new py_simplecustview_t();
|
|
bool ok = _this->init(py_link, title);
|
|
if ( !ok )
|
|
{
|
|
delete _this;
|
|
Py_RETURN_NONE;
|
|
}
|
|
return _this->get_pythis();
|
|
}
|
|
#define DECL_THIS py_simplecustview_t *_this = py_simplecustview_t::get_this(py_this)
|
|
|
|
//--------------------------------------------------------------------------
|
|
bool pyscv_refresh(PyObject *py_this)
|
|
{
|
|
DECL_THIS;
|
|
return _this != nullptr && _this->refresh();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
PyObject *pyscv_get_current_line(PyObject *py_this, bool mouse, bool notags)
|
|
{
|
|
DECL_THIS;
|
|
PYW_GIL_CHECK_LOCKED_SCOPE();
|
|
if ( _this == nullptr )
|
|
Py_RETURN_NONE;
|
|
qstring line;
|
|
_this->get_current_line(&line, mouse, notags);
|
|
if ( line.empty() )
|
|
Py_RETURN_NONE;
|
|
return PyUnicode_FromStringAndSize(line.c_str(), line.length());
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
bool pyscv_is_focused(PyObject *py_this)
|
|
{
|
|
DECL_THIS;
|
|
return _this != nullptr && _this->is_focused();
|
|
}
|
|
|
|
size_t pyscv_count(PyObject *py_this)
|
|
{
|
|
DECL_THIS;
|
|
return _this == nullptr ? 0 : _this->count();
|
|
}
|
|
|
|
bool pyscv_show(PyObject *py_this)
|
|
{
|
|
DECL_THIS;
|
|
return _this != nullptr && _this->show();
|
|
}
|
|
|
|
void pyscv_close(PyObject *py_this)
|
|
{
|
|
DECL_THIS;
|
|
if ( _this != nullptr )
|
|
_this->close();
|
|
}
|
|
|
|
bool pyscv_jumpto(PyObject *py_this, size_t ln, int x, int y)
|
|
{
|
|
DECL_THIS;
|
|
return _this != nullptr && _this->jumpto(ln, x, y);
|
|
}
|
|
|
|
// Returns the line tuple
|
|
PyObject *pyscv_get_line(PyObject *py_this, size_t nline)
|
|
{
|
|
DECL_THIS;
|
|
if ( _this == nullptr )
|
|
{
|
|
PYW_GIL_CHECK_LOCKED_SCOPE();
|
|
Py_RETURN_NONE;
|
|
}
|
|
return _this->get_line(nline);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Gets the position and returns a tuple (lineno, x, y)
|
|
PyObject *pyscv_get_pos(PyObject *py_this, bool mouse)
|
|
{
|
|
DECL_THIS;
|
|
if ( _this == nullptr )
|
|
{
|
|
PYW_GIL_CHECK_LOCKED_SCOPE();
|
|
Py_RETURN_NONE;
|
|
}
|
|
return _this->get_pos(mouse);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
PyObject *pyscv_clear_lines(PyObject *py_this)
|
|
{
|
|
DECL_THIS;
|
|
if ( _this != nullptr )
|
|
_this->clear();
|
|
PYW_GIL_CHECK_LOCKED_SCOPE();
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Adds a line tuple
|
|
bool pyscv_add_line(PyObject *py_this, PyObject *py_sl)
|
|
{
|
|
DECL_THIS;
|
|
return _this != nullptr && _this->add_line(py_sl);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
bool pyscv_insert_line(PyObject *py_this, size_t nline, PyObject *py_sl)
|
|
{
|
|
DECL_THIS;
|
|
return _this != nullptr && _this->insert_line(nline, py_sl);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
bool pyscv_patch_line(PyObject *py_this, size_t nline, size_t offs, int value)
|
|
{
|
|
DECL_THIS;
|
|
return _this != nullptr && _this->patch_line(nline, offs, value);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
bool pyscv_del_line(PyObject *py_this, size_t nline)
|
|
{
|
|
DECL_THIS;
|
|
return _this != nullptr && _this->del_line(nline);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
PyObject *pyscv_get_selection(PyObject *py_this)
|
|
{
|
|
DECL_THIS;
|
|
if ( _this == nullptr )
|
|
{
|
|
PYW_GIL_CHECK_LOCKED_SCOPE();
|
|
Py_RETURN_NONE;
|
|
}
|
|
return _this->py_get_selection();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
PyObject *pyscv_get_current_word(PyObject *py_this, bool mouse)
|
|
{
|
|
DECL_THIS;
|
|
PYW_GIL_CHECK_LOCKED_SCOPE();
|
|
if ( _this != nullptr )
|
|
{
|
|
qstring word;
|
|
if ( _this->get_current_word(mouse, word) )
|
|
return PyUnicode_FromString(word.c_str());
|
|
}
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Edits an existing line
|
|
bool pyscv_edit_line(PyObject *py_this, size_t nline, PyObject *py_sl)
|
|
{
|
|
DECL_THIS;
|
|
return _this != nullptr && _this->edit_line(nline, py_sl);
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
TWidget *pyscv_get_widget(PyObject *py_this)
|
|
{
|
|
DECL_THIS;
|
|
return _this == nullptr ? nullptr : _this->get_widget();
|
|
}
|
|
|
|
|
|
#undef DECL_THIS
|
|
//</inline(py_kernwin_custview)>
|
|
//---------------------------------------------------------------------------
|
|
#endif // __PYWRAPS_CUSTVIEWER__
|