// Ignore the va_list functions
%ignore AskUsingForm_cv;
%ignore close_form;
%ignore vaskstr;
%ignore vasktext;
%ignore add_menu_item;
%ignore vwarning;
%ignore vinfo;
%ignore vnomem;
%ignore vmsg;
%ignore show_wait_box_v;
%ignore askbuttons_cv;
%ignore askfile_cv;
%ignore askyn_cv;
%ignore askyn_v;
// Ignore these string functions. There are trivial replacements in Python.
%ignore addblanks;
%ignore trim;
%ignore skipSpaces;
%ignore stristr;
// Ignore the cli_t class
%ignore cli_t;
%include "typemaps.i"
// Make askaddr(), askseg(), and asklong() return a
// tuple: (result, value)
%apply unsigned long *INOUT { sval_t *value };
%rename (_asklong) asklong;
%apply unsigned long *INOUT { ea_t *addr };
%rename (_askaddr) askaddr;
%apply unsigned long *INOUT { sel_t *sel };
%rename (_askseg) askseg;
%inline %{
void refresh_lists(void)
{
callui(ui_list);
}
%}
%pythoncode %{
def asklong(defval, format):
res, val = _idaapi._asklong(defval, format)
if res == 1:
return val
else:
return None
def askaddr(defval, format):
res, ea = _idaapi._askaddr(defval, format)
if res == 1:
return ea
else:
return None
def askseg(defval, format):
res, sel = _idaapi._askseg(defval, format)
if res == 1:
return sel
else:
return None
%}
# This is for get_cursor()
%apply int *OUTPUT {int *x, int *y};
# This is for read_selection()
%apply unsigned long *OUTPUT { ea_t *ea1, ea_t *ea2 };
%{
bool idaapi py_menu_item_callback(void *userdata)
{
PyObject *func, *args, *result;
bool ret = 0;
// userdata is a tuple of ( func, args )
// func and args are borrowed references from userdata
func = PyTuple_GET_ITEM(userdata, 0);
args = PyTuple_GET_ITEM(userdata, 1);
// call the python function
result = PyEval_CallObject(func, args);
// we cannot raise an exception in the callback, just print it.
if (!result) {
PyErr_Print();
return 0;
}
// if the function returned a non-false value, then return 1 to ida,
// overwise return 0
if (PyObject_IsTrue(result)) {
ret = 1;
}
Py_DECREF(result);
return ret;
}
%}
%rename (add_menu_item) wrap_add_menu_item;
%inline %{
//
#ifdef CH_ATTRS
PyObject *choose2_find(const char *title);
#endif
int choose2_add_command(PyObject *self, const char *caption, int flags, int menu_index, int icon);
void choose2_refresh(PyObject *self);
void choose2_close(PyObject *self);
int choose2_show(PyObject *self);
void choose2_activate(PyObject *self);
//
bool wrap_add_menu_item (
const char *menupath,
const char *name,
const char *hotkey,
int flags,
PyObject *pyfunc,
PyObject *args) {
// FIXME: probably should keep track of this data, and destroy it when the menu item is removed
PyObject *cb_data;
if (args == Py_None) {
Py_DECREF(Py_None);
args = PyTuple_New( 0 );
if (!args)
return 0;
}
if(!PyTuple_Check(args)) {
PyErr_SetString(PyExc_TypeError, "args must be a tuple or None");
return 0;
}
cb_data = Py_BuildValue("(OO)", pyfunc, args);
return add_menu_item(menupath, name, hotkey, flags, py_menu_item_callback, (void *)cb_data);
}
%}
%include "kernwin.hpp"
uint32 choose_choose(PyObject *self,
int flags,
int x0,int y0,
int x1,int y1,
int width);
%{
//
//------------------------------------------------------------------------
static PyObject *PyObject_TryGetAttrString(PyObject *object, const char *attr)
{
if (!PyObject_HasAttrString(object, attr))
return NULL;
return PyObject_GetAttrString(object, attr);
}
//------------------------------------------------------------------------
// Some defines
#define POPUP_NAMES_COUNT 4
#define MAX_CHOOSER_MENU_COMMANDS 10
#define thisobj ((py_choose2_t *) obj)
#define thisdecl py_choose2_t *_this = thisobj
#define MENU_COMMAND_CB(id) static uint32 idaapi s_menu_command_##id(void *obj, uint32 n) { return thisobj->on_command(id, int(n)); }
#define DECL_MENU_COMMAND_CB(id) s_menu_command_##id
#define S_ON_EDIT_LINE "OnEditLine"
#define S_ON_INSERT_LINE "OnInsertLine"
#define S_ON_GET_LINE "OnGetLine"
#define S_ON_DELETE_LINE "OnDeleteLine"
#define S_ON_REFRESH "OnRefresh"
#define S_ON_SELECT_LINE "OnSelectLine"
#define S_ON_COMMAND "OnCommand"
#define S_ON_GET_ICON "OnGetIcon"
#ifdef CH_ATTRS
#define S_ON_GET_LINE_ATTR "OnGetLineAttr"
#endif
#define S_ON_GET_SIZE "OnGetSize"
#define S_ON_CLOSE "OnClose"
#define CHOOSE2_HAVE_DEL 0x0001
#define CHOOSE2_HAVE_INS 0x0002
#define CHOOSE2_HAVE_UPDATE 0x0004
#define CHOOSE2_HAVE_EDIT 0x0008
#define CHOOSE2_HAVE_ENTER 0x0010
#define CHOOSE2_HAVE_GETICON 0x0020
#define CHOOSE2_HAVE_GETATTR 0x0040
#define CHOOSE2_HAVE_COMMAND 0x0080
#define CHOOSE2_HAVE_ONCLOSE 0x0100
//------------------------------------------------------------------------
// Helper functions
class py_choose2_t;
typedef std::map pychoose2_to_choose2_map_t;
static pychoose2_to_choose2_map_t choosers;
py_choose2_t *choose2_find_instance(PyObject *self)
{
pychoose2_to_choose2_map_t::iterator it = choosers.find(self);
if (it == choosers.end())
return NULL;
return it->second;
}
void choose2_add_instance(PyObject *self, py_choose2_t *c2)
{
choosers[self] = c2;
}
void choose2_del_instance(PyObject *self)
{
pychoose2_to_choose2_map_t::iterator it = choosers.find(self);
if (it != choosers.end())
choosers.erase(it);
}
//------------------------------------------------------------------------
class py_choose2_t
{
private:
int flags;
int cb_flags;
qstring title;
PyObject *self;
qstrvec_t cols;
// the number of declarations should follow the MAX_CHOOSER_MENU_COMMANDS value
MENU_COMMAND_CB(0) MENU_COMMAND_CB(1)
MENU_COMMAND_CB(2) MENU_COMMAND_CB(3)
MENU_COMMAND_CB(4) MENU_COMMAND_CB(5)
MENU_COMMAND_CB(6) MENU_COMMAND_CB(7)
MENU_COMMAND_CB(8) MENU_COMMAND_CB(9)
static chooser_cb_t *menu_cbs[MAX_CHOOSER_MENU_COMMANDS];
int menu_cb_idx;
//------------------------------------------------------------------------
// Static methods to dispatch to member functions
//------------------------------------------------------------------------
#ifdef CH_ATTRS
static int idaapi ui_cb(void *obj, int notification_code, va_list va)
{
if ( notification_code != ui_get_chooser_item_attrs )
return 0;
va_arg(va, void *);
int n = int(va_arg(va, uint32));
chooser_item_attrs_t *attr = va_arg(va, chooser_item_attrs_t *);
thisobj->on_get_line_attr(n, attr);
return 1;
}
#endif
static uint32 idaapi s_sizer(void *obj)
{
return (uint32)thisobj->on_get_size();
}
static void idaapi s_getl(void *obj, uint32 n, char * const *arrptr)
{
thisobj->on_get_line(int(n), arrptr);
}
static uint32 idaapi s_del(void *obj, uint32 n)
{
return uint32(thisobj->on_delete_line(int(n)));
}
static void idaapi s_ins(void *obj)
{
thisobj->on_insert_line();
}
static uint32 idaapi s_update(void *obj, uint32 n)
{
return uint32(thisobj->on_refresh(int(n)));
}
static void idaapi s_edit(void *obj, uint32 n)
{
thisobj->on_edit_line(int(n));
}
static void idaapi s_enter(void * obj, uint32 n)
{
thisobj->on_select_line(int(n));
}
static int idaapi s_get_icon(void *obj, uint32 n)
{
return thisobj->on_get_icon(int(n));
}
static void idaapi s_destroy(void *obj)
{
thisobj->on_close();
}
private:
//------------------------------------------------------------------------
// Member functions corresponding to each chooser2() callback
//------------------------------------------------------------------------
void on_get_line(int lineno, char * const *line_arr)
{
if (lineno == 0)
{
for (size_t i=0;i=0;i--)
line_arr[i][0] = '\0';
// Call Python
PyObject *list = PyObject_CallMethod(self, S_ON_GET_LINE, "l", lineno - 1);
if (list == NULL)
return;
for (int i=ncols-1;i>=0;i--)
{
PyObject *item = PyList_GetItem(list, Py_ssize_t(i));
if (item == NULL)
continue;
const char *str = PyString_AsString(item);
if (str != NULL)
qstrncpy(line_arr[i], str, MAXSTR);
}
Py_DECREF(list);
}
size_t on_get_size()
{
PyObject *pyres = PyObject_CallMethod(self, S_ON_GET_SIZE, NULL);
if (pyres == NULL)
return 0;
size_t res = PyInt_AsLong(pyres);
Py_DECREF(pyres);
return res;
}
void on_close()
{
#ifdef CH_ATTRS
if ( (flags & CH_ATTRS) != 0 )
unhook_from_notification_point(HT_UI, ui_cb, this);
#endif
// Call Python
PyObject *pyres = PyObject_CallMethod(self, S_ON_CLOSE, NULL);
Py_XDECREF(pyres);
Py_XDECREF(self);
// Remove from list
choose2_del_instance(self);
// delete this instance if none modal
if ( (flags & CH_MODAL) == 0 )
delete this;
}
int on_delete_line(int lineno)
{
PyObject *pyres = PyObject_CallMethod(self, S_ON_DELETE_LINE, "l", lineno - 1);
if (pyres == NULL)
return lineno;
size_t res = PyInt_AsLong(pyres);
Py_DECREF(pyres);
return res + 1;
}
int on_refresh(int lineno)
{
PyObject *pyres = PyObject_CallMethod(self, S_ON_REFRESH, "l", lineno - 1);
if (pyres == NULL)
return lineno;
size_t res = PyInt_AsLong(pyres);
Py_DECREF(pyres);
return res + 1;
}
void on_insert_line()
{
PyObject *pyres = PyObject_CallMethod(self, S_ON_INSERT_LINE, NULL);
Py_XDECREF(pyres);
}
void on_select_line(int lineno)
{
PyObject *pyres = PyObject_CallMethod(self, S_ON_SELECT_LINE, "l", lineno - 1);
Py_XDECREF(pyres);
}
void on_edit_line(int lineno)
{
PyObject *pyres = PyObject_CallMethod(self, S_ON_EDIT_LINE, "l", lineno - 1);
Py_XDECREF(pyres);
}
int on_command(int cmd_id, int lineno)
{
PyObject *pyres = PyObject_CallMethod(self, S_ON_COMMAND, "ll", lineno - 1, cmd_id);
if (pyres==NULL)
return lineno;
size_t res = PyInt_AsLong(pyres);
Py_XDECREF(pyres);
return res;
}
int on_get_icon(int lineno)
{
PyObject *pyres = PyObject_CallMethod(self, S_ON_GET_ICON, "l", lineno - 1);
size_t res = PyInt_AsLong(pyres);
Py_XDECREF(pyres);
return res;
}
#ifdef CH_ATTRS
void on_get_line_attr(int lineno, chooser_item_attrs_t *attr)
{
PyObject *pyres = PyObject_CallMethod(self, S_ON_GET_LINE_ATTR, "l", lineno - 1);
if (pyres == NULL)
return;
if (PyList_Check(pyres))
{
PyObject *item;
if ((item = PyList_GetItem(pyres, 0)) != NULL)
attr->color = PyInt_AsLong(item);
if ((item = PyList_GetItem(pyres, 1)) != NULL)
attr->flags = PyInt_AsLong(item);
}
Py_XDECREF(pyres);
}
#endif
public:
//------------------------------------------------------------------------
// Public methods
//------------------------------------------------------------------------
py_choose2_t()
{
flags = 0;
cb_flags = 0;
menu_cb_idx = 0;
self = NULL;
}
#ifdef CH_ATTRS
static py_choose2_t *find_chooser(const char *title)
{
return (py_choose2_t *) get_chooser_obj(title);
}
#endif
void close()
{
close_chooser(title.c_str());
}
bool activate()
{
TForm *frm = find_tform(title.c_str());
if (frm == NULL)
return false;
switchto_tform(frm, true);
return true;
}
int choose2(
int fl,
int ncols,
const int *widths,
const char *title,
int deflt = -1,
// An array of 4 strings: ("Insert", "Delete", "Edit", "Refresh"
const char * const *popup_names = NULL,
int icon = -1,
int x1 = -1, int y1 = -1, int x2 = -1, int y2 = -1)
{
flags = fl;
#ifdef CH_ATTRS
if ( (flags & CH_ATTRS) != 0 )
{
if ( !hook_to_notification_point(HT_UI, ui_cb, this) )
flags &= ~CH_ATTRS;
}
#endif
this->title = title;
return ::choose2(
flags,
x1, y1, x2, y2,
this,
ncols, widths,
s_sizer,
s_getl,
title,
icon,
deflt,
cb_flags & CHOOSE2_HAVE_DEL ? s_del : NULL,
cb_flags & CHOOSE2_HAVE_INS ? s_ins : NULL,
cb_flags & CHOOSE2_HAVE_UPDATE ? s_update : NULL,
cb_flags & CHOOSE2_HAVE_EDIT ? s_edit : NULL,
cb_flags & CHOOSE2_HAVE_ENTER ? s_enter : NULL,
s_destroy,
popup_names,
cb_flags & CHOOSE2_HAVE_GETICON ? s_get_icon : NULL);
}
int add_command(const char *caption, int flags=0, int menu_index=-1, int icon=-1)
{
if (menu_cb_idx >= MAX_CHOOSER_MENU_COMMANDS)
return -1;
bool ret = add_chooser_command(title.c_str(), caption, menu_cbs[menu_cb_idx], menu_index, icon, flags);
if (!ret)
return -1;
return menu_cb_idx++;
}
int show(PyObject *self)
{
PyObject *attr;
// get title
if ( (attr = PyObject_TryGetAttrString(self, "title")) == NULL )
return -1;
qstring title = PyString_AsString(attr);
Py_DECREF(attr);
// get flags
if ( (attr = PyObject_TryGetAttrString(self, "flags")) == NULL )
return -1;
int flags = PyInt_AsLong(attr);
Py_DECREF(attr);
// get columns
if ( (attr = PyObject_TryGetAttrString(self, "cols")) == NULL )
return -1;
// get col count
int ncols = PyList_Size(attr);
// get cols caption and widthes
intvec_t widths;
cols.qclear();
for (int i=0;iself = self;
// Create chooser
int r = this->choose2(flags, ncols, &widths[0], title.c_str(), deflt, popup_names, icon, pts[0], pts[1], pts[2], pts[3]);
// Clear temporary popup_names
if (popup_names != NULL)
{
for (int i=0;iactivate();
return 1;
}
c2 = new py_choose2_t();
choose2_add_instance(self, c2);
return c2->show(self);
}
//------------------------------------------------------------------------
void choose2_close(PyObject *self)
{
py_choose2_t *c2 = choose2_find_instance(self);
if (c2 != NULL)
c2->close();
}
//------------------------------------------------------------------------
void choose2_refresh(PyObject *self)
{
py_choose2_t *c2 = choose2_find_instance(self);
if (c2 != NULL)
c2->refresh();
}
//------------------------------------------------------------------------
void choose2_activate(PyObject *self)
{
py_choose2_t *c2 = choose2_find_instance(self);
if (c2 != NULL)
c2->activate();
}
//------------------------------------------------------------------------
int choose2_add_command(PyObject *self, const char *caption, int flags=0, int menu_index=-1, int icon=-1)
{
py_choose2_t *c2 = choose2_find_instance(self);
if (c2 != NULL)
return c2->add_command(caption, flags, menu_index, icon);
else
return -2;
}
//------------------------------------------------------------------------
#ifdef CH_ATTRS
PyObject *choose2_find(const char *title)
{
py_choose2_t *c2 = py_choose2_t::find_chooser(title);
if (c2 == NULL)
return NULL;
return c2->get_self();
}
#endif
//
uint32 idaapi choose_sizer(void *self)
{
PyObject *pyres;
uint32 res;
pyres = PyObject_CallMethod((PyObject *)self, "sizer", "");
res = PyInt_AsLong(pyres);
Py_DECREF(pyres);
return res;
}
char * idaapi choose_getl(void *self, uint32 n, char *buf)
{
PyObject *pyres;
char *res;
pyres = PyObject_CallMethod((PyObject *)self, "getl", "l", n);
if (!pyres)
{
strcpy(buf, "");
return buf;
}
res = PyString_AsString(pyres);
if (res)
{
strncpy(buf, res, MAXSTR);
res = buf;
}
else
{
strcpy(buf, "");
res = buf;
}
Py_DECREF(pyres);
return res;
}
void idaapi choose_enter(void *self, uint32 n)
{
PyObject_CallMethod((PyObject *)self, "enter", "l", n);
return;
}
uint32 choose_choose(void *self,
int flags,
int x0,int y0,
int x1,int y1,
int width)
{
PyObject *pytitle;
const char *title;
if ((pytitle = PyObject_GetAttrString((PyObject *)self, "title")))
{
title = PyString_AsString(pytitle);
}
else
{
title = "Choose";
pytitle = NULL;
}
int r = choose(
flags,
x0, y0,
x1, y1,
self,
width,
&choose_sizer,
&choose_getl,
title,
1,
1,
NULL, /* del */
NULL, /* inst */
NULL, /* update */
NULL, /* edit */
&choose_enter,
NULL, /* destroy */
NULL, /* popup_names */
NULL /* get_icon */
);
Py_XDECREF(pytitle);
return r;
}
%}
%pythoncode %{
class Choose:
"""
Choose - class for choose() with callbacks
"""
def __init__(self, list, title, flags=0):
self.list = list
self.title = title
self.flags = flags
self.x0 = -1
self.x1 = -1
self.y0 = -1
self.y1 = -1
self.width = -1
# HACK: Add a circular reference for non-modal choosers. This prevents the GC
# from collecting the class object the callbacks need. Unfortunately this means
# that the class will never be collected, unless refhack is set to None explicitly.
if (flags & 1) == 0:
self.refhack = self
def sizer(self):
"""
Callback: sizer - returns the length of the list
"""
return len(self.list)
def getl(self, n):
"""
Callback: getl - get one item from the list
"""
if n == 0:
return self.title
if n <= self.sizer():
return str(self.list[n-1])
else:
return ""
def ins(self):
pass
def update(self, n):
pass
def edit(self, n):
pass
def enter(self, n):
print "enter(%d) called" % n
def destroy(self):
pass
def get_icon(self, n):
pass
def choose(self):
"""
choose - Display the choose dialogue
"""
return _idaapi.choose_choose(self, self.flags, self.x0, self.y0, self.x1, self.y1, self.width)
#
class Choose2:
"""Choose2 wrapper class"""
# refer to kernwin.hpp for more information on how to use these constants
CH_MODAL = 0x01
CH_MULTI = 0x02
CH_MULTI_EDIT = 0x04
CH_NOBTNS = 0x08
CH_ATTRS = 0x10
CH_BUILTIN_MASK = 0xF80000
# column flags (are specified in the widths array)
CHCOL_PLAIN = 0x00000000
CHCOL_PATH = 0x00010000
CHCOL_HEX = 0x00020000
CHCOL_DEC = 0x00030000
CHCOL_FORMAT = 0x00070000
def __init__(self, title, cols, flags=0, popup_names=None, icon=-1, x1=-1, y1=-1, x2=-1, y2=-1):
self.title = title
self.flags = flags
# a list of colums; each list item is a list of two items
# example: [ ["Address", 10 | Choose2.CHCOL_HEX], ["Name", 30 | CHCOL_PLAIN] ]
self.cols = cols
self.deflt = -1
# list of new captions to replace this list ["Insert", "Delete", "Edit", "Refresh"]
self.popup_names = popup_names
self.icon = icon
self.x1 = x1
self.y1 = y1
self.x2 = x2
self.y2 = y2
def Show(self, modal=False):
"""Activates or creates a chooser window"""
if modal:
self.flags |= Choose2.CH_MODAL
else:
self.flags &= ~Choose2.CH_MODAL
return _idaapi.choose2_show(self)
def Activate():
"""Activates a visible chooser"""
return _idaapi.choose2_activate(self)
def Refresh():
"""Causes the refresh callback to trigger"""
return _idaapi.choose2_refresh(self)
def Close():
"""Closes the chooser"""
return _idaapi.choose2_close(self)
def AddCommand(self, caption, flags = _idaapi.CHOOSER_POPUP_MENU, menu_index=-1,icon = -1):
"""Adds a new chooser command
Save the returned value and later use it in the OnCommand handler
@return: Returns a negative value on failure or the command index
"""
return _idaapi.choose2_add_command(self, caption, flags, menu_index, icon)
#
# Implement these methods in the subclass:
#
# def OnClose(self):
# # return nothing
# pass
# def OnEditLine(self, n):
# # return nothing (mandatory callback)
# pass
# def OnInsertLine(self):
# # return nothing
# pass
# def OnSelectLine(self, n):
# # return nothing
# pass
# def OnGetLine(self, n):
# # return a list [col1, col2, col3, ...] describing the n-th line
# return ["col1", "col2", ...]
# def OnGetSize(self):
# # return the size (mandatory callback)
# return len(self.the_list)
# def OnDeleteLine(self, n):
# # return new line number
# return self.n
# def OnRefresh(self, n):
# # return new line number
# return self.n
# def OnCommand(self, n, cmd_id):
# # return int ; check add_chooser_command()
# return 0
# def OnGetIcon(self, n):
# # return icon number (or -1)
# return -1
# def OnGetLineAttr(self, n):
# # return list [color, flags] or None; check chooser_item_attrs_t
# pass
#
%}