diff --git a/configure.ac b/configure.ac index fac9ee8a..98cea144 100644 --- a/configure.ac +++ b/configure.ac @@ -352,13 +352,17 @@ if test "x$python" != xno ; then PYPLAT_INC=`$pythonpath -c 'import distutils.sysconfig; print(distutils.sysconfig.get_python_inc(plat_specific=True));'` changequote([, ])dnl AC_MSG_RESULT($PY_VER) - $pythonpath -c "import sys; float(sys.version[[:3]]) >= 2.2 and int(sys.version[[0]]) < 3 or sys.exit(1)" + $pythonpath -c "import sys; float(sys.version[[:3]]) >= 2.6 and int(sys.version[[0]]) <= 3 or sys.exit(1)" if test "$?" != "1"; then AC_MSG_CHECKING(Python compile flags) PY_PREFIX=`$pythonpath -c 'import sys; print(sys.prefix)'` PY_EXEC_PREFIX=`$pythonpath -c 'import sys; print(sys.exec_prefix)'` if test -f $PY_INC/Python.h || test -f $PYPLAT_INC/Python.h; then - PY_LIBS="-L$PY_LIB/config -lpython$PY_VER -lpthread -lutil" + AS_VERSION_COMPARE($PY_VER, 3.0, + [PYL="$PY_VER"], # less than + [PYL="${PY_VER}m"], # equal + [PYL="${PY_VER}m"]) # greater than + PY_LIBS="-L$PY_LIB/config -lpython$PYL -lpthread -lutil" PY_CFLAGS="-I$PY_INC -I$PYPLAT_INC" AC_MSG_RESULT(ok) else @@ -366,7 +370,7 @@ if test "x$python" != xno ; then AC_MSG_RESULT([Can\'t find Python.h]) fi else - echo "Python is too old or too new. Only 2.2-2.7 are supported." + echo "Python is too old or too new. Only 2.6-3.x are supported." python=no fi fi diff --git a/plugins/python/python.c b/plugins/python/python.c index 7c2e5a95..707da20a 100644 --- a/plugins/python/python.c +++ b/plugins/python/python.c @@ -58,6 +58,7 @@ #ifdef WIN32 #include +#include #include "../../src/dirent/dirent-win32.h" #include "../../config-win32.h" #else @@ -71,14 +72,36 @@ #include "structmember.h" #include "pythread.h" -#define VERSION_MAJOR 0 -#define VERSION_MINOR 9 +#define VERSION_MAJOR 1 +#define VERSION_MINOR 0 +#if PY_MAJOR_VERSION == 2 #ifdef WIN32 -#undef WITH_THREAD /* Thread support locks up xchat on Win32. */ -#define VERSION "0.9/2.7" /* Linked to python27.dll */ +#undef WITH_THREAD +#define VERSION "1.0/2.7" /* Linked to python27.dll */ +#endif + +#undef PyLong_Check +#define PyLong_Check PyInt_Check +#define PyLong_AsLong PyInt_AsLong +#define PyLong_FromLong PyInt_FromLong + +#undef PyUnicode_Check +#undef PyUnicode_FromString +#define PyUnicode_Check PyString_Check +#define PyUnicode_AsFormat PyString_AsFormat +#define PyUnicode_FromString PyString_FromString +#define PyUnicode_AsUTF8 PyString_AsString + #else -#define VERSION "0.9" +#define IS_PY3K +#ifdef WIN32 +#define VERSION "1.0/3.3" /* Linked to python33.dll */ +#endif +#endif + +#ifndef VERSION +#define VERSION "1.0" #endif #define NONE 0 @@ -252,8 +275,7 @@ static PyObject *Context_compare(ContextObject *a, ContextObject *b, int op); static PyObject *Context_FromContext(hexchat_context *context); static PyObject *Context_FromServerAndChannel(char *server, char *channel); -static PyObject *Plugin_New(char *filename, PyMethodDef *xchat_methods, - PyObject *xcoobj); +static PyObject *Plugin_New(char *filename, PyObject *xcoobj); static PyObject *Plugin_GetCurrent(); static PluginObject *Plugin_ByString(char *str); static Hook *Plugin_AddHook(int type, PyObject *plugin, PyObject *callback, @@ -299,10 +321,10 @@ static int Command_Py(char *word[], char *word_eol[], void *userdata); /* ===================================================================== */ /* Static declarations and definitions */ -staticforward PyTypeObject Plugin_Type; -staticforward PyTypeObject XChatOut_Type; -staticforward PyTypeObject Context_Type; -staticforward PyTypeObject ListItem_Type; +static PyTypeObject Plugin_Type; +static PyTypeObject XChatOut_Type; +static PyTypeObject Context_Type; +static PyTypeObject ListItem_Type; static PyThreadState *main_tstate = NULL; static void *thread_timer = NULL; @@ -355,7 +377,7 @@ Util_BuildList(char *word[]) return NULL; } for (i = 0; i != listsize; i++) { - PyObject *o = PyString_FromString(word[i]); + PyObject *o = PyUnicode_FromString(word[i]); if (o == NULL) { Py_DECREF(list); PyErr_Print(); @@ -400,25 +422,10 @@ Util_Autoload() xdir = hexchat_get_info(ph, "configdir"); - /* don't pollute the filesystem with script files, this only causes misuse of the folders - * only use ~/.config/hexchat/addons/ and %APPDATA%\HexChat\addons */ -#if 0 - /* auto-load from ~/.config/hexchat/ or %APPDATA%\HexChat\ */ - Util_Autoload_from(hexchat_get_info(ph, "configdir")); -#endif - /* auto-load from subdirectory addons */ - sub_dir = malloc (strlen (xdir) + 8); - strcpy (sub_dir, xdir); - strcat (sub_dir, "/addons"); + sub_dir = g_build_filename (xdir, "addons", NULL); Util_Autoload_from(sub_dir); - free (sub_dir); - -#if 0 -#ifdef WIN32 /* also auto-load C:\Program Files\HexChat\Plugins\*.py */ - Util_Autoload_from(HEXCHATLIBDIR"/plugins"); -#endif -#endif + g_free (sub_dir); } static char * @@ -511,7 +518,7 @@ Callback_Command(char *word[], char *word_eol[], void *userdata) ret = HEXCHAT_EAT_NONE; Py_DECREF(retobj); } else if (retobj) { - ret = PyInt_AsLong(retobj); + ret = PyLong_AsLong(retobj); Py_DECREF(retobj); } else { PyErr_Print(); @@ -597,7 +604,7 @@ Callback_Print(char *word[], void *userdata) ret = HEXCHAT_EAT_NONE; Py_DECREF(retobj); } else if (retobj) { - ret = PyInt_AsLong(retobj); + ret = PyLong_AsLong(retobj); Py_DECREF(retobj); } else { PyErr_Print(); @@ -643,7 +650,9 @@ static int Callback_ThreadTimer(void *userdata) { RELEASE_XCHAT_LOCK(); +#ifndef WIN32 usleep(1); +#endif ACQUIRE_XCHAT_LOCK(); return 1; } @@ -672,7 +681,7 @@ XChatOut_New() static void XChatOut_dealloc(PyObject *self) { - self->ob_type->tp_free((PyObject *)self); + Py_TYPE(self)->tp_free((PyObject *)self); } /* This is a little bit complex because we have to buffer data @@ -765,9 +774,8 @@ static PyMethodDef XChatOut_methods[] = { {NULL, NULL} }; -statichere PyTypeObject XChatOut_Type = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ +static PyTypeObject XChatOut_Type = { + PyVarObject_HEAD_INIT(NULL, 0) "hexchat.XChatOut", /*tp_name*/ sizeof(XChatOutObject), /*tp_basicsize*/ 0, /*tp_itemsize*/ @@ -805,7 +813,7 @@ statichere PyTypeObject XChatOut_Type = { 0, /*tp_init*/ PyType_GenericAlloc, /*tp_alloc*/ PyType_GenericNew, /*tp_new*/ - _PyObject_Del, /*tp_free*/ + PyObject_Del, /*tp_free*/ 0, /*tp_is_gc*/ }; @@ -816,7 +824,7 @@ statichere PyTypeObject XChatOut_Type = { static void Context_dealloc(PyObject *self) { - self->ob_type->tp_free((PyObject *)self); + Py_TYPE(self)->tp_free((PyObject *)self); } static PyObject * @@ -874,7 +882,7 @@ Context_emit_print(ContextObject *self, PyObject *args) argv[3], argv[4], argv[5], argv[6], argv[7], argv[8]); END_XCHAT_CALLS(); - return PyInt_FromLong(res); + return PyLong_FromLong(res); } static PyObject * @@ -892,7 +900,7 @@ Context_get_info(ContextObject *self, PyObject *args) Py_INCREF(Py_None); return Py_None; } - return PyString_FromString(info); + return PyUnicode_FromString(info); } static PyObject * @@ -922,10 +930,10 @@ Context_compare(ContextObject *a, ContextObject *b, int op) else { PyErr_SetString(PyExc_TypeError, "contexts are either equal or not equal"); + Py_INCREF(Py_None); ret = Py_None; } - Py_INCREF(ret); return ret; } @@ -939,9 +947,8 @@ static PyMethodDef Context_methods[] = { {NULL, NULL} }; -statichere PyTypeObject Context_Type = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ +static PyTypeObject Context_Type = { + PyVarObject_HEAD_INIT(NULL, 0) "hexchat.Context", /*tp_name*/ sizeof(ContextObject), /*tp_basicsize*/ 0, /*tp_itemsize*/ @@ -979,7 +986,7 @@ statichere PyTypeObject Context_Type = { 0, /*tp_init*/ PyType_GenericAlloc, /*tp_alloc*/ PyType_GenericNew, /*tp_new*/ - _PyObject_Del, /*tp_free*/ + PyObject_Del, /*tp_free*/ 0, /*tp_is_gc*/ }; @@ -1025,19 +1032,18 @@ static void ListItem_dealloc(PyObject *self) { Py_DECREF(((ListItemObject*)self)->dict); - self->ob_type->tp_free((PyObject *)self); + Py_TYPE(self)->tp_free((PyObject *)self); } static PyObject * ListItem_repr(PyObject *self) { - return PyString_FromFormat("<%s list item at %p>", + return PyUnicode_FromFormat("<%s list item at %p>", ((ListItemObject*)self)->listname, self); } -statichere PyTypeObject ListItem_Type = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ +static PyTypeObject ListItem_Type = { + PyVarObject_HEAD_INIT(NULL, 0) "hexchat.ListItem", /*tp_name*/ sizeof(ListItemObject), /*tp_basicsize*/ 0, /*tp_itemsize*/ @@ -1075,7 +1081,7 @@ statichere PyTypeObject ListItem_Type = { 0, /*tp_init*/ PyType_GenericAlloc, /*tp_alloc*/ PyType_GenericNew, /*tp_new*/ - _PyObject_Del, /*tp_free*/ + PyObject_Del, /*tp_free*/ 0, /*tp_is_gc*/ }; @@ -1110,12 +1116,12 @@ ListItem_New(const char *listname) } \ plugin->x = g_strdup(""); \ } else {\ - if (!PyString_Check(o)) { \ + if (!PyUnicode_Check(o)) { \ hexchat_print(ph, "Variable __module_" #x "__ " \ "must be a string"); \ goto error; \ } \ - plugin->x = g_strdup(PyString_AsString(o)); \ + plugin->x = g_strdup(PyUnicode_AsUTF8(o)); \ if (plugin->x == NULL) { \ hexchat_print(ph, "Not enough memory to allocate " #x); \ goto error; \ @@ -1123,11 +1129,15 @@ ListItem_New(const char *listname) } static PyObject * -Plugin_New(char *filename, PyMethodDef *xchat_methods, PyObject *xcoobj) +Plugin_New(char *filename, PyObject *xcoobj) { PluginObject *plugin = NULL; - PyObject *m, *hm, *xm, *o; - char *argv[] = {"", 0}; + PyObject *m, *o; +#ifdef IS_PY3K + wchar_t *argv[] = { L"", 0 }; +#else + char *argv[] = { "", 0 }; +#endif if (filename) { char *old_filename = filename; @@ -1153,7 +1163,7 @@ Plugin_New(char *filename, PyMethodDef *xchat_methods, PyObject *xcoobj) Plugin_SetContext(plugin, hexchat_get_context(ph)); /* Start a new interpreter environment for this plugin. */ - PyEval_AcquireLock(); + PyEval_AcquireThread(main_tstate); plugin->tstate = Py_NewInterpreter(); if (plugin->tstate == NULL) { hexchat_print(ph, "Can't create interpreter state"); @@ -1169,67 +1179,27 @@ Plugin_New(char *filename, PyMethodDef *xchat_methods, PyObject *xcoobj) Py_INCREF(xcoobj); PySys_SetObject("stderr", xcoobj); - /* Add xchat module to the environment. */ - xm = Py_InitModule("xchat", xchat_methods); - if (xm == NULL) { - hexchat_print(ph, "Can't create xchat module"); - goto error; - } - hm = Py_InitModule("hexchat", xchat_methods); - if (hm == NULL) { - hexchat_print(ph, "Can't create hexchat module"); - goto error; - } - - PyModule_AddIntConstant(xm, "EAT_NONE", HEXCHAT_EAT_NONE); - PyModule_AddIntConstant(xm, "EAT_XCHAT", HEXCHAT_EAT_HEXCHAT); - PyModule_AddIntConstant(xm, "EAT_PLUGIN", HEXCHAT_EAT_PLUGIN); - PyModule_AddIntConstant(xm, "EAT_ALL", HEXCHAT_EAT_ALL); - PyModule_AddIntConstant(xm, "PRI_HIGHEST", HEXCHAT_PRI_HIGHEST); - PyModule_AddIntConstant(xm, "PRI_HIGH", HEXCHAT_PRI_HIGH); - PyModule_AddIntConstant(xm, "PRI_NORM", HEXCHAT_PRI_NORM); - PyModule_AddIntConstant(xm, "PRI_LOW", HEXCHAT_PRI_LOW); - PyModule_AddIntConstant(xm, "PRI_LOWEST", HEXCHAT_PRI_LOWEST); - PyModule_AddIntConstant(hm, "EAT_NONE", HEXCHAT_EAT_NONE); - PyModule_AddIntConstant(hm, "EAT_HEXCHAT", HEXCHAT_EAT_HEXCHAT); - PyModule_AddIntConstant(hm, "EAT_PLUGIN", HEXCHAT_EAT_PLUGIN); - PyModule_AddIntConstant(hm, "EAT_ALL", HEXCHAT_EAT_ALL); - PyModule_AddIntConstant(hm, "PRI_HIGHEST", HEXCHAT_PRI_HIGHEST); - PyModule_AddIntConstant(hm, "PRI_HIGH", HEXCHAT_PRI_HIGH); - PyModule_AddIntConstant(hm, "PRI_NORM", HEXCHAT_PRI_NORM); - PyModule_AddIntConstant(hm, "PRI_LOW", HEXCHAT_PRI_LOW); - PyModule_AddIntConstant(hm, "PRI_LOWEST", HEXCHAT_PRI_LOWEST); - - - - o = Py_BuildValue("(ii)", VERSION_MAJOR, VERSION_MINOR); - if (o == NULL) { - hexchat_print(ph, "Can't create version tuple"); - goto error; - } - PyObject_SetAttrString(xm, "__version__", o); - PyObject_SetAttrString(hm, "__version__", o); - if (filename) { #ifdef WIN32 - PyObject* PyFileObject = PyFile_FromString(filename, "r"); - if (PyFileObject == NULL) { + char *file; + if (!g_file_get_contents_utf8(filename, &file, NULL, NULL)) { hexchat_printf(ph, "Can't open file %s: %s\n", filename, strerror(errno)); goto error; } - if (PyRun_SimpleFile(PyFile_AsFile(PyFileObject), filename) != 0) { + if (PyRun_SimpleString(file) != 0) { hexchat_printf(ph, "Error loading module %s\n", filename); + g_free (file); goto error; } plugin->filename = filename; filename = NULL; + g_free (file); #else FILE *fp; - plugin->filename = filename; /* It's now owned by the plugin. */ @@ -1276,7 +1246,11 @@ error: if (plugin) { if (plugin->tstate) - Py_EndInterpreter(plugin->tstate); + { + /* FIXME: Handle this? */ + if (plugin->tstate == PyInterpreterState_ThreadHead(plugin->tstate->interp)) + Py_EndInterpreter(plugin->tstate); + } Py_DECREF(plugin); } PyEval_ReleaseLock(); @@ -1417,12 +1391,11 @@ Plugin_dealloc(PluginObject *self) g_free(self->name); g_free(self->version); g_free(self->description); - self->ob_type->tp_free((PyObject *)self); + Py_TYPE(self)->tp_free((PyObject *)self); } -statichere PyTypeObject Plugin_Type = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ +static PyTypeObject Plugin_Type = { + PyVarObject_HEAD_INIT(NULL, 0) "hexchat.Plugin", /*tp_name*/ sizeof(PluginObject), /*tp_basicsize*/ 0, /*tp_itemsize*/ @@ -1460,7 +1433,7 @@ statichere PyTypeObject Plugin_Type = { 0, /*tp_init*/ PyType_GenericAlloc, /*tp_alloc*/ PyType_GenericNew, /*tp_new*/ - _PyObject_Del, /*tp_free*/ + PyObject_Del, /*tp_free*/ 0, /*tp_is_gc*/ }; @@ -1511,7 +1484,7 @@ Module_hexchat_emit_print(PyObject *self, PyObject *args) argv[3], argv[4], argv[5], argv[6], argv[7], argv[8]); END_XCHAT_CALLS(); - return PyInt_FromLong(res); + return PyLong_FromLong(res); } static PyObject * @@ -1528,7 +1501,7 @@ Module_hexchat_get_info(PyObject *self, PyObject *args) Py_INCREF(Py_None); return Py_None; } - return PyString_FromString(info); + return PyUnicode_FromString(info); } static PyObject * @@ -1550,11 +1523,11 @@ Module_xchat_get_prefs(PyObject *self, PyObject *args) res = Py_None; break; case 1: - res = PyString_FromString((char*)info); + res = PyUnicode_FromString((char*)info); break; case 2: case 3: - res = PyInt_FromLong(integer); + res = PyLong_FromLong(integer); break; default: PyErr_Format(PyExc_RuntimeError, @@ -1608,16 +1581,20 @@ Module_hexchat_pluginpref_set(PyObject *self, PyObject *args) PyObject *value; if (!PyArg_ParseTuple(args, "sO:set_pluginpref", &var, &value)) return NULL; - if (PyInt_Check(value)) { - int intvalue = PyInt_AsLong(value); - result = PyInt_FromLong(hexchat_pluginpref_set_int(ph, var, intvalue)); + if (PyLong_Check(value)) { + int intvalue = PyLong_AsLong(value); + BEGIN_XCHAT_CALLS(NONE); + result = PyLong_FromLong(hexchat_pluginpref_set_int(ph, var, intvalue)); + END_XCHAT_CALLS(); } - else if (PyString_Check(value)) { - char *charvalue = PyString_AsString(value); - result = PyInt_FromLong(hexchat_pluginpref_set_str(ph, var, charvalue)); + else if (PyUnicode_Check(value)) { + char *charvalue = PyUnicode_AsUTF8(value); + BEGIN_XCHAT_CALLS(NONE); + result = PyLong_FromLong(hexchat_pluginpref_set_str(ph, var, charvalue)); + END_XCHAT_CALLS(); } else - result = PyInt_FromLong(0); + result = PyLong_FromLong(0); return result; } @@ -1628,20 +1605,27 @@ Module_hexchat_pluginpref_get(PyObject *self, PyObject *args) char *var; char retstr[512]; int retint; + int result; if (!PyArg_ParseTuple(args, "s:get_pluginpref", &var)) return NULL; // This will always return numbers as integers. - if (hexchat_pluginpref_get_str(ph, var, retstr)) { + BEGIN_XCHAT_CALLS(NONE); + result = hexchat_pluginpref_get_str(ph, var, retstr); + END_XCHAT_CALLS(); + if (result) { if (strlen (retstr) <= 12) { + BEGIN_XCHAT_CALLS(NONE); retint = hexchat_pluginpref_get_int(ph, var); + END_XCHAT_CALLS(); if ((retint == 0) && (strcmp(retstr, "0") != 0)) - ret = PyString_FromString(retstr); + ret = PyUnicode_FromString(retstr); else - ret = PyInt_FromLong(retint); + ret = PyLong_FromLong(retint); } else - ret = PyString_FromString(retstr); + ret = PyUnicode_FromString(retstr); } else + Py_INCREF(Py_None); ret = Py_None; return ret; } @@ -1653,8 +1637,10 @@ Module_hexchat_pluginpref_delete(PyObject *self, PyObject *args) int result; if (!PyArg_ParseTuple(args, "s:del_pluginpref", &var)) return NULL; + BEGIN_XCHAT_CALLS(NONE); result = hexchat_pluginpref_delete(ph, var); - return PyInt_FromLong(result); + END_XCHAT_CALLS(); + return PyLong_FromLong(result); } static PyObject * @@ -1662,12 +1648,16 @@ Module_hexchat_pluginpref_list(PyObject *self, PyObject *args) { char list[512]; char* token; + int result; PyObject *pylist; pylist = PyList_New(0); - if (hexchat_pluginpref_list(ph, list)) { + BEGIN_XCHAT_CALLS(NONE); + result = hexchat_pluginpref_list(ph, list); + END_XCHAT_CALLS(); + if (result) { token = strtok(list, ","); while (token != NULL) { - PyList_Append(pylist, PyString_FromString(token)); + PyList_Append(pylist, PyUnicode_FromString(token)); token = strtok (NULL, ","); } } @@ -1709,7 +1699,7 @@ Module_hexchat_hook_command(PyObject *self, PyObject *args, PyObject *kwargs) Callback_Command, help, hook); END_XCHAT_CALLS(); - return PyInt_FromLong((long)hook); + return PyLong_FromLong((long)hook); } static PyObject * @@ -1745,7 +1735,7 @@ Module_hexchat_hook_server(PyObject *self, PyObject *args, PyObject *kwargs) Callback_Command, hook); END_XCHAT_CALLS(); - return PyInt_FromLong((long)hook); + return PyLong_FromLong((long)hook); } static PyObject * @@ -1781,10 +1771,9 @@ Module_hexchat_hook_print(PyObject *self, PyObject *args, PyObject *kwargs) Callback_Print, hook); END_XCHAT_CALLS(); - return PyInt_FromLong((long)hook); + return PyLong_FromLong((long)hook); } - static PyObject * Module_hexchat_hook_timer(PyObject *self, PyObject *args, PyObject *kwargs) { @@ -1817,7 +1806,7 @@ Module_hexchat_hook_timer(PyObject *self, PyObject *args, PyObject *kwargs) Callback_Timer, hook); END_XCHAT_CALLS(); - return PyInt_FromLong((long)hook); + return PyLong_FromLong((long)hook); } static PyObject * @@ -1845,7 +1834,7 @@ Module_hexchat_hook_unload(PyObject *self, PyObject *args, PyObject *kwargs) if (hook == NULL) return NULL; - return PyInt_FromLong((long)hook); + return PyLong_FromLong((long)hook); } static PyObject * @@ -1911,11 +1900,11 @@ Module_xchat_get_list(PyObject *self, PyObject *args) switch(fields[i][0]) { case 's': sattr = hexchat_list_str(ph, list, (char*)fld); - attr = PyString_FromString(sattr?sattr:""); + attr = PyUnicode_FromString(sattr?sattr:""); break; case 'i': iattr = hexchat_list_int(ph, list, (char*)fld); - attr = PyInt_FromLong((long)iattr); + attr = PyLong_FromLong((long)iattr); break; case 'p': sattr = hexchat_list_str(ph, list, (char*)fld); @@ -1959,7 +1948,7 @@ Module_xchat_get_lists(PyObject *self, PyObject *args) if (l == NULL) return NULL; for (i = 0; fields[i]; i++) { - o = PyString_FromString(fields[i]); + o = PyUnicode_FromString(fields[i]); if (o == NULL || PyList_Append(l, o) == -1) { Py_DECREF(l); Py_XDECREF(o); @@ -1976,7 +1965,7 @@ Module_hexchat_nickcmp(PyObject *self, PyObject *args) char *s1, *s2; if (!PyArg_ParseTuple(args, "ss:nickcmp", &s1, &s2)) return NULL; - return PyInt_FromLong((long) hexchat_nickcmp(ph, s1, s2)); + return PyLong_FromLong((long) hexchat_nickcmp(ph, s1, s2)); } static PyObject * @@ -1988,7 +1977,7 @@ Module_hexchat_strip(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "s|ii:strip", &str, &len, &flags)) return NULL; str2 = hexchat_strip(ph, str, len, flags); - result = PyString_FromString(str2); + result = PyUnicode_FromString(str2); hexchat_free(ph, str2); return result; } @@ -2039,6 +2028,106 @@ static PyMethodDef Module_xchat_methods[] = { {NULL, NULL} }; +#ifdef IS_PY3K +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + "hexchat", /* m_name */ + "HexChat Scripting Interface", /* m_doc */ + -1, /* m_size */ + Module_xchat_methods, /* m_methods */ + NULL, /* m_reload */ + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL, /* m_free */ +}; + +static struct PyModuleDef xchat_moduledef = { + PyModuleDef_HEAD_INIT, + "xchat", /* m_name */ + "HexChat Scripting Interface", /* m_doc */ + -1, /* m_size */ + Module_xchat_methods, /* m_methods */ + NULL, /* m_reload */ + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL, /* m_free */ +}; +#endif + +static PyObject * +moduleinit_hexchat(void) +{ + PyObject *hm; +#ifdef IS_PY3K + hm = PyModule_Create(&moduledef); +#else + hm = Py_InitModule3("hexchat", Module_xchat_methods, "HexChat Scripting Interface"); +#endif + + PyModule_AddIntConstant(hm, "EAT_NONE", HEXCHAT_EAT_NONE); + PyModule_AddIntConstant(hm, "EAT_HEXCHAT", HEXCHAT_EAT_HEXCHAT); + PyModule_AddIntConstant(hm, "EAT_XCHAT", HEXCHAT_EAT_HEXCHAT); /* for compat */ + PyModule_AddIntConstant(hm, "EAT_PLUGIN", HEXCHAT_EAT_PLUGIN); + PyModule_AddIntConstant(hm, "EAT_ALL", HEXCHAT_EAT_ALL); + PyModule_AddIntConstant(hm, "PRI_HIGHEST", HEXCHAT_PRI_HIGHEST); + PyModule_AddIntConstant(hm, "PRI_HIGH", HEXCHAT_PRI_HIGH); + PyModule_AddIntConstant(hm, "PRI_NORM", HEXCHAT_PRI_NORM); + PyModule_AddIntConstant(hm, "PRI_LOW", HEXCHAT_PRI_LOW); + PyModule_AddIntConstant(hm, "PRI_LOWEST", HEXCHAT_PRI_LOWEST); + + PyObject_SetAttrString(hm, "__version__", Py_BuildValue("(ii)", VERSION_MAJOR, VERSION_MINOR)); + + return hm; +} + +static PyObject * +moduleinit_xchat(void) +{ + PyObject *xm; +#ifdef IS_PY3K + xm = PyModule_Create(&xchat_moduledef); +#else + xm = Py_InitModule3("xchat", Module_xchat_methods, "HexChat Scripting Interface"); +#endif + + PyModule_AddIntConstant(xm, "EAT_NONE", HEXCHAT_EAT_NONE); + PyModule_AddIntConstant(xm, "EAT_XCHAT", HEXCHAT_EAT_HEXCHAT); + PyModule_AddIntConstant(xm, "EAT_PLUGIN", HEXCHAT_EAT_PLUGIN); + PyModule_AddIntConstant(xm, "EAT_ALL", HEXCHAT_EAT_ALL); + PyModule_AddIntConstant(xm, "PRI_HIGHEST", HEXCHAT_PRI_HIGHEST); + PyModule_AddIntConstant(xm, "PRI_HIGH", HEXCHAT_PRI_HIGH); + PyModule_AddIntConstant(xm, "PRI_NORM", HEXCHAT_PRI_NORM); + PyModule_AddIntConstant(xm, "PRI_LOW", HEXCHAT_PRI_LOW); + PyModule_AddIntConstant(xm, "PRI_LOWEST", HEXCHAT_PRI_LOWEST); + + PyObject_SetAttrString(xm, "__version__", Py_BuildValue("(ii)", VERSION_MAJOR, VERSION_MINOR)); + + return xm; +} + +#ifdef IS_PY3K +PyMODINIT_FUNC +PyInit_hexchat(void) +{ + return moduleinit_hexchat(); +} +PyMODINIT_FUNC +PyInit_xchat(void) +{ + return moduleinit_xchat(); +} +#else +PyMODINIT_FUNC +inithexchat(void) +{ + moduleinit_hexchat(); +} +PyMODINIT_FUNC +initxchat(void) +{ + moduleinit_xchat(); +} +#endif /* ===================================================================== */ /* Python interactive interpreter functions */ @@ -2046,18 +2135,18 @@ static PyMethodDef Module_xchat_methods[] = { static void IInterp_Exec(char *command) { - PyObject *m, *d, *o; + PyObject *m, *d, *o; char *buffer; int len; BEGIN_PLUGIN(interp_plugin); - m = PyImport_AddModule("__main__"); - if (m == NULL) { + m = PyImport_AddModule("__main__"); + if (m == NULL) { hexchat_print(ph, "Can't get __main__ module"); goto fail; } - d = PyModule_GetDict(m); + d = PyModule_GetDict(m); len = strlen(command); buffer = (char *) g_malloc(len+2); if (buffer == NULL) { @@ -2067,20 +2156,17 @@ IInterp_Exec(char *command) memcpy(buffer, command, len); buffer[len] = '\n'; buffer[len+1] = 0; - o = PyRun_StringFlags(buffer, Py_single_input, d, d, NULL); + o = PyRun_StringFlags(buffer, Py_single_input, d, d, NULL); g_free(buffer); - if (o == NULL) { - PyErr_Print(); + if (o == NULL) { + PyErr_Print(); goto fail; - } - Py_DECREF(o); - if (Py_FlushLine()) - PyErr_Clear(); + } + Py_DECREF(o); fail: END_PLUGIN(interp_plugin); - - return; + return; } static int @@ -2132,7 +2218,7 @@ Command_PyLoad(char *filename) { PyObject *plugin; RELEASE_XCHAT_LOCK(); - plugin = Plugin_New(filename, Module_xchat_methods, xchatout); + plugin = Plugin_New(filename, xchatout); ACQUIRE_XCHAT_LOCK(); if (plugin) plugin_list = g_slist_append(plugin_list, plugin); @@ -2162,7 +2248,6 @@ Command_PyReload(char *name) char *filename = g_strdup(plugin->filename); Command_PyUnload(filename); Command_PyLoad(filename); - /* cppcheck-suppress deallocDealloc */ g_free(filename); } } @@ -2225,22 +2310,22 @@ Command_Load(char *word[], char *word_eol[], void *userdata) } static int -Command_Unload(char *word[], char *word_eol[], void *userdata) +Command_Reload(char *word[], char *word_eol[], void *userdata) { int len = strlen(word[2]); if (len > 3 && strcasecmp(".py", word[2]+len-3) == 0) { - Command_PyUnload(word[2]); - return HEXCHAT_EAT_HEXCHAT; + Command_PyReload(word[2]); + return HEXCHAT_EAT_HEXCHAT; } return HEXCHAT_EAT_NONE; } static int -Command_Reload(char *word[], char *word_eol[], void *userdata) +Command_Unload(char *word[], char *word_eol[], void *userdata) { int len = strlen(word[2]); if (len > 3 && strcasecmp(".py", word[2]+len-3) == 0) { - Command_PyReload(word[2]); + Command_PyUnload(word[2]); return HEXCHAT_EAT_HEXCHAT; } return HEXCHAT_EAT_NONE; @@ -2272,7 +2357,11 @@ hexchat_plugin_init(hexchat_plugin *plugin_handle, char **plugin_version, char *arg) { - char *argv[] = {"", 0}; +#ifdef IS_PY3K + wchar_t *argv[] = { L"", 0 }; +#else + char *argv[] = { "", 0 }; +#endif ph = plugin_handle; @@ -2291,14 +2380,18 @@ hexchat_plugin_init(hexchat_plugin *plugin_handle, *plugin_desc = "Python scripting interface"; /* Initialize python. */ - Py_SetProgramName("xchat"); +#ifdef IS_PY3K + Py_SetProgramName(L"hexchat"); + PyImport_AppendInittab("hexchat", PyInit_hexchat); + PyImport_AppendInittab("xchat", PyInit_xchat); +#else + Py_SetProgramName("hexchat"); + PyImport_AppendInittab("hexchat", inithexchat); + PyImport_AppendInittab("xchat", initxchat); +#endif Py_Initialize(); PySys_SetArgv(1, argv); - Plugin_Type.ob_type = &PyType_Type; - Context_Type.ob_type = &PyType_Type; - XChatOut_Type.ob_type = &PyType_Type; - xchatout = XChatOut_New(); if (xchatout == NULL) { hexchat_print(ph, "Can't allocate xchatout object"); @@ -2309,7 +2402,7 @@ hexchat_plugin_init(hexchat_plugin *plugin_handle, PyEval_InitThreads(); xchat_lock = PyThread_allocate_lock(); if (xchat_lock == NULL) { - hexchat_print(ph, "Can't allocate xchat lock"); + hexchat_print(ph, "Can't allocate hexchat lock"); Py_DECREF(xchatout); xchatout = NULL; return 0; @@ -2318,7 +2411,7 @@ hexchat_plugin_init(hexchat_plugin *plugin_handle, main_tstate = PyEval_SaveThread(); - interp_plugin = Plugin_New(NULL, Module_xchat_methods, xchatout); + interp_plugin = Plugin_New(NULL, xchatout); if (interp_plugin == NULL) { hexchat_print(ph, "Plugin_New() failed.\n"); #ifdef WITH_THREAD @@ -2381,6 +2474,7 @@ hexchat_plugin_deinit() /* Switch back to the main thread state. */ if (main_tstate) { + PyEval_RestoreThread(main_tstate); PyThreadState_Swap(main_tstate); main_tstate = NULL; } diff --git a/plugins/python/python.vcxproj b/plugins/python/python2.vcxproj similarity index 84% rename from plugins/python/python.vcxproj rename to plugins/python/python2.vcxproj index 6d95d056..e2153c4a 100644 --- a/plugins/python/python.vcxproj +++ b/plugins/python/python2.vcxproj @@ -16,7 +16,7 @@ {19C52A0A-A790-409E-A28A-9745FF990F5C} Win32Proj - python + python2 @@ -51,7 +51,7 @@ false - $(PythonOutput) + $(Python2Output) $(HexChatBin) $(HexChatObj)$(ProjectName)\ @@ -63,7 +63,7 @@ true true WIN32;NDEBUG;_WINDOWS;_USRDLL;PYTHON_EXPORTS;$(OwnFlags);%(PreprocessorDefinitions) - $(Glib);$(PythonPath)\include;..\..\src\common;%(AdditionalIncludeDirectories) + $(Glib);$(Python2Path)\include;..\..\src\common;%(AdditionalIncludeDirectories) true @@ -72,8 +72,8 @@ true true python.def - "$(PythonLib).lib";$(DepLibs);%(AdditionalDependencies) - $(DepsRoot)\lib;$(OutDir);$(PythonPath)\libs;%(AdditionalLibraryDirectories) + "$(Python2Lib).lib";$(DepLibs);%(AdditionalDependencies) + $(DepsRoot)\lib;$(OutDir);$(Python2Path)\libs;%(AdditionalLibraryDirectories) @@ -84,7 +84,7 @@ true true WIN32;_WIN64;_AMD64_;NDEBUG;_WINDOWS;_USRDLL;PYTHON_EXPORTS;$(OwnFlags);%(PreprocessorDefinitions) - $(Glib);$(PythonPath)\include;..\..\src\common;%(AdditionalIncludeDirectories) + $(Glib);$(Python2Path)\include;..\..\src\common;%(AdditionalIncludeDirectories) true @@ -93,8 +93,8 @@ true true python.def - "$(PythonLib).lib";$(DepLibs);%(AdditionalDependencies) - $(DepsRoot)\lib;$(OutDir);$(PythonPath)\libs;%(AdditionalLibraryDirectories) + "$(Python2Lib).lib";$(DepLibs);%(AdditionalDependencies) + $(DepsRoot)\lib;$(OutDir);$(Python2Path)\libs;%(AdditionalLibraryDirectories) diff --git a/plugins/python/python.vcxproj.filters b/plugins/python/python2.vcxproj.filters similarity index 100% rename from plugins/python/python.vcxproj.filters rename to plugins/python/python2.vcxproj.filters diff --git a/plugins/python/python3.vcxproj b/plugins/python/python3.vcxproj new file mode 100644 index 00000000..ddf56132 --- /dev/null +++ b/plugins/python/python3.vcxproj @@ -0,0 +1,109 @@ + + + + v110 + + + + Release + Win32 + + + Release + x64 + + + + {C2321A03-0BA7-45B3-8740-ABD82B36B0BF} + Win32Proj + python3 + + + + DynamicLibrary + false + true + MultiByte + + + DynamicLibrary + false + true + MultiByte + + + + + + + + + + + + + + + false + $(Python3Output) + $(HexChatBin) + $(HexChatObj)$(ProjectName)\ + + + false + $(Python3Output) + $(HexChatBin) + $(HexChatObj)$(ProjectName)\ + + + + + + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;PYTHON_EXPORTS;$(OwnFlags);%(PreprocessorDefinitions) + $(Glib);$(Python3Path)\include;..\..\src\common;%(AdditionalIncludeDirectories) + true + + + Windows + true + true + true + python.def + "$(Python3Lib).lib";$(DepLibs);%(AdditionalDependencies) + $(DepsRoot)\lib;$(OutDir);$(Python3Path)\libs;%(AdditionalLibraryDirectories) + + + + + + + MaxSpeed + true + true + WIN32;_WIN64;_AMD64_;NDEBUG;_WINDOWS;_USRDLL;PYTHON_EXPORTS;$(OwnFlags);%(PreprocessorDefinitions) + $(Glib);$(Python3Path)\include;..\..\src\common;%(AdditionalIncludeDirectories) + true + + + Windows + true + true + true + python.def + "$(Python3Lib).lib";$(DepLibs);%(AdditionalDependencies) + $(DepsRoot)\lib;$(OutDir);$(Python3Path)\libs;%(AdditionalLibraryDirectories) + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/python/python3.vcxproj.filters b/plugins/python/python3.vcxproj.filters new file mode 100644 index 00000000..9165e798 --- /dev/null +++ b/plugins/python/python3.vcxproj.filters @@ -0,0 +1,21 @@ + + + + + {f4eaf231-f095-42d3-8427-b2b6006cacb1} + + + {0166c0f9-7968-4a09-9ef5-a5179c7746eb} + + + + + Source Files + + + + + Resource Files + + + \ No newline at end of file diff --git a/src/common/plugin.c b/src/common/plugin.c index a9955327..c9183ede 100644 --- a/src/common/plugin.c +++ b/src/common/plugin.c @@ -489,7 +489,8 @@ plugin_auto_load (session *sess) for_files (HEXCHATLIBDIR, "hcfishlim.dll", plugin_auto_load_cb); for_files (HEXCHATLIBDIR, "hcmpcinfo.dll", plugin_auto_load_cb); for_files (HEXCHATLIBDIR, "hcperl.dll", plugin_auto_load_cb); - for_files (HEXCHATLIBDIR, "hcpython.dll", plugin_auto_load_cb); + for_files (HEXCHATLIBDIR, "hcpython2.dll", plugin_auto_load_cb); + for_files (HEXCHATLIBDIR, "hcpython3.dll", plugin_auto_load_cb); for_files (HEXCHATLIBDIR, "hcupd.dll", plugin_auto_load_cb); for_files (HEXCHATLIBDIR, "hcwinamp.dll", plugin_auto_load_cb); for_files (HEXCHATLIBDIR, "hcsysinfo.dll", plugin_auto_load_cb); diff --git a/win32/hexchat.props b/win32/hexchat.props index 5feac5ad..4da1a3ff 100644 --- a/win32/hexchat.props +++ b/win32/hexchat.props @@ -10,7 +10,8 @@ c:\mozilla-build\gendef c:\mozilla-build\msgfmt c:\mozilla-build\perl-5.18 - c:\mozilla-build\python-2.7 + c:\mozilla-build\python-2.7 + c:\mozilla-build\python-3.3 @@ -22,9 +23,12 @@ $(YourPerlPath)\$(PlatformName) perl517 hcperl - $(YourPythonPath)\$(PlatformName) - python27 - hcpython + $(YourPython2Path)\$(PlatformName) + python27 + hcpython2 + $(YourPython3Path)\$(PlatformName) + python33 + hcpython3 $(DepsRoot)\include\glib-2.0;$(DepsRoot)\lib\glib-2.0\include;$(DepsRoot)\include\libxml2 $(DepsRoot)\include\gtk-2.0;$(DepsRoot)\lib\gtk-2.0\include;$(DepsRoot)\include\atk-1.0;$(DepsRoot)\include\cairo;$(DepsRoot)\include\pango-1.0;$(DepsRoot)\include\gdk-pixbuf-2.0 png_ulist_voice "$(SolutionDir)\..\src\pixmaps\ulist_voice.png" png_ulist_halfop "$(SolutionDir)\..\src\pixmaps\ulist_halfop.png" png_ulist_op "$(SolutionDir)\..\src\pixmaps\ulist_op.png" png_ulist_owner "$(SolutionDir)\..\src\pixmaps\ulist_owner.png" png_ulist_founder "$(SolutionDir)\..\src\pixmaps\ulist_founder.png" png_ulist_netop "$(SolutionDir)\..\src\pixmaps\ulist_netop.png" png_tray_fileoffer "$(SolutionDir)\..\src\pixmaps\tray_fileoffer.png" png_tray_highlight "$(SolutionDir)\..\src\pixmaps\tray_highlight.png" png_tray_message "$(SolutionDir)\..\src\pixmaps\tray_message.png" png_tree_channel "$(SolutionDir)\..\src\pixmaps\tree_channel.png" png_tree_dialog "$(SolutionDir)\..\src\pixmaps\tree_dialog.png" png_tree_server "$(SolutionDir)\..\src\pixmaps\tree_server.png" png_tree_util "$(SolutionDir)\..\src\pixmaps\tree_util.png" png_book "$(SolutionDir)\..\src\pixmaps\book.png" png_hexchat "$(SolutionDir)\..\src\pixmaps\hexchat.png" @@ -82,7 +86,8 @@ copy "$(HexChatBin)hcexec.dll" "$(HexChatRel)\plugins" copy "$(HexChatBin)hcfishlim.dll" "$(HexChatRel)\plugins" copy "$(HexChatBin)hcmpcinfo.dll" "$(HexChatRel)\plugins" copy "$(HexChatBin)hcperl.dll" "$(HexChatRel)\plugins" -copy "$(HexChatBin)hcpython.dll" "$(HexChatRel)\plugins" +copy "$(HexChatBin)hcpython2.dll" "$(HexChatRel)\plugins" +copy "$(HexChatBin)hcpython3.dll" "$(HexChatRel)\plugins" copy "$(HexChatBin)hcupd.dll" "$(HexChatRel)\plugins" copy "$(HexChatBin)hcwinamp.dll" "$(HexChatRel)\plugins" copy "$(HexChatBin)hcsysinfo.dll" "$(HexChatRel)\plugins" diff --git a/win32/hexchat.sln b/win32/hexchat.sln index 4bc940e3..cba64c36 100644 --- a/win32/hexchat.sln +++ b/win32/hexchat.sln @@ -1,6 +1,6 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Express 2012 for Windows Desktop +# Visual Studio 2012 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "common", "..\src\common\common.vcxproj", "{87554B59-006C-4D94-9714-897B27067BA3}" ProjectSection(ProjectDependencies) = postProject {A7D7CE59-2A31-48AE-BED2-A9828E241832} = {A7D7CE59-2A31-48AE-BED2-A9828E241832} @@ -30,7 +30,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "scripting", "scripting", "{ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "common", "common", "{BB051F0F-A841-4A9A-BAF6-51DD9866D65A}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "python", "..\plugins\python\python.vcxproj", "{19C52A0A-A790-409E-A28A-9745FF990F5C}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "python2", "..\plugins\python\python2.vcxproj", "{19C52A0A-A790-409E-A28A-9745FF990F5C}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doat", "..\plugins\doat\doat.vcxproj", "{4980AF24-9D42-427D-A8E6-0DF3B97C455D}" EndProject @@ -87,6 +87,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "make-te", "..\src\common\ma EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "perl", "..\plugins\perl\perl.vcxproj", "{D90BC3E3-1341-4849-9354-5F40489D39D1}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "python3", "..\plugins\python\python3.vcxproj", "{C2321A03-0BA7-45B3-8740-ABD82B36B0BF}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Release|Win32 = Release|Win32 @@ -179,6 +181,10 @@ Global {D90BC3E3-1341-4849-9354-5F40489D39D1}.Release|Win32.Build.0 = Release|Win32 {D90BC3E3-1341-4849-9354-5F40489D39D1}.Release|x64.ActiveCfg = Release|x64 {D90BC3E3-1341-4849-9354-5F40489D39D1}.Release|x64.Build.0 = Release|x64 + {C2321A03-0BA7-45B3-8740-ABD82B36B0BF}.Release|Win32.ActiveCfg = Release|Win32 + {C2321A03-0BA7-45B3-8740-ABD82B36B0BF}.Release|Win32.Build.0 = Release|Win32 + {C2321A03-0BA7-45B3-8740-ABD82B36B0BF}.Release|x64.ActiveCfg = Release|x64 + {C2321A03-0BA7-45B3-8740-ABD82B36B0BF}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -203,6 +209,7 @@ Global {3024CF36-85E5-4E00-9608-7002E2C7EF14} = {561126F4-FA18-45FC-A2BF-8F858F161D6D} {19C52A0A-A790-409E-A28A-9745FF990F5C} = {D237DA6B-BD5F-46C0-8BEA-50E9A1340240} {D90BC3E3-1341-4849-9354-5F40489D39D1} = {D237DA6B-BD5F-46C0-8BEA-50E9A1340240} + {C2321A03-0BA7-45B3-8740-ABD82B36B0BF} = {D237DA6B-BD5F-46C0-8BEA-50E9A1340240} {B10A2C41-344C-43E0-A32D-B9587C198D8B} = {0FD996A7-464F-4981-8380-3DCA3A244A13} {C9B735E4-75BC-45AC-A5E3-39A6D076F912} = {0FD996A7-464F-4981-8380-3DCA3A244A13} {5A0F4962-E670-4DA2-9E45-52CC47F26E2F} = {0FD996A7-464F-4981-8380-3DCA3A244A13} diff --git a/win32/installer/hexchat-x64.skel.iss b/win32/installer/hexchat-x64.skel.iss index d742fdfa..64b1b2e7 100644 --- a/win32/installer/hexchat-x64.skel.iss +++ b/win32/installer/hexchat-x64.skel.iss @@ -47,7 +47,9 @@ Name: "plugins\upd"; Description: "Update Checker"; Types: normal custom; Flags: Name: "plugins\winamp"; Description: "Winamp"; Types: custom; Flags: disablenouninstallwarning Name: "langs"; Description: "Language Interfaces"; Types: custom; Flags: disablenouninstallwarning Name: "langs\perl"; Description: "Perl (requires Perl 5.18)"; Types: custom; Flags: disablenouninstallwarning -Name: "langs\python"; Description: "Python (requires Python 2.7)"; Types: custom; Flags: disablenouninstallwarning +Name: "langs\python"; Description: "Python Interface"; Types: custom; Flags: disablenouninstallwarning +Name: "langs\python\python2"; Description: "Python (requires Python 2.7)"; Types: custom; Flags: disablenouninstallwarning exclusive +Name: "langs\python\python3"; Description: "Python (requires Python 3.3)"; Types: custom; Flags: disablenouninstallwarning exclusive [Tasks] Name: portable; Description: "Yes"; GroupDescription: "Portable Install (no Registry entries, no Start Menu icons, no uninstaller):"; Flags: unchecked @@ -71,9 +73,9 @@ Root: HKCR; Subkey: ".hct\shell\open\command"; ValueType: string; ValueName: ""; Filename: "{app}\hexchat.exe"; Description: "Run HexChat after closing the Wizard"; Flags: nowait postinstall skipifsilent Filename: "http://www.microsoft.com/en-us/download/details.aspx?id=30679"; Description: "Download Visual C++ 2012 Update 1 Redistributable"; Flags: shellexec runasoriginaluser postinstall skipifsilent Filename: "http://docs.hexchat.org/en/latest/changelog.html"; Description: "See what's changed"; Flags: shellexec runasoriginaluser postinstall skipifsilent unchecked -Filename: "http://hexchat.org/downloads.html"; Description: "Download Perl 5.18"; Flags: shellexec runasoriginaluser postinstall skipifsilent unchecked; Components: langs\perl and not langs\python -Filename: "http://hexchat.org/downloads.html"; Description: "Download Python 2.7"; Flags: shellexec runasoriginaluser postinstall skipifsilent unchecked; Components: langs\python and not langs\perl -Filename: "http://hexchat.org/downloads.html"; Description: "Download Perl 5.18 and Python 2.7"; Flags: shellexec runasoriginaluser postinstall skipifsilent unchecked; Components: langs\perl and langs\python +Filename: "http://hexchat.org/downloads.html"; Description: "Download Perl"; Flags: shellexec runasoriginaluser postinstall skipifsilent unchecked; Components: langs\perl and not langs\python +Filename: "http://hexchat.org/downloads.html"; Description: "Download Python"; Flags: shellexec runasoriginaluser postinstall skipifsilent unchecked; Components: langs\python and not langs\perl +Filename: "http://hexchat.org/downloads.html"; Description: "Download Perl and Python"; Flags: shellexec runasoriginaluser postinstall skipifsilent unchecked; Components: langs\perl and langs\python [Files] Source: "portable-mode"; DestDir: "{app}"; Tasks: portable @@ -145,7 +147,8 @@ Source: "plugins\hcwinamp.dll"; DestDir: "{app}\plugins"; Flags: ignoreversion; Source: "share\system.png"; DestDir: "{app}\share"; Flags: ignoreversion; Components: plugins\sysinfo Source: "plugins\hcsysinfo.dll"; DestDir: "{app}\plugins"; Flags: ignoreversion; Components: plugins\sysinfo -Source: "plugins\hcpython.dll"; DestDir: "{app}\plugins"; Flags: ignoreversion; Components: langs\python +Source: "plugins\hcpython2.dll"; DestDir: "{app}\plugins"; Flags: ignoreversion; Components: langs\python\python2 +Source: "plugins\hcpython3.dll"; DestDir: "{app}\plugins"; Flags: ignoreversion; Components: langs\python\python3 Source: "plugins\hcperl.dll"; DestDir: "{app}\plugins"; Flags: ignoreversion; Components: langs\perl Source: "hexchat.exe"; DestDir: "{app}"; Flags: ignoreversion; Components: libs diff --git a/win32/installer/hexchat-x86.skel.iss b/win32/installer/hexchat-x86.skel.iss index fa86cd0c..10e9d277 100644 --- a/win32/installer/hexchat-x86.skel.iss +++ b/win32/installer/hexchat-x86.skel.iss @@ -46,7 +46,9 @@ Name: "plugins\upd"; Description: "Update Checker"; Types: normal custom; Flags: Name: "plugins\winamp"; Description: "Winamp"; Types: custom; Flags: disablenouninstallwarning Name: "langs"; Description: "Language Interfaces"; Types: custom; Flags: disablenouninstallwarning Name: "langs\perl"; Description: "Perl (requires Perl 5.18)"; Types: custom; Flags: disablenouninstallwarning -Name: "langs\python"; Description: "Python (requires Python 2.7)"; Types: custom; Flags: disablenouninstallwarning +Name: "langs\python"; Description: "Python Interface"; Types: custom; Flags: disablenouninstallwarning +Name: "langs\python\python2"; Description: "Python (requires Python 2.7)"; Types: custom; Flags: disablenouninstallwarning exclusive +Name: "langs\python\python3"; Description: "Python (requires Python 3.3)"; Types: custom; Flags: disablenouninstallwarning exclusive [Tasks] Name: portable; Description: "Yes"; GroupDescription: "Portable Install (no Registry entries, no Start Menu icons, no uninstaller):"; Flags: unchecked @@ -70,9 +72,9 @@ Root: HKCR; Subkey: ".hct\shell\open\command"; ValueType: string; ValueName: ""; Filename: "{app}\hexchat.exe"; Description: "Run HexChat after closing the Wizard"; Flags: nowait postinstall skipifsilent Filename: "http://www.microsoft.com/en-us/download/details.aspx?id=30679"; Description: "Download Visual C++ 2012 Update 1 Redistributable"; Flags: shellexec runasoriginaluser postinstall skipifsilent Filename: "http://docs.hexchat.org/en/latest/changelog.html"; Description: "See what's changed"; Flags: shellexec runasoriginaluser postinstall skipifsilent unchecked -Filename: "http://hexchat.org/downloads.html"; Description: "Download Perl 5.18"; Flags: shellexec runasoriginaluser postinstall skipifsilent unchecked; Components: langs\perl and not langs\python -Filename: "http://hexchat.org/downloads.html"; Description: "Download Python 2.7"; Flags: shellexec runasoriginaluser postinstall skipifsilent unchecked; Components: langs\python and not langs\perl -Filename: "http://hexchat.org/downloads.html"; Description: "Download Perl 5.18 and Python 2.7"; Flags: shellexec runasoriginaluser postinstall skipifsilent unchecked; Components: langs\perl and langs\python +Filename: "http://hexchat.org/downloads.html"; Description: "Download Perl"; Flags: shellexec runasoriginaluser postinstall skipifsilent unchecked; Components: langs\perl and not langs\python +Filename: "http://hexchat.org/downloads.html"; Description: "Download Python"; Flags: shellexec runasoriginaluser postinstall skipifsilent unchecked; Components: langs\python and not langs\perl +Filename: "http://hexchat.org/downloads.html"; Description: "Download Perl and Python"; Flags: shellexec runasoriginaluser postinstall skipifsilent unchecked; Components: langs\perl and langs\python [Files] Source: "portable-mode"; DestDir: "{app}"; Tasks: portable @@ -144,7 +146,8 @@ Source: "plugins\hcwinamp.dll"; DestDir: "{app}\plugins"; Flags: ignoreversion; Source: "share\system.png"; DestDir: "{app}\share"; Flags: ignoreversion; Components: plugins\sysinfo Source: "plugins\hcsysinfo.dll"; DestDir: "{app}\plugins"; Flags: ignoreversion; Components: plugins\sysinfo -Source: "plugins\hcpython.dll"; DestDir: "{app}\plugins"; Flags: ignoreversion; Components: langs\python +Source: "plugins\hcpython2.dll"; DestDir: "{app}\plugins"; Flags: ignoreversion; Components: langs\python\python2 +Source: "plugins\hcpython3.dll"; DestDir: "{app}\plugins"; Flags: ignoreversion; Components: langs\python\python3 Source: "plugins\hcperl.dll"; DestDir: "{app}\plugins"; Flags: ignoreversion; Components: langs\perl Source: "hexchat.exe"; DestDir: "{app}"; Flags: ignoreversion; Components: libs