- some code cleanup

- added idaapi. struct_unpack / copy_bits / as_signed utility functions
- added pywraps.hpp utility header
This commit is contained in:
elias.bachaalany 2010-03-05 11:16:27 +00:00
parent 33c93df0cf
commit b935e24aba
3 changed files with 304 additions and 123 deletions

82
pywraps.hpp Normal file
View File

@ -0,0 +1,82 @@
#ifndef __PYWRAPS_HPP__
#define __PYWRAPS_HPP__
//------------------------------------------------------------------------
// Types
#ifndef PYUL_DEFINED
#define PYUL_DEFINED
#ifdef __EA64__
typedef unsigned PY_LONG_LONG pyul_t;
#else
typedef unsigned long pyul_t;
#endif
#endif
#ifdef __EA64__
#define PY_FMT64 "K"
#else
#define PY_FMT64 "k"
#endif
// Vector of PyObject*
typedef qvector<PyObject *> ppyobject_vec_t;
//------------------------------------------------------------------------
// PyIdc conversion object IDs
#define PY_ICID_INT64 0
#define PY_ICID_BYREF 1
#define PY_ICID_OPAQUE 2
//------------------------------------------------------------------------
// Constants used by the pyvar_to_idcvar and idcvar_to_pyvar functions
#define CIP_FAILED -1 // Conversion error
#define CIP_IMMUTABLE 0 // Immutable object passed. Will not update the object but no error occured
#define CIP_OK 1 // Success
#define CIP_OK_NODECREF 2 // Success but do not decrement its reference
//------------------------------------------------------------------------
// All the exported functions from PyWraps are forward declared here
// Tries to import a module and swallows the exception if it fails and returns NULL
PyObject *PyImport_TryImportModule(const char *name);
// Tries to get an attribute and swallows the exception if it fails and returns NULL
PyObject *PyObject_TryGetAttrString(PyObject *py_var, const char *attr);
// Converts a Python number (LONGLONG or normal integer) to an IDC variable (VT_LONG or VT_INT64)
bool PyGetNumberAsIDC(PyObject *py_var, idc_value_t *idc_var);
// Converts a Python number to an uint64 and indicates whether the number was a long number
bool PyGetNumber(PyObject *py_var, uint64 *num, bool *is_64 = NULL);
// Checks if an Python object can be treated like a sequence
bool PyIsSequenceType(PyObject *obj);
// Returns an error string from the last exception (and clears it)
bool PyGetError(qstring *out = NULL);
// If an error occured (it calls PyGetError) it displays it and return TRUE
bool PyShowErr(const char *cb_name);
// [De]Initializes PyWraps
bool init_pywraps();
void deinit_pywraps();
// Returns the string representation of a PyObject
bool PyObjectToString(PyObject *obj, qstring *out);
// Converts Python variable to IDC variable
// gvar_sn is used in case the Python object was a created from a call to idcvar_to_pyvar and the IDC object was a VT_REF
int pyvar_to_idcvar(
PyObject *py_var,
idc_value_t *idc_var,
int *gvar_sn = NULL);
// Converts from IDC to Python
// We support converting VT_REF IDC variable types
int idcvar_to_pyvar(
const idc_value_t &idc_var,
PyObject **py_var);
#endif

View File

@ -55,45 +55,82 @@
//<code(py_idaapi)>
#ifndef PYUL_DEFINED
#define PYUL_DEFINED
typedef unsigned PY_LONG_LONG pyul_t;
#include "pywraps.hpp"
//------------------------------------------------------------------------
// String constants used
static const char PY_IDC_CLASS_NAME[] = "py_idc_object_class";
static const char PY_IDC_GLOBAL_VAR_FMT[] = "__py_cvt_gvar_%d";
static const char PY_IDCCVT_ID_ATTR[] = "__idc_cvt_id__";
static const char PY_IDCCVT_VALUE_ATTR[] = "__idc_cvt_value__";
static const char S_PY_IDC_OPAQUE_T[] = "py_idc_cvt_helper_t";
static const char S_PROPS[] = "props";
static const char S_NAME[] = "name";
static const char S_ASM_KEYWORD[] = "asm_keyword";
static const char S_MENU_NAME[] = "menu_name";
static const char S_HOTKEY[] = "hotkey";
static const char S_VALUE_SIZE[] = "value_size";
static const char S_MAY_CREATE_AT[] = "may_create_at";
static const char S_CALC_ITEM_SIZE[] = "calc_item_size";
static const char S_ID[] = "id";
static const char S_PRINTF[] = "printf";
static const char S_TEXT_WIDTH[] = "text_width";
static const char S_SCAN[] = "scan";
static const char S_ANALYZE[] = "analyze";
static const char S_CBSIZE[] = "cbsize";
static const char S_ON_CLICK[] = "OnClick";
static const char S_ON_CLOSE[] = "OnClose";
static const char S_ON_DBL_CLICK[] = "OnDblClick";
static const char S_ON_CURSOR_POS_CHANGED[] = "OnCursorPosChanged";
static const char S_ON_KEYDOWN[] = "OnKeydown";
static const char S_ON_POPUP[] = "OnPopup";
static const char S_ON_HINT[] = "OnHint";
static const char S_ON_POPUP_MENU[] = "OnPopupMenu";
static const char S_ON_EDIT_LINE[] = "OnEditLine";
static const char S_ON_INSERT_LINE[] = "OnInsertLine";
static const char S_ON_GET_LINE[] = "OnGetLine";
static const char S_ON_DELETE_LINE[] = "OnDeleteLine";
static const char S_ON_REFRESH[] = "OnRefresh";
static const char S_ON_SELECT_LINE[] = "OnSelectLine";
static const char S_ON_COMMAND[] = "OnCommand";
static const char S_ON_GET_ICON[] = "OnGetIcon";
static const char S_ON_GET_LINE_ATTR[] = "OnGetLineAttr";
static const char S_ON_GET_SIZE[] = "OnGetSize";
static const char S_ON_GETTEXT[] = "OnGetText";
static const char S_ON_ACTIVATE[] = "OnActivate";
static const char S_ON_DEACTIVATE[] = "OnDeactivate";
static const char S_ON_SELECT[] = "OnSelect";
static const char S_M_EDGES[] = "_edges";
static const char S_M_NODES[] = "_nodes";
static const char S_M_THIS[] = "_this";
static const char S_M_TITLE[] = "_title";
#ifdef __PYWRAPS__
static const char S_PY_IDAAPI_MODNAME[] = "__main__";
#else
static const char S_PY_IDAAPI_MODNAME[] = "idaapi";
#endif
//------------------------------------------------------------------------
static const char PY_IDC_CLASS_NAME[] = "py_idc_object_class";
static const char PY_IDC_GLOBAL_VAR_FMT[] = "__py_cvt_gvar_%d";
static const char PY_IDCCVT_ID_ATTR[] = "__idc_cvt_id__";
static const char PY_IDCCVT_VALUE_ATTR[] = "__idc_cvt_value__";
static const char S_PY_IDC_OPAQUE_T[] = "py_idc_cvt_helper_t";
#ifndef __PYWRAPS__
static const char S_PY_IDAAPI_MODNAME[] = "idaapi";
#else
static const char S_PY_IDAAPI_MODNAME[] = "__main__";
#endif
// Constants used by get_idaapi_class_reference()
#define PY_CLSID_CVT_INT64 0
#define PY_CLSID_APPCALL_SKEL_OBJ 1
#define PY_CLSID_CVT_BYREF 2
#define PY_CLSID_LAST 3
//------------------------------------------------------------------------
// PyIdc conversion object ids
#define PY_ICID_INT64 0
#define PY_ICID_BYREF 1
#define PY_ICID_OPAQUE 2
static PyObject *py_cvt_helper_module = NULL;
static bool pywraps_initialized = false;
//------------------------------------------------------------------------
idc_class_t *get_py_idc_cvt_opaque()
static idc_class_t *get_py_idc_cvt_opaque()
{
return find_idc_class(S_PY_IDC_OPAQUE_T);
}
//------------------------------------------------------------------------
// IDC Opaque object destructor: when the IDC object dies we kill the
// opaque Python object along with it
static const char py_idc_cvt_helper_dtor_args[] = { VT_OBJ, 0 };
static error_t idaapi py_idc_opaque_dtor(
idc_value_t *argv,
@ -122,7 +159,7 @@ bool init_pywraps()
if (py_cvt_helper_module == NULL)
{
// Take a reference to the module so we can create the needed class instances
py_cvt_helper_module = PyImport_ImportModule(S_PY_IDAAPI_MODNAME);
py_cvt_helper_module = PyImport_TryImportModule(S_PY_IDAAPI_MODNAME);
if (py_cvt_helper_module == NULL)
return false;
}
@ -175,7 +212,6 @@ static PyObject *get_idaapi_class_reference(const int class_id)
"Appcall_object__",
"PyIdc_cvt_refclass__"
};
return PyObject_GetAttrString(py_cvt_helper_module, class_names[class_id]);
}
@ -209,7 +245,7 @@ PyObject *PyImport_TryImportModule(const char *name)
// converted to a VT_INT64 or not. For example: 2**32-1 = 0xffffffff which
// can fit in a C long but Python creates a PyLong object for it.
// And because of that we are confused as to whether to convert to 32 or 64
bool PyGetNumber(PyObject *py_var, idc_value_t *idc_var)
bool PyGetNumberAsIDC(PyObject *py_var, idc_value_t *idc_var)
{
if (!(PyInt_CheckExact(py_var) || PyLong_CheckExact(py_var)))
return false;
@ -235,6 +271,49 @@ bool PyGetNumber(PyObject *py_var, idc_value_t *idc_var)
return true;
}
//-------------------------------------------------------------------------
// Parses a Python object as a long or long long
bool PyGetNumber(PyObject *py_var, uint64 *num, bool *is_64)
{
if (!(PyInt_CheckExact(py_var) || PyLong_CheckExact(py_var)))
return false;
// Can we convert to C long?
long l = PyInt_AsLong(py_var);
if (!PyErr_Occurred())
{
if (num != NULL)
*num = uint64(l);
if (is_64 != NULL)
*is_64 = false;
return true;
}
// Clear last error
PyErr_Clear();
// Can be fit into a C unsigned long?
unsigned long ul = PyLong_AsUnsignedLong(py_var);
if (!PyErr_Occurred())
{
if (num != NULL)
*num = uint64(ul);
if (is_64 != NULL)
*is_64 = false;
return true;
}
PyErr_Clear();
PY_LONG_LONG ll = PyLong_AsLongLong(py_var);
if (!PyErr_Occurred())
{
if (num != NULL)
*num = uint64(ll);
if (is_64 != NULL)
*is_64 = true;
return true;
}
PyErr_Clear();
return false;
}
//-------------------------------------------------------------------------
// Checks if a given object is of sequence type
bool PyIsSequenceType(PyObject *obj)
@ -271,10 +350,10 @@ bool PyObjectToString(PyObject *obj, qstring *out)
//--------------------------------------------------------------------------
// Checks if a Python error occured and fills the out parameter with the
// exception string
bool PyGetError(qstring *out = NULL)
bool PyGetError(qstring *out)
{
PyObject *py_err;
if ( (py_err = PyErr_Occurred()) == NULL)
if ((py_err = PyErr_Occurred()) == NULL)
return false;
PyObject *err_type, *err_value, *err_traceback;
@ -284,6 +363,17 @@ bool PyGetError(qstring *out = NULL)
return true;
}
//-------------------------------------------------------------------------
// A loud version of PyGetError() which gets the error and displays it
bool PyShowErr(const char *cb_name)
{
static qstring err_str;
if (!PyGetError(&err_str))
return false;
warning("IDAPython: Error while calling Python callback <%s>:\n%s", cb_name, err_str.c_str());
return true;
}
//-------------------------------------------------------------------------
// Checks if the given py_var is a special PyIdc_cvt_helper object.
// It does that by examining the magic attribute and returns its numeric value.
@ -328,22 +418,19 @@ static bool create_py_idc_opaque_obj(PyObject *py_var, idc_value_t *idc_var)
//-------------------------------------------------------------------------
// Converts a Python variable into an IDC variable
// This function returns:
// 0 - failure
// 1 - success
// 2 - success but do not decrement the reference of the py_var (used by opaque values)
// This function returns on one CIP_XXXX
int pyvar_to_idcvar(
PyObject *py_var,
idc_value_t *idc_var,
int *gvar_sn = NULL)
int *gvar_sn)
{
PyObject *attr;
// None / NULL
if (py_var == NULL || py_var == Py_None)
idc_var->set_long(0);
// Numbers?
else if (PyGetNumber(py_var, idc_var))
return 1;
else if (PyGetNumberAsIDC(py_var, idc_var))
return CIP_OK;
// String
else if (PyString_Check(py_var))
idc_var->_set_string(PyString_AsString(py_var), PyString_Size(py_var));
@ -360,6 +447,7 @@ int pyvar_to_idcvar(
// void*
else if (PyCObject_Check(py_var))
idc_var->set_pvoid(PyCObject_AsVoidPtr(py_var));
// Is it a Python list?
else if (PyList_CheckExact(py_var) || PyIsSequenceType(py_var))
{
// Create the object
@ -379,7 +467,7 @@ int pyvar_to_idcvar(
// Convert the item into an IDC variable
idc_value_t v;
ok = pyvar_to_idcvar(py_item, &v, gvar_sn) > 0;
ok = pyvar_to_idcvar(py_item, &v, gvar_sn) >= CIP_OK;
if (ok)
{
// Form the attribute name
@ -397,7 +485,7 @@ int pyvar_to_idcvar(
if (!ok)
break;
}
return ok ? 1 : 0;
return ok ? CIP_OK : CIP_FAILED;
}
// Dictionary: we convert to an IDC object
else if (PyDict_Check(py_var))
@ -426,7 +514,7 @@ int pyvar_to_idcvar(
// Convert the attribute into an IDC value
idc_value_t v;
ok = pyvar_to_idcvar(val, &v, gvar_sn) > 0;
ok = pyvar_to_idcvar(val, &v, gvar_sn) >= CIP_OK;
if (ok)
{
// Store the attribute
@ -439,7 +527,15 @@ int pyvar_to_idcvar(
}
// Decrement attribute reference
Py_DECREF(py_items);
return ok ? 1 : 0;
return ok ? CIP_OK : CIP_FAILED;
}
// Possible function?
else if (PyCallable_Check(py_var))
{
idc_var->clear();
idc_var->vtype = VT_FUNC;
idc_var->funcidx = -1; // Does not apply
return CIP_OK;
}
// Objects:
// - pyidc_cvt objects: int64, byref, opaque
@ -460,7 +556,7 @@ int pyvar_to_idcvar(
return false;
idc_var->set_int64(PyLong_AsLongLong(attr));
Py_DECREF(attr);
return 1;
return CIP_OK;
//
// BYREF
//
@ -468,19 +564,19 @@ int pyvar_to_idcvar(
{
// BYREF always require this parameter
if (gvar_sn == NULL)
return 0;
return CIP_FAILED;
// Get the value attribute
attr = PyObject_TryGetAttrString(py_var, PY_IDCCVT_VALUE_ATTR);
if (attr == NULL)
return 0;
return CIP_FAILED;
// Create a global variable
char buf[MAXSTR];
qsnprintf(buf, sizeof(buf), PY_IDC_GLOBAL_VAR_FMT, *gvar_sn);
idc_value_t *gvar = add_idc_gvar(buf);
// Convert the python value into the IDC global variable
bool ok = pyvar_to_idcvar(attr, gvar, gvar_sn) > 0;
bool ok = pyvar_to_idcvar(attr, gvar, gvar_sn) >= CIP_OK;
if (ok)
{
(*gvar_sn)++;
@ -488,7 +584,7 @@ int pyvar_to_idcvar(
VarRef(idc_var, gvar);
}
Py_DECREF(attr);
return ok ? 1 : 0;
return ok ? CIP_OK : CIP_FAILED;
}
//
// OPAQUE
@ -496,8 +592,8 @@ int pyvar_to_idcvar(
case PY_ICID_OPAQUE:
{
if (!create_py_idc_opaque_obj(py_var, idc_var))
return 0;
return 2; // do not decrement the reference
return CIP_FAILED;
return CIP_OK_NODECREF;
}
//
// Other objects
@ -509,7 +605,7 @@ int pyvar_to_idcvar(
if (py_dir == NULL || !PyList_Check(py_dir) || size == 0)
{
Py_XDECREF(py_dir);
return 0;
return CIP_FAILED;
}
// Create the IDC object
VarObject(idc_var);
@ -532,10 +628,10 @@ int pyvar_to_idcvar(
attr = PyObject_GetAttrString(py_var, field_name);
if (attr == NULL
// Convert the attribute into an IDC value
|| pyvar_to_idcvar(attr, &v, gvar_sn) <= 0)
|| pyvar_to_idcvar(attr, &v, gvar_sn) < CIP_OK)
{
Py_XDECREF(attr);
return 0;
return CIP_FAILED;
}
// Store the attribute
VarSetAttr(idc_var, field_name, &v);
@ -544,18 +640,14 @@ int pyvar_to_idcvar(
}
}
}
return 1;
return CIP_OK;
}
//-------------------------------------------------------------------------
// Converts an IDC variable to a Python variable
// If py_var points to an existing object then the object will be updated
// If py_var points to an existing immutable object then ZERO is returned
// Return codes:
#define CIP_FAILED -1 // Conversion error
#define CIP_IMMUTABLE 0 // Immutable object passed. Will not update the object but no error occured
#define CIP_OK 1 // Success
#define CIP_OK_NODECREF 2 // Success but do not decrement its reference
// Returns one of CIP_xxxx. Check pywraps.hpp
int idcvar_to_pyvar(
const idc_value_t &idc_var,
PyObject **py_var)
@ -588,9 +680,11 @@ int idcvar_to_pyvar(
Py_DECREF(py_cls);
break;
}
#if !defined(NO_OBSOLETE_FUNCS) || defined(__EXPR_SRC)
case VT_STR:
*py_var = PyString_FromString(idc_var.str);
break;
#endif
case VT_STR2:
if (*py_var == NULL)
{
@ -736,7 +830,7 @@ int idcvar_to_pyvar(
%}
// Do not create separate wrappers for default arguments
%feature("compactdefaultargs");
%feature("compactdefaultargs");
#ifdef __EA64__
#ifdef __GNUC__
@ -783,7 +877,7 @@ typedef int error_t;
%binary_output_or_none(void *buf, size_t bufsize);
%binary_output_with_size(void *buf, size_t *bufsize);
// Accept single Python string for const void * + size input arguments
// Accept single Python string for const void * + size input arguments
// For example: put_many_bytes() and patch_many_bytes()
%apply (char *STRING, int LENGTH) { (const void *buf, size_t size) };
%apply (char *STRING, int LENGTH) { (const void *buf, size_t len) };
@ -858,7 +952,7 @@ idainfo *get_inf_structure(void)
%pythoncode %{
#<pycode(py_idaapi)>
import struct
# -----------------------------------------------------------------------
# Seek constants
SEEK_SET = 0 # from the file start
@ -971,6 +1065,52 @@ def as_uint32(v):
def as_int32(v):
return -((~v & 0xffffffff)+1)
# -----------------------------------------------------------------------
def as_signed(v, nbits = 32):
return -(( ~v & ((1 << nbits)-1) ) + 1) if v & (1 << nbits-1) else v
# ----------------------------------------------------------------------
# Copy bits from a value
def copy_bits(b, s, e=-1):
# end-bit not specified? use start bit (thus extract one bit)
if e == -1:
e = s
# swap start and end if start > end
if s > e:
e, s = s, e
mask = 0
for i in xrange(s, e+1):
mask |= 1 << i
return (b & mask) >> s
# ----------------------------------------------------------------------
struct_unpack_table = {
1: ('b', 'B'),
2: ('h', 'H'),
4: ('l', 'L'),
8: ('q', 'Q')
}
# ----------------------------------------------------------------------
def struct_unpack(value, signed = False, offs = 0):
"""
Unpack a value given its length and offset using struct.unpack_from().
This function will know how to unpack the given value by using the lookup table 'struct_unpack_table'
"""
# Supported length?
n = len(value)
if not n in struct_unpack_table:
return None
# Conver to number
signed = 1 if signed else 0
# Unpack
return struct.unpack_from(struct_unpack_table[n][signed], value, offs)[0]
#</pycode(py_idaapi)>
%}

View File

@ -163,29 +163,6 @@ uint32 choose_choose(PyObject *self,
#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
@ -217,6 +194,18 @@ void choose2_del_instance(PyObject *self)
class py_choose2_t
{
private:
enum
{
CHOOSE2_HAVE_DEL = 0x0001,
CHOOSE2_HAVE_INS = 0x0002,
CHOOSE2_HAVE_UPDATE = 0x0004,
CHOOSE2_HAVE_EDIT = 0x0008,
CHOOSE2_HAVE_ENTER = 0x0010,
CHOOSE2_HAVE_GETICON = 0x0020,
CHOOSE2_HAVE_GETATTR = 0x0040,
CHOOSE2_HAVE_COMMAND = 0x0080,
CHOOSE2_HAVE_ONCLOSE = 0x0100
};
int flags;
int cb_flags;
qstring title;
@ -233,7 +222,6 @@ private:
//------------------------------------------------------------------------
// 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 )
@ -244,7 +232,6 @@ private:
thisobj->on_get_line_attr(n, attr);
return 1;
}
#endif
static uint32 idaapi s_sizer(void *obj)
{
return (uint32)thisobj->on_get_size();
@ -300,7 +287,7 @@ private:
line_arr[i][0] = '\0';
// Call Python
PyObject *list = PyObject_CallMethod(self, S_ON_GET_LINE, "l", lineno - 1);
PyObject *list = PyObject_CallMethod(self, (char *)S_ON_GET_LINE, "i", lineno - 1);
if (list == NULL)
return;
for (int i=ncols-1;i>=0;i--)
@ -317,7 +304,7 @@ private:
size_t on_get_size()
{
PyObject *pyres = PyObject_CallMethod(self, S_ON_GET_SIZE, NULL);
PyObject *pyres = PyObject_CallMethod(self, (char *)S_ON_GET_SIZE, NULL);
if (pyres == NULL)
return 0;
size_t res = PyInt_AsLong(pyres);
@ -332,7 +319,7 @@ private:
unhook_from_notification_point(HT_UI, ui_cb, this);
#endif
// Call Python
PyObject *pyres = PyObject_CallMethod(self, S_ON_CLOSE, NULL);
PyObject *pyres = PyObject_CallMethod(self, (char *)S_ON_CLOSE, NULL);
Py_XDECREF(pyres);
Py_XDECREF(self);
@ -346,7 +333,7 @@ private:
int on_delete_line(int lineno)
{
PyObject *pyres = PyObject_CallMethod(self, S_ON_DELETE_LINE, "l", lineno - 1);
PyObject *pyres = PyObject_CallMethod(self, (char *)S_ON_DELETE_LINE, "i", lineno - 1);
if (pyres == NULL)
return lineno;
size_t res = PyInt_AsLong(pyres);
@ -356,7 +343,7 @@ private:
int on_refresh(int lineno)
{
PyObject *pyres = PyObject_CallMethod(self, S_ON_REFRESH, "l", lineno - 1);
PyObject *pyres = PyObject_CallMethod(self, (char *)S_ON_REFRESH, "i", lineno - 1);
if (pyres == NULL)
return lineno;
size_t res = PyInt_AsLong(pyres);
@ -366,25 +353,25 @@ private:
void on_insert_line()
{
PyObject *pyres = PyObject_CallMethod(self, S_ON_INSERT_LINE, NULL);
PyObject *pyres = PyObject_CallMethod(self, (char *)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);
PyObject *pyres = PyObject_CallMethod(self, (char *)S_ON_SELECT_LINE, "i", lineno - 1);
Py_XDECREF(pyres);
}
void on_edit_line(int lineno)
{
PyObject *pyres = PyObject_CallMethod(self, S_ON_EDIT_LINE, "l", lineno - 1);
PyObject *pyres = PyObject_CallMethod(self, (char *)S_ON_EDIT_LINE, "i", 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);
PyObject *pyres = PyObject_CallMethod(self, (char *)S_ON_COMMAND, "ii", lineno - 1, cmd_id);
if (pyres==NULL)
return lineno;
size_t res = PyInt_AsLong(pyres);
@ -394,15 +381,14 @@ private:
int on_get_icon(int lineno)
{
PyObject *pyres = PyObject_CallMethod(self, S_ON_GET_ICON, "l", lineno - 1);
PyObject *pyres = PyObject_CallMethod(self, (char *)S_ON_GET_ICON, "i", 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);
PyObject *pyres = PyObject_CallMethod(self, (char *)S_ON_GET_LINE_ATTR, "i", lineno - 1);
if (pyres == NULL)
return;
@ -416,7 +402,6 @@ private:
}
Py_XDECREF(pyres);
}
#endif
public:
//------------------------------------------------------------------------
// Public methods
@ -428,12 +413,10 @@ public:
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());
@ -459,13 +442,11 @@ public:
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,
@ -595,9 +576,7 @@ public:
{S_ON_REFRESH, CHOOSE2_HAVE_UPDATE},
{S_ON_SELECT_LINE, CHOOSE2_HAVE_ENTER},
{S_ON_COMMAND, CHOOSE2_HAVE_COMMAND},
#ifdef CH_ATTRS
{S_ON_GET_LINE_ATTR, CHOOSE2_HAVE_GETATTR},
#endif
{S_ON_GET_ICON, CHOOSE2_HAVE_GETICON}
};
cb_flags = 0;
@ -631,11 +610,10 @@ public:
}
Py_XDECREF(attr);
#ifdef CH_ATTRS
// Adjust flags (if needed)
if ( (cb_flags & CHOOSE2_HAVE_GETATTR) != 0 )
flags |= CH_ATTRS;
#endif
// Increase object reference
Py_INCREF(self);
this->self = self;
@ -666,6 +644,7 @@ public:
//------------------------------------------------------------------------
// Initialize the callback pointers
#define DECL_MENU_COMMAND_CB(id) s_menu_command_##id
chooser_cb_t *py_choose2_t::menu_cbs[MAX_CHOOSER_MENU_COMMANDS] =
{
DECL_MENU_COMMAND_CB(0), DECL_MENU_COMMAND_CB(1),
@ -674,33 +653,13 @@ chooser_cb_t *py_choose2_t::menu_cbs[MAX_CHOOSER_MENU_COMMANDS] =
DECL_MENU_COMMAND_CB(6), DECL_MENU_COMMAND_CB(7),
DECL_MENU_COMMAND_CB(8), DECL_MENU_COMMAND_CB(9)
};
#undef DECL_MENU_COMMAND_CB
#undef POPUP_NAMES_COUNT
#undef MAX_CHOOSER_MENU_COMMANDS
#undef thisobj
#undef thisdecl
#undef MENU_COMMAND_CB
#undef DECL_MENU_COMMAND_CB
#undef S_ON_EDIT_LINE
#undef S_ON_INSERT_LINE
#undef S_ON_GET_LINE
#undef S_ON_DELETE_LINE
#undef S_ON_REFRESH
#undef S_ON_SELECT_LINE
#undef S_ON_COMMAND
#undef S_ON_GET_ICON
#undef S_ON_GET_LINE_ATTR
#undef S_ON_GET_SIZE
#undef S_ON_CLOSE
#undef CHOOSE2_HAVE_DEL
#undef CHOOSE2_HAVE_INS
#undef CHOOSE2_HAVE_UPDATE
#undef CHOOSE2_HAVE_EDIT
#undef CHOOSE2_HAVE_ENTER
#undef CHOOSE2_HAVE_GETICON
#undef CHOOSE2_HAVE_GETATTR
#undef CHOOSE2_HAVE_COMMAND
#undef CHOOSE2_HAVE_ONCLOSE
//------------------------------------------------------------------------
int choose2_show(PyObject *self)