From 3a028090359e5d5d24ccbfc11d9b6ff5681aab4f Mon Sep 17 00:00:00 2001 From: Christopher Davis Date: Sat, 12 Aug 2006 22:16:53 +0000 Subject: directory structure change git-svn-id: http://svn.irssi.org/repos/irssi-python@4312 dbcabf3a-b0e7-0310-adc4-f8d773084564 --- Makefile | 35 - constants.awk | 20 - constants.txt | 45 - irssi.py | 31 - irssi_startup.py | 202 ---- objects/Makefile | 28 - objects/ban-object.c | 155 --- objects/ban-object.h | 18 - objects/base-objects.c | 235 ---- objects/base-objects.h | 105 -- objects/channel-object.c | 379 ------- objects/channel-object.h | 22 - objects/chatnet-object.c | 182 ---- objects/chatnet-object.h | 22 - objects/command-object.c | 145 --- objects/command-object.h | 18 - objects/connect-object.c | 198 ---- objects/connect-object.h | 22 - objects/dcc-chat-object.c | 137 --- objects/dcc-chat-object.h | 21 - objects/dcc-get-object.c | 138 --- objects/dcc-get-object.h | 18 - objects/dcc-object.c | 347 ------ objects/dcc-object.h | 24 - objects/dcc-send-object.c | 138 --- objects/dcc-send-object.h | 18 - objects/factory.c | 326 ------ objects/factory.h | 58 - objects/ignore-object.c | 284 ----- objects/ignore-object.h | 21 - objects/irc-channel-object.c | 173 --- objects/irc-channel-object.h | 21 - objects/irc-connect-object.c | 86 -- objects/irc-connect-object.h | 21 - objects/irc-server-object.c | 491 --------- objects/irc-server-object.h | 21 - objects/log-object.c | 477 -------- objects/log-object.h | 21 - objects/logitem-object.c | 156 --- objects/logitem-object.h | 21 - objects/main-window-object.c | 199 ---- objects/main-window-object.h | 20 - objects/netsplit-channel-object.c | 170 --- objects/netsplit-channel-object.h | 21 - objects/netsplit-object.c | 184 ---- objects/netsplit-object.h | 19 - objects/netsplit-server-object.c | 157 --- objects/netsplit-server-object.h | 18 - objects/nick-object.c | 237 ---- objects/nick-object.h | 22 - objects/notifylist-object.c | 221 ---- objects/notifylist-object.h | 18 - objects/process-object.c | 222 ---- objects/process-object.h | 22 - objects/pyscript-object.c | 801 -------------- objects/pyscript-object.h | 33 - objects/query-object.c | 172 --- objects/query-object.h | 21 - objects/rawlog-object.c | 323 ------ objects/rawlog-object.h | 22 - objects/reconnect-object.c | 151 --- objects/reconnect-object.h | 20 - objects/server-object.c | 807 -------------- objects/server-object.h | 28 - objects/statusbar-item-object.c | 253 ----- objects/statusbar-item-object.h | 22 - objects/textdest-object.c | 285 ----- objects/textdest-object.h | 24 - objects/theme-object.c | 195 ---- objects/theme-object.h | 18 - objects/window-item-object.c | 334 ------ objects/window-item-object.h | 26 - objects/window-object.c | 678 ------------ objects/window-object.h | 21 - pyconstants.h | 7 - pycore.c | 160 --- pycore.h | 7 - pyirssi.h | 32 - pyirssi_irc.h | 20 - pyloader.c | 358 ------- pyloader.h | 23 - pymodule.c | 1909 --------------------------------- pymodule.h | 11 - pysigmap.h | 188 ---- pysignals.c | 805 -------------- pysignals.h | 44 - pysource.c | 130 --- pysource.h | 10 - pystatusbar.c | 132 --- pystatusbar.h | 13 - pythemes.c | 287 ----- pythemes.h | 13 - pyutils.c | 81 -- pyutils.h | 12 - sig2code.awk | 61 -- sig2code.txt | 44 - src/Makefile | 35 + src/constants.awk | 20 + src/constants.txt | 45 + src/irssi.py | 31 + src/irssi_startup.py | 202 ++++ src/objects/Makefile | 28 + src/objects/ban-object.c | 155 +++ src/objects/ban-object.h | 18 + src/objects/base-objects.c | 235 ++++ src/objects/base-objects.h | 105 ++ src/objects/channel-object.c | 379 +++++++ src/objects/channel-object.h | 22 + src/objects/chatnet-object.c | 182 ++++ src/objects/chatnet-object.h | 22 + src/objects/command-object.c | 145 +++ src/objects/command-object.h | 18 + src/objects/connect-object.c | 198 ++++ src/objects/connect-object.h | 22 + src/objects/dcc-chat-object.c | 137 +++ src/objects/dcc-chat-object.h | 21 + src/objects/dcc-get-object.c | 138 +++ src/objects/dcc-get-object.h | 18 + src/objects/dcc-object.c | 347 ++++++ src/objects/dcc-object.h | 24 + src/objects/dcc-send-object.c | 138 +++ src/objects/dcc-send-object.h | 18 + src/objects/factory.c | 326 ++++++ src/objects/factory.h | 58 + src/objects/ignore-object.c | 284 +++++ src/objects/ignore-object.h | 21 + src/objects/irc-channel-object.c | 173 +++ src/objects/irc-channel-object.h | 21 + src/objects/irc-connect-object.c | 86 ++ src/objects/irc-connect-object.h | 21 + src/objects/irc-server-object.c | 491 +++++++++ src/objects/irc-server-object.h | 21 + src/objects/log-object.c | 477 ++++++++ src/objects/log-object.h | 21 + src/objects/logitem-object.c | 156 +++ src/objects/logitem-object.h | 21 + src/objects/main-window-object.c | 199 ++++ src/objects/main-window-object.h | 20 + src/objects/netsplit-channel-object.c | 170 +++ src/objects/netsplit-channel-object.h | 21 + src/objects/netsplit-object.c | 184 ++++ src/objects/netsplit-object.h | 19 + src/objects/netsplit-server-object.c | 157 +++ src/objects/netsplit-server-object.h | 18 + src/objects/nick-object.c | 237 ++++ src/objects/nick-object.h | 22 + src/objects/notifylist-object.c | 221 ++++ src/objects/notifylist-object.h | 18 + src/objects/process-object.c | 222 ++++ src/objects/process-object.h | 22 + src/objects/pyscript-object.c | 801 ++++++++++++++ src/objects/pyscript-object.h | 33 + src/objects/query-object.c | 172 +++ src/objects/query-object.h | 21 + src/objects/rawlog-object.c | 323 ++++++ src/objects/rawlog-object.h | 22 + src/objects/reconnect-object.c | 151 +++ src/objects/reconnect-object.h | 20 + src/objects/server-object.c | 807 ++++++++++++++ src/objects/server-object.h | 28 + src/objects/statusbar-item-object.c | 253 +++++ src/objects/statusbar-item-object.h | 22 + src/objects/textdest-object.c | 285 +++++ src/objects/textdest-object.h | 24 + src/objects/theme-object.c | 195 ++++ src/objects/theme-object.h | 18 + src/objects/window-item-object.c | 334 ++++++ src/objects/window-item-object.h | 26 + src/objects/window-object.c | 678 ++++++++++++ src/objects/window-object.h | 21 + src/pyconstants.h | 7 + src/pycore.c | 160 +++ src/pycore.h | 7 + src/pyirssi.h | 32 + src/pyirssi_irc.h | 20 + src/pyloader.c | 358 +++++++ src/pyloader.h | 23 + src/pymodule.c | 1909 +++++++++++++++++++++++++++++++++ src/pymodule.h | 11 + src/pysigmap.h | 188 ++++ src/pysignals.c | 805 ++++++++++++++ src/pysignals.h | 44 + src/pysource.c | 130 +++ src/pysource.h | 10 + src/pystatusbar.c | 132 +++ src/pystatusbar.h | 13 + src/pythemes.c | 287 +++++ src/pythemes.h | 13 + src/pyutils.c | 81 ++ src/pyutils.h | 12 + src/sig2code.awk | 61 ++ src/sig2code.txt | 44 + 192 files changed, 14991 insertions(+), 14991 deletions(-) delete mode 100644 Makefile delete mode 100644 constants.awk delete mode 100644 constants.txt delete mode 100644 irssi.py delete mode 100644 irssi_startup.py delete mode 100644 objects/Makefile delete mode 100644 objects/ban-object.c delete mode 100644 objects/ban-object.h delete mode 100644 objects/base-objects.c delete mode 100644 objects/base-objects.h delete mode 100644 objects/channel-object.c delete mode 100644 objects/channel-object.h delete mode 100644 objects/chatnet-object.c delete mode 100644 objects/chatnet-object.h delete mode 100644 objects/command-object.c delete mode 100644 objects/command-object.h delete mode 100644 objects/connect-object.c delete mode 100644 objects/connect-object.h delete mode 100644 objects/dcc-chat-object.c delete mode 100644 objects/dcc-chat-object.h delete mode 100644 objects/dcc-get-object.c delete mode 100644 objects/dcc-get-object.h delete mode 100644 objects/dcc-object.c delete mode 100644 objects/dcc-object.h delete mode 100644 objects/dcc-send-object.c delete mode 100644 objects/dcc-send-object.h delete mode 100644 objects/factory.c delete mode 100644 objects/factory.h delete mode 100644 objects/ignore-object.c delete mode 100644 objects/ignore-object.h delete mode 100644 objects/irc-channel-object.c delete mode 100644 objects/irc-channel-object.h delete mode 100644 objects/irc-connect-object.c delete mode 100644 objects/irc-connect-object.h delete mode 100644 objects/irc-server-object.c delete mode 100644 objects/irc-server-object.h delete mode 100644 objects/log-object.c delete mode 100644 objects/log-object.h delete mode 100644 objects/logitem-object.c delete mode 100644 objects/logitem-object.h delete mode 100644 objects/main-window-object.c delete mode 100644 objects/main-window-object.h delete mode 100644 objects/netsplit-channel-object.c delete mode 100644 objects/netsplit-channel-object.h delete mode 100644 objects/netsplit-object.c delete mode 100644 objects/netsplit-object.h delete mode 100644 objects/netsplit-server-object.c delete mode 100644 objects/netsplit-server-object.h delete mode 100644 objects/nick-object.c delete mode 100644 objects/nick-object.h delete mode 100644 objects/notifylist-object.c delete mode 100644 objects/notifylist-object.h delete mode 100644 objects/process-object.c delete mode 100644 objects/process-object.h delete mode 100644 objects/pyscript-object.c delete mode 100644 objects/pyscript-object.h delete mode 100644 objects/query-object.c delete mode 100644 objects/query-object.h delete mode 100644 objects/rawlog-object.c delete mode 100644 objects/rawlog-object.h delete mode 100644 objects/reconnect-object.c delete mode 100644 objects/reconnect-object.h delete mode 100644 objects/server-object.c delete mode 100644 objects/server-object.h delete mode 100644 objects/statusbar-item-object.c delete mode 100644 objects/statusbar-item-object.h delete mode 100644 objects/textdest-object.c delete mode 100644 objects/textdest-object.h delete mode 100644 objects/theme-object.c delete mode 100644 objects/theme-object.h delete mode 100644 objects/window-item-object.c delete mode 100644 objects/window-item-object.h delete mode 100644 objects/window-object.c delete mode 100644 objects/window-object.h delete mode 100644 pyconstants.h delete mode 100644 pycore.c delete mode 100644 pycore.h delete mode 100644 pyirssi.h delete mode 100644 pyirssi_irc.h delete mode 100644 pyloader.c delete mode 100644 pyloader.h delete mode 100644 pymodule.c delete mode 100644 pymodule.h delete mode 100644 pysigmap.h delete mode 100644 pysignals.c delete mode 100644 pysignals.h delete mode 100644 pysource.c delete mode 100644 pysource.h delete mode 100644 pystatusbar.c delete mode 100644 pystatusbar.h delete mode 100644 pythemes.c delete mode 100644 pythemes.h delete mode 100644 pyutils.c delete mode 100644 pyutils.h delete mode 100644 sig2code.awk delete mode 100644 sig2code.txt create mode 100644 src/Makefile create mode 100644 src/constants.awk create mode 100644 src/constants.txt create mode 100644 src/irssi.py create mode 100644 src/irssi_startup.py create mode 100644 src/objects/Makefile create mode 100644 src/objects/ban-object.c create mode 100644 src/objects/ban-object.h create mode 100644 src/objects/base-objects.c create mode 100644 src/objects/base-objects.h create mode 100644 src/objects/channel-object.c create mode 100644 src/objects/channel-object.h create mode 100644 src/objects/chatnet-object.c create mode 100644 src/objects/chatnet-object.h create mode 100644 src/objects/command-object.c create mode 100644 src/objects/command-object.h create mode 100644 src/objects/connect-object.c create mode 100644 src/objects/connect-object.h create mode 100644 src/objects/dcc-chat-object.c create mode 100644 src/objects/dcc-chat-object.h create mode 100644 src/objects/dcc-get-object.c create mode 100644 src/objects/dcc-get-object.h create mode 100644 src/objects/dcc-object.c create mode 100644 src/objects/dcc-object.h create mode 100644 src/objects/dcc-send-object.c create mode 100644 src/objects/dcc-send-object.h create mode 100644 src/objects/factory.c create mode 100644 src/objects/factory.h create mode 100644 src/objects/ignore-object.c create mode 100644 src/objects/ignore-object.h create mode 100644 src/objects/irc-channel-object.c create mode 100644 src/objects/irc-channel-object.h create mode 100644 src/objects/irc-connect-object.c create mode 100644 src/objects/irc-connect-object.h create mode 100644 src/objects/irc-server-object.c create mode 100644 src/objects/irc-server-object.h create mode 100644 src/objects/log-object.c create mode 100644 src/objects/log-object.h create mode 100644 src/objects/logitem-object.c create mode 100644 src/objects/logitem-object.h create mode 100644 src/objects/main-window-object.c create mode 100644 src/objects/main-window-object.h create mode 100644 src/objects/netsplit-channel-object.c create mode 100644 src/objects/netsplit-channel-object.h create mode 100644 src/objects/netsplit-object.c create mode 100644 src/objects/netsplit-object.h create mode 100644 src/objects/netsplit-server-object.c create mode 100644 src/objects/netsplit-server-object.h create mode 100644 src/objects/nick-object.c create mode 100644 src/objects/nick-object.h create mode 100644 src/objects/notifylist-object.c create mode 100644 src/objects/notifylist-object.h create mode 100644 src/objects/process-object.c create mode 100644 src/objects/process-object.h create mode 100644 src/objects/pyscript-object.c create mode 100644 src/objects/pyscript-object.h create mode 100644 src/objects/query-object.c create mode 100644 src/objects/query-object.h create mode 100644 src/objects/rawlog-object.c create mode 100644 src/objects/rawlog-object.h create mode 100644 src/objects/reconnect-object.c create mode 100644 src/objects/reconnect-object.h create mode 100644 src/objects/server-object.c create mode 100644 src/objects/server-object.h create mode 100644 src/objects/statusbar-item-object.c create mode 100644 src/objects/statusbar-item-object.h create mode 100644 src/objects/textdest-object.c create mode 100644 src/objects/textdest-object.h create mode 100644 src/objects/theme-object.c create mode 100644 src/objects/theme-object.h create mode 100644 src/objects/window-item-object.c create mode 100644 src/objects/window-item-object.h create mode 100644 src/objects/window-object.c create mode 100644 src/objects/window-object.h create mode 100644 src/pyconstants.h create mode 100644 src/pycore.c create mode 100644 src/pycore.h create mode 100644 src/pyirssi.h create mode 100644 src/pyirssi_irc.h create mode 100644 src/pyloader.c create mode 100644 src/pyloader.h create mode 100644 src/pymodule.c create mode 100644 src/pymodule.h create mode 100644 src/pysigmap.h create mode 100644 src/pysignals.c create mode 100644 src/pysignals.h create mode 100644 src/pysource.c create mode 100644 src/pysource.h create mode 100644 src/pystatusbar.c create mode 100644 src/pystatusbar.h create mode 100644 src/pythemes.c create mode 100644 src/pythemes.h create mode 100644 src/pyutils.c create mode 100644 src/pyutils.h create mode 100644 src/sig2code.awk create mode 100644 src/sig2code.txt diff --git a/Makefile b/Makefile deleted file mode 100644 index 123e0ed..0000000 --- a/Makefile +++ /dev/null @@ -1,35 +0,0 @@ -CC = gcc - -PYTHON = /usr/include/python2.4 -IRSSI = /home/chrisd/irssi-0.8.10 - -CFLAGS = -fpic -ggdb -Wall -I$(PYTHON) -I$(IRSSI) -I$(IRSSI)/src \ --I$(IRSSI)/src/fe-common/core -I$(IRSSI)/src/core -I$(IRSSI)/src/fe-text \ --I$(IRSSI)/src/irc -I$(IRSSI)/src/irc/core -I$(IRSSI)/src/irc/dcc \ --I$(IRSSI)/src/irc/notifylist -I.. -I. -Iobjects \ -`pkg-config glib-2.0 --cflags` - -LDFLAGS = -fpic /usr/lib/libpython2.4.so - -OBJ = pycore.o pyutils.o pymodule.o pyloader.o pysignals.o pysource.o \ -pythemes.o pystatusbar.o pyconstants.o - -pyirssi: pyobjects.a $(OBJ) - $(CC) -shared -o libirssi_python.so $(OBJ) objects/pyobjects.a $(LDFLAGS) - -pyobjects.a: - cd objects/ && make - -%.o: %.c - $(CC) -c $< $(CFLAGS) - -signalmap: - awk -f sig2code.awk ~/irssi-0.8.10/docs/signals.txt > pysigmap.h - -constants: - awk -f constants.awk constants.txt > pyconstants.c - -clean: - rm -f *.o *.so - cd objects/ && make clean - diff --git a/constants.awk b/constants.awk deleted file mode 100644 index 3aa5034..0000000 --- a/constants.awk +++ /dev/null @@ -1,20 +0,0 @@ -BEGIN { - print "#include \"pymodule.h\""; - print "#include \"pyirssi_irc.h\""; - print - print "void pyconstants_init(void)" - print "{" -} - -{ - if (NF >= 2) - constant = $2; - else - constant = $1; - - printf(" PyModule_AddIntConstant(py_module, \"%s\", %s);\n", $1, constant); -} - -END { - print "}" -} diff --git a/constants.txt b/constants.txt deleted file mode 100644 index a3b8917..0000000 --- a/constants.txt +++ /dev/null @@ -1,45 +0,0 @@ -IO_IN G_IO_IN -IO_OUT G_IO_OUT -IO_PRI G_IO_PRI -IO_ERR G_IO_ERR -IO_HUP G_IO_HUP -IRSSI_GUI_GNOME -IRSSI_GUI_GTK -IRSSI_GUI_KDE -IRSSI_GUI_NONE -IRSSI_GUI_QT -IRSSI_GUI_TEXT -IRC_MASK_DOMAIN -IRC_MASK_HOST -IRC_MASK_NICK -IRC_MASK_USER -MSGLEVEL_ACTIONS -MSGLEVEL_ALL -MSGLEVEL_CLIENTCRAP -MSGLEVEL_CLIENTERROR -MSGLEVEL_CLIENTNOTICE -MSGLEVEL_CRAP -MSGLEVEL_CTCPS -MSGLEVEL_DCC -MSGLEVEL_DCCMSGS -MSGLEVEL_HILIGHT -MSGLEVEL_INVITES -MSGLEVEL_JOINS -MSGLEVEL_KICKS -MSGLEVEL_LASTLOG -MSGLEVEL_MODES -MSGLEVEL_MSGS -MSGLEVEL_NEVER -MSGLEVEL_NICKS -MSGLEVEL_NO_ACT -MSGLEVEL_NOHILIGHT -MSGLEVEL_NOTICES -MSGLEVEL_PARTS -MSGLEVEL_PUBLIC -MSGLEVEL_QUITS -MSGLEVEL_SNOTES -MSGLEVEL_TOPICS -MSGLEVEL_WALLOPS -SIGNAL_PRIORITY_DEFAULT -SIGNAL_PRIORITY_HIGH -SIGNAL_PRIORITY_LOW diff --git a/irssi.py b/irssi.py deleted file mode 100644 index 3f193ad..0000000 --- a/irssi.py +++ /dev/null @@ -1,31 +0,0 @@ -""" -""" - -import sys -import _irssi -from _irssi import * - -def command_bind(*args, **kwargs): - """ see Script.command_bind """ - get_script().command_bind(*args, **kwargs) - -def command_unbind(*args, **kwargs): - """ see Script.command_unbind """ - get_script().command_unbind(*args, **kwargs) - -def signal_add(*args, **kwargs): - """ see Script.signal_add """ - get_script().signal_add(*args, **kwargs) - -def signal_remove(*args, **kwargs): - """ see Script.signal_remove """ - get_script().signal_remove(*args, **kwargs) - -def timeout_add(*args, **kwargs): - """ see Script.timeout_add """ - get_script().timeout_add(*args, **kwargs) - -def io_add_watch(*args, **kwargs): - """ see Script.io_add_watch """ - get_script().io_add_watch(*args, **kwargs) - diff --git a/irssi_startup.py b/irssi_startup.py deleted file mode 100644 index ee8dbdd..0000000 --- a/irssi_startup.py +++ /dev/null @@ -1,202 +0,0 @@ -import sys, imp, __builtin__ -import _irssi - -class Output: - def __init__(self, level): - self.level = level - self.buf = [] - def write(self, text): - if not text: - return - self.buf.append(text) - if '\n' == text[-1]: - text = ''.join(self.buf)[:-1] - for line in text.split('\\n'): - _irssi.active_win().prnt(line, self.level) - self.buf = [] - -#XXX: hardcode -#try: -sys.stdout = Output(level = 0x0080000) -sys.stderr = Output(level = 0x0100000) -#except Exception, e: -# print 'Cant set output', e -# sys.stdout = sys.__stdout__ -# sys.stderr = sys.__stderr__ - -""" -#Import stuff modified from /Demo/imputil/knee.py -#If a script instance is available, it's module dictionary -#is used in place of sys.modules -#XXX: needs testing -#XXX: copyright? - -# Save the original hooks -original_import = __builtin__.__import__ -original_reload = __builtin__.reload - -# Replacement for __import__() -def import_hook(name, globals=None, locals=None, fromlist=None): - print 'LOADING', name - if name == 'sys': - return sys - #if name == '_irssi': - # return _irssi - - try: - script = _irssi.get_script() - except RuntimeError: - print 'ORIG IMPORT', name - return original_import(name, globals, locals, fromlist) - - parent = determine_parent(globals, script) - q, tail = find_head_package(parent, name, script) - m = load_tail(q, tail, script) - if not fromlist: - return q - - if hasattr(m, "__path__"): - ensure_fromlist(m, fromlist, script) - - recur -= 1 - return m - -def determine_parent(globals, script): - if not globals or not globals.has_key("__name__"): - print 'DP no __name__ in globals' - return None - pname = globals['__name__'] - print 'DP pname', pname - if globals.has_key("__path__"): - parent = script.modules[pname] - assert globals is parent.__dict__ - return parent - if '.' in pname: - i = pname.rfind('.') - pname = pname[:i] - parent = script.modules[pname] - assert parent.__name__ == pname - return parent - return None - -def find_head_package(parent, name, script): - if '.' in name: - i = name.find('.') - head = name[:i] - tail = name[i+1:] - else: - head = name - tail = "" - if parent: - qname = "%s.%s" % (parent.__name__, head) - else: - qname = head - q = import_module(head, qname, parent, script) - if q: - return q, tail - else: - print 'FHP (1) no q module for', name - - if parent: - qname = head - parent = None - q = import_module(head, qname, parent, script) - if q: - return q, tail - else: - print 'FHP (2) no q module for', name - - raise ImportError, "No module named " + qname - -def load_tail(q, tail, script): - m = q - while tail: - i = tail.find('.') - if i < 0: i = len(tail) - head, tail = tail[:i], tail[i+1:] - mname = "%s.%s" % (m.__name__, head) - m = import_module(head, mname, m, script) - if not m: - raise ImportError, "No module named " + mname - return m - -def ensure_fromlist(m, fromlist, script, recursive=0): - for sub in fromlist: - if sub == "*": - if not recursive: - try: - all = m.__all__ - except AttributeError: - pass - else: - assert recursive == 0 - ensure_fromlist(m, all, script, 1) - continue - if sub != "*" and not hasattr(m, sub): - subname = "%s.%s" % (m.__name__, sub) - submod = import_module(sub, subname, m, script) - if not submod: - raise ImportError, "No module named " + subname - -def import_module(partname, fqname, parent, script): - try: - m = script.modules[fqname] - #if hasattr(m, '_script'): - # assert m._script == script - - _irssi.prnt('LOADING CACHED %s script -> %s' % (fqname, repr(script))) - - return m - except KeyError: - print 'IM no cached moddule for', fqname - pass - - try: - fp, pathname, stuff = imp.find_module(partname, - parent and parent.__path__) - except ImportError, e: - print 'IM import error', e - return None - - try: - m = imp.load_module(fqname, fp, pathname, stuff) - finally: - if fp: fp.close() - if parent: - setattr(parent, partname, m) - - #don't load script into builtins, extensions, or this wrapper - if hasattr(m, '__file__') and fqname != 'irssi': - m._script = script - script.modules[fqname] = m - - #if hasattr(m, '__file__') and fqname not in ('__builtin__', 'sys', '__main__', '_irssi'): - # del sys.modules[fqname] - - _irssi.prnt('GOT -> %s, SCRIPT -> %s' % (m, repr(script))) - - return m - - -# Replacement for reload() -def reload_hook(module): - _irssi.prnt('reloading ' + repr(module)) - try: - script = _irssi.get_script() - except RuntimeError: - return original_reload(module) - - name = module.__name__ - if '.' not in name: - return import_module(name, name, None, script) - i = name.rfind('.') - pname = name[:i] - parent = script.modules[pname] - return import_module(name[i+1:], name, parent, script) - - -# Now install our hooks -__builtin__.__import__ = import_hook -__builtin__.reload = reload_hook -""" - diff --git a/objects/Makefile b/objects/Makefile deleted file mode 100644 index 6cc56fb..0000000 --- a/objects/Makefile +++ /dev/null @@ -1,28 +0,0 @@ -CC = gcc - -PYTHON = /usr/include/python2.4 -IRSSI = /home/chrisd/irssi-0.8.10 -CFLAGS = -fpic -ggdb -Wall -I$(PYTHON) -I$(IRSSI) -I$(IRSSI)/src \ --I$(IRSSI)/src/fe-common/core -I$(IRSSI)/src/core -I$(IRSSI)/src/fe-text \ --I$(IRSSI)/src/irc -I$(IRSSI)/src/irc/core -I$(IRSSI)/src/irc/dcc \ --I$(IRSSI)/src/irc/notifylist -I.. \ -`pkg-config glib-2.0 --cflags` - -OBJ = pyscript-object.o base-objects.o window-item-object.o channel-object.o \ -query-object.o server-object.o connect-object.o irc-server-object.o \ -irc-connect-object.o irc-channel-object.o ban-object.o nick-object.o \ -chatnet-object.o reconnect-object.o window-object.o textdest-object.o \ -rawlog-object.o log-object.o logitem-object.o ignore-object.o \ -dcc-object.o dcc-chat-object.o dcc-get-object.o dcc-send-object.o \ -netsplit-object.o netsplit-server-object.o netsplit-channel-object.o \ -notifylist-object.o process-object.o command-object.o theme-object.o \ -statusbar-item-object.o main-window-object.o factory.o - -pyobjects.a: $(OBJ) - ar r pyobjects.a $(OBJ) - -%.o: %.c - $(CC) -c $< $(CFLAGS) - -clean: - rm -f *.o *.so *.a diff --git a/objects/ban-object.c b/objects/ban-object.c deleted file mode 100644 index 908bae2..0000000 --- a/objects/ban-object.c +++ /dev/null @@ -1,155 +0,0 @@ -#include -#include "pyirssi_irc.h" -#include "pymodule.h" -#include "ban-object.h" -#include "pycore.h" - -/* monitor "ban remove" signal */ -static void ban_cleanup(CHANNEL_REC *chan, BAN_REC *ban) -{ - PyBan *pyban = signal_get_user_data(); - - if (ban == pyban->data) - { - pyban->data = NULL; - pyban->cleanup_installed = 0; - signal_remove_data("ban remove", ban_cleanup, pyban); - } -} - -static void PyBan_dealloc(PyBan *self) -{ - if (self->cleanup_installed) - signal_remove_data("ban remove", ban_cleanup, self); - - self->ob_type->tp_free((PyObject*)self); -} - -static PyObject *PyBan_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyBan *self; - - self = (PyBan *)type->tp_alloc(type, 0); - if (!self) - return NULL; - - return (PyObject *)self; -} - -PyDoc_STRVAR(PyBan_ban_doc, - "The ban" -); -static PyObject *PyBan_ban_get(PyBan *self, void *closure) -{ - BAN_REC *data = self->data; - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(data->ban); -} - -PyDoc_STRVAR(PyBan_setby_doc, - "Nick of who set the ban" -); -static PyObject *PyBan_setby_get(PyBan *self, void *closure) -{ - BAN_REC *data = self->data; - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(data->setby); -} - -PyDoc_STRVAR(PyBan_time_doc, - "Timestamp when ban was set" -); -static PyObject *PyBan_time_get(PyBan *self, void *closure) -{ - BAN_REC *data = self->data; - RET_NULL_IF_INVALID(self->data); - return PyLong_FromUnsignedLong(data->time); -} - -/* specialized getters/setters */ -static PyGetSetDef PyBan_getseters[] = { - {"ban", (getter)PyBan_ban_get, NULL, - PyBan_ban_doc, NULL}, - {"setby", (getter)PyBan_setby_get, NULL, - PyBan_setby_doc, NULL}, - {"time", (getter)PyBan_time_get, NULL, - PyBan_time_doc, NULL}, - {NULL} -}; - -/* Methods for object */ -static PyMethodDef PyBan_methods[] = { - {NULL} /* Sentinel */ -}; - -PyTypeObject PyBanType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "Ban", /*tp_name*/ - sizeof(PyBan), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)PyBan_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - "PyBan objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - PyBan_methods, /* tp_methods */ - 0, /* tp_members */ - PyBan_getseters, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - PyBan_new, /* tp_new */ -}; - - -/* window item wrapper factory function */ -PyObject *pyban_new(void *ban) -{ - PyBan *pyban; - - pyban = py_inst(PyBan, PyBanType); - if (!pyban) - return NULL; - - pyban->data = ban; - pyban->cleanup_installed = 1; - signal_add_last_data("ban remove", ban_cleanup, pyban); - - return (PyObject *)pyban; -} - -int ban_object_init(void) -{ - g_return_val_if_fail(py_module != NULL, 0); - - if (PyType_Ready(&PyBanType) < 0) - return 0; - - Py_INCREF(&PyBanType); - PyModule_AddObject(py_module, "Ban", (PyObject *)&PyBanType); - - return 1; -} diff --git a/objects/ban-object.h b/objects/ban-object.h deleted file mode 100644 index 59ec9e7..0000000 --- a/objects/ban-object.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef _BAN_OBJECT_H_ -#define _BAN_OBJECT_H_ - -#include -#include "base-objects.h" - -typedef struct -{ - PyIrssiFinal_HEAD(void) -} PyBan; - -extern PyTypeObject PyBanType; - -int ban_object_init(void); -PyObject *pyban_new(void *ban); -#define pyban_check(op) PyObject_TypeCheck(op, &PyBanType) - -#endif diff --git a/objects/base-objects.c b/objects/base-objects.c deleted file mode 100644 index 42f5cac..0000000 --- a/objects/base-objects.c +++ /dev/null @@ -1,235 +0,0 @@ -#include -#include "structmember.h" -#include "pymodule.h" -#include "base-objects.h" -#include "pyirssi.h" - -/* This is the base type for Irssi objects with a type id. The user can find - * the type name, type id, and check if the object is wrapping a valid Irssi - * record. - */ - -static void PyIrssiBase_dealloc(PyIrssiBase *self) -{ - self->ob_type->tp_free((PyObject*)self); -} - -static PyObject *PyIrssiBase_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyIrssiBase *self; - - self = (PyIrssiBase *)type->tp_alloc(type, 0); - if (!self) - return NULL; - - return (PyObject *)self; -} - -/* Getters */ -PyDoc_STRVAR(PyIrssiBase_type_id_doc, - "Irssi's type id for object" -); -static PyObject *PyIrssiBase_type_id_get(PyIrssiBase *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyInt_FromLong(self->data->type); -} - -PyDoc_STRVAR(PyIrssiBase_type_doc, - "Irssi's name for object" -); -static PyObject *PyIrssiBase_type_get(PyIrssiBase *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->base_name); -} - -PyDoc_STRVAR(PyIrssiBase_valid_doc, - "True if the object is valid" -); -static PyObject *PyIrssiBase_valid_get(PyIrssiBase *self, void *closure) -{ - if (self->data != NULL) - Py_RETURN_TRUE; - - Py_RETURN_FALSE; -} - -/* specialized getters/setters */ -static PyGetSetDef PyIrssiBase_getseters[] = { - {"type_id", (getter)PyIrssiBase_type_id_get, NULL, - PyIrssiBase_type_id_doc, NULL}, - {"type", (getter)PyIrssiBase_type_get, NULL, - PyIrssiBase_type_doc, NULL}, - {"valid", (getter)PyIrssiBase_valid_get, NULL, - PyIrssiBase_valid_doc, NULL}, - {NULL} -}; - -/* Methods for object */ -static PyMethodDef PyIrssiBase_methods[] = { - {NULL} -}; - -PyTypeObject PyIrssiBaseType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "IrssiBase", /*tp_name*/ - sizeof(PyIrssiBase), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)PyIrssiBase_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - "PyIrssiBase objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - PyIrssiBase_methods, /* tp_methods */ - 0, /* tp_members */ - PyIrssiBase_getseters, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - PyIrssiBase_new, /* tp_new */ -}; - - -/* IrssiChatBase is a base type for any object with a chat type. The user - can find the chat type string name with the chat_type member or - the type id with the chat_type_id member. It inherits from IrssiBase - so the type, valid, and type_id members are visible to the user, too */ - -static void PyIrssiChatBase_dealloc(PyIrssiChatBase *self) -{ - self->ob_type->tp_free((PyObject*)self); -} - -static PyObject *PyIrssiChatBase_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyIrssiChatBase *self; - - self = (PyIrssiChatBase *)type->tp_alloc(type, 0); - if (!self) - return NULL; - - return (PyObject *)self; -} - -/* Getters */ -PyDoc_STRVAR(PyIrssiChatBase_chat_type_id_doc, - "Chat Type id (int)" -); -static PyObject *PyIrssiChatBase_chat_type_id_get(PyIrssiChatBase *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyInt_FromLong(self->data->chat_type); -} - -PyDoc_STRVAR(PyIrssiChatBase_chat_type_doc, - "Chat name (str)" -); -static PyObject *PyIrssiChatBase_chat_type_get(PyIrssiChatBase *self, void *closure) -{ - CHAT_PROTOCOL_REC *rec; - - RET_NULL_IF_INVALID(self->data); - - rec = chat_protocol_find_id(self->data->chat_type); - if (rec) - RET_AS_STRING_OR_NONE(rec->name); - else - Py_RETURN_NONE; -} - -/* specialized getters/setters */ -static PyGetSetDef PyIrssiChatBase_getseters[] = { - {"chat_type_id", (getter)PyIrssiChatBase_chat_type_id_get, NULL, - PyIrssiChatBase_chat_type_id_doc, NULL}, - {"chat_type", (getter)PyIrssiChatBase_chat_type_get, NULL, - PyIrssiChatBase_chat_type_doc, NULL}, - {NULL} -}; - -/* Methods */ -static PyMethodDef PyIrssiChatBase_methods[] = { - {NULL} -}; - -PyTypeObject PyIrssiChatBaseType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "IrssiChatBase", /*tp_name*/ - sizeof(PyIrssiChatBase), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)PyIrssiChatBase_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - "PyIrssiChatBase objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - PyIrssiChatBase_methods, /* tp_methods */ - 0, /* tp_members */ - PyIrssiChatBase_getseters, /* tp_getset */ - &PyIrssiBaseType, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - PyIrssiChatBase_new, /* tp_new */ -}; - -int base_objects_init(void) -{ - g_return_val_if_fail(py_module != NULL, 0); - - if (PyType_Ready(&PyIrssiBaseType) < 0) - return 0; - if (PyType_Ready(&PyIrssiChatBaseType) < 0) - return 0; - - Py_INCREF(&PyIrssiBaseType); - Py_INCREF(&PyIrssiChatBaseType); - PyModule_AddObject(py_module, "IrssiBase", (PyObject *)&PyIrssiBaseType); - PyModule_AddObject(py_module, "IrssiChatBase", (PyObject *)&PyIrssiChatBaseType); - - return 1; -} diff --git a/objects/base-objects.h b/objects/base-objects.h deleted file mode 100644 index 5351ead..0000000 --- a/objects/base-objects.h +++ /dev/null @@ -1,105 +0,0 @@ -#ifndef _BASE_OBJECTS_H_ -#define _BASE_OBJECTS_H_ - -#include - -/* data is a pointer to the underlying Irssi record */ -/* base_name is the type name of the object returned from the type member - it can be SERVER, CHANNEL, QUERY, etc. Note: base_name isn't freed, so - it cannot point to heap memory */ -/* cleanup_installed: 1 = a cleanup signal handler is installed, 0 = not installed */ -#define PyIrssi_HEAD(type) \ - PyObject_HEAD \ - type *data; \ - const char *base_name; \ - int cleanup_installed; - -/* for uninheritable objects without a type id (Ban, Log, etc) */ -#define PyIrssiFinal_HEAD(type) \ - PyObject_HEAD \ - type *data; \ - int cleanup_installed; - -/* to access data from any irssi object */ -typedef struct -{ - PyObject_HEAD - void *data; -} PyIrssiObject; - -#define DATA(obj) (obj? ((PyIrssiObject *)obj)->data : NULL) - -/* base for classes with a type */ -typedef struct -{ - int type; -} IRSSI_BASE_REC; - -typedef struct -{ - PyIrssi_HEAD(IRSSI_BASE_REC) -} PyIrssiBase; - - -/* base for classes with type and a chat type */ -typedef struct -{ - int type; - int chat_type; -} IRSSI_CHAT_REC; - -typedef struct -{ - PyIrssi_HEAD(IRSSI_CHAT_REC) -} PyIrssiChatBase; - -extern PyTypeObject PyIrssiBaseType; -extern PyTypeObject PyIrssiChatBaseType; - -#define pybase_check(op) PyObject_TypeCheck(op, &PyIrssiBaseType) -#define pychatbase_check(op) PyObject_TypeCheck(op, &PyIrssiChatBaseType) -#define py_instp(tp, to) ((tp *) (to)->tp_alloc(to, 0)) -#define py_inst(tp, to) py_instp(tp, &to) - -int base_objects_init(void); - -#define RET_NULL_IF_INVALID(data) \ - if (data == NULL) \ - return PyErr_Format(PyExc_RuntimeError, "wrapped object is invalid") - -#define RET_N1_IF_INVALID(data) \ -do { \ - if (data == NULL) \ - { \ - PyErr_Format(PyExc_RuntimeError, "wrapped object is invalid"); \ - return -1; \ - } \ -} while (0) - -#define RET_AS_STRING_OR_NONE(str) \ -do { \ - if (str) \ - return PyString_FromString(str); \ - else \ - { \ - Py_INCREF(Py_None); \ - return Py_None; \ - } \ -} while (0) - - -#define RET_AS_STRING_OR_EMPTY(str) return PyString_FromString(str? str : "") - -#define RET_AS_OBJ_OR_NONE(obj) \ -do { \ - PyObject *tmp = obj; \ - if (!tmp) \ - tmp = Py_None; \ - Py_INCREF(tmp); \ - return tmp; \ -} while (0) - -#define INVALID_MEMBER(member) \ - return PyErr_Format(PyExc_RuntimeError, "invalid member id, %d", member) - -#endif diff --git a/objects/channel-object.c b/objects/channel-object.c deleted file mode 100644 index fa4edd4..0000000 --- a/objects/channel-object.c +++ /dev/null @@ -1,379 +0,0 @@ -#include -#include "pyirssi.h" -#include "pymodule.h" -#include "factory.h" -#include "channel-object.h" -#include "pycore.h" - -/* monitor "channel destroyed" signal */ -static void chan_cleanup(CHANNEL_REC *chan) -{ - PyChannel *pychan = signal_get_user_data(); - - if (chan == pychan->data) - { - pychan->data = NULL; - pychan->cleanup_installed = 0; - signal_remove_data("channel destroyed", chan_cleanup, pychan); - } -} - -static void PyChannel_dealloc(PyChannel *self) -{ - if (self->cleanup_installed) - signal_remove_data("channel destroyed", chan_cleanup, self); - - self->ob_type->tp_free((PyObject*)self); -} - -/* Getters */ -PyDoc_STRVAR(PyChannel_topic_doc, - "Channel topic" -); -static PyObject *PyChannel_topic_get(PyChannel *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->topic); -} - -PyDoc_STRVAR(PyChannel_topic_by_doc, - "Nick who set the topic" -); -static PyObject *PyChannel_topic_by_get(PyChannel *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->topic_by); -} - -PyDoc_STRVAR(PyChannel_topic_time_doc, - "Timestamp when the topic was set" -); -static PyObject *PyChannel_topic_time_get(PyChannel *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyLong_FromLong(self->data->topic_time); -} - -PyDoc_STRVAR(PyChannel_no_modes_doc, - "Channel is modeless" -); -static PyObject *PyChannel_no_modes_get(PyChannel *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyBool_FromLong(self->data->no_modes); -} - -PyDoc_STRVAR(PyChannel_mode_doc, - "Channel mode" -); -static PyObject *PyChannel_mode_get(PyChannel *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->mode); -} - -PyDoc_STRVAR(PyChannel_limit_doc, - "Max. users in channel (+l mode)" -); -static PyObject *PyChannel_limit_get(PyChannel *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyInt_FromLong(self->data->limit); -} - -PyDoc_STRVAR(PyChannel_key_doc, - "Channel key (password)" -); -static PyObject *PyChannel_key_get(PyChannel *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->key); -} - -PyDoc_STRVAR(PyChannel_chanop_doc, - "You are channel operator" -); -static PyObject *PyChannel_chanop_get(PyChannel *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyBool_FromLong(self->data->chanop); -} - -PyDoc_STRVAR(PyChannel_names_got_doc, - "/NAMES list has been received" -); -static PyObject *PyChannel_names_got_get(PyChannel *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyBool_FromLong(self->data->names_got); -} - -PyDoc_STRVAR(PyChannel_wholist_doc, - "/WHO list has been received" -); -static PyObject *PyChannel_wholist_get(PyChannel *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyBool_FromLong(self->data->wholist); -} - -PyDoc_STRVAR(PyChannel_synced_doc, - "Channel is fully synchronized" -); -static PyObject *PyChannel_synced_get(PyChannel *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyBool_FromLong(self->data->synced); -} - -PyDoc_STRVAR(PyChannel_joined_doc, - "JOIN event for this channel has been received" -); -static PyObject *PyChannel_joined_get(PyChannel *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyBool_FromLong(self->data->joined); -} - -PyDoc_STRVAR(PyChannel_left_doc, - "You just left the channel (for 'channel destroyed' event)" -); -static PyObject *PyChannel_left_get(PyChannel *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyBool_FromLong(self->data->left); -} - -PyDoc_STRVAR(PyChannel_kicked_doc, - "You were just kicked out of the channel (for 'channel destroyed' event)" -); -static PyObject *PyChannel_kicked_get(PyChannel *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyBool_FromLong(self->data->kicked); -} - -/* specialized getters/setters */ -static PyGetSetDef PyChannel_getseters[] = { - {"topic", (getter)PyChannel_topic_get, NULL, - PyChannel_topic_doc, NULL}, - {"topic_by", (getter)PyChannel_topic_by_get, NULL, - PyChannel_topic_by_doc, NULL}, - {"topic_time", (getter)PyChannel_topic_time_get, NULL, - PyChannel_topic_time_doc, NULL}, - {"no_modes", (getter)PyChannel_no_modes_get, NULL, - PyChannel_no_modes_doc, NULL}, - {"mode", (getter)PyChannel_mode_get, NULL, - PyChannel_mode_doc, NULL}, - {"limit", (getter)PyChannel_limit_get, NULL, - PyChannel_limit_doc, NULL}, - {"key", (getter)PyChannel_key_get, NULL, - PyChannel_key_doc, NULL}, - {"chanop", (getter)PyChannel_chanop_get, NULL, - PyChannel_chanop_doc, NULL}, - {"names_got", (getter)PyChannel_names_got_get, NULL, - PyChannel_names_got_doc, NULL}, - {"wholist", (getter)PyChannel_wholist_get, NULL, - PyChannel_wholist_doc, NULL}, - {"synced", (getter)PyChannel_synced_get, NULL, - PyChannel_synced_doc, NULL}, - {"joined", (getter)PyChannel_joined_get, NULL, - PyChannel_joined_doc, NULL}, - {"left", (getter)PyChannel_left_get, NULL, - PyChannel_left_doc, NULL}, - {"kicked", (getter)PyChannel_kicked_get, NULL, - PyChannel_kicked_doc, NULL}, - {NULL} -}; - -/* Methods */ -PyDoc_STRVAR(PyChannel_nicks_doc, - "nicks() -> list of Nick objects\n" - "\n" - "Return a list of nicks in the channel.\n" -); -static PyObject *PyChannel_nicks(PyChannel *self, PyObject *args) -{ - RET_NULL_IF_INVALID(self->data); - - return py_irssi_chatlist_new(nicklist_getnicks(self->data), 1); -} - -PyDoc_STRVAR(PyChannel_nicks_find_mask_doc, - "nicks_find_mask(mask) -> Nick object or None\n" - "\n" - "Find nick mask from nicklist, wildcards allowed.\n" -); -static PyObject *PyChannel_nicks_find_mask(PyChannel *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"mask", NULL}; - char *mask = ""; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &mask)) - return NULL; - - return py_irssi_chat_new(nicklist_find_mask(self->data, mask), 1); -} - -PyDoc_STRVAR(PyChannel_nick_find_doc, - "nick_find(nick) -> Nick object or None\n" - "\n" - "Find nick from nicklist.\n" -); -static PyObject *PyChannel_nick_find(PyChannel *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"nick", NULL}; - char *nick = ""; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &nick)) - return NULL; - - return py_irssi_chat_new(nicklist_find(self->data, nick), 1); -} - -PyDoc_STRVAR(PyChannel_nick_remove_doc, - "nick_remove(nick) -> None\n" - "\n" - "Remove nick from nicklist.\n" -); -static PyObject *PyChannel_nick_remove(PyChannel *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"nick", NULL}; - PyObject *nick = NULL; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, - &nick)) - return NULL; - - if (!pynick_check(nick)) - return PyErr_Format(PyExc_TypeError, "arg must be nick"); - - nicklist_remove(self->data, ((PyNick*)nick)->data); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyChannel_nick_insert_obj_doc, - "nick_insert(nick) -> None\n" - "\n" - "Insert nick object into nicklist.\n" -); -static PyObject *PyChannel_nick_insert_obj(PyChannel *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"nick", NULL}; - PyObject *nick = NULL; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, - &nick)) - return NULL; - - if (!pynick_check(nick)) - return PyErr_Format(PyExc_TypeError, "arg must be nick"); - - nicklist_insert(self->data, ((PyNick*)nick)->data); - - Py_RETURN_NONE; -} - -/* Methods for object */ -static PyMethodDef PyChannel_methods[] = { - {"nicks", (PyCFunction)PyChannel_nicks, METH_NOARGS, - PyChannel_nicks_doc}, - {"nicks_find_mask", (PyCFunction)PyChannel_nicks_find_mask, METH_VARARGS | METH_KEYWORDS, - PyChannel_nicks_find_mask_doc}, - {"nick_find", (PyCFunction)PyChannel_nick_find, METH_VARARGS | METH_KEYWORDS, - PyChannel_nick_find_doc}, - {"nick_remove", (PyCFunction)PyChannel_nick_remove, METH_VARARGS | METH_KEYWORDS, - PyChannel_nick_remove_doc}, - {"nick_insert_obj", (PyCFunction)PyChannel_nick_insert_obj, METH_VARARGS | METH_KEYWORDS, - PyChannel_nick_insert_obj_doc}, - {NULL} /* Sentinel */ -}; - -PyTypeObject PyChannelType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "Channel", /*tp_name*/ - sizeof(PyChannel), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)PyChannel_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - "PyChannel objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - PyChannel_methods, /* tp_methods */ - 0, /* tp_members */ - PyChannel_getseters, /* tp_getset */ - &PyWindowItemType, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ -}; - - -/* window item wrapper factory function */ -PyObject *pychannel_sub_new(void *chan, const char *name, PyTypeObject *type) -{ - PyObject *pychan; - - pychan = pywindow_item_sub_new(chan, name, type); - if (pychan) - { - PyChannel *pych = (PyChannel *)pychan; - signal_add_last_data("channel destroyed", chan_cleanup, pych); - pych->cleanup_installed = 1; - } - - return pychan; -} - -PyObject *pychannel_new(void *chan) -{ - static const char *name = "CHANNEL"; - return pychannel_sub_new(chan, name, &PyChannelType); -} - -int channel_object_init(void) -{ - g_return_val_if_fail(py_module != NULL, 0); - - if (PyType_Ready(&PyChannelType) < 0) - return 0; - - Py_INCREF(&PyChannelType); - PyModule_AddObject(py_module, "Channel", (PyObject *)&PyChannelType); - - return 1; -} diff --git a/objects/channel-object.h b/objects/channel-object.h deleted file mode 100644 index 0858e7b..0000000 --- a/objects/channel-object.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef _CHANNEL_OBJECT_H_ -#define _CHANNEL_OBJECT_H_ - -#include -#include "window-item-object.h" - -/* forward */ -struct _CHANNEL_REC; - -typedef struct -{ - PyWindowItem_HEAD(struct _CHANNEL_REC) -} PyChannel; - -extern PyTypeObject PyChannelType; - -int channel_object_init(void); -PyObject *pychannel_sub_new(void *chan, const char *name, PyTypeObject *type); -PyObject *pychannel_new(void *chan); -#define pychannel_check(op) PyObject_TypeCheck(op, &PyChannelType) - -#endif diff --git a/objects/chatnet-object.c b/objects/chatnet-object.c deleted file mode 100644 index c22f0cb..0000000 --- a/objects/chatnet-object.c +++ /dev/null @@ -1,182 +0,0 @@ -#include -#include "pymodule.h" -#include "base-objects.h" -#include "chatnet-object.h" -#include "pyirssi.h" -#include "pycore.h" -#include "pyutils.h" - -static void chatnet_cleanup(CHATNET_REC *cn) -{ - PyChatnet *pycn = signal_get_user_data(); - - if (cn == pycn->data) - { - pycn->data = NULL; - pycn->cleanup_installed = 0; - signal_remove_data("chatnet destroyed", chatnet_cleanup, pycn); - } -} - -static void PyChatnet_dealloc(PyChatnet *self) -{ - if (self->cleanup_installed) - signal_remove_data("chatnet destroyed", chatnet_cleanup, self); - - self->ob_type->tp_free((PyObject*)self); -} - -/* Getters */ -PyDoc_STRVAR(PyChatnet_name_doc, - "name of chat network" -); -static PyObject *PyChatnet_name_get(PyChatnet *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->name); -} - -PyDoc_STRVAR(PyChatnet_nick_doc, - "if not empty, nick preferred in this network" -); -static PyObject *PyChatnet_nick_get(PyChatnet *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->nick); -} - -PyDoc_STRVAR(PyChatnet_username_doc, - "if not empty, username preferred in this network" -); -static PyObject *PyChatnet_username_get(PyChatnet *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->username); -} - -PyDoc_STRVAR(PyChatnet_realname_doc, - "if not empty, realname preferred in this network" -); -static PyObject *PyChatnet_realname_get(PyChatnet *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->realname); -} - -PyDoc_STRVAR(PyChatnet_own_host_doc, - "address to use when connecting to this network" -); -static PyObject *PyChatnet_own_host_get(PyChatnet *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->own_host); -} - -PyDoc_STRVAR(PyChatnet_autosendcmd_doc, - "command to send after connecting to this network" -); -static PyObject *PyChatnet_autosendcmd_get(PyChatnet *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->autosendcmd); -} - -/* specialized getters/setters */ -static PyGetSetDef PyChatnet_getseters[] = { - {"name", (getter)PyChatnet_name_get, NULL, - PyChatnet_name_doc, NULL}, - {"nick", (getter)PyChatnet_nick_get, NULL, - PyChatnet_nick_doc, NULL}, - {"username", (getter)PyChatnet_username_get, NULL, - PyChatnet_username_doc, NULL}, - {"realname", (getter)PyChatnet_realname_get, NULL, - PyChatnet_realname_doc, NULL}, - {"own_host", (getter)PyChatnet_own_host_get, NULL, - PyChatnet_own_host_doc, NULL}, - {"autosendcmd", (getter)PyChatnet_autosendcmd_get, NULL, - PyChatnet_autosendcmd_doc, NULL}, - {NULL} -}; - -static PyMethodDef PyChatnet_methods[] = { - {NULL} /* Sentinel */ -}; - -PyTypeObject PyChatnetType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "Chatnet", /*tp_name*/ - sizeof(PyChatnet), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)PyChatnet_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - "PyChatnet objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - PyChatnet_methods, /* tp_methods */ - 0, /* tp_members */ - PyChatnet_getseters, /* tp_getset */ - &PyIrssiChatBaseType, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ -}; - - -/* chatnet factory function */ -PyObject *pychatnet_sub_new(void *cn, PyTypeObject *subclass) -{ - static const char *name = "CHATNET"; - PyChatnet *pycn = NULL; - - pycn = py_instp(PyChatnet, subclass); - if (!pycn) - return NULL; - - pycn->data = cn; - pycn->base_name = name; - signal_add_last_data("chatnet destroyed", chatnet_cleanup, pycn); - pycn->cleanup_installed = 1; - - return (PyObject *)pycn; -} - -PyObject *pychatnet_new(void *cn) -{ - return pychatnet_sub_new(cn, &PyChatnetType); -} - -int chatnet_object_init(void) -{ - g_return_val_if_fail(py_module != NULL, 0); - - if (PyType_Ready(&PyChatnetType) < 0) - return 0; - - Py_INCREF(&PyChatnetType); - PyModule_AddObject(py_module, "Chatnet", (PyObject *)&PyChatnetType); - - return 1; -} diff --git a/objects/chatnet-object.h b/objects/chatnet-object.h deleted file mode 100644 index 8a6d1fc..0000000 --- a/objects/chatnet-object.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef _CHATNET_OBJECT_H_ -#define _CHATNET_OBJECT_H_ - -#include -#include "base-objects.h" - -/* forward */ -struct _CHATNET_REC; - -typedef struct -{ - PyIrssi_HEAD(struct _CHATNET_REC) -} PyChatnet; - -extern PyTypeObject PyChatnetType; - -int chatnet_object_init(void); -PyObject *pychatnet_sub_new(void *cn, PyTypeObject *subclass); -PyObject *pychatnet_new(void *cn); -#define pychatnet_check(op) PyObject_TypeCheck(op, &PyChatnetType) - -#endif diff --git a/objects/command-object.c b/objects/command-object.c deleted file mode 100644 index ad60012..0000000 --- a/objects/command-object.c +++ /dev/null @@ -1,145 +0,0 @@ -#include -#include "pyirssi.h" -#include "pymodule.h" -#include "command-object.h" -#include "pycore.h" - -#define COMMAND(cmd) ((COMMAND_REC *)cmd) - -/* monitor "commandlist remove" signal */ -static void command_cleanup(COMMAND_REC *command) -{ - PyCommand *pycommand = signal_get_user_data(); - - if (command == pycommand->data) - { - pycommand->data = NULL; - pycommand->cleanup_installed = 0; - signal_remove_data("commandlist remove", command_cleanup, pycommand); - } -} - -static void PyCommand_dealloc(PyCommand *self) -{ - if (self->cleanup_installed) - signal_remove_data("commandlist remove", command_cleanup, self); - - self->ob_type->tp_free((PyObject*)self); -} - -static PyObject *PyCommand_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyCommand *self; - - self = (PyCommand *)type->tp_alloc(type, 0); - if (!self) - return NULL; - - return (PyObject *)self; -} - -/* Getters */ -PyDoc_STRVAR(PyCommand_cmd_doc, - "Command name" -); -static PyObject *PyCommand_cmd_get(PyCommand *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(COMMAND(self->data)->cmd); -} - -PyDoc_STRVAR(PyCommand_category_doc, - "Category" -); -static PyObject *PyCommand_category_get(PyCommand *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(COMMAND(self->data)->category); -} - -/* specialized getters/setters */ -static PyGetSetDef PyCommand_getseters[] = { - {"cmd", (getter)PyCommand_cmd_get, NULL, - PyCommand_cmd_doc, NULL}, - {"category", (getter)PyCommand_category_get, NULL, - PyCommand_category_doc, NULL}, - {NULL} -}; - -/* Methods */ -/* Methods for object */ -static PyMethodDef PyCommand_methods[] = { - {NULL} /* Sentinel */ -}; - -PyTypeObject PyCommandType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "Command", /*tp_name*/ - sizeof(PyCommand), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)PyCommand_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - "PyCommand objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - PyCommand_methods, /* tp_methods */ - 0, /* tp_members */ - PyCommand_getseters, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - PyCommand_new, /* tp_new */ -}; - - -/* command factory function */ -PyObject *pycommand_new(void *command) -{ - PyCommand *pycommand; - - pycommand = py_inst(PyCommand, PyCommandType); - if (!pycommand) - return NULL; - - pycommand->data = command; - pycommand->cleanup_installed = 1; - signal_add_last_data("commandlist remove", command_cleanup, pycommand); - - return (PyObject *)pycommand; -} - -int command_object_init(void) -{ - g_return_val_if_fail(py_module != NULL, 0); - - if (PyType_Ready(&PyCommandType) < 0) - return 0; - - Py_INCREF(&PyCommandType); - PyModule_AddObject(py_module, "Command", (PyObject *)&PyCommandType); - - return 1; -} diff --git a/objects/command-object.h b/objects/command-object.h deleted file mode 100644 index e6402cf..0000000 --- a/objects/command-object.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef _COMMAND_OBJECT_H_ -#define _COMMAND_OBJECT_H_ - -#include -#include "base-objects.h" - -typedef struct -{ - PyIrssiFinal_HEAD(void) -} PyCommand; - -extern PyTypeObject PyCommandType; - -int command_object_init(void); -PyObject *pycommand_new(void *command); -#define pycommand_check(op) PyObject_TypeCheck(op, &PyCommandType) - -#endif diff --git a/objects/connect-object.c b/objects/connect-object.c deleted file mode 100644 index 8ef9a29..0000000 --- a/objects/connect-object.c +++ /dev/null @@ -1,198 +0,0 @@ -#include -#include "pymodule.h" -#include "base-objects.h" -#include "connect-object.h" -#include "pyirssi.h" -#include "pycore.h" -#include "pyutils.h" - -static void connect_cleanup(SERVER_CONNECT_REC *connect) -{ - PyConnect *pyconn = signal_get_user_data(); - - /* - if (server == pyconn->data) - { - pyserver->data = NULL; - pyserver->cleanup_installed = 0; - signal_remove_data("server disconnected", connect_cleanup, pyserver); - } - */ -} - -static void PyConnect_dealloc(PyConnect *self) -{ - if (self->cleanup_installed) - signal_remove_data("server disconnected", connect_cleanup, self); - - self->ob_type->tp_free((PyObject*)self); -} - -/* Getters */ -PyDoc_STRVAR(PyConnect_address_doc, - "Address where we connected (irc.blah.org)" -); -static PyObject *PyConnect_address_get(PyConnect *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->address); -} - -PyDoc_STRVAR(PyConnect_port_doc, - "Port where we're connected" -); -static PyObject *PyConnect_port_get(PyConnect *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyInt_FromLong(self->data->port); -} - -PyDoc_STRVAR(PyConnect_chatnet_doc, - "Chat network" -); -static PyObject *PyConnect_chatnet_get(PyConnect *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->chatnet); -} - -PyDoc_STRVAR(PyConnect_password_doc, - "Password we used in connection." -); -static PyObject *PyConnect_password_get(PyConnect *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->password); -} - -PyDoc_STRVAR(PyConnect_wanted_nick_doc, - "Nick which we would prefer to use" -); -static PyObject *PyConnect_wanted_nick_get(PyConnect *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->nick); -} - -PyDoc_STRVAR(PyConnect_username_doc, - "User name" -); -static PyObject *PyConnect_username_get(PyConnect *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->username); -} - -PyDoc_STRVAR(PyConnect_realname_doc, - "Real name" -); -static PyObject *PyConnect_realname_get(PyConnect *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->realname); -} - -/* Get/Set */ -static PyGetSetDef PyConnect_getseters[] = { - {"address", (getter)PyConnect_address_get, NULL, - PyConnect_address_doc, NULL}, - {"port", (getter)PyConnect_port_get, NULL, - PyConnect_port_doc, NULL}, - {"chatnet", (getter)PyConnect_chatnet_get, NULL, - PyConnect_chatnet_doc, NULL}, - {"password", (getter)PyConnect_password_get, NULL, - PyConnect_password_doc, NULL}, - {"wanted_nick", (getter)PyConnect_wanted_nick_get, NULL, - PyConnect_wanted_nick_doc, NULL}, - {"username", (getter)PyConnect_username_get, NULL, - PyConnect_username_doc, NULL}, - {"realname", (getter)PyConnect_realname_get, NULL, - PyConnect_realname_doc, NULL}, - {NULL} -}; - -PyTypeObject PyConnectType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "Connect", /*tp_name*/ - sizeof(PyConnect), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)PyConnect_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - "PyConnect objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - 0, /* tp_members */ - PyConnect_getseters, /* tp_getset */ - &PyIrssiChatBaseType, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ -}; - - -/* server connect factory function (managed == 0, don't do signal cleanup, 1 == do sig cleanup */ -PyObject *pyconnect_sub_new(void *connect, PyTypeObject *subclass, int managed) -{ - static const char *CONNECT_TYPE = "SERVER CONNECT"; - PyConnect *pyconn = NULL; - - g_return_val_if_fail(connect != NULL, NULL); - - pyconn = py_instp(PyConnect, subclass); - if (!pyconn) - return NULL; - - pyconn->base_name = CONNECT_TYPE; - pyconn->data = connect; - - if (managed) - { - //XXX: how to handle cleanup? - //signal_add_last_data("server disconnected", connect_cleanup, pyconn); - //pyconn->cleanup_installed = 1; - } - - return (PyObject *)pyconn; -} - -PyObject *pyconnect_new(void *connect, int managed) -{ - return pyconnect_sub_new(connect, &PyConnectType, managed); -} - -int connect_object_init(void) -{ - g_return_val_if_fail(py_module != NULL, 0); - - if (PyType_Ready(&PyConnectType) < 0) - return 0; - - Py_INCREF(&PyConnectType); - PyModule_AddObject(py_module, "Connect", (PyObject *)&PyConnectType); - - return 1; -} diff --git a/objects/connect-object.h b/objects/connect-object.h deleted file mode 100644 index 53bd509..0000000 --- a/objects/connect-object.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef _CONNECT_OBJECT_H_ -#define _CONNECT_OBJECT_H_ - -#include -#include "base-objects.h" - -/* forward */ -struct _SERVER_CONNECT_REC; - -typedef struct -{ - PyIrssi_HEAD(struct _SERVER_CONNECT_REC) -} PyConnect; - -extern PyTypeObject PyConnectType; - -int connect_object_init(void); -PyObject *pyconnect_sub_new(void *connect, PyTypeObject *subtype, int managed); -PyObject *pyconnect_new(void *connect, int managed); -#define pyconnect_check(op) PyObject_TypeCheck(op, &PyConnectType) - -#endif diff --git a/objects/dcc-chat-object.c b/objects/dcc-chat-object.c deleted file mode 100644 index 5cfe796..0000000 --- a/objects/dcc-chat-object.c +++ /dev/null @@ -1,137 +0,0 @@ -#include -#include "pyirssi_irc.h" -#include "pymodule.h" -#include "dcc-chat-object.h" -#include "factory.h" -#include "pycore.h" - -/* inherit destroy and cleanup from DccChat type */ - -/* Getters */ -PyDoc_STRVAR(PyDccChat_id_doc, - "Unique identifier - usually same as nick" -); -static PyObject *PyDccChat_id_get(PyDccChat *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->id); -} - -PyDoc_STRVAR(PyDccChat_mirc_ctcp_doc, - "Send CTCPs without the CTCP_MESSAGE prefix" -); -static PyObject *PyDccChat_mirc_ctcp_get(PyDccChat *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyBool_FromLong(self->data->mirc_ctcp); -} - -PyDoc_STRVAR(PyDccChat_connection_lost_doc, - "Other side closed connection" -); -static PyObject *PyDccChat_connection_lost_get(PyDccChat *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyBool_FromLong(self->data->connection_lost); -} - -/* specialized getters/setters */ -static PyGetSetDef PyDccChat_getseters[] = { - {"id", (getter)PyDccChat_id_get, NULL, - PyDccChat_id_doc, NULL}, - {"mirc_ctcp", (getter)PyDccChat_mirc_ctcp_get, NULL, - PyDccChat_mirc_ctcp_doc, NULL}, - {"connection_lost", (getter)PyDccChat_connection_lost_get, NULL, - PyDccChat_connection_lost_doc, NULL}, - {NULL} -}; - -/* Methods */ -PyDoc_STRVAR(PyDccChat_chat_send_doc, - "chat_send(data) -> None\n" - "\n" - "Send data to a dcc chat session.\n" -); -static PyObject *PyDccChat_chat_send(PyDccChat *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"data", NULL}; - char *data = ""; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &data)) - return NULL; - - dcc_chat_send(self->data, data); - - Py_RETURN_NONE; -} - -/* Methods for object */ -static PyMethodDef PyDccChat_methods[] = { - {"chat_send", (PyCFunction)PyDccChat_chat_send, METH_VARARGS | METH_KEYWORDS, - PyDccChat_chat_send_doc}, - {NULL} /* Sentinel */ -}; - -PyTypeObject PyDccChatType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "DccChat", /*tp_name*/ - sizeof(PyDccChat), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - 0, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - "PyDccChat objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - PyDccChat_methods, /* tp_methods */ - 0, /* tp_members */ - PyDccChat_getseters, /* tp_getset */ - &PyDccType, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ -}; - -PyObject *pydcc_chat_new(void *dcc) -{ - static const char *name = "DCC CHAT"; - return pydcc_sub_new(dcc, name, &PyDccChatType); -} - -int dcc_chat_object_init(void) -{ - g_return_val_if_fail(py_module != NULL, 0); - - if (PyType_Ready(&PyDccChatType) < 0) - return 0; - - Py_INCREF(&PyDccChatType); - PyModule_AddObject(py_module, "DccChat", (PyObject *)&PyDccChatType); - - return 1; -} diff --git a/objects/dcc-chat-object.h b/objects/dcc-chat-object.h deleted file mode 100644 index 955e6be..0000000 --- a/objects/dcc-chat-object.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef _DCC_CHAT_OBJECT_H_ -#define _DCC_CHAT_OBJECT_H_ - -#include -#include "dcc-object.h" - -/* forward */ -struct CHAT_DCC_REC; - -typedef struct -{ - PyDcc_HEAD(struct CHAT_DCC_REC) -} PyDccChat; - -extern PyTypeObject PyDccChatType; - -PyObject *pydcc_chat_new(void *dcc); -#define pydcc_chat_check(op) PyObject_TypeCheck(op, &PyDccChatType) -int dcc_chat_object_init(void); - -#endif diff --git a/objects/dcc-get-object.c b/objects/dcc-get-object.c deleted file mode 100644 index fa7c13a..0000000 --- a/objects/dcc-get-object.c +++ /dev/null @@ -1,138 +0,0 @@ -#include -#include "pyirssi_irc.h" -#include "pymodule.h" -#include "dcc-get-object.h" -#include "factory.h" -#include "pycore.h" - -#define DCC_GET_CAST(rec) ((GET_DCC_REC *)rec) - -/* inherit destroy and cleanup from Dcc type */ - -/* Getters */ -PyDoc_STRVAR(PyDccGet_size_doc, - "File size" -); -static PyObject *PyDccGet_size_get(PyDccGet *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyLong_FromUnsignedLong(DCC_GET_CAST(self->data)->size); -} - -PyDoc_STRVAR(PyDccGet_skipped_doc, - "Bytes skipped from start (resuming file)" -); -static PyObject *PyDccGet_skipped_get(PyDccGet *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyLong_FromUnsignedLong(DCC_GET_CAST(self->data)->skipped); -} - -PyDoc_STRVAR(PyDccGet_get_type_doc, - "What to do if file exists? 0=default, 1=rename, 2=overwrite, 3=resume" -); -static PyObject *PyDccGet_get_type_get(PyDccGet *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyInt_FromLong(DCC_GET_CAST(self->data)->get_type); -} - -PyDoc_STRVAR(PyDccGet_file_doc, - "The real file name which we use." -); -static PyObject *PyDccGet_file_get(PyDccGet *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(DCC_GET_CAST(self->data)->file); -} - -PyDoc_STRVAR(PyDccGet_file_quoted_doc, - "true if file name was received quoted (\"file name\")" -); -static PyObject *PyDccGet_file_quoted_get(PyDccGet *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyBool_FromLong(DCC_GET_CAST(self->data)->file_quoted); -} - -/* specialized getters/setters */ -static PyGetSetDef PyDccGet_getseters[] = { - {"size", (getter)PyDccGet_size_get, NULL, - PyDccGet_size_doc, NULL}, - {"skipped", (getter)PyDccGet_skipped_get, NULL, - PyDccGet_skipped_doc, NULL}, - {"get_type", (getter)PyDccGet_get_type_get, NULL, - PyDccGet_get_type_doc, NULL}, - {"file", (getter)PyDccGet_file_get, NULL, - PyDccGet_file_doc, NULL}, - {"file_quoted", (getter)PyDccGet_file_quoted_get, NULL, - PyDccGet_file_quoted_doc, NULL}, - {NULL} -}; - -/* Methods */ -/* Methods for object */ -static PyMethodDef PyDccGet_methods[] = { - {NULL} /* Sentinel */ -}; - -PyTypeObject PyDccGetType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "DccGet", /*tp_name*/ - sizeof(PyDccGet), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - 0, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - "PyDccGet objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - PyDccGet_methods, /* tp_methods */ - 0, /* tp_members */ - PyDccGet_getseters, /* tp_getset */ - &PyDccType, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ -}; - -PyObject *pydcc_get_new(void *dcc) -{ - static const char *name = "DCC GET"; - return pydcc_sub_new(dcc, name, &PyDccGetType); -} - -int dcc_get_object_init(void) -{ - g_return_val_if_fail(py_module != NULL, 0); - - if (PyType_Ready(&PyDccGetType) < 0) - return 0; - - Py_INCREF(&PyDccGetType); - PyModule_AddObject(py_module, "DccGet", (PyObject *)&PyDccGetType); - - return 1; -} diff --git a/objects/dcc-get-object.h b/objects/dcc-get-object.h deleted file mode 100644 index 532b854..0000000 --- a/objects/dcc-get-object.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef _DCC_GET_OBJECT_H_ -#define _DCC_GET_OBJECT_H_ - -#include -#include "dcc-object.h" - -typedef struct -{ - PyDcc_HEAD(void) -} PyDccGet; - -extern PyTypeObject PyDccGetType; - -PyObject *pydcc_get_new(void *dcc); -#define pydcc_get_check(op) PyObject_TypeCheck(op, &PyDccGetType) -int dcc_get_object_init(void); - -#endif diff --git a/objects/dcc-object.c b/objects/dcc-object.c deleted file mode 100644 index 95a3a4a..0000000 --- a/objects/dcc-object.c +++ /dev/null @@ -1,347 +0,0 @@ -#include -#include "pyirssi_irc.h" -#include "pymodule.h" -#include "dcc-object.h" -#include "factory.h" -#include "pycore.h" - - -/* monitor "dcc destroyed signal" */ -static void dcc_cleanup(DCC_REC *dcc) -{ - PyDcc *pydcc = signal_get_user_data(); - - if (dcc == pydcc->data) - { - pydcc->data = NULL; - pydcc->cleanup_installed = 0; - signal_remove_data("dcc destroyed", dcc_cleanup, pydcc); - } -} - -static void PyDcc_dealloc(PyDcc *self) -{ - if (self->cleanup_installed) - signal_remove_data("dcc destroyed", dcc_cleanup, self); - - Py_XDECREF(self->server); - Py_XDECREF(self->chat); - - self->ob_type->tp_free((PyObject*)self); -} - -/* Getters */ -PyDoc_STRVAR(PyDcc_orig_type_doc, - "Original DCC type that was sent to us - same as type except GET and SEND are swapped" -); -static PyObject *PyDcc_orig_type_get(PyDcc *self, void *closure) -{ - const char *type; - - RET_NULL_IF_INVALID(self->data); - - type = module_find_id_str("DCC", DCC(self->data)->orig_type); - RET_AS_STRING_OR_NONE(type); -} - -PyDoc_STRVAR(PyDcc_created_doc, - "Time stamp when the DCC record was created" -); -static PyObject *PyDcc_created_get(PyDcc *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyLong_FromUnsignedLong(DCC(self->data)->created); -} - -PyDoc_STRVAR(PyDcc_server_doc, - "Server record where the DCC was initiated." -); -static PyObject *PyDcc_server_get(PyDcc *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_OBJ_OR_NONE(self->server); -} - -PyDoc_STRVAR(PyDcc_servertag_doc, - "Tag of the server where the DCC was initiated." -); -static PyObject *PyDcc_servertag_get(PyDcc *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(DCC(self->data)->servertag); -} - -PyDoc_STRVAR(PyDcc_mynick_doc, - "Our nick to use in DCC chat." -); -static PyObject *PyDcc_mynick_get(PyDcc *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(DCC(self->data)->mynick); -} - -PyDoc_STRVAR(PyDcc_nick_doc, - "Other side's nick name." -); -static PyObject *PyDcc_nick_get(PyDcc *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(DCC(self->data)->nick); -} - -PyDoc_STRVAR(PyDcc_chat_doc, - "Dcc chat record if the request came through DCC chat" -); -static PyObject *PyDcc_chat_get(PyDcc *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_OBJ_OR_NONE(self->chat); -} - -PyDoc_STRVAR(PyDcc_target_doc, - "Who the request was sent to - your nick, channel or empty if you sent the request" -); -static PyObject *PyDcc_target_get(PyDcc *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(DCC(self->data)->target); -} - -PyDoc_STRVAR(PyDcc_arg_doc, - "Given argument .. file name usually" -); -static PyObject *PyDcc_arg_get(PyDcc *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(DCC(self->data)->arg); -} - -PyDoc_STRVAR(PyDcc_addr_doc, - "Other side's IP address." -); -static PyObject *PyDcc_addr_get(PyDcc *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(DCC(self->data)->addrstr); -} - -PyDoc_STRVAR(PyDcc_port_doc, - "Port we're connecting in." -); -static PyObject *PyDcc_port_get(PyDcc *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyInt_FromLong(DCC(self->data)->port); -} - -PyDoc_STRVAR(PyDcc_starttime_doc, - "Unix time stamp when the DCC transfer was started" -); -static PyObject *PyDcc_starttime_get(PyDcc *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyLong_FromUnsignedLong(DCC(self->data)->starttime); -} - -PyDoc_STRVAR(PyDcc_transfd_doc, - "Bytes transferred" -); -static PyObject *PyDcc_transfd_get(PyDcc *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyLong_FromUnsignedLong(DCC(self->data)->transfd); -} - -/* specialized getters/setters */ -static PyGetSetDef PyDcc_getseters[] = { - {"orig_type", (getter)PyDcc_orig_type_get, NULL, - PyDcc_orig_type_doc, NULL}, - {"created", (getter)PyDcc_created_get, NULL, - PyDcc_created_doc, NULL}, - {"server", (getter)PyDcc_server_get, NULL, - PyDcc_server_doc, NULL}, - {"servertag", (getter)PyDcc_servertag_get, NULL, - PyDcc_servertag_doc, NULL}, - {"mynick", (getter)PyDcc_mynick_get, NULL, - PyDcc_mynick_doc, NULL}, - {"nick", (getter)PyDcc_nick_get, NULL, - PyDcc_nick_doc, NULL}, - {"chat", (getter)PyDcc_chat_get, NULL, - PyDcc_chat_doc, NULL}, - {"target", (getter)PyDcc_target_get, NULL, - PyDcc_target_doc, NULL}, - {"arg", (getter)PyDcc_arg_get, NULL, - PyDcc_arg_doc, NULL}, - {"addr", (getter)PyDcc_addr_get, NULL, - PyDcc_addr_doc, NULL}, - {"port", (getter)PyDcc_port_get, NULL, - PyDcc_port_doc, NULL}, - {"starttime", (getter)PyDcc_starttime_get, NULL, - PyDcc_starttime_doc, NULL}, - {"transfd", (getter)PyDcc_transfd_get, NULL, - PyDcc_transfd_doc, NULL}, - {NULL} -}; - -/* Methods */ -PyDoc_STRVAR(PyDcc_destroy_doc, - "destroy() -> None\n" - "\n" - "Destroy DCC connection\n" -); -static PyObject *PyDcc_destroy(PyDcc *self, PyObject *args) -{ - RET_NULL_IF_INVALID(self->data); - - dcc_destroy(DCC(self->data)); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyDcc_reject_doc, - "reject() -> None\n" - "\n" - "?\n" -); -static PyObject *PyDcc_reject(PyDcc *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"server", NULL}; - PyObject *server = NULL; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, - &server)) - return NULL; - - if (!pyirc_server_check(server)) - return PyErr_Format(PyExc_TypeError, "arg must be IRC server object"); - - dcc_reject(self->data, ((PyIrcServer*)server)->data); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyDcc_close_doc, - "close() -> None\n" - "\n" - "Close and destroy DCC connection.\n" -); -static PyObject *PyDcc_close(PyDcc *self, PyObject *args) -{ - RET_NULL_IF_INVALID(self->data); - - dcc_close(self->data); - - Py_RETURN_NONE; -} - -/* Methods for object */ -static PyMethodDef PyDcc_methods[] = { - {"destroy", (PyCFunction)PyDcc_destroy, METH_NOARGS, - PyDcc_destroy_doc}, - {"reject", (PyCFunction)PyDcc_reject, METH_VARARGS | METH_KEYWORDS, - PyDcc_reject_doc}, - {"close", (PyCFunction)PyDcc_close, METH_NOARGS, - PyDcc_close_doc}, - {NULL} /* Sentinel */ -}; - -PyTypeObject PyDccType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "Dcc", /*tp_name*/ - sizeof(PyDcc), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)PyDcc_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - "PyDcc objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - PyDcc_methods, /* tp_methods */ - 0, /* tp_members */ - PyDcc_getseters, /* tp_getset */ - &PyIrssiBaseType, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ -}; - - -/* Dcc factory function */ -PyObject *pydcc_sub_new(void *dcc, const char *name, PyTypeObject *subclass) -{ - PyObject *chat = NULL, *server = NULL; - PyDcc *pydcc; - DCC_REC *rec = dcc; - - server = py_irssi_chat_new(rec->server, 1); - if (!server) - return NULL; - - chat = py_irssi_chat_new(rec->chat, 1); - if (!chat) - { - Py_DECREF(server); - return NULL; - } - - pydcc = py_instp(PyDcc, subclass); - if (!pydcc) - { - Py_DECREF(server); - Py_DECREF(chat); - return NULL; - } - - pydcc->data = dcc; - pydcc->server = server; - pydcc->chat = chat; - pydcc->base_name = name; - - pydcc->cleanup_installed = 1; - signal_add_last_data("dcc destroyed", dcc_cleanup, pydcc); - - return (PyObject *)pydcc; -} - -PyObject *pydcc_new(void *dcc) -{ - static const char *name = "DCC"; - return pydcc_sub_new(dcc, name, &PyDccType); -} - -int dcc_object_init(void) -{ - g_return_val_if_fail(py_module != NULL, 0); - - if (PyType_Ready(&PyDccType) < 0) - return 0; - - Py_INCREF(&PyDccType); - PyModule_AddObject(py_module, "Dcc", (PyObject *)&PyDccType); - - return 1; -} diff --git a/objects/dcc-object.h b/objects/dcc-object.h deleted file mode 100644 index d44d3db..0000000 --- a/objects/dcc-object.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef _DCC_OBJECT_H_ -#define _DCC_OBJECT_H_ - -#include -#include "base-objects.h" - -#define PyDcc_HEAD(type) \ - PyIrssi_HEAD(type) \ - PyObject *server; \ - PyObject *chat; - -typedef struct -{ - PyDcc_HEAD(void) -} PyDcc; - -extern PyTypeObject PyDccType; - -PyObject *pydcc_sub_new(void *dcc, const char *name, PyTypeObject *subclass); -PyObject *pydcc_new(void *dcc); -#define pydcc_check(op) PyObject_TypeCheck(op, &PyDccType) -int dcc_object_init(void); - -#endif diff --git a/objects/dcc-send-object.c b/objects/dcc-send-object.c deleted file mode 100644 index 643f741..0000000 --- a/objects/dcc-send-object.c +++ /dev/null @@ -1,138 +0,0 @@ -#include -#include "pyirssi_irc.h" -#include "pymodule.h" -#include "dcc-send-object.h" -#include "factory.h" -#include "pycore.h" - -#define DCC_SEND_CAST(rec) ((SEND_DCC_REC *)rec) - -/* inherit destroy and cleanup from Dcc type */ - -/* Getters */ -PyDoc_STRVAR(PyDccSend_size_doc, - "File size" -); -static PyObject *PyDccSend_size_get(PyDccSend *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyLong_FromUnsignedLong(DCC_SEND_CAST(self->data)->size); -} - -PyDoc_STRVAR(PyDccSend_skipped_doc, - "Bytes skipped from start (resuming file)" -); -static PyObject *PyDccSend_skipped_get(PyDccSend *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyLong_FromUnsignedLong(DCC_SEND_CAST(self->data)->skipped); -} - -PyDoc_STRVAR(PyDccSend_file_quoted_doc, - "True if file name was received quoted (\"file name\")" -); -static PyObject *PyDccSend_file_quoted_get(PyDccSend *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyBool_FromLong(DCC_SEND_CAST(self->data)->file_quoted); -} - -PyDoc_STRVAR(PyDccSend_waitforend_doc, - "File is sent, just wait for the replies from the other side" -); -static PyObject *PyDccSend_waitforend_get(PyDccSend *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyBool_FromLong(DCC_SEND_CAST(self->data)->waitforend); -} - -PyDoc_STRVAR(PyDccSend_gotalldata_doc, - "Got all acks from the other end" -); -static PyObject *PyDccSend_gotalldata_get(PyDccSend *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyBool_FromLong(DCC_SEND_CAST(self->data)->gotalldata); -} - -/* specialized getters/setters */ -static PyGetSetDef PyDccSend_getseters[] = { - {"size", (getter)PyDccSend_size_get, NULL, - PyDccSend_size_doc, NULL}, - {"skipped", (getter)PyDccSend_skipped_get, NULL, - PyDccSend_skipped_doc, NULL}, - {"file_quoted", (getter)PyDccSend_file_quoted_get, NULL, - PyDccSend_file_quoted_doc, NULL}, - {"waitforend", (getter)PyDccSend_waitforend_get, NULL, - PyDccSend_waitforend_doc, NULL}, - {"gotalldata", (getter)PyDccSend_gotalldata_get, NULL, - PyDccSend_gotalldata_doc, NULL}, - {NULL} -}; - -/* Methods */ -/* Methods for object */ -static PyMethodDef PyDccSend_methods[] = { - {NULL} /* Sentinel */ -}; - -PyTypeObject PyDccSendType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "DccSend", /*tp_name*/ - sizeof(PyDccSend), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - 0, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - "PyDccSend objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - PyDccSend_methods, /* tp_methods */ - 0, /* tp_members */ - PyDccSend_getseters, /* tp_getset */ - &PyDccType, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ -}; - -PyObject *pydcc_send_new(void *dcc) -{ - static const char *name = "DCC SEND"; - return pydcc_sub_new(dcc, name, &PyDccSendType); -} - -int dcc_send_object_init(void) -{ - g_return_val_if_fail(py_module != NULL, 0); - - if (PyType_Ready(&PyDccSendType) < 0) - return 0; - - Py_INCREF(&PyDccSendType); - PyModule_AddObject(py_module, "DccSend", (PyObject *)&PyDccSendType); - - return 1; -} diff --git a/objects/dcc-send-object.h b/objects/dcc-send-object.h deleted file mode 100644 index 6303f86..0000000 --- a/objects/dcc-send-object.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef _DCC_SEND_OBJECT_H_ -#define _DCC_SEND_OBJECT_H_ - -#include -#include "dcc-object.h" - -typedef struct -{ - PyDcc_HEAD(void) -} PyDccSend; - -extern PyTypeObject PyDccSendType; - -PyObject *pydcc_send_new(void *dcc); -#define pydcc_send_check(op) PyObject_TypeCheck(op, &PyDccSendType) -int dcc_send_object_init(void); - -#endif diff --git a/objects/factory.c b/objects/factory.c deleted file mode 100644 index 49336e6..0000000 --- a/objects/factory.c +++ /dev/null @@ -1,326 +0,0 @@ -#include -#include "pyirssi.h" -#include "factory.h" - -/* Irssi object factory works for all items with at least a type member. - * - * Use py_irssi_new() or py_irssi_chat_new() to get a new wrapper for an - * IrssiObject or an IrssiChatObject, respectively. - * - * For objects not descending from IrssiObject or IrssiChatObject, you must - * use the object-specific init function directly. - */ - -#define MAKEKEY(type, chat) ((chat << 16 ) | type) -#define GETTYPE(key) (key & 0xffff) -#define GETCHAT(key) ((key >> 16) & 0xffff) - - -GHashTable *init_map = NULL; - -static int init_objects(void); -static void register_chat(CHAT_PROTOCOL_REC *rec); -static void unregister_chat(CHAT_PROTOCOL_REC *rec); -static void insert_map(int type, int chat_type, InitFunc func); -static int remove_chat(void *key, void *value, void *chat_typep); -static void register_nonchat(void); -static InitFunc find_map(int type, int chat_type); - -static int init_objects(void) -{ - if (!pyscript_init()) - return 0; - - /* order is somewhat important here */ - if (!base_objects_init()) - return 0; - - if (!window_item_object_init()) - return 0; - - if (!channel_object_init()) - return 0; - - if (!query_object_init()) - return 0; - - if (!server_object_init()) - return 0; - - if (!connect_object_init()) - return 0; - - if (!irc_server_object_init()) - return 0; - - if (!irc_connect_object_init()) - return 0; - - if (!irc_channel_object_init()) - return 0; - - if (!ban_object_init()) - return 0; - - if (!nick_object_init()) - return 0; - - if (!chatnet_object_init()) - return 0; - - if (!reconnect_object_init()) - return 0; - - if (!window_object_init()) - return 0; - - if (!textdest_object_init()) - return 0; - - if (!rawlog_object_init()) - return 0; - - if (!log_object_init()) - return 0; - - if (!logitem_object_init()) - return 0; - - if (!ignore_object_init()) - return 0; - - if (!dcc_object_init()) - return 0; - - if (!dcc_chat_object_init()) - return 0; - - if (!dcc_get_object_init()) - return 0; - - if (!dcc_send_object_init()) - return 0; - - if (!netsplit_object_init()) - return 0; - - if (!netsplit_server_object_init()) - return 0; - - if (!netsplit_channel_object_init()) - return 0; - - if (!notifylist_object_init()) - return 0; - - if (!process_object_init()) - return 0; - - if (!command_object_init()) - return 0; - - if (!theme_object_init()) - return 0; - - if (!statusbar_item_object_init()) - return 0; - - if (!main_window_object_init()) - return 0; - - return 1; -} - -static InitFunc find_map(int type, int chat_type) -{ - unsigned hash; - - g_return_val_if_fail(type <= 0xffff, NULL); - g_return_val_if_fail(chat_type <= 0xffff, NULL); - - hash = MAKEKEY(type, chat_type); - return g_hash_table_lookup(init_map, GUINT_TO_POINTER(hash)); -} - -static void insert_map(int type, int chat_type, InitFunc func) -{ - unsigned hash; - - g_return_if_fail(type <= 0xffff); - g_return_if_fail(chat_type <= 0xffff); - - hash = MAKEKEY(type, chat_type); - g_hash_table_insert(init_map, GUINT_TO_POINTER(hash), func); -} - -static void register_chat(CHAT_PROTOCOL_REC *rec) -{ - int type; - int chat_type; - int is_irc = 0; - - /* chat_type == rec->id ??? */ - chat_type = chat_protocol_lookup(rec->name); - g_return_if_fail(chat_type >= 0 && chat_type < 0xffff); - - if (!g_strcasecmp(rec->name, "IRC")) - is_irc = 1; - - type = module_get_uniq_id("SERVER", 0); - if (is_irc) - insert_map(type, chat_type, (InitFunc)pyirc_server_new); - else - insert_map(type, chat_type, (InitFunc)pyserver_new); - - type = module_get_uniq_id("SERVER CONNECT", 0); - if (is_irc) - insert_map(type, chat_type, (InitFunc)pyirc_connect_new); - else - insert_map(type, chat_type, (InitFunc)pyconnect_new); - - type = module_get_uniq_id_str("WINDOW ITEM TYPE", "CHANNEL"); - if (is_irc) - insert_map(type, chat_type, (InitFunc)pyirc_channel_new); - else - insert_map(type, chat_type, (InitFunc)pychannel_new); - - type = module_get_uniq_id_str("WINDOW ITEM TYPE", "QUERY"); - insert_map(type, chat_type, (InitFunc)pyquery_new); - - type = module_get_uniq_id("CHATNET", 0); - insert_map(type, chat_type, (InitFunc)pychatnet_new); - - type = module_get_uniq_id("NICK", 0); - insert_map(type, chat_type, (InitFunc)pynick_new); -} - -/* register funcs for objects without a chat type */ -static void register_nonchat(void) -{ - int type; - int chat_type = 0xffff; - - type = module_get_uniq_id_str("DCC", "CHAT"); - insert_map(type, chat_type, (InitFunc)pydcc_chat_new); - - type = module_get_uniq_id_str("DCC", "GET"); - insert_map(type, chat_type, (InitFunc)pydcc_get_new); - - type = module_get_uniq_id_str("DCC", "SEND"); - insert_map(type, chat_type, (InitFunc)pydcc_send_new); - - type = module_get_uniq_id_str("DCC", "SERVER"); - insert_map(type, chat_type, (InitFunc)pydcc_new); -} - -static int remove_chat(void *key, void *value, void *chat_typep) -{ - unsigned hash = GPOINTER_TO_UINT(key); - int chat_type = GPOINTER_TO_INT(chat_type); - - if (GETCHAT(hash) == chat_type) - return TRUE; - - return FALSE; -} - -/* remove all items matching chat_type */ -static void unregister_chat(CHAT_PROTOCOL_REC *rec) -{ - /*int chat_type = chat_protocol_lookup(rec->name);*/ - g_hash_table_foreach_remove(init_map, - (GHRFunc)remove_chat, - GINT_TO_POINTER(rec->id)); -} - -PyObject *py_irssi_new(void *typeobj, int managed) -{ - IRSSI_BASE_REC *base = typeobj; - InitFunc ifunc; - - if (!base) - Py_RETURN_NONE; - - ifunc = find_map(base->type, 0xffff); - - if (ifunc) - return ifunc(typeobj, managed); - - return PyErr_Format(PyExc_RuntimeError, "no initfunc for object type %d", base->type); -} - -PyObject *py_irssi_chat_new(void *typeobj, int managed) -{ - IRSSI_CHAT_REC *chat = typeobj; - InitFunc ifunc; - - if (!chat) - Py_RETURN_NONE; - - ifunc = find_map(chat->type, chat->chat_type); - - if (ifunc) - return ifunc(typeobj, managed); - - return PyErr_Format(PyExc_RuntimeError, "no initfunc for object type %d, chat_type %d", - chat->type, chat->chat_type); -} - -PyObject *py_irssi_objlist_new(GSList *node, int managed, InitFunc init) -{ - PyObject *list = NULL; - - list = PyList_New(0); - if (!list) - goto error; - - for (; node != NULL; node = node->next) - { - int ret; - PyObject *obj = init(node->data, managed); - - if (!obj) - goto error; - - ret = PyList_Append(list, obj); - Py_DECREF(obj); - - if (ret != 0) - goto error; - } - - return list; - -error: - Py_XDECREF(list); - return NULL; -} - -int factory_init(void) -{ - g_return_val_if_fail(init_map == NULL, 0); - - if (!init_objects()) - return 0; - - init_map = g_hash_table_new(g_direct_hash, g_direct_equal); - g_slist_foreach(chat_protocols, (GFunc) register_chat, NULL); - register_nonchat(); - - signal_add("chat protocol created", (SIGNAL_FUNC) register_chat); - signal_add("chat protocol destroyed", (SIGNAL_FUNC) unregister_chat); - - return 1; -} - -void factory_deinit(void) -{ - g_return_if_fail(init_map != NULL); - - g_hash_table_destroy(init_map); - init_map = NULL; - - signal_remove("chat protocol created", (SIGNAL_FUNC) register_chat); - signal_remove("chat protocol destroyed", (SIGNAL_FUNC) unregister_chat); -} - diff --git a/objects/factory.h b/objects/factory.h deleted file mode 100644 index 9d4bd79..0000000 --- a/objects/factory.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef _FACTORY_H_ -#define _FACTORY_H_ - -#include -#include "pyscript-object.h" -#include "base-objects.h" -#include "window-item-object.h" -#include "channel-object.h" -#include "query-object.h" -#include "server-object.h" -#include "connect-object.h" -#include "irc-server-object.h" -#include "irc-connect-object.h" -#include "irc-channel-object.h" -#include "ban-object.h" -#include "nick-object.h" -#include "chatnet-object.h" -#include "reconnect-object.h" -#include "window-object.h" -#include "textdest-object.h" -#include "rawlog-object.h" -#include "log-object.h" -#include "logitem-object.h" -#include "ignore-object.h" -#include "dcc-object.h" -#include "dcc-chat-object.h" -#include "dcc-get-object.h" -#include "dcc-send-object.h" -#include "netsplit-object.h" -#include "netsplit-server-object.h" -#include "netsplit-channel-object.h" -#include "notifylist-object.h" -#include "process-object.h" -#include "command-object.h" -#include "theme-object.h" -#include "statusbar-item-object.h" -#include "main-window-object.h" - -int factory_init(void); -void factory_deinit(void); - -/*managed == 1: object invalidates itself - *managed == 0: caller responsible for invalidating object - *XXX: most objects invalidate themselves, ignoring "managed" switch, - * and some are never managed (Reconnect) - */ - -/* For objects with a type member but no chat_type */ -PyObject *py_irssi_new(void *typeobj, int managed); -/* For objects with both type and chat_type members */ -PyObject *py_irssi_chat_new(void *typeobj, int managed); - -typedef PyObject *(*InitFunc)(void *, int); -PyObject *py_irssi_objlist_new(GSList *node, int managed, InitFunc init); -#define py_irssi_chatlist_new(n, m) py_irssi_objlist_new(n, m, py_irssi_chat_new) -#define py_irssi_list_new(n, m) py_irssi_objlist_new(n, m, py_irssi_new) - -#endif diff --git a/objects/ignore-object.c b/objects/ignore-object.c deleted file mode 100644 index 979c9b1..0000000 --- a/objects/ignore-object.c +++ /dev/null @@ -1,284 +0,0 @@ -#include -#include "pyirssi_irc.h" -#include "pymodule.h" -#include "ignore-object.h" -#include "factory.h" -#include "pycore.h" - -/* monitor "ignore destroy" signal */ -static void ignore_cleanup(IGNORE_REC *ignore) -{ - PyIgnore *pyignore = signal_get_user_data(); - - if (ignore == pyignore->data) - { - pyignore->data = NULL; - pyignore->cleanup_installed = 0; - signal_remove_data("ignore destroy", ignore_cleanup, pyignore); - } -} - -static void PyIgnore_dealloc(PyIgnore *self) -{ - if (self->cleanup_installed) - signal_remove_data("ignore destroy", ignore_cleanup, self); - - self->ob_type->tp_free((PyObject*)self); -} - -static PyObject *PyIgnore_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyIgnore *self; - - self = (PyIgnore *)type->tp_alloc(type, 0); - if (!self) - return NULL; - - return (PyObject *)self; -} - -/* Getters */ -PyDoc_STRVAR(PyIgnore_mask_doc, - "Ignore mask" -); -static PyObject *PyIgnore_mask_get(PyIgnore *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->mask); -} - -PyDoc_STRVAR(PyIgnore_servertag_doc, - "Ignore only in server" -); -static PyObject *PyIgnore_servertag_get(PyIgnore *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->servertag); -} - -PyDoc_STRVAR(PyIgnore_pattern_doc, - "Ignore text patern" -); -static PyObject *PyIgnore_pattern_get(PyIgnore *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->pattern); -} - -PyDoc_STRVAR(PyIgnore_level_doc, - "Ignore level" -); -static PyObject *PyIgnore_level_get(PyIgnore *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyInt_FromLong(self->data->level); -} - -PyDoc_STRVAR(PyIgnore_exception_doc, - "This is an exception ignore" -); -static PyObject *PyIgnore_exception_get(PyIgnore *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyBool_FromLong(self->data->exception); -} - -PyDoc_STRVAR(PyIgnore_regexp_doc, - "Regexp pattern matching" -); -static PyObject *PyIgnore_regexp_get(PyIgnore *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyBool_FromLong(self->data->regexp); -} - -PyDoc_STRVAR(PyIgnore_fullword_doc, - "Pattern matches only full words" -); -static PyObject *PyIgnore_fullword_get(PyIgnore *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyBool_FromLong(self->data->fullword); -} - -PyDoc_STRVAR(PyIgnore_replies_doc, - "Ignore replies to nick in channel" -); -static PyObject *PyIgnore_replies_get(PyIgnore *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyBool_FromLong(self->data->replies); -} - -/* specialized getters/setters */ -static PyGetSetDef PyIgnore_getseters[] = { - {"mask", (getter)PyIgnore_mask_get, NULL, - PyIgnore_mask_doc, NULL}, - {"servertag", (getter)PyIgnore_servertag_get, NULL, - PyIgnore_servertag_doc, NULL}, - {"pattern", (getter)PyIgnore_pattern_get, NULL, - PyIgnore_pattern_doc, NULL}, - {"level", (getter)PyIgnore_level_get, NULL, - PyIgnore_level_doc, NULL}, - {"exception", (getter)PyIgnore_exception_get, NULL, - PyIgnore_exception_doc, NULL}, - {"regexp", (getter)PyIgnore_regexp_get, NULL, - PyIgnore_regexp_doc, NULL}, - {"fullword", (getter)PyIgnore_fullword_get, NULL, - PyIgnore_fullword_doc, NULL}, - {"replies", (getter)PyIgnore_replies_get, NULL, - PyIgnore_replies_doc, NULL}, - {NULL} -}; - -/* Methods */ -PyDoc_STRVAR(PyIgnore_channels_doc, - "channels() -> list of str\n" - "\n" - "Ignore only in channels (list of names)\n" -); -static PyObject *PyIgnore_channels(PyIgnore *self, PyObject *args) -{ - char **p; - PyObject *list; - - RET_NULL_IF_INVALID(self->data); - - list = PyList_New(0); - if (!list) - return NULL; - - for (p = self->data->channels; *p; p++) - { - int ret; - PyObject *str; - - str = PyString_FromString(*p); - if (!str) - { - Py_XDECREF(list); - return NULL; - } - - ret = PyList_Append(list, str); - Py_DECREF(str); - if (ret != 0) - { - Py_XDECREF(list); - return NULL; - } - } - - return list; -} - -PyDoc_STRVAR(PyIgnore_add_rec_doc, - "add_rec() -> None\n" - "\n" - "Add ignore record" -); -static PyObject *PyIgnore_add_rec(PyIgnore *self, PyObject *args) -{ - RET_NULL_IF_INVALID(self->data); - - ignore_add_rec(self->data); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyIgnore_update_rec_doc, - "update_rec() -> None\n" - "\n" - "Update ignore record in configuration" -); -static PyObject *PyIgnore_update_rec(PyIgnore *self, PyObject *args) -{ - RET_NULL_IF_INVALID(self->data); - - ignore_update_rec(self->data); - - Py_RETURN_NONE; -} - -/* Methods for object */ -static PyMethodDef PyIgnore_methods[] = { - {"add_rec", (PyCFunction)PyIgnore_add_rec, METH_NOARGS, - PyIgnore_add_rec_doc}, - {"update_rec", (PyCFunction)PyIgnore_update_rec, METH_NOARGS, - PyIgnore_update_rec_doc}, - {"channels", (PyCFunction)PyIgnore_channels, METH_NOARGS, - PyIgnore_channels_doc}, - {NULL} /* Sentinel */ -}; - -PyTypeObject PyIgnoreType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "Ignore", /*tp_name*/ - sizeof(PyIgnore), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)PyIgnore_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - "PyIgnore objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - PyIgnore_methods, /* tp_methods */ - 0, /* tp_members */ - PyIgnore_getseters, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - PyIgnore_new, /* tp_new */ -}; - - -/* ignore factory function */ -PyObject *pyignore_new(void *ignore) -{ - PyIgnore *pyignore; - - pyignore = py_inst(PyIgnore, PyIgnoreType); - if (!pyignore) - return NULL; - - pyignore->data = ignore; - pyignore->cleanup_installed = 1; - signal_add_last_data("ignore destroy", ignore_cleanup, pyignore); - - return (PyObject *)pyignore; -} - -int ignore_object_init(void) -{ - g_return_val_if_fail(py_module != NULL, 0); - - if (PyType_Ready(&PyIgnoreType) < 0) - return 0; - - Py_INCREF(&PyIgnoreType); - PyModule_AddObject(py_module, "Ignore", (PyObject *)&PyIgnoreType); - - return 1; -} diff --git a/objects/ignore-object.h b/objects/ignore-object.h deleted file mode 100644 index 39f7425..0000000 --- a/objects/ignore-object.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef _IGNORE_OBJECT_H_ -#define _IGNORE_OBJECT_H_ - -#include -#include "base-objects.h" - -/* forward */ -struct _IGNORE_REC; - -typedef struct -{ - PyIrssiFinal_HEAD(struct _IGNORE_REC) -} PyIgnore; - -extern PyTypeObject PyIgnoreType; - -int ignore_object_init(void); -PyObject *pyignore_new(void *ignore); -#define pyignore_check(op) PyObject_TypeCheck(op, &PyIgnoreType) - -#endif diff --git a/objects/irc-channel-object.c b/objects/irc-channel-object.c deleted file mode 100644 index 5e9531d..0000000 --- a/objects/irc-channel-object.c +++ /dev/null @@ -1,173 +0,0 @@ -#include -#include "pyirssi_irc.h" -#include "pymodule.h" -#include "pycore.h" -#include "irc-channel-object.h" -#include "factory.h" - -/* PyIrcChannel destructor is inherited from PyChannel */ - -/* specialized getters/setters */ -static PyGetSetDef PyIrcChannel_getseters[] = { - {NULL} -}; - -/* Methods */ -PyDoc_STRVAR(bans_doc, - "bans() -> list of Ban objects\n" - "\n" - "Returns a list of bans in the channel.\n" -); -static PyObject *PyIrcChannel_bans(PyIrcChannel *self, PyObject *args) -{ - RET_NULL_IF_INVALID(self->data); - - return py_irssi_objlist_new(self->data->banlist, 1, (InitFunc)pyban_new); -} - -PyDoc_STRVAR(ban_get_mask_doc, - "ban_get_mask(nick, ban_type=0) -> str\n" - "\n" - "Get ban mask for 'nick'.\n" -); -static PyObject *PyIrcChannel_ban_get_mask(PyIrcChannel *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"nick", "ban_type", NULL}; - char *nick, *str; - int ban_type = 0; - PyObject *ret; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|i", kwlist, &nick, &ban_type)) - return NULL; - - str = ban_get_mask(self->data, nick, ban_type); - if (!str) - Py_RETURN_NONE; - - ret = PyString_FromString(str); - g_free(str); - - return ret; -} - -PyDoc_STRVAR(banlist_add_doc, - "banlist_add(ban, nick, time) -> Ban object or None\n" - "\n" - "Add a new ban to channel. Return None if duplicate." -); -static PyObject *PyIrcChannel_banlist_add(PyIrcChannel *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"ban", "nick", "time", NULL}; - char *ban, *nick; - time_t btime; - BAN_REC *newban; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "ssk", kwlist, &ban, &nick, &btime)) - return NULL; - - newban = banlist_add(self->data, ban, nick, btime); - /* XXX: return none or throw error? */ - if (!newban) - Py_RETURN_NONE; - - return pyban_new(newban); -} - -PyDoc_STRVAR(banlist_remove_doc, - "banlist_remove(ban, nick) -> None\n" - "\n" - "Remove a new ban from channel.\n" -); -static PyObject *PyIrcChannel_banlist_remove(PyIrcChannel *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"ban", "nick", NULL}; - char *ban, *nick; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss", kwlist, &ban, &nick)) - return NULL; - - banlist_remove(self->data, ban, nick); - Py_RETURN_NONE; -} - -/* Methods for object */ -static PyMethodDef PyIrcChannel_methods[] = { - {"bans", (PyCFunction)PyIrcChannel_bans, METH_NOARGS, - bans_doc}, - {"ban_get_mask", (PyCFunction)PyIrcChannel_ban_get_mask, METH_VARARGS | METH_KEYWORDS, - ban_get_mask_doc}, - {"banlist_add", (PyCFunction)PyIrcChannel_banlist_add, METH_VARARGS | METH_KEYWORDS, - banlist_add_doc}, - {"banlist_remove", (PyCFunction)PyIrcChannel_banlist_remove, METH_VARARGS | METH_KEYWORDS, - banlist_remove_doc}, - {NULL} /* Sentinel */ -}; - -PyTypeObject PyIrcChannelType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "IrcChannel", /*tp_name*/ - sizeof(PyIrcChannel), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - 0, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - "PyIrcChannel objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - PyIrcChannel_methods, /* tp_methods */ - 0, /* tp_members */ - PyIrcChannel_getseters, /* tp_getset */ - &PyChannelType, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ -}; - - -/* irc channel factory function */ -PyObject *pyirc_channel_new(void *chan) -{ - static const char *BASE_NAME = "CHANNEL"; - return pychannel_sub_new(chan, BASE_NAME, &PyIrcChannelType); -} - -int irc_channel_object_init(void) -{ - g_return_val_if_fail(py_module != NULL, 0); - - if (PyType_Ready(&PyIrcChannelType) < 0) - return 0; - - Py_INCREF(&PyIrcChannelType); - PyModule_AddObject(py_module, "IrcChannel", (PyObject *)&PyIrcChannelType); - - return 1; -} diff --git a/objects/irc-channel-object.h b/objects/irc-channel-object.h deleted file mode 100644 index a1d845a..0000000 --- a/objects/irc-channel-object.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef _IRC_CHANNEL_OBJECT_H_ -#define _IRC_CHANNEL_OBJECT_H_ - -#include -#include "window-item-object.h" - -/* forward */ -struct _IRC_CHANNEL_REC; - -typedef struct -{ - PyWindowItem_HEAD(struct _IRC_CHANNEL_REC) -} PyIrcChannel; - -extern PyTypeObject PyIrcChannelType; - -int irc_channel_object_init(void); -PyObject *pyirc_channel_new(void *chan); -#define pyirc_channel_check(op) PyObject_TypeCheck(op, &PyIrcChannelType) - -#endif diff --git a/objects/irc-connect-object.c b/objects/irc-connect-object.c deleted file mode 100644 index 5068dea..0000000 --- a/objects/irc-connect-object.c +++ /dev/null @@ -1,86 +0,0 @@ -#include -#include "pymodule.h" -#include "base-objects.h" -#include "irc-connect-object.h" -#include "pyirssi_irc.h" -#include "pycore.h" -#include "pyutils.h" - -/* cleanup and deallocation handled by Connect base */ - -/* Getters */ -PyDoc_STRVAR(PyIrcConnect_alternate_nick_doc, - "Alternate nick to use if default nick is taken" -); -static PyObject *PyIrcConnect_alternate_nick_get(PyIrcConnect *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->alternate_nick); -} - -/* Get/Set */ -static PyGetSetDef PyIrcConnect_getseters[] = { - {"alternate_nick", (getter)PyIrcConnect_alternate_nick_get, NULL, - PyIrcConnect_alternate_nick_doc, NULL}, - {NULL} -}; - -PyTypeObject PyIrcConnectType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "IrcConnect", /*tp_name*/ - sizeof(PyIrcConnect), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - 0, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - "PyIrcConnect objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - 0, /* tp_members */ - PyIrcConnect_getseters, /* tp_getset */ - &PyConnectType, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ -}; - -PyObject *pyirc_connect_new(void *connect, int managed) -{ - return pyconnect_sub_new(connect, &PyIrcConnectType, managed); -} - -int irc_connect_object_init(void) -{ - g_return_val_if_fail(py_module != NULL, 0); - - if (PyType_Ready(&PyIrcConnectType) < 0) - return 0; - - Py_INCREF(&PyIrcConnectType); - PyModule_AddObject(py_module, "IrcConnect", (PyObject *)&PyIrcConnectType); - - return 1; -} diff --git a/objects/irc-connect-object.h b/objects/irc-connect-object.h deleted file mode 100644 index 3f6cad4..0000000 --- a/objects/irc-connect-object.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef _IRC_CONNECT_OBJECT_H_ -#define _IRC_CONNECT_OBJECT_H_ - -#include -#include "connect-object.h" - -/* forward */ -struct _IRC_SERVER_CONNECT_REC; - -typedef struct -{ - PyIrssi_HEAD(struct _IRC_SERVER_CONNECT_REC) -} PyIrcConnect; - -extern PyTypeObject PyIrcConnectType; - -int irc_connect_object_init(void); -PyObject *pyirc_connect_new(void *connect, int managed); -#define pyirc_connect_check(op) PyObject_TypeCheck(op, &PyIrcConnectType) - -#endif diff --git a/objects/irc-server-object.c b/objects/irc-server-object.c deleted file mode 100644 index 4e9a28e..0000000 --- a/objects/irc-server-object.c +++ /dev/null @@ -1,491 +0,0 @@ -#include -#include "pymodule.h" -#include "base-objects.h" -#include "irc-server-object.h" -#include "factory.h" -#include "pyirssi_irc.h" -#include "pycore.h" -#include "pyutils.h" - -/* cleanup and dealloc inherited from base Server */ - -/* Getters */ -PyDoc_STRVAR(PyIrcServer_real_address_doc, - "Address the IRC server gives" -); -static PyObject *PyIrcServer_real_address_get(PyIrcServer *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->real_address); -} - -PyDoc_STRVAR(PyIrcServer_usermode_doc, - "User mode in server" -); -static PyObject *PyIrcServer_usermode_get(PyIrcServer *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->usermode); -} - -PyDoc_STRVAR(PyIrcServer_userhost_doc, - "Your user host in server" -); -static PyObject *PyIrcServer_userhost_get(PyIrcServer *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->userhost); -} - -static PyGetSetDef PyIrcServer_getseters[] = { - {"real_address", (getter)PyIrcServer_real_address_get, NULL, - PyIrcServer_real_address_doc, NULL}, - {"usermode", (getter)PyIrcServer_usermode_get, NULL, - PyIrcServer_usermode_doc, NULL}, - {"userhost", (getter)PyIrcServer_userhost_get, NULL, - PyIrcServer_userhost_doc, NULL}, - {NULL} -}; - -/* Methods */ -PyDoc_STRVAR(get_channels_doc, - "get_channels() -> str\n" - "\n" - "Return a string of all channels (and keys, if any have them) in server,\n" - "like '#a,#b,#c,#d x,b_chan_key,x,x' or just '#e,#f,#g'\n" -); -static PyObject *PyIrcServer_get_channels(PyIrcServer *self, PyObject *args) -{ - char *list; - PyObject *ret; - - RET_NULL_IF_INVALID(self->data); - - list = irc_server_get_channels(self->data); - ret = PyString_FromString(list); - g_free(list); - - return ret; -} - -PyDoc_STRVAR(send_raw_doc, - "send_raw(cmd) -> None\n" - "\n" - "Send raw message to server, it will be flood protected so you\n" - "don't need to worry about it.\n" -); -static PyObject *PyIrcServer_send_raw(PyIrcServer *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"cmd", NULL}; - char *cmd; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &cmd)) - return NULL; - - irc_send_cmd(self->data, cmd); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(send_raw_now_doc, - "send_raw_now(cmd) -> None\n" - "\n" - "Send raw message to server immediately without flood protection.\n" -); -static PyObject *PyIrcServer_send_raw_now(PyIrcServer *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"cmd", NULL}; - char *cmd; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &cmd)) - return NULL; - - irc_send_cmd_now(self->data, cmd); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(send_raw_split_doc, - "send_raw_split(cmd, nickarg, max_nicks) -> None\n" - "\n" - "Split the `cmd' into several commands so `nickarg' argument has only\n" - "`max_nicks' number of nicks.\n" - "\n" - "Example:\n" - "server.send_raw_split('KICK #channel nick1,nick2,nick3 :byebye', 3, 2)\n" - "\n" - "Irssi will send commands 'KICK #channel nick1,nick2 :byebye' and\n" - "'KICK #channel nick3 :byebye' to server.\n" -); -static PyObject *PyIrcServer_send_raw_split(PyIrcServer *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"cmd", "nickarg", "max_nicks", NULL}; - char *cmd; - int nickarg; - int max_nicks; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "sii", kwlist, &cmd, &nickarg, &max_nicks)) - return NULL; - - irc_send_cmd_split(self->data, cmd, nickarg, max_nicks); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(ctcp_send_reply_doc, - "ctcp_send_reply(data) -> None\n" - "\n" - "Send CTCP reply. This will be 'CTCP flood protected' so if there's too\n" - "many CTCP requests in buffer, this reply might not get sent. The data\n" - "is the full raw command to be sent to server, like\n" - "'NOTICE nick :\001VERSION irssi\001'\n" -); -static PyObject *PyIrcServer_ctcp_send_reply(PyIrcServer *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"data", NULL}; - char *data; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &data)) - return NULL; - - ctcp_send_reply(self->data, data); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(isupport_doc, - "isupport(name) -> str or None\n" - "\n" - "Returns the value of the named item in the ISUPPORT (005) numeric to the\n" - "script. If the item is not present returns undef, if the item has no value\n" - "then '' is returned use defined server.isupport('name') if you need to\n" - "check whether a property is present.\n" - "See http://www.ietf.org/internet-drafts/draft-brocklesby-irc-isupport-01.txt\n" - "for more information on the ISUPPORT numeric.\n" -); -static PyObject *PyIrcServer_isupport(PyIrcServer *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"name", NULL}; - char *name; - char *found; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &name)) - return NULL; - - found = g_hash_table_lookup(self->data->isupport, name); - - RET_AS_STRING_OR_NONE(found); -} - -PyDoc_STRVAR(PyIrcServer_netsplit_find_doc, - "netsplit_find(nick, address) -> Netsplit object or None\n" - "\n" - "Check if nick!address is on the other side of netsplit. Netsplit records\n" - "are automatically removed after 30 minutes (current default)..\n" -); -static PyObject *PyIrcServer_netsplit_find(PyIrcServer *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"nick", "address", NULL}; - char *nick = ""; - char *address = ""; - NETSPLIT_REC *ns; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss", kwlist, - &nick, &address)) - return NULL; - - ns = netsplit_find(self->data, nick, address); - if (ns) - return pynetsplit_new(ns); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyIrcServer_netsplit_find_channel_doc, - "netsplit_find_channel(nick, address, channel) -> NetsplitChannel object or None\n" - "\n" - "Find nick record for nick!address in channel `channel'.\n" -); -static PyObject *PyIrcServer_netsplit_find_channel(PyIrcServer *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"nick", "address", "channel", NULL}; - char *nick = ""; - char *address = ""; - char *channel = ""; - NETSPLIT_CHAN_REC *nsc; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "sss", kwlist, - &nick, &address, &channel)) - return NULL; - - nsc = netsplit_find_channel(self->data, nick, address, channel); - if (nsc) - return pynetsplit_channel_new(nsc); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyIrcServer_notifylist_ison_doc, - "notifylist_ison(nick) -> bool\n" - "\n" - "Check if nick is on server\n" -); -static PyObject *PyIrcServer_notifylist_ison(PyIrcServer *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"nick", NULL}; - char *nick = ""; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &nick)) - return NULL; - - return PyBool_FromLong(notifylist_ison_server(self->data, nick)); -} - -/* expect a list of tuples [('str', 'str'), ...] */ -static GSList *py_event_conv(PyObject *list) -{ - int i; - GSList *ret = NULL; - - if (!PyList_Check(list)) - { - PyErr_Format(PyExc_TypeError, "expect a list of tuples of two strings"); - return NULL; - } - - for (i = 0; i < PyList_Size(list); i++) - { - char *key; - char *val; - PyObject *tup = PyList_GET_ITEM(list, i); - - if (!PyTuple_Check(tup) || !PyArg_ParseTuple(tup, "ss", &key, &val)) - { - GSList *node; - - for (node = ret; node; node = node->next) - g_free(node->data); - - g_slist_free(ret); - - if (!PyErr_Occurred() || PyErr_ExceptionMatches(PyExc_TypeError)) - { - PyErr_Clear(); - PyErr_SetString(PyExc_TypeError, "expect a list of tuples of two strings"); - } - - return NULL; - } - - ret = g_slist_append(ret, g_strdup(key)); - ret = g_slist_append(ret, g_strdup(val)); - } - - return ret; -} - -PyDoc_STRVAR(PyIrcServer_redirect_event_doc, - "redirect_event(command, signals, arg=None, count=1, remote=-1, failure_signal=None) -> None\n" - "\n" - "Specify that the next command sent to server will be redirected.\n" - "NOTE: This command MUST be called before sending the command to server.\n" - "\n" - "`command' - Name of the registered redirection that we're using.\n" - "\n" - "`count' - How many times to execute the redirection. Some commands may\n" - "send multiple stop events, like MODE #a,#b.\n" - "\n" - "`arg' - The argument to be compared in event strings. You can give multiple\n" - "arguments separated with space.\n" - "\n" - "`remote' - Specifies if the command is a remote command, -1 = use default.\n" - "\n" - "`failure_signal' - If irssi can't find the stop signal for the redirection,\n" - "this signal is called.\n" - "\n" - "`signals' - hash reference with \"event\" => \"redir signal\" entries.\n" - "If the event is "", all the events belonging to the redirection but not\n" - "specified here, will be sent there.\n" - "\n" - "Example:\n" - "\n" - "# ignore all events generated by whois query, except 311.\n" - "\n" - "server.redirect_event(\"whois\",\n" - " remote = 0,\n" - " arg = \"cras\",\n" - " signals = [\n" - " ('event 311', 'redir whois'),\n" - " ('', 'event empty') \n" - " ]\n" - ")\n" - "server.send_raw(\"WHOIS :cras\")\n" -); -static PyObject *PyIrcServer_redirect_event(PyIrcServer *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"command", "signals", "arg", "count", "remote", "failure_signal", NULL}; - char *command = ""; - int count = 1; - char *arg = NULL; - int remote = -1; - char *failure_signal = NULL; - PyObject *signals = NULL; - GSList *gsignals; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "sO|ziiz", kwlist, - &command, &signals, &arg, &count, &remote, &failure_signal)) - return NULL; - - gsignals = py_event_conv(signals); - if (!gsignals) - return NULL; - - server_redirect_event(self->data, command, count, arg, remote, failure_signal, gsignals); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyIrcServer_redirect_get_signal_doc, - "redirect_get_signal(event, args) -> str\n" -); -static PyObject *PyIrcServer_redirect_get_signal(PyIrcServer *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"event", "args", NULL}; - char *event = ""; - char *pargs = ""; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss", kwlist, - &event, &pargs)) - return NULL; - - RET_AS_STRING_OR_NONE(server_redirect_get_signal(self->data, event, pargs)); -} - -PyDoc_STRVAR(PyIrcServer_redirect_peek_signal_doc, - "redirect_peek_signal(event, args) -> str\n" -); -static PyObject *PyIrcServer_redirect_peek_signal(PyIrcServer *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"event", "args", NULL}; - char *event = ""; - char *pargs = ""; - int redirection; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss", kwlist, - &event, &pargs)) - return NULL; - - RET_AS_STRING_OR_NONE(server_redirect_peek_signal(self->data, event, pargs, &redirection)); -} - -/* Methods for object */ -static PyMethodDef PyIrcServer_methods[] = { - {"get_channels", (PyCFunction)PyIrcServer_get_channels, METH_NOARGS, - get_channels_doc}, - {"send_raw", (PyCFunction)PyIrcServer_send_raw, METH_VARARGS | METH_KEYWORDS, - send_raw_doc}, - {"send_raw_now", (PyCFunction)PyIrcServer_send_raw_now, METH_VARARGS | METH_KEYWORDS, - send_raw_now_doc}, - {"send_raw_split", (PyCFunction)PyIrcServer_send_raw_split, METH_VARARGS | METH_KEYWORDS, - send_raw_split_doc}, - {"ctcp_send_reply", (PyCFunction)PyIrcServer_ctcp_send_reply, METH_VARARGS | METH_KEYWORDS, - ctcp_send_reply_doc}, - {"isupport", (PyCFunction)PyIrcServer_isupport, METH_VARARGS | METH_KEYWORDS, - isupport_doc}, - {"netsplit_find", (PyCFunction)PyIrcServer_netsplit_find, METH_VARARGS | METH_KEYWORDS, - PyIrcServer_netsplit_find_doc}, - {"netsplit_find_channel", (PyCFunction)PyIrcServer_netsplit_find_channel, METH_VARARGS | METH_KEYWORDS, - PyIrcServer_netsplit_find_channel_doc}, - {"notifylist_ison", (PyCFunction)PyIrcServer_notifylist_ison, METH_VARARGS | METH_KEYWORDS, - PyIrcServer_notifylist_ison_doc}, - {"redirect_event", (PyCFunction)PyIrcServer_redirect_event, METH_VARARGS | METH_KEYWORDS, - PyIrcServer_redirect_event_doc}, - {"redirect_get_signal", (PyCFunction)PyIrcServer_redirect_get_signal, METH_VARARGS | METH_KEYWORDS, - PyIrcServer_redirect_get_signal_doc}, - {"redirect_peek_signal", (PyCFunction)PyIrcServer_redirect_peek_signal, METH_VARARGS | METH_KEYWORDS, - PyIrcServer_redirect_peek_signal_doc}, - {NULL} /* Sentinel */ -}; - -PyTypeObject PyIrcServerType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "IrcServer", /*tp_name*/ - sizeof(PyIrcServer), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - 0, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - "PyIrcServer objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - PyIrcServer_methods, /* tp_methods */ - 0, /* tp_members */ - PyIrcServer_getseters, /* tp_getset */ - &PyServerType, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ -}; - -PyObject *pyirc_server_new(void *server) -{ - return pyserver_sub_new(server, &PyIrcServerType); -} - -int irc_server_object_init(void) -{ - g_return_val_if_fail(py_module != NULL, 0); - - if (PyType_Ready(&PyIrcServerType) < 0) - return 0; - - Py_INCREF(&PyIrcServerType); - PyModule_AddObject(py_module, "IrcServer", (PyObject *)&PyIrcServerType); - - return 1; -} diff --git a/objects/irc-server-object.h b/objects/irc-server-object.h deleted file mode 100644 index b3eb76a..0000000 --- a/objects/irc-server-object.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef _IRC_SERVER_OBJECT_H_ -#define _IRC_SERVER_OBJECT_H_ - -#include -#include "server-object.h" - -/* forward */ -struct _IRC_SERVER_REC; - -typedef struct -{ - PyServer_HEAD(struct _IRC_SERVER_REC) -} PyIrcServer; - -extern PyTypeObject PyIrcServerType; - -int irc_server_object_init(void); -PyObject *pyirc_server_new(void *server); -#define pyirc_server_check(op) PyObject_TypeCheck(op, &PyIrcServerType) - -#endif diff --git a/objects/log-object.c b/objects/log-object.c deleted file mode 100644 index b18f826..0000000 --- a/objects/log-object.c +++ /dev/null @@ -1,477 +0,0 @@ -#include -#include "pyirssi_irc.h" -#include "pymodule.h" -#include "log-object.h" -#include "factory.h" -#include "pycore.h" - -static LOG_ITEM_REC *find_item(LOG_REC *log, PyLogitem *item); -static void log_cleanup(LOG_REC *log); -static int logtype(int *type, int target, int window); - -/* find/convert a py log item */ -static LOG_ITEM_REC *find_item(LOG_REC *log, PyLogitem *item) -{ - int type; - char *name; - char *servertag = NULL; - - if (!item->type || !item->name) - return NULL; - - type = PyInt_AS_LONG(item->type); - name = PyString_AS_STRING(item->name); - if (item->servertag) - servertag = PyString_AS_STRING(item->servertag); - - return log_item_find(log, type, name, servertag); -} - -/* monitor "log remove" signal */ -static void log_cleanup(LOG_REC *log) -{ - PyLog *pylog = signal_get_user_data(); - - if (log == pylog->data) - { - pylog->data = NULL; - pylog->cleanup_installed = 0; - signal_remove_data("log remove", log_cleanup, pylog); - } -} - -static void PyLog_dealloc(PyLog *self) -{ - if (self->cleanup_installed) - signal_remove_data("log remove", log_cleanup, self); - - if (self->data && !g_slist_find(logs, self->data)) - { - printtext(NULL, NULL, MSGLEVEL_CRAP, "destroying orphan log %s", self->data->fname); - log_close(self->data); - } - - self->ob_type->tp_free((PyObject*)self); -} - -static PyObject *PyLog_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyLog *self; - - self = (PyLog *)type->tp_alloc(type, 0); - if (!self) - return NULL; - - return (PyObject *)self; -} - -/* function to create the log */ -PyDoc_STRVAR(PyLog_doc, - "__init__(fname, level=MSGLEVEL_ALL)\n" - "\n" - "Create a log\n" -); -static int PyLog_init(PyLog *self, PyObject *args, PyObject *kwds) -{ - char *fname; - int level = MSGLEVEL_ALL; - LOG_REC *log; - - static char *kwlist[] = {"fname", "level", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|i", kwlist, - &fname, &level)) - return -1; - - /*XXX: anything better than RuntimeError ? */ - if (self->data || self->cleanup_installed) - { - PyErr_Format(PyExc_RuntimeError, "log already opened; close it first"); - return -1; - } - - log = log_create_rec(fname, level); - if (!log) - { - PyErr_Format(PyExc_RuntimeError, "failed to create log"); - return -1; - } - - self->data = log; - self->cleanup_installed = 1; - signal_add_last_data("log remove", log_cleanup, self); - - return 0; -} - -/* Getters */ -PyDoc_STRVAR(PyLog_fname_doc, - "Log file name" -); -static PyObject *PyLog_fname_get(PyLog *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->fname); -} - -PyDoc_STRVAR(PyLog_real_fname_doc, - "The actual opened log file (after %d.%m.Y etc. are expanded)" -); -static PyObject *PyLog_real_fname_get(PyLog *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->real_fname); -} - -PyDoc_STRVAR(PyLog_opened_doc, - "Log file is open" -); -static PyObject *PyLog_opened_get(PyLog *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyLong_FromUnsignedLong(self->data->opened); -} - -PyDoc_STRVAR(PyLog_level_doc, - "Log only these levels" -); -static PyObject *PyLog_level_get(PyLog *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyInt_FromLong(self->data->level); -} - -PyDoc_STRVAR(PyLog_last_doc, - "Timestamp when last message was written" -); -static PyObject *PyLog_last_get(PyLog *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyLong_FromUnsignedLong(self->data->last); -} - -PyDoc_STRVAR(PyLog_autoopen_doc, - "Automatically open log at startup" -); -static PyObject *PyLog_autoopen_get(PyLog *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyBool_FromLong(self->data->autoopen); -} - -PyDoc_STRVAR(PyLog_failed_doc, - "Opening log failed last time" -); -static PyObject *PyLog_failed_get(PyLog *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyBool_FromLong(self->data->failed); -} - -PyDoc_STRVAR(PyLog_temp_doc, - "Log isn't saved to config file" -); -static PyObject *PyLog_temp_get(PyLog *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyBool_FromLong(self->data->temp); -} - -/* specialized getters/setters */ -static PyGetSetDef PyLog_getseters[] = { - {"fname", (getter)PyLog_fname_get, NULL, - PyLog_fname_doc, NULL}, - {"real_fname", (getter)PyLog_real_fname_get, NULL, - PyLog_real_fname_doc, NULL}, - {"opened", (getter)PyLog_opened_get, NULL, - PyLog_opened_doc, NULL}, - {"level", (getter)PyLog_level_get, NULL, - PyLog_level_doc, NULL}, - {"last", (getter)PyLog_last_get, NULL, - PyLog_last_doc, NULL}, - {"autoopen", (getter)PyLog_autoopen_get, NULL, - PyLog_autoopen_doc, NULL}, - {"failed", (getter)PyLog_failed_get, NULL, - PyLog_failed_doc, NULL}, - {"temp", (getter)PyLog_temp_get, NULL, - PyLog_temp_doc, NULL}, - {NULL} -}; - -/* Methods */ -PyDoc_STRVAR(PyLog_items_doc, - "items() -> list of Log objects\n" - "\n" - "Return a list of log items\n" -); -static PyObject *PyLog_items(PyLog *self, PyObject *args) -{ - RET_NULL_IF_INVALID(self->data); - return py_irssi_objlist_new(self->data->items, 1, (InitFunc)pylogitem_new); -} - -PyDoc_STRVAR(PyLog_update_doc, - "update() -> None\n" - "\n" - "Add log to list of logs / save changes to config file.\n" -); -static PyObject *PyLog_update(PyLog *self, PyObject *args) -{ - RET_NULL_IF_INVALID(self->data); - - log_update(self->data); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyLog_close_doc, - "destroy() -> None\n" - "\n" - "Destroy the log file\n" -); -static PyObject *PyLog_close(PyLog *self, PyObject *args) -{ - RET_NULL_IF_INVALID(self->data); - - log_close(self->data); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyLog_start_logging_doc, - "start_logging() -> None\n" - "\n" - "Open log file and start logging.\n" -); -static PyObject *PyLog_start_logging(PyLog *self, PyObject *args) -{ - RET_NULL_IF_INVALID(self->data); - - log_start_logging(self->data); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyLog_stop_logging_doc, - "stop_logging() -> None\n" - "\n" - "Stop and close the log file.\n" -); -static PyObject *PyLog_stop_logging(PyLog *self, PyObject *args) -{ - RET_NULL_IF_INVALID(self->data); - - log_stop_logging(self->data); - - Py_RETURN_NONE; -} - -static int logtype(int *type, int target, int window) -{ - if (target || window) - { - if (target && window) - { - PyErr_SetString(PyExc_TypeError, "must specify target or window, not both"); - return 0; - } - - *type = target? 0 : 1; - } - else if (*type < 0) - { - PyErr_SetString(PyExc_TypeError, "must specify type, target, or window"); - return 0; - } - - return 1; -} - -PyDoc_STRVAR(PyLog_item_add_doc, - "item_add(item, servertag=None, type=0, target=False, window=False) -> None\n" - "\n" - "Add a log item to log.\n" - "\n" - "Add a target item (nick, chan): \n" - " item_add('#linux', target=True)\n" - " item_add('#linux', type=0)\n" - "\n" - "Add a window ref: \n" - " item_add('2', window=True)\n" - " item_add('2', type=1)\n" -); -static PyObject *PyLog_item_add(PyLog *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"item", "servertag", "type", "target", "window", NULL}; - char *item = ""; - char *servertag = NULL; - int type = 0; - int target = 0; - int window = 0; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|ziii", kwlist, - &item, &servertag, &type, &target, &window)) - return NULL; - - if (!logtype(&type, target, window)) - return NULL; - - log_item_add(self->data, type, item, servertag); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyLog_item_destroy_doc, - "item_destroy(item) -> None\n" - "\n" - "Remove log item from log.\n" -); -static PyObject *PyLog_item_destroy(PyLog *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"item", NULL}; - PyObject *item = NULL; - LOG_ITEM_REC *li; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, - &item)) - return NULL; - - if (!pylogitem_check(item)) - return PyErr_Format(PyExc_TypeError, "arg 1 should be log item"); - - li = find_item(self->data, (PyLogitem *)item); - if (!li) - return PyErr_Format(PyExc_TypeError, "log item invalid or not found"); - - log_item_destroy(self->data, li); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyLog_item_find_doc, - "item_find(item, servertag=None, type=-1, target=False, window=False) -> item or None\n" - "\n" - "Find item from log.\n" -); -static PyObject *PyLog_item_find(PyLog *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"item", "servertag", "type", "target", "window", NULL}; - char *item = ""; - char *server = NULL; - int type = 0; - int target = 0; - int window = 0; - LOG_ITEM_REC *li; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|ziii", kwlist, - &item, &server, &type, &target, &window)) - return NULL; - - if (!logtype(&type, target, window)) - return NULL; - - li = log_item_find(self->data, type, item, server); - if (li) - return pylogitem_new(li); - - Py_RETURN_NONE; -} - -/* Methods for object */ -static PyMethodDef PyLog_methods[] = { - {"items", (PyCFunction)PyLog_items, METH_NOARGS, - PyLog_items_doc}, - {"update", (PyCFunction)PyLog_update, METH_NOARGS, - PyLog_update_doc}, - {"close", (PyCFunction)PyLog_close, METH_NOARGS, - PyLog_close_doc}, - {"start_logging", (PyCFunction)PyLog_start_logging, METH_NOARGS, - PyLog_start_logging_doc}, - {"stop_logging", (PyCFunction)PyLog_stop_logging, METH_NOARGS, - PyLog_stop_logging_doc}, - {"item_add", (PyCFunction)PyLog_item_add, METH_VARARGS | METH_KEYWORDS, - PyLog_item_add_doc}, - {"item_destroy", (PyCFunction)PyLog_item_destroy, METH_VARARGS | METH_KEYWORDS, - PyLog_item_destroy_doc}, - {"item_find", (PyCFunction)PyLog_item_find, METH_VARARGS | METH_KEYWORDS, - PyLog_item_find_doc}, - {NULL} /* Sentinel */ -}; - -PyTypeObject PyLogType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "Log", /*tp_name*/ - sizeof(PyLog), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)PyLog_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - PyLog_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - PyLog_methods, /* tp_methods */ - 0, /* tp_members */ - PyLog_getseters, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)PyLog_init, /* tp_init */ - 0, /* tp_alloc */ - PyLog_new, /* tp_new */ -}; - - -/* window item wrapper factory function */ -PyObject *pylog_new(void *log) -{ - PyLog *pylog; - - pylog = (PyLog *)PyLogType.tp_alloc(&PyLogType, 0); - if (!pylog) - return NULL; - - pylog->data = log; - pylog->cleanup_installed = 1; - signal_add_last_data("log remove", log_cleanup, pylog); - - return (PyObject *)pylog; -} - -int log_object_init(void) -{ - g_return_val_if_fail(py_module != NULL, 0); - - if (PyType_Ready(&PyLogType) < 0) - return 0; - - Py_INCREF(&PyLogType); - PyModule_AddObject(py_module, "Log", (PyObject *)&PyLogType); - - return 1; -} diff --git a/objects/log-object.h b/objects/log-object.h deleted file mode 100644 index 9893bc5..0000000 --- a/objects/log-object.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef _LOG_OBJECT_H_ -#define _LOG_OBJECT_H_ - -#include -#include "base-objects.h" - -/* forward */ -struct _LOG_REC; - -typedef struct -{ - PyIrssiFinal_HEAD(struct _LOG_REC) -} PyLog; - -extern PyTypeObject PyLogType; - -int log_object_init(void); -PyObject *pylog_new(void *log); -#define pylog_check(op) PyObject_TypeCheck(op, &PyLogType) - -#endif diff --git a/objects/logitem-object.c b/objects/logitem-object.c deleted file mode 100644 index 4dc2275..0000000 --- a/objects/logitem-object.c +++ /dev/null @@ -1,156 +0,0 @@ -#include -#include "pyirssi_irc.h" -#include "pymodule.h" -#include "logitem-object.h" -#include "pycore.h" - -/* no special cleanup -- value copy is made */ - -static void PyLogitem_dealloc(PyLogitem *self) -{ - Py_XDECREF(self->type); - Py_XDECREF(self->name); - Py_XDECREF(self->servertag); - - self->ob_type->tp_free((PyObject*)self); -} - -static PyObject *PyLogitem_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyLogitem *self; - - self = (PyLogitem *)type->tp_alloc(type, 0); - if (!self) - return NULL; - - return (PyObject *)self; -} - -/* Getters */ -PyDoc_STRVAR(PyLogitem_type_doc, - "0=target, 1=window refnum" -); -static PyObject *PyLogitem_type_get(PyLogitem *self, void *closure) -{ - RET_AS_OBJ_OR_NONE(self->type); -} - -PyDoc_STRVAR(PyLogitem_name_doc, - "Name" -); -static PyObject *PyLogitem_name_get(PyLogitem *self, void *closure) -{ - RET_AS_OBJ_OR_NONE(self->name); -} - -PyDoc_STRVAR(PyLogitem_servertag_doc, - "Server tag" -); -static PyObject *PyLogitem_servertag_get(PyLogitem *self, void *closure) -{ - RET_AS_OBJ_OR_NONE(self->servertag); -} - -/* specialized getters/setters */ -static PyGetSetDef PyLogitem_getseters[] = { - {"type", (getter)PyLogitem_type_get, NULL, - PyLogitem_type_doc, NULL}, - {"name", (getter)PyLogitem_name_get, NULL, - PyLogitem_name_doc, NULL}, - {"servertag", (getter)PyLogitem_servertag_get, NULL, - PyLogitem_servertag_doc, NULL}, - {NULL} -}; - -/* Methods for object */ -static PyMethodDef PyLogitem_methods[] = { - {NULL} /* Sentinel */ -}; - -PyTypeObject PyLogitemType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "Logitem", /*tp_name*/ - sizeof(PyLogitem), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)PyLogitem_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - "PyLogitem objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - PyLogitem_methods, /* tp_methods */ - 0, /* tp_members */ - PyLogitem_getseters, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - PyLogitem_new, /* tp_new */ -}; - - -/* log item factory function */ -PyObject *pylogitem_new(void *log) -{ - LOG_ITEM_REC *li = log; - PyLogitem *pylog = NULL; - - pylog = py_inst(PyLogitem, PyLogitemType); - if (!pylog) - return NULL; - - pylog->type = PyInt_FromLong(li->type); - if (!pylog->type) - goto error; - - pylog->name = PyString_FromString(li->name); - if (!pylog->name) - goto error; - - if (li->servertag) - { - pylog->servertag = PyString_FromString(li->servertag); - if (!pylog->servertag) - goto error; - } - - return (PyObject *)pylog; - -error: - Py_XDECREF(pylog); - return NULL; -} - -int logitem_object_init(void) -{ - g_return_val_if_fail(py_module != NULL, 0); - - if (PyType_Ready(&PyLogitemType) < 0) - return 0; - - Py_INCREF(&PyLogitemType); - PyModule_AddObject(py_module, "Logitem", (PyObject *)&PyLogitemType); - - return 1; -} diff --git a/objects/logitem-object.h b/objects/logitem-object.h deleted file mode 100644 index b7fd588..0000000 --- a/objects/logitem-object.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef _LOG_ITEM_OBJECT_H_ -#define _LOG_ITEM_OBJECT_H_ - -#include -#include "base-objects.h" - -typedef struct -{ - PyObject_HEAD - PyObject *type; - PyObject *name; - PyObject *servertag; -} PyLogitem; - -extern PyTypeObject PyLogitemType; - -int logitem_object_init(void); -PyObject *pylogitem_new(void *log); -#define pylogitem_check(op) PyObject_TypeCheck(op, &PyLogitemType) - -#endif diff --git a/objects/main-window-object.c b/objects/main-window-object.c deleted file mode 100644 index 6541f2b..0000000 --- a/objects/main-window-object.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include "pyirssi.h" -#include "pymodule.h" -#include "main-window-object.h" -#include "factory.h" -#include "pycore.h" - -#define MW(data) ((MAIN_WINDOW_REC *) data) - -/* monitor "mainwindow destroyed" signal */ -static void main_window_cleanup(MAIN_WINDOW_REC *mw) -{ - PyMainWindow *pymw = signal_get_user_data(); - - if (mw == pymw->data) - { - pymw->data = NULL; - pymw->cleanup_installed = 0; - signal_remove_data("mainwindow destroyed", main_window_cleanup, pymw); - } -} - -static void PyMainWindow_dealloc(PyMainWindow *self) -{ - if (self->cleanup_installed) - signal_remove_data("mainwindow destroyed", main_window_cleanup, self); - - Py_XDECREF(self->active); - self->ob_type->tp_free((PyObject*)self); -} - -static PyObject *PyMainWindow_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyMainWindow *self; - - self = (PyMainWindow *)type->tp_alloc(type, 0); - if (!self) - return NULL; - - return (PyObject *)self; -} - -/* getters */ -PyDoc_STRVAR(PyMainWindow_active_doc, - "active window object" -); -static PyObject *PyMainWindow_active_get(PyMainWindow *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_OBJ_OR_NONE(self->active); -} - -PyDoc_STRVAR(PyMainWindow_first_line_doc, - "first line used by this window (0..x) (includes statusbars)" -); -static PyObject *PyMainWindow_first_line_get(PyMainWindow *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyInt_FromLong(MW(self->data)->first_line); -} - -PyDoc_STRVAR(PyMainWindow_last_line_doc, - "last line used by this window (0..x) (includes statusbars)" -); -static PyObject *PyMainWindow_last_line_get(PyMainWindow *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyInt_FromLong(MW(self->data)->last_line); -} - -PyDoc_STRVAR(PyMainWindow_width_doc, - "width of the window (includes statusbars)" -); -static PyObject *PyMainWindow_width_get(PyMainWindow *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyInt_FromLong(MW(self->data)->width); -} - -PyDoc_STRVAR(PyMainWindow_height_doc, - "height of the window (includes statusbars)" -); -static PyObject *PyMainWindow_height_get(PyMainWindow *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyInt_FromLong(MW(self->data)->height); -} - -PyDoc_STRVAR(PyMainWindow_statusbar_lines_doc, - "???" -); -static PyObject *PyMainWindow_statusbar_lines_get(PyMainWindow *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyInt_FromLong(MW(self->data)->statusbar_lines); -} - -/* specialized getters/setters */ -static PyGetSetDef PyMainWindow_getseters[] = { - {"active", (getter)PyMainWindow_active_get, NULL, - PyMainWindow_active_doc, NULL}, - {"first_line", (getter)PyMainWindow_first_line_get, NULL, - PyMainWindow_first_line_doc, NULL}, - {"last_line", (getter)PyMainWindow_last_line_get, NULL, - PyMainWindow_last_line_doc, NULL}, - {"width", (getter)PyMainWindow_width_get, NULL, - PyMainWindow_width_doc, NULL}, - {"height", (getter)PyMainWindow_height_get, NULL, - PyMainWindow_height_doc, NULL}, - {"statusbar_lines", (getter)PyMainWindow_statusbar_lines_get, NULL, - PyMainWindow_statusbar_lines_doc, NULL}, - {NULL} -}; - -/* Methods for object */ -static PyMethodDef PyMainWindow_methods[] = { - {NULL} /* Sentinel */ -}; - -PyTypeObject PyMainWindowType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "MainWindow", /*tp_name*/ - sizeof(PyMainWindow), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)PyMainWindow_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - "PyMainWindow objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - PyMainWindow_methods, /* tp_methods */ - 0, /* tp_members */ - PyMainWindow_getseters, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - PyMainWindow_new, /* tp_new */ -}; - - -/* main window wrapper factory function */ -PyObject *pymain_window_new(MAIN_WINDOW_REC *mw) -{ - PyObject *pyactive = NULL; - PyMainWindow *pymw; - - pyactive = pywindow_new(mw->active); - if (!pyactive) - return NULL; - - pymw = py_inst(PyMainWindow, PyMainWindowType); - if (!pymw) - { - Py_DECREF(pyactive); - return NULL; - } - - pymw->active = pyactive; - pymw->data = mw; - pymw->cleanup_installed = 1; - signal_add_last_data("mainwindow destroyed", main_window_cleanup, pymw); - - return (PyObject *)pymw; -} - -int main_window_object_init(void) -{ - g_return_val_if_fail(py_module != NULL, 0); - - if (PyType_Ready(&PyMainWindowType) < 0) - return 0; - - Py_INCREF(&PyMainWindowType); - PyModule_AddObject(py_module, "MainWindow", (PyObject *)&PyMainWindowType); - - return 1; -} diff --git a/objects/main-window-object.h b/objects/main-window-object.h deleted file mode 100644 index fbbdac0..0000000 --- a/objects/main-window-object.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef _MAIN_WINDOW_OBJECT_H_ -#define _MAIN_WINDOW_OBJECT_H_ - -#include -#include "base-objects.h" -#include "pyirssi.h" - -typedef struct -{ - PyIrssiFinal_HEAD(void) - PyObject *active; -} PyMainWindow; - -extern PyTypeObject PyMainWindowType; - -int main_window_object_init(void); -PyObject *pymain_window_new(MAIN_WINDOW_REC *mw); -#define pymain_window_check(op) PyObject_TypeCheck(op, &PyMainWindowType) - -#endif diff --git a/objects/netsplit-channel-object.c b/objects/netsplit-channel-object.c deleted file mode 100644 index 3e2639b..0000000 --- a/objects/netsplit-channel-object.c +++ /dev/null @@ -1,170 +0,0 @@ -#include -#include "pyirssi_irc.h" -#include "pymodule.h" -#include "netsplit-channel-object.h" -#include "factory.h" -#include "pycore.h" - -/* value copied -- no special cleanup */ - -static void PyNetsplitChannel_dealloc(PyNetsplitChannel *self) -{ - Py_XDECREF(self->name); - - self->ob_type->tp_free((PyObject*)self); -} - -static PyObject *PyNetsplitChannel_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyNetsplitChannel *self; - - self = (PyNetsplitChannel *)type->tp_alloc(type, 0); - if (!self) - return NULL; - - return (PyObject *)self; -} - -/* Getters */ -PyDoc_STRVAR(PyNetsplitChannel_name_doc, - "Channel name" -); -static PyObject *PyNetsplitChannel_name_get(PyNetsplitChannel *self, void *closure) -{ - RET_AS_OBJ_OR_NONE(self->name); -} - -PyDoc_STRVAR(PyNetsplitChannel_op_doc, - "is op" -); -static PyObject *PyNetsplitChannel_op_get(PyNetsplitChannel *self, void *closure) -{ - return PyBool_FromLong(self->op); -} - -PyDoc_STRVAR(PyNetsplitChannel_halfop_doc, - "is halfop" -); -static PyObject *PyNetsplitChannel_halfop_get(PyNetsplitChannel *self, void *closure) -{ - return PyBool_FromLong(self->halfop); -} - -PyDoc_STRVAR(PyNetsplitChannel_voice_doc, - "is voice" -); -static PyObject *PyNetsplitChannel_voice_get(PyNetsplitChannel *self, void *closure) -{ - return PyBool_FromLong(self->voice); -} - -PyDoc_STRVAR(PyNetsplitChannel_other_doc, - "?" -); -static PyObject *PyNetsplitChannel_other_get(PyNetsplitChannel *self, void *closure) -{ - return PyInt_FromLong(self->other); -} - -/* specialized getters/setters */ -static PyGetSetDef PyNetsplitChannel_getseters[] = { - {"name", (getter)PyNetsplitChannel_name_get, NULL, - PyNetsplitChannel_name_doc, NULL}, - {"op", (getter)PyNetsplitChannel_op_get, NULL, - PyNetsplitChannel_op_doc, NULL}, - {"halfop", (getter)PyNetsplitChannel_halfop_get, NULL, - PyNetsplitChannel_halfop_doc, NULL}, - {"voice", (getter)PyNetsplitChannel_voice_get, NULL, - PyNetsplitChannel_voice_doc, NULL}, - {"other", (getter)PyNetsplitChannel_other_get, NULL, - PyNetsplitChannel_other_doc, NULL}, - {NULL} -}; - -/* Methods */ -/* Methods for object */ -static PyMethodDef PyNetsplitChannel_methods[] = { - {NULL} /* Sentinel */ -}; - -PyTypeObject PyNetsplitChannelType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "NetsplitChannel", /*tp_name*/ - sizeof(PyNetsplitChannel), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)PyNetsplitChannel_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - "PyNetsplitChannel objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - PyNetsplitChannel_methods, /* tp_methods */ - 0, /* tp_members */ - PyNetsplitChannel_getseters, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - PyNetsplitChannel_new, /* tp_new */ -}; - - -/* window item wrapper factory function */ -PyObject *pynetsplit_channel_new(void *netsplit) -{ - NETSPLIT_CHAN_REC *rec = netsplit; - PyNetsplitChannel *pynetsplit; - PyObject *name; - - name = PyString_FromString(rec->name); - if (!name) - return NULL; - - pynetsplit = py_inst(PyNetsplitChannel, PyNetsplitChannelType); - if (!pynetsplit) - { - Py_DECREF(name); - return NULL; - } - - pynetsplit->name = name; - pynetsplit->op = rec->op; - pynetsplit->halfop = rec->halfop; - pynetsplit->other = rec->other; - - return (PyObject *)pynetsplit; -} - -int netsplit_channel_object_init(void) -{ - g_return_val_if_fail(py_module != NULL, 0); - - if (PyType_Ready(&PyNetsplitChannelType) < 0) - return 0; - - Py_INCREF(&PyNetsplitChannelType); - PyModule_AddObject(py_module, "NetsplitChannel", (PyObject *)&PyNetsplitChannelType); - - return 1; -} diff --git a/objects/netsplit-channel-object.h b/objects/netsplit-channel-object.h deleted file mode 100644 index 3a00fbb..0000000 --- a/objects/netsplit-channel-object.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef _NETSPLIT_CHANNEL_OBJECT_H_ -#define _NETSPLIT_CHANNEL_OBJECT_H_ - -#include -#include "base-objects.h" - -typedef struct -{ - PyObject_HEAD - PyObject *name; - int op, halfop; - int voice, other; -} PyNetsplitChannel; - -extern PyTypeObject PyNetsplitChannelType; - -int netsplit_channel_object_init(void); -PyObject *pynetsplit_channel_new(void *ns); -#define pynetsplit_channel_check(op) PyObject_TypeCheck(op, &PyNetsplitChannelType) - -#endif diff --git a/objects/netsplit-object.c b/objects/netsplit-object.c deleted file mode 100644 index d64bd97..0000000 --- a/objects/netsplit-object.c +++ /dev/null @@ -1,184 +0,0 @@ -#include -#include "pyirssi_irc.h" -#include "pymodule.h" -#include "netsplit-object.h" -#include "factory.h" -#include "pycore.h" - -#define NETSPLIT(ns) ((NETSPLIT_REC*)ns) - -/* monitor "netsplit remove" signal */ -static void netsplit_cleanup(NETSPLIT_REC *netsplit) -{ - PyNetsplit *pynetsplit = signal_get_user_data(); - - if (netsplit == pynetsplit->data) - { - pynetsplit->data = NULL; - pynetsplit->cleanup_installed = 0; - signal_remove_data("netsplit remove", netsplit_cleanup, pynetsplit); - } -} - -static void PyNetsplit_dealloc(PyNetsplit *self) -{ - if (self->cleanup_installed) - signal_remove_data("netsplit remove", netsplit_cleanup, self); - - self->ob_type->tp_free((PyObject*)self); -} - -static PyObject *PyNetsplit_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyNetsplit *self; - - self = (PyNetsplit *)type->tp_alloc(type, 0); - if (!self) - return NULL; - - return (PyObject *)self; -} - -/* Getters */ -PyDoc_STRVAR(PyNetsplit_nick_doc, - "Nick" -); -static PyObject *PyNetsplit_nick_get(PyNetsplit *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(NETSPLIT(self->data)->nick); -} - -PyDoc_STRVAR(PyNetsplit_address_doc, - "Nick's host" -); -static PyObject *PyNetsplit_address_get(PyNetsplit *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(NETSPLIT(self->data)->address); -} - -PyDoc_STRVAR(PyNetsplit_destroy_doc, - "Timestamp when this record should be destroyed" -); -static PyObject *PyNetsplit_destroy_get(PyNetsplit *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyLong_FromUnsignedLong(NETSPLIT(self->data)->destroy); -} - -PyDoc_STRVAR(PyNetsplit_server_doc, - "Netsplitserver object" -); -static PyObject *PyNetsplit_server_get(PyNetsplit *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_OBJ_OR_NONE(self->server); -} - -/* specialized getters/setters */ -static PyGetSetDef PyNetsplit_getseters[] = { - {"nick", (getter)PyNetsplit_nick_get, NULL, - PyNetsplit_nick_doc, NULL}, - {"address", (getter)PyNetsplit_address_get, NULL, - PyNetsplit_address_doc, NULL}, - {"destroy", (getter)PyNetsplit_destroy_get, NULL, - PyNetsplit_destroy_doc, NULL}, - {"server", (getter)PyNetsplit_server_get, NULL, - PyNetsplit_server_doc, NULL}, - {NULL} -}; - -/* Methods */ -PyDoc_STRVAR(PyNetsplit_channels_doc, - "channels() -> list of NetsplitChannel objects\n" - "\n" - "Return list of NetsplitChannel objects\n" -); -static PyObject *PyNetsplit_channels(PyNetsplit *self, PyObject *args) -{ - RET_NULL_IF_INVALID(self->data); - return py_irssi_objlist_new(NETSPLIT(self->data)->channels, 1, - (InitFunc)pynetsplit_channel_new); -} - -/* Methods for object */ -static PyMethodDef PyNetsplit_methods[] = { - {"channels", (PyCFunction)PyNetsplit_channels, METH_NOARGS, - PyNetsplit_channels_doc}, - {NULL} /* Sentinel */ -}; - -PyTypeObject PyNetsplitType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "Netsplit", /*tp_name*/ - sizeof(PyNetsplit), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)PyNetsplit_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - "PyNetsplit objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - PyNetsplit_methods, /* tp_methods */ - 0, /* tp_members */ - PyNetsplit_getseters, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - PyNetsplit_new, /* tp_new */ -}; - - -/* window item wrapper factory function */ -PyObject *pynetsplit_new(void *netsplit) -{ - PyNetsplit *pynetsplit; - - //FIXME: add netsplit server - - pynetsplit = py_inst(PyNetsplit, PyNetsplitType); - if (!pynetsplit) - return NULL; - - pynetsplit->data = netsplit; - pynetsplit->cleanup_installed = 1; - signal_add_last_data("netsplit remove", netsplit_cleanup, pynetsplit); - - return (PyObject *)pynetsplit; -} - -int netsplit_object_init(void) -{ - g_return_val_if_fail(py_module != NULL, 0); - - if (PyType_Ready(&PyNetsplitType) < 0) - return 0; - - Py_INCREF(&PyNetsplitType); - PyModule_AddObject(py_module, "Netsplit", (PyObject *)&PyNetsplitType); - - return 1; -} diff --git a/objects/netsplit-object.h b/objects/netsplit-object.h deleted file mode 100644 index bd166e0..0000000 --- a/objects/netsplit-object.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef _NETSPLIT_OBJECT_H_ -#define _NETSPLIT_OBJECT_H_ - -#include -#include "base-objects.h" - -typedef struct -{ - PyIrssiFinal_HEAD(void) - PyObject *server; -} PyNetsplit; - -extern PyTypeObject PyNetsplitType; - -int netsplit_object_init(void); -PyObject *pynetsplit_new(void *ns); -#define pynetsplit_check(op) PyObject_TypeCheck(op, &PyNetsplitType) - -#endif diff --git a/objects/netsplit-server-object.c b/objects/netsplit-server-object.c deleted file mode 100644 index 7208ae1..0000000 --- a/objects/netsplit-server-object.c +++ /dev/null @@ -1,157 +0,0 @@ -#include -#include "pyirssi_irc.h" -#include "pymodule.h" -#include "netsplit-object.h" -#include "factory.h" -#include "pycore.h" - -#define NETSPLIT_SERVER(ns) ((NETSPLIT_SERVER_REC*)ns) - -/* monitor "netsplit remove" signal */ -static void netsplit_server_cleanup(NETSPLIT_SERVER_REC *netsplit) -{ - PyNetsplitServer *pynetsplit = signal_get_user_data(); - - if (netsplit == pynetsplit->data) - { - pynetsplit->data = NULL; - pynetsplit->cleanup_installed = 0; - signal_remove_data("netsplit remove", netsplit_server_cleanup, pynetsplit); - } -} - -static void PyNetsplitServer_dealloc(PyNetsplitServer *self) -{ - if (self->cleanup_installed) - signal_remove_data("netsplit remove", netsplit_server_cleanup, self); - - self->ob_type->tp_free((PyObject*)self); -} - -static PyObject *PyNetsplitServer_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyNetsplitServer *self; - - self = (PyNetsplitServer *)type->tp_alloc(type, 0); - if (!self) - return NULL; - - return (PyObject *)self; -} - -/* Getters */ -PyDoc_STRVAR(PyNetsplitServer_server_doc, - "The server nick was in" -); -static PyObject *PyNetsplitServer_server_get(PyNetsplitServer *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(NETSPLIT_SERVER(self->data)->server); -} - -PyDoc_STRVAR(PyNetsplitServer_destserver_doc, - "The other server where split occured." -); -static PyObject *PyNetsplitServer_destserver_get(PyNetsplitServer *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(NETSPLIT_SERVER(self->data)->destserver); -} - -PyDoc_STRVAR(PyNetsplitServer_count_doc, - "Number of splits in server" -); -static PyObject *PyNetsplitServer_count_get(PyNetsplitServer *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyInt_FromLong(NETSPLIT_SERVER(self->data)->count); -} - -/* specialized getters/setters */ -static PyGetSetDef PyNetsplitServer_getseters[] = { - {"server", (getter)PyNetsplitServer_server_get, NULL, - PyNetsplitServer_server_doc, NULL}, - {"destserver", (getter)PyNetsplitServer_destserver_get, NULL, - PyNetsplitServer_destserver_doc, NULL}, - {"count", (getter)PyNetsplitServer_count_get, NULL, - PyNetsplitServer_count_doc, NULL}, - {NULL} -}; - -/* Methods */ -/* Methods for object */ -static PyMethodDef PyNetsplitServer_methods[] = { - {NULL} /* Sentinel */ -}; - -PyTypeObject PyNetsplitServerType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "NetsplitServer", /*tp_name*/ - sizeof(PyNetsplitServer), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)PyNetsplitServer_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - "PyNetsplitServer objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - PyNetsplitServer_methods, /* tp_methods */ - 0, /* tp_members */ - PyNetsplitServer_getseters, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - PyNetsplitServer_new, /* tp_new */ -}; - - -/* window item wrapper factory function */ -PyObject *pynetsplit_server_new(void *nss) -{ - PyNetsplitServer *pynss; - - pynss = py_inst(PyNetsplitServer, PyNetsplitServerType); - if (!pynss) - return NULL; - - pynss->data = nss; - pynss->cleanup_installed = 1; - signal_add_last_data("netsplit server remove", netsplit_server_cleanup, pynss); - - return (PyObject *)pynss; -} - -int netsplit_server_object_init(void) -{ - g_return_val_if_fail(py_module != NULL, 0); - - if (PyType_Ready(&PyNetsplitServerType) < 0) - return 0; - - Py_INCREF(&PyNetsplitServerType); - PyModule_AddObject(py_module, "NetsplitServer", (PyObject *)&PyNetsplitServerType); - - return 1; -} diff --git a/objects/netsplit-server-object.h b/objects/netsplit-server-object.h deleted file mode 100644 index f1d5fbf..0000000 --- a/objects/netsplit-server-object.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef _NETSPLIT_SERVER_OBJECT_H_ -#define _NETSPLIT_SERVER_OBJECT_H_ - -#include -#include "base-objects.h" - -typedef struct -{ - PyIrssiFinal_HEAD(void) -} PyNetsplitServer; - -extern PyTypeObject PyNetsplitServerType; - -int netsplit_server_object_init(void); -PyObject *pynetsplit_server_new(void *nss); -#define pynetsplit_server_check(op) PyObject_TypeCheck(op, &PyNetsplitServerType) - -#endif diff --git a/objects/nick-object.c b/objects/nick-object.c deleted file mode 100644 index 79f3a85..0000000 --- a/objects/nick-object.c +++ /dev/null @@ -1,237 +0,0 @@ -#include -#include "pymodule.h" -#include "base-objects.h" -#include "nick-object.h" -#include "pyirssi.h" -#include "pycore.h" -#include "pyutils.h" - -static void nick_cleanup(CHANNEL_REC *chan, NICK_REC *nick) -{ - PyNick *pynick = signal_get_user_data(); - - if (nick == pynick->data) - { - pynick->data = NULL; - pynick->cleanup_installed = 0; - signal_remove_data("nicklist remove", nick_cleanup, pynick); - } -} - -static void PyNick_dealloc(PyNick *self) -{ - if (self->cleanup_installed) - signal_remove_data("nicklist remove", nick_cleanup, self); - - self->ob_type->tp_free((PyObject*)self); -} - -/* Getters */ -PyDoc_STRVAR(PyNick_send_massjoin_doc, - "Waiting to be sent in a 'massjoin' signal, True or False" -); -static PyObject *PyNick_send_massjoin_get(PyNick *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyBool_FromLong(self->data->send_massjoin); -} - -PyDoc_STRVAR(PyNick_nick_doc, - "Plain nick" -); -static PyObject *PyNick_nick_get(PyNick *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->nick); -} - -PyDoc_STRVAR(PyNick_host_doc, - "Host address" -); -static PyObject *PyNick_host_get(PyNick *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->host); -} - -PyDoc_STRVAR(PyNick_realname_doc, - "Real name" -); -static PyObject *PyNick_realname_get(PyNick *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->realname); -} - -PyDoc_STRVAR(PyNick_hops_doc, - "Hop count to the server the nick is using" -); -static PyObject *PyNick_hops_get(PyNick *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyInt_FromLong(self->data->hops); -} - -PyDoc_STRVAR(PyNick_gone_doc, - "User status" -); -static PyObject *PyNick_gone_get(PyNick *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyBool_FromLong(self->data->gone); -} - -PyDoc_STRVAR(PyNick_serverop_doc, - "User status" -); -static PyObject *PyNick_serverop_get(PyNick *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyBool_FromLong(self->data->serverop); -} - -PyDoc_STRVAR(PyNick_op_doc, - "User status" -); -static PyObject *PyNick_op_get(PyNick *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyBool_FromLong(self->data->op); -} - -PyDoc_STRVAR(PyNick_voice_doc, - "User status" -); -static PyObject *PyNick_voice_get(PyNick *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyBool_FromLong(self->data->voice); -} - -PyDoc_STRVAR(PyNick_halfop_doc, - "User status" -); -static PyObject *PyNick_halfop_get(PyNick *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyBool_FromLong(self->data->halfop); -} - -PyDoc_STRVAR(PyNick_last_check_doc, - "timestamp when last checked gone/ircop status." -); -static PyObject *PyNick_last_check_get(PyNick *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyLong_FromUnsignedLong(self->data->last_check); -} - -/* specialized getters/setters */ -static PyGetSetDef PyNick_getseters[] = { - {"send_massjoin", (getter)PyNick_send_massjoin_get, NULL, - PyNick_send_massjoin_doc, NULL}, - {"nick", (getter)PyNick_nick_get, NULL, - PyNick_nick_doc, NULL}, - {"host", (getter)PyNick_host_get, NULL, - PyNick_host_doc, NULL}, - {"realname", (getter)PyNick_realname_get, NULL, - PyNick_realname_doc, NULL}, - {"hops", (getter)PyNick_hops_get, NULL, - PyNick_hops_doc, NULL}, - {"gone", (getter)PyNick_gone_get, NULL, - PyNick_gone_doc, NULL}, - {"serverop", (getter)PyNick_serverop_get, NULL, - PyNick_serverop_doc, NULL}, - {"op", (getter)PyNick_op_get, NULL, - PyNick_op_doc, NULL}, - {"voice", (getter)PyNick_voice_get, NULL, - PyNick_voice_doc, NULL}, - {"halfop", (getter)PyNick_halfop_get, NULL, - PyNick_halfop_doc, NULL}, - {"last_check", (getter)PyNick_last_check_get, NULL, - PyNick_last_check_doc, NULL}, - {NULL} -}; - -static PyMethodDef PyNick_methods[] = { - {NULL} /* Sentinel */ -}; - -PyTypeObject PyNickType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "Nick", /*tp_name*/ - sizeof(PyNick), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)PyNick_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - "PyNick objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - PyNick_methods, /* tp_methods */ - 0, /* tp_members */ - PyNick_getseters, /* tp_getset */ - &PyIrssiChatBaseType, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ -}; - - -/* nick factory function */ -PyObject *pynick_sub_new(void *nick, PyTypeObject *subclass) -{ - static const char *name = "NICK"; - PyNick *pynick = NULL; - - pynick = py_instp(PyNick, subclass); - if (!pynick) - return NULL; - - pynick->data = nick; - pynick->base_name = name; - signal_add_last_data("nicklist remove", nick_cleanup, pynick); - pynick->cleanup_installed = 1; - - return (PyObject *)pynick; -} - -PyObject *pynick_new(void *nick) -{ - return pynick_sub_new(nick, &PyNickType); -} - -int nick_object_init(void) -{ - g_return_val_if_fail(py_module != NULL, 0); - - if (PyType_Ready(&PyNickType) < 0) - return 0; - - Py_INCREF(&PyNickType); - PyModule_AddObject(py_module, "Nick", (PyObject *)&PyNickType); - - return 1; -} diff --git a/objects/nick-object.h b/objects/nick-object.h deleted file mode 100644 index 6831994..0000000 --- a/objects/nick-object.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef _NICK_OBJECT_H_ -#define _NICK_OBJECT_H_ - -#include -#include "base-objects.h" - -/* forward */ -struct _NICK_REC; - -typedef struct -{ - PyIrssi_HEAD(struct _NICK_REC) -} PyNick; - -extern PyTypeObject PyNickType; - -int nick_object_init(void); -PyObject *pynick_sub_new(void *nick, PyTypeObject *subclass); -PyObject *pynick_new(void *nick); -#define pynick_check(op) PyObject_TypeCheck(op, &PyNickType) - -#endif diff --git a/objects/notifylist-object.c b/objects/notifylist-object.c deleted file mode 100644 index 3366d0f..0000000 --- a/objects/notifylist-object.c +++ /dev/null @@ -1,221 +0,0 @@ -#include -#include "pyirssi_irc.h" -#include "pymodule.h" -#include "notifylist-object.h" -#include "pycore.h" - -#define NOTIFYLIST(nl) ((NOTIFYLIST_REC *)nl) - -/* monitor "notifylist remove" signal */ -static void notifylist_cleanup(NOTIFYLIST_REC *notifylist) -{ - PyNotifylist *pynotifylist = signal_get_user_data(); - - if (notifylist == pynotifylist->data) - { - pynotifylist->data = NULL; - pynotifylist->cleanup_installed = 0; - signal_remove_data("notifylist remove", notifylist_cleanup, pynotifylist); - } -} - -static void PyNotifylist_dealloc(PyNotifylist *self) -{ - if (self->cleanup_installed) - signal_remove_data("notifylist remove", notifylist_cleanup, self); - - self->ob_type->tp_free((PyObject*)self); -} - -static PyObject *PyNotifylist_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyNotifylist *self; - - self = (PyNotifylist *)type->tp_alloc(type, 0); - if (!self) - return NULL; - - return (PyObject *)self; -} - -/* Getters */ -PyDoc_STRVAR(PyNotifylist_mask_doc, - "Notify nick mask" -); -static PyObject *PyNotifylist_mask_get(PyNotifylist *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(NOTIFYLIST(self->data)->mask); -} - -PyDoc_STRVAR(PyNotifylist_away_check_doc, - "Notify away status changes" -); -static PyObject *PyNotifylist_away_check_get(PyNotifylist *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyBool_FromLong(NOTIFYLIST(self->data)->away_check); -} - -PyDoc_STRVAR(PyNotifylist_idle_check_time_doc, - "Notify when idle time is reset and idle was bigger than this (seconds)" -); -static PyObject *PyNotifylist_idle_check_time_get(PyNotifylist *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyLong_FromUnsignedLong(NOTIFYLIST(self->data)->idle_check_time); -} - -/* specialized getters/setters */ -static PyGetSetDef PyNotifylist_getseters[] = { - {"mask", (getter)PyNotifylist_mask_get, NULL, - PyNotifylist_mask_doc, NULL}, - {"away_check", (getter)PyNotifylist_away_check_get, NULL, - PyNotifylist_away_check_doc, NULL}, - {"idle_check_time", (getter)PyNotifylist_idle_check_time_get, NULL, - PyNotifylist_idle_check_time_doc, NULL}, - {NULL} -}; - -/* Methods */ -PyDoc_STRVAR(PyNotifylist_ircnets_doc, - "ircnets() -> list of str\n" - "\n" - "Return list of ircnets the notify is checked\n" -); -static PyObject *PyNotifylist_ircnets(PyNotifylist *self, PyObject *args) -{ - PyObject *list; - char **nets; - - RET_NULL_IF_INVALID(self->data); - - nets = NOTIFYLIST(self->data)->ircnets; - list = PyList_New(0); - if (!list) - return NULL; - - while (nets && *nets) - { - int ret; - PyObject *str = PyString_FromString(*nets); - - if (!str) - { - Py_DECREF(list); - return NULL; - } - - ret = PyList_Append(list, str); - Py_DECREF(str); - if (ret != 0) - { - Py_DECREF(list); - return NULL; - } - - nets++; - } - - return list; -} - -PyDoc_STRVAR(PyNotifylist_ircnets_match_doc, - "ircnets_match(ircnet) -> bool\n" - "\n" - "Return True if notify is checked in ircnet\n" -); -static PyObject *PyNotifylist_ircnets_match(PyNotifylist *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"ircnet", NULL}; - char *ircnet = ""; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &ircnet)) - return NULL; - - return PyBool_FromLong(notifylist_ircnets_match(self->data, ircnet)); -} - -/* Methods for object */ -static PyMethodDef PyNotifylist_methods[] = { - {"ircnets", (PyCFunction)PyNotifylist_ircnets, METH_NOARGS, - PyNotifylist_ircnets_doc}, - {"ircnets_match", (PyCFunction)PyNotifylist_ircnets_match, METH_VARARGS | METH_KEYWORDS, - PyNotifylist_ircnets_match_doc}, - {NULL} /* Sentinel */ -}; - -PyTypeObject PyNotifylistType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "Notifylist", /*tp_name*/ - sizeof(PyNotifylist), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)PyNotifylist_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - "PyNotifylist objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - PyNotifylist_methods, /* tp_methods */ - 0, /* tp_members */ - PyNotifylist_getseters, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - PyNotifylist_new, /* tp_new */ -}; - - -/* window item wrapper factory function */ -PyObject *pynotifylist_new(void *notifylist) -{ - PyNotifylist *pynotifylist; - - pynotifylist = py_inst(PyNotifylist, PyNotifylistType); - if (!pynotifylist) - return NULL; - - pynotifylist->data = notifylist; - pynotifylist->cleanup_installed = 1; - signal_add_last_data("notifylist remove", notifylist_cleanup, pynotifylist); - - return (PyObject *)pynotifylist; -} - -int notifylist_object_init(void) -{ - g_return_val_if_fail(py_module != NULL, 0); - - if (PyType_Ready(&PyNotifylistType) < 0) - return 0; - - Py_INCREF(&PyNotifylistType); - PyModule_AddObject(py_module, "Notifylist", (PyObject *)&PyNotifylistType); - - return 1; -} diff --git a/objects/notifylist-object.h b/objects/notifylist-object.h deleted file mode 100644 index 9db6922..0000000 --- a/objects/notifylist-object.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef _NOTIFYLIST_OBJECT_H_ -#define _NOTIFYLIST_OBJECT_H_ - -#include -#include "base-objects.h" - -typedef struct -{ - PyIrssiFinal_HEAD(void) -} PyNotifylist; - -extern PyTypeObject PyNotifylistType; - -int notifylist_object_init(void); -PyObject *pynotifylist_new(void *notifylist); -#define pynotifylist_check(op) PyObject_TypeCheck(op, &PyNotifylistType) - -#endif diff --git a/objects/process-object.c b/objects/process-object.c deleted file mode 100644 index 43c0fd7..0000000 --- a/objects/process-object.c +++ /dev/null @@ -1,222 +0,0 @@ -#include -#include "pyirssi_irc.h" -#include "pymodule.h" -#include "process-object.h" -#include "pycore.h" - -/* monitor "exec remove" signal */ -static void process_cleanup(PROCESS_REC *process, int status) -{ - PyProcess *pyprocess = signal_get_user_data(); - - if (process == pyprocess->data) - { - pyprocess->data = NULL; - pyprocess->cleanup_installed = 0; - signal_remove_data("exec remove", process_cleanup, pyprocess); - } -} - -static void PyProcess_dealloc(PyProcess *self) -{ - if (self->cleanup_installed) - signal_remove_data("exec remove", process_cleanup, self); - - Py_XDECREF(self->target_win); - - self->ob_type->tp_free((PyObject*)self); -} - -static PyObject *PyProcess_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyProcess *self; - - self = (PyProcess *)type->tp_alloc(type, 0); - if (!self) - return NULL; - - return (PyObject *)self; -} - -/* Getters */ -PyDoc_STRVAR(PyProcess_id_doc, - "ID for the process" -); -static PyObject *PyProcess_id_get(PyProcess *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyInt_FromLong(self->data->id); -} - -PyDoc_STRVAR(PyProcess_name_doc, - "Name for the process (if given)" -); -static PyObject *PyProcess_name_get(PyProcess *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->name); -} - -PyDoc_STRVAR(PyProcess_args_doc, - "The command that is being executed" -); -static PyObject *PyProcess_args_get(PyProcess *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->args); -} - -PyDoc_STRVAR(PyProcess_pid_doc, - "PID for the executed command" -); -static PyObject *PyProcess_pid_get(PyProcess *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyInt_FromLong(self->data->pid); -} - -PyDoc_STRVAR(PyProcess_target_doc, - "send text with /msg ..." -); -static PyObject *PyProcess_target_get(PyProcess *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->target); -} - -PyDoc_STRVAR(PyProcess_target_win_doc, - "print text to this window" -); -static PyObject *PyProcess_target_win_get(PyProcess *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_OBJ_OR_NONE(self->target_win); -} - -PyDoc_STRVAR(PyProcess_shell_doc, - "start the program via /bin/sh" -); -static PyObject *PyProcess_shell_get(PyProcess *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyBool_FromLong(self->data->shell); -} - -PyDoc_STRVAR(PyProcess_notice_doc, - "send text with /notice, not /msg if target is set" -); -static PyObject *PyProcess_notice_get(PyProcess *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyBool_FromLong(self->data->notice); -} - -PyDoc_STRVAR(PyProcess_silent_doc, - "don't print \"process exited with level xx\"" -); -static PyObject *PyProcess_silent_get(PyProcess *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyBool_FromLong(self->data->silent); -} - -/* specialized getters/setters */ -static PyGetSetDef PyProcess_getseters[] = { - {"id", (getter)PyProcess_id_get, NULL, - PyProcess_id_doc, NULL}, - {"name", (getter)PyProcess_name_get, NULL, - PyProcess_name_doc, NULL}, - {"args", (getter)PyProcess_args_get, NULL, - PyProcess_args_doc, NULL}, - {"pid", (getter)PyProcess_pid_get, NULL, - PyProcess_pid_doc, NULL}, - {"target", (getter)PyProcess_target_get, NULL, - PyProcess_target_doc, NULL}, - {"target_win", (getter)PyProcess_target_win_get, NULL, - PyProcess_target_win_doc, NULL}, - {"shell", (getter)PyProcess_shell_get, NULL, - PyProcess_shell_doc, NULL}, - {"notice", (getter)PyProcess_notice_get, NULL, - PyProcess_notice_doc, NULL}, - {"silent", (getter)PyProcess_silent_get, NULL, - PyProcess_silent_doc, NULL}, - {NULL} -}; - -/* Methods */ -/* Methods for object */ -static PyMethodDef PyProcess_methods[] = { - {NULL} /* Sentinel */ -}; - -PyTypeObject PyProcessType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "Process", /*tp_name*/ - sizeof(PyProcess), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)PyProcess_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - "PyProcess objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - PyProcess_methods, /* tp_methods */ - 0, /* tp_members */ - PyProcess_getseters, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - PyProcess_new, /* tp_new */ -}; - - -/* process factory function */ -PyObject *pyprocess_new(void *process) -{ - PyProcess *pyprocess; - - pyprocess = py_inst(PyProcess, PyProcessType); - if (!pyprocess) - return NULL; - - pyprocess->data = process; - pyprocess->cleanup_installed = 1; - signal_add_last_data("exec remove", process_cleanup, pyprocess); - - return (PyObject *)pyprocess; -} - -int process_object_init(void) -{ - g_return_val_if_fail(py_module != NULL, 0); - - if (PyType_Ready(&PyProcessType) < 0) - return 0; - - Py_INCREF(&PyProcessType); - PyModule_AddObject(py_module, "Process", (PyObject *)&PyProcessType); - - return 1; -} diff --git a/objects/process-object.h b/objects/process-object.h deleted file mode 100644 index 041f187..0000000 --- a/objects/process-object.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef _PROCESS_OBJECT_H_ -#define _PROCESS_OBJECT_H_ - -#include -#include "base-objects.h" - -/* forward */ -struct PROCESS_REC; - -typedef struct -{ - PyIrssiFinal_HEAD(struct PROCESS_REC) - PyObject *target_win; -} PyProcess; - -extern PyTypeObject PyProcessType; - -int process_object_init(void); -PyObject *pyprocess_new(void *process); -#define pyprocess_check(op) PyObject_TypeCheck(op, &PyProcessType) - -#endif diff --git a/objects/pyscript-object.c b/objects/pyscript-object.c deleted file mode 100644 index ae4770e..0000000 --- a/objects/pyscript-object.c +++ /dev/null @@ -1,801 +0,0 @@ -#include -#include -#include "pyscript-object.h" -#include "pyirssi.h" -#include "pysignals.h" -#include "pymodule.h" -#include "pysource.h" -#include "pythemes.h" -#include "pystatusbar.h" - -/* handle cycles... - Can't think of any reason why the user would put script into one of the lists - but who knows. Call GC after unloading module. -*/ -static int PyScript_traverse(PyScript *self, visitproc visit, void *arg) -{ - Py_VISIT(self->module); - Py_VISIT(self->argv); - Py_VISIT(self->modules); - - return 0; -} - -static int PyScript_clear(PyScript *self) -{ - Py_CLEAR(self->module); - Py_CLEAR(self->argv); - Py_CLEAR(self->modules); - - return 0; -} - -static void PyScript_dealloc(PyScript* self) -{ - PyScript_clear(self); - pyscript_remove_signals((PyObject*)self); - pyscript_remove_sources((PyObject*)self); - - self->ob_type->tp_free((PyObject*)self); -} - -static PyObject *PyScript_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyScript *self; - PyObject *argv = NULL, *modules = NULL; - - argv = PyList_New(0); - if (!argv) - goto error; - - modules = PyDict_New(); - if (!modules) - goto error; - - self = (PyScript *)type->tp_alloc(type, 0); - if (!self) - goto error; - - self->argv = argv; - self->modules = modules; - - return (PyObject *)self; - -error: - Py_XDECREF(argv); - Py_XDECREF(modules); - return NULL; -} - -PyDoc_STRVAR(PyScript_command_bind_doc, - "command_bind(command, func, catetory=None, priority=SIGNAL_PRIORITY_DEFAULT) -> None\n" - "\n" - "Add handler for a command\n" -); -static PyObject *PyScript_command_bind(PyScript *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"cmd", "func", "category", "priority", NULL}; - char *cmd; - PyObject *func; - char *category = NULL; - int priority = SIGNAL_PRIORITY_DEFAULT; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "sO|zi", kwlist, - &cmd, &func, &category, &priority)) - return NULL; - - if (!PyCallable_Check(func)) - return PyErr_Format(PyExc_TypeError, "func must be callable"); - - if (!pysignals_command_bind_list(&self->signals, cmd, func, category, priority)) - return PyErr_Format(PyExc_RuntimeError, "unable to bind command"); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyScript_signal_add_doc, - "signal_add(signal, func, priority=SIGNAL_PRIORITY_DEFAULT) -> None\n" - "\n" - "Add handler for signal" -); -static PyObject *PyScript_signal_add(PyScript *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"signal", "func", "priority", NULL}; - char *signal; - PyObject *func; - int priority = SIGNAL_PRIORITY_DEFAULT; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "sO|i", kwlist, - &signal, &func, &priority)) - return NULL; - - if (!PyCallable_Check(func)) - return PyErr_Format(PyExc_TypeError, "func must be callable"); - - if (!pysignals_signal_add_list(&self->signals, signal, func, priority)) - return PyErr_Format(PyExc_KeyError, "unable to find signal, '%s'", signal); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyScript_signal_remove_doc, - "signal_remove(signal, func=None) -> None\n" - "\n" - "Remove signal handler\n" -); -static PyObject *PyScript_signal_remove(PyScript *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"signal", "func", NULL}; - char *signal = ""; - PyObject *func = Py_None; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|O", kwlist, - &signal, &func)) - return NULL; - - if (!PyCallable_Check(func) && func != Py_None) - return PyErr_Format(PyExc_TypeError, "func must be callable or None"); - - if (func == Py_None) - func = NULL; - - if (!pysignals_remove_search(&self->signals, signal, func, PSG_SIGNAL)) - return PyErr_Format(PyExc_KeyError, "can't find signal"); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyScript_command_unbind_doc, - "command_unbind(command, func=None) -> None\n" - "\n" - "Remove command handler\n" -); -static PyObject *PyScript_command_unbind(PyScript *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"command", "func", NULL}; - char *command = ""; - PyObject *func = Py_None; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|O", kwlist, - &command, &func)) - return NULL; - - if (!PyCallable_Check(func) && func != Py_None) - return PyErr_Format(PyExc_TypeError, "func must be callable or None"); - - if (func == Py_None) - func = NULL; - - if (!pysignals_remove_search(&self->signals, command, func, PSG_COMMAND)) - return PyErr_Format(PyExc_KeyError, "can't find command"); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyScript_signal_register_doc, - "signal_register(signal, arglist) -> None\n" - "\n" - "Register a new dynamic signal for use with irssi_python\n" - "arglist is a string of character codes representing the type of each argument\n" - "of the signal handler function.\n" - "\n" - " Scalars\n" - " s -> char *\n" - " i -> int\n" - "\n" - " Chat objects\n" - " c -> CHATNET_REC\n" - " S -> SERVER_REC\n" - " C -> CHANNEL_REC\n" - " q -> QUERY_REC\n" - " n -> NICK_REC\n" - " W -> WI_ITEM_REC\n" - "\n" - " Irssi objects\n" - " d -> DCC_REC\n" - "\n" - " Other objects\n" - " r -> RECONNECT_REC\n" - " o -> COMMAND_REC\n" - " l -> LOG_REC\n" - " a -> RAWLOG_REC\n" - " g -> IGNORE_REC\n" - " b -> BAN_REC\n" - " N -> NETSPLIT_REC\n" - " e -> NETSPLIT_SERVER_REC\n" - " O -> NOTIFYLIST_REC\n" - " p -> PROCESS_REC\n" - " t -> TEXT_DEST_REC\n" - " w -> WINDOW_REC\n" -); -static PyObject *PyScript_signal_register(PyScript *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"signal", "arglist", NULL}; - static const char *good_codes = "sicSCqnWdrolagbNeOptw"; - char *signal = ""; - char *arglist = ""; - int i; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss", kwlist, - &signal, &arglist)) - return NULL; - - for (i = 0; arglist[i]; i++) - if (!strchr(good_codes, arglist[i])) - return PyErr_Format(PyExc_TypeError, "invalid code, %c", arglist[i]); - - if (i >= SIGNAL_MAX_ARGUMENTS) - return PyErr_Format(PyExc_TypeError, - "arglist greater than SIGNAL_MAX_ARGUMENTS (%d)", - SIGNAL_MAX_ARGUMENTS); - - if (!pysignals_register(signal, arglist)) - return PyErr_Format(PyExc_TypeError, "signal present with different args"); - - self->registered_signals = g_slist_append(self->registered_signals, - g_strdup(signal)); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyScript_signal_unregister_doc, - "signal_unregister(signal) -> None\n" - "\n" - "Unregister dynamic signal\n" -); -static PyObject *PyScript_signal_unregister(PyScript *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"signal", NULL}; - char *signal = ""; - GSList *search; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &signal)) - return NULL; - - search = g_slist_find_custom(self->registered_signals, signal, (GCompareFunc)strcmp); - if (!search) - return PyErr_Format(PyExc_KeyError, "script has not registered that signal"); - - g_free(search->data); - self->registered_signals = g_slist_delete_link(self->registered_signals, search); - - if (!pysignals_unregister(signal)) - return PyErr_Format(PyExc_SystemError, - "script registered signal, but signal does not exist"); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyScript_timeout_add_doc, - "timeout_add(msecs, func, data=None) -> int source tag\n" - "\n" - "Add a timeout handler called every 'msecs' milliseconds until func\n" - "returns False or the source is removed with source_remove().\n" - "\n" - "func is called as func(data) or func(), depending on whether data\n" - "is specified or not.\n" -); -static PyObject *PyScript_timeout_add(PyScript *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"msecs", "func", "data", NULL}; - int msecs = 0; - PyObject *func = NULL; - PyObject *data = NULL; - int ret; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "iO|O", kwlist, - &msecs, &func, &data)) - return NULL; - - if (msecs < 10) - return PyErr_Format(PyExc_ValueError, "msecs must be at least 10"); - - if (!PyCallable_Check(func)) - return PyErr_Format(PyExc_TypeError, "func not callable"); - - ret = pysource_timeout_add_list(&self->sources, msecs, func, data); - - return PyInt_FromLong(ret); -} - -PyDoc_STRVAR(PyScript_io_add_watch_doc, - "io_add_watch(fd, func, data=None, condition=IO_IN|IO_PRI) -> int source tag\n" -); -static PyObject *PyScript_io_add_watch(PyScript *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"fd", "func", "data", "condition", NULL}; - int fd = 0; - PyObject *pyfd = NULL; - PyObject *func = NULL; - PyObject *data = NULL; - int condition = G_IO_IN | G_IO_PRI; - int ret; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO|Oi", kwlist, - &pyfd, &func, &data, &condition)) - return NULL; - - fd = PyObject_AsFileDescriptor(pyfd); - if (fd < 0) - return NULL; - - if (!PyCallable_Check(func)) - return PyErr_Format(PyExc_TypeError, "func not callable"); - - ret = pysource_io_add_watch_list(&self->sources, fd, condition, func, data); - - return PyInt_FromLong(ret); -} - -PyDoc_STRVAR(PyScript_source_remove_doc, - "source_remove(tag) -> bool\n" - "\n" - "Remove IO or timeout source by tag. Return True if tag found and removed.\n" -); -static PyObject *PyScript_source_remove(PyScript *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"tag", NULL}; - int tag = 0; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, - &tag)) - return NULL; - - /* the destroy notify func will remove the list link, but first - check that the tag exists in this Script object */ - if (g_slist_find(self->sources, GINT_TO_POINTER(tag))) - return PyBool_FromLong(g_source_remove(tag)); - - Py_RETURN_FALSE; -} - -static int py_settings_add(PyScript *self, const char *name) -{ - GSList *node; - - node = gslist_find_icase_string(self->settings, name); - if (node) - return 0; - - self->settings = g_slist_append(self->settings, g_strdup(name)); - - return 1; -} - -static int py_settings_remove(PyScript *self, const char *name) -{ - GSList *node; - - node = gslist_find_icase_string(self->settings, name); - if (!node) - return 0; - - settings_remove(node->data); - g_free(node->data); - - self->settings = g_slist_delete_link(self->settings, node); - - return 1; -} - -PyDoc_STRVAR(PyScript_settings_add_str_doc, - "settings_add_str(section, key, def) -> None\n" -); -static PyObject *PyScript_settings_add_str(PyScript *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"section", "key", "def", NULL}; - char *section = ""; - char *key = ""; - char *def = ""; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "sss", kwlist, - §ion, &key, &def)) - return NULL; - - if (!py_settings_add(self, key)) - return PyErr_Format(PyExc_ValueError, "key, %s, already added by script", key); - - settings_add_str_module(MODULE_NAME"/scripts", section, key, def); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyScript_settings_add_int_doc, - "settings_add_int(section, key, def) -> None\n" -); -static PyObject *PyScript_settings_add_int(PyScript *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"section", "key", "def", NULL}; - char *section = ""; - char *key = ""; - int def = 0; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "ssi", kwlist, - §ion, &key, &def)) - return NULL; - - if (!py_settings_add(self, key)) - return PyErr_Format(PyExc_ValueError, "key, %s, already added by script", key); - - settings_add_int_module(MODULE_NAME"/scripts", section, key, def); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyScript_settings_add_bool_doc, - "settings_add_bool(section, key, def) -> None\n" -); -static PyObject *PyScript_settings_add_bool(PyScript *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"section", "key", "def", NULL}; - char *section = ""; - char *key = ""; - int def = 0; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "ssi", kwlist, - §ion, &key, &def)) - return NULL; - - if (!py_settings_add(self, key)) - return PyErr_Format(PyExc_ValueError, "key, %s, already added by script", key); - - settings_add_bool_module(MODULE_NAME"/scripts", section, key, def); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyScript_settings_add_time_doc, - "settings_add_time(section, key, def) -> None\n" -); -static PyObject *PyScript_settings_add_time(PyScript *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"section", "key", "def", NULL}; - char *section = ""; - char *key = ""; - char *def = ""; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "sss", kwlist, - §ion, &key, &def)) - return NULL; - - if (!py_settings_add(self, key)) - return PyErr_Format(PyExc_ValueError, "key, %s, already added by script", key); - - settings_add_time_module(MODULE_NAME"/scripts", section, key, def); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyScript_settings_add_level_doc, - "settings_add_level(section, key, def) -> None\n" -); -static PyObject *PyScript_settings_add_level(PyScript *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"section", "key", "def", NULL}; - char *section = ""; - char *key = ""; - char *def = ""; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "sss", kwlist, - §ion, &key, &def)) - return NULL; - - if (!py_settings_add(self, key)) - return PyErr_Format(PyExc_ValueError, "key, %s, already added by script", key); - - settings_add_level_module(MODULE_NAME"/scripts", section, key, def); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyScript_settings_add_size_doc, - "settings_add_size(section, key, def) -> None\n" -); -static PyObject *PyScript_settings_add_size(PyScript *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"section", "key", "def", NULL}; - char *section = ""; - char *key = ""; - char *def = ""; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "sss", kwlist, - §ion, &key, &def)) - return NULL; - - if (!py_settings_add(self, key)) - return PyErr_Format(PyExc_ValueError, "key, %s, already added by script", key); - - settings_add_size_module(MODULE_NAME"/scripts", section, key, def); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyScript_settings_remove_doc, - "settings_remove(key) -> bool\n" -); -static PyObject *PyScript_settings_remove(PyScript *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"key", NULL}; - char *key = ""; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &key)) - return NULL; - - return PyBool_FromLong(py_settings_remove(self, key)); -} - -PyDoc_STRVAR(PyScript_theme_register_doc, - "theme_register(list) -> None\n" -); -static PyObject *PyScript_theme_register(PyScript *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"list", NULL}; - PyObject *list = NULL; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, - &list)) - return NULL; - - if (!pythemes_register(pyscript_get_name(self), list)) - return NULL; - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyScript_statusbar_item_register_doc, - "statusbar_item_register(name, value=None, func=None) -> None\n" -); -static PyObject *PyScript_statusbar_item_register(PyScript *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"name", "value", "func", NULL}; - char *name = ""; - char *value = NULL; - PyObject *func = NULL; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|zO", kwlist, - &name, &value, &func)) - return NULL; - - pystatusbar_item_register((PyObject *)self, name, value, func); - - Py_RETURN_NONE; -} - -/* Methods for object */ -static PyMethodDef PyScript_methods[] = { - {"command_bind", (PyCFunction)PyScript_command_bind, METH_VARARGS | METH_KEYWORDS, - PyScript_command_bind_doc}, - {"signal_add", (PyCFunction)PyScript_signal_add, METH_VARARGS | METH_KEYWORDS, - PyScript_signal_add_doc}, - {"signal_remove", (PyCFunction)PyScript_signal_remove, METH_VARARGS | METH_KEYWORDS, - PyScript_signal_remove_doc}, - {"command_unbind", (PyCFunction)PyScript_command_unbind, METH_VARARGS | METH_KEYWORDS, - PyScript_command_unbind_doc}, - {"signal_register", (PyCFunction)PyScript_signal_register, METH_VARARGS | METH_KEYWORDS, - PyScript_signal_register_doc}, - {"signal_unregister", (PyCFunction)PyScript_signal_unregister, METH_VARARGS | METH_KEYWORDS, - PyScript_signal_unregister_doc}, - {"timeout_add", (PyCFunction)PyScript_timeout_add, METH_VARARGS | METH_KEYWORDS, - PyScript_timeout_add_doc}, - {"io_add_watch", (PyCFunction)PyScript_io_add_watch, METH_VARARGS | METH_KEYWORDS, - PyScript_io_add_watch_doc}, - {"source_remove", (PyCFunction)PyScript_source_remove, METH_VARARGS | METH_KEYWORDS, - PyScript_source_remove_doc}, - {"settings_add_str", (PyCFunction)PyScript_settings_add_str, METH_VARARGS | METH_KEYWORDS, - PyScript_settings_add_str_doc}, - {"settings_add_int", (PyCFunction)PyScript_settings_add_int, METH_VARARGS | METH_KEYWORDS, - PyScript_settings_add_int_doc}, - {"settings_add_bool", (PyCFunction)PyScript_settings_add_bool, METH_VARARGS | METH_KEYWORDS, - PyScript_settings_add_bool_doc}, - {"settings_add_time", (PyCFunction)PyScript_settings_add_time, METH_VARARGS | METH_KEYWORDS, - PyScript_settings_add_time_doc}, - {"settings_add_level", (PyCFunction)PyScript_settings_add_level, METH_VARARGS | METH_KEYWORDS, - PyScript_settings_add_level_doc}, - {"settings_add_size", (PyCFunction)PyScript_settings_add_size, METH_VARARGS | METH_KEYWORDS, - PyScript_settings_add_size_doc}, - {"settings_remove", (PyCFunction)PyScript_settings_remove, METH_VARARGS | METH_KEYWORDS, - PyScript_settings_remove_doc}, - {"theme_register", (PyCFunction)PyScript_theme_register, METH_VARARGS | METH_KEYWORDS, - PyScript_theme_register_doc}, - {"statusbar_item_register", (PyCFunction)PyScript_statusbar_item_register, METH_VARARGS | METH_KEYWORDS, - PyScript_statusbar_item_register_doc}, - {NULL} /* Sentinel */ -}; - -static PyMemberDef PyScript_members[] = { - {"argv", T_OBJECT, offsetof(PyScript, argv), 0, "Script arguments"}, - {"module", T_OBJECT_EX, offsetof(PyScript, module), RO, "Script module"}, - {"modules", T_OBJECT_EX, offsetof(PyScript, modules), 0, "Imported modules"}, - {NULL} /* Sentinel */ -}; - -PyTypeObject PyScriptType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "Script", /*tp_name*/ - sizeof(PyScript), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)PyScript_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ - "PyScript objects", /* tp_doc */ - (traverseproc)PyScript_traverse, /* tp_traverse */ - (inquiry)PyScript_clear, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - PyScript_methods, /* tp_methods */ - PyScript_members, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - PyScript_new, /* tp_new */ -}; - -/* PyScript factory function */ -PyObject *pyscript_new(PyObject *module, char **argv) -{ - PyObject *script; - - script = PyObject_CallFunction((PyObject*)&PyScriptType, "()"); - - if (script) - { - PyScript *scr = (PyScript *)script; - - while (*argv) - { - if (**argv != '\0') - { - PyObject *str = PyString_FromString(*argv); - if (!str) - { - /* The destructor should DECREF argv */ - Py_DECREF(script); - return NULL; - } - - PyList_Append(scr->argv, str); - Py_DECREF(str); - } - - *argv++; - } - - Py_INCREF(module); - scr->module = module; - } - - return script; -} - -void pyscript_remove_signals(PyObject *script) -{ - GSList *node; - PyScript *self; - - g_return_if_fail(pyscript_check(script)); - - self = (PyScript *) script; - - /* remove bound signals */ - pysignals_remove_list(self->signals); - g_slist_free(self->signals); - self->signals = NULL; - - /* remove registered signals */ - for (node = self->registered_signals; node; node = node->next) - { - pysignals_unregister(node->data); - g_free(node->data); - } - - g_slist_free(self->registered_signals); - self->registered_signals = NULL; -} - -void pyscript_remove_sources(PyObject *script) -{ - GSList *node; - PyScript *self; - - g_return_if_fail(pyscript_check(script)); - - self = (PyScript *) script; - - node = self->sources; - while (node) - { - /* the notify func will destroy the link so save next */ - GSList *next = node->next; - g_source_remove(GPOINTER_TO_INT(node->data)); - node = next; - } - - g_return_if_fail(self->sources == NULL); -} - -void pyscript_remove_settings(PyObject *script) -{ - PyScript *self; - - g_return_if_fail(pyscript_check(script)); - - self = (PyScript *) script; - - g_slist_foreach(self->settings, (GFunc)settings_remove, NULL); - g_slist_foreach(self->settings, (GFunc)g_free, NULL); - g_slist_free(self->settings); -} - -void pyscript_remove_themes(PyObject *script) -{ - PyScript *self; - - g_return_if_fail(pyscript_check(script)); - - self = (PyScript *) script; - - pythemes_unregister(pyscript_get_name(script)); -} - -void pyscript_remove_statusbars(PyObject *script) -{ - g_return_if_fail(pyscript_check(script)); - - pystatusbar_cleanup_script(script); -} - -void pyscript_clear_modules(PyObject *script) -{ - PyScript *self; - - g_return_if_fail(pyscript_check(script)); - - self = (PyScript *) script; - - PyDict_Clear(self->modules); -} - -void pyscript_cleanup(PyObject *script) -{ - pyscript_remove_signals(script); - pyscript_remove_sources(script); - pyscript_remove_settings(script); - pyscript_remove_themes(script); - pyscript_remove_statusbars(script); - pyscript_clear_modules(script); -} - -int pyscript_init(void) -{ - if (PyType_Ready(&PyScriptType) < 0) - return 0; - - Py_INCREF(&PyScriptType); - PyModule_AddObject(py_module, "Script", (PyObject *)&PyScriptType); - - return 1; -} - diff --git a/objects/pyscript-object.h b/objects/pyscript-object.h deleted file mode 100644 index 624a578..0000000 --- a/objects/pyscript-object.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef _PYSCRIPT_OBJECT_H_ -#define _PYSCRIPT_OBJECT_H_ -#include -#include - -typedef struct { - PyObject_HEAD - PyObject *module; /* module object */ - PyObject *argv; /* list of argument strings from the load command */ - PyObject *modules; /* dict of imported modules for script */ - GSList *signals; /* list of bound signals and commands */ - GSList *registered_signals; /* list of signal names registered */ - GSList *sources; /* list of io and timeout sources */ - GSList *settings; /* list of settings from settings_add_*() */ -} PyScript; - -extern PyTypeObject PyScriptType; - -int pyscript_init(void); -PyObject *pyscript_new(PyObject *module, char **argv); -void pyscript_remove_signals(PyObject *script); -void pyscript_remove_sources(PyObject *script); -void pyscript_remove_settings(PyObject *script); -void pyscript_remove_themes(PyObject *script); -void pyscript_remove_statusbars(PyObject *script); -void pyscript_clear_modules(PyObject *script); -void pyscript_cleanup(PyObject *script); -#define pyscript_check(op) PyObject_TypeCheck(op, &PyScriptType) -#define pyscript_get_name(scr) PyModule_GetName(((PyScript*)scr)->module) -#define pyscript_get_filename(scr) PyModule_GetFilename(((PyScript*)scr)->module) -#define pyscript_get_module(scr) (((PyScript*)scr)->module) - -#endif diff --git a/objects/query-object.c b/objects/query-object.c deleted file mode 100644 index 47badd5..0000000 --- a/objects/query-object.c +++ /dev/null @@ -1,172 +0,0 @@ -#include -#include "pyirssi.h" -#include "pymodule.h" -#include "base-objects.h" -#include "window-item-object.h" -#include "query-object.h" -#include "server-object.h" -#include "pycore.h" - -/* monitor "query destroyed" signal */ -static void query_cleanup(QUERY_REC *query) -{ - PyQuery *pyquery = signal_get_user_data(); - - if (query == pyquery->data) - { - pyquery->data = NULL; - pyquery->cleanup_installed = 0; - signal_remove_data("query destroyed", query_cleanup, pyquery); - } -} - -static void PyQuery_dealloc(PyQuery *self) -{ - if (self->cleanup_installed) - signal_remove_data("query destroyed", query_cleanup, self); - - self->ob_type->tp_free((PyObject*)self); -} - -/* Getters */ -PyDoc_STRVAR(PyQuery_address_doc, - "Host address of the queries nick" -); -static PyObject *PyQuery_address_get(PyQuery *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->address); -} - -PyDoc_STRVAR(PyQuery_server_tag_doc, - "Server tag used for this nick (doesn't get erased if server gets disconnected)" -); -static PyObject *PyQuery_server_tag_get(PyQuery *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->server_tag); -} - -PyDoc_STRVAR(PyQuery_unwanted_doc, - "1 if the other side closed or some error occured (DCC chats)" -); -static PyObject *PyQuery_unwanted_get(PyQuery *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyBool_FromLong(self->data->unwanted); -} - -/* specialized getters/setters */ -static PyGetSetDef PyQuery_getseters[] = { - {"address", (getter)PyQuery_address_get, NULL, - PyQuery_address_doc, NULL}, - {"server_tag", (getter)PyQuery_server_tag_get, NULL, - PyQuery_server_tag_doc, NULL}, - {"unwanted", (getter)PyQuery_unwanted_get, NULL, - PyQuery_unwanted_doc, NULL}, - {NULL} -}; - -PyDoc_STRVAR(change_server_doc, - "change_server(server) -> None\n" - "\n" - "Change the active server for the query.\n" -); -static PyObject *PyQuery_change_server(PyQuery *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"server", NULL}; - PyObject *server; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &server)) - return NULL; - - if (!pyserver_check(server)) - return PyErr_Format(PyExc_TypeError, "argument must be server object"); - - query_change_server(self->data, ((PyServer*)server)->data); - - Py_RETURN_NONE; -} - -/* Methods for object */ -static PyMethodDef PyQuery_methods[] = { - {"change_server", (PyCFunction)PyQuery_change_server, METH_VARARGS | METH_KEYWORDS, - change_server_doc}, - - {NULL} /* Sentinel */ -}; - -PyTypeObject PyQueryType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "Query", /*tp_name*/ - sizeof(PyQuery), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)PyQuery_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - "PyQuery objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - PyQuery_methods, /* tp_methods */ - 0, /* tp_members */ - PyQuery_getseters, /* tp_getset */ - &PyWindowItemType, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ -}; - - -/* query factory function */ -PyObject *pyquery_new(void *query) -{ - static const char *BASE_NAME = "QUERY"; - PyObject *pyquery; - - pyquery = pywindow_item_sub_new(query, BASE_NAME, &PyQueryType); - if (pyquery) - { - PyQuery *pyq = (PyQuery *)pyquery; - signal_add_last_data("query destroyed", query_cleanup, pyq); - pyq->cleanup_installed = 1; - } - - return pyquery; -} - -int query_object_init(void) -{ - g_return_val_if_fail(py_module != NULL, 0); - - if (PyType_Ready(&PyQueryType) < 0) - return 0; - - Py_INCREF(&PyQueryType); - PyModule_AddObject(py_module, "Query", (PyObject *)&PyQueryType); - - return 1; -} diff --git a/objects/query-object.h b/objects/query-object.h deleted file mode 100644 index 844ce55..0000000 --- a/objects/query-object.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef _QUERY_OBJECT_H_ -#define _QUERY_OBJECT_H_ - -#include -#include "window-item-object.h" - -/* forward */ -struct _QUERY_REC; - -typedef struct -{ - PyWindowItem_HEAD(struct _QUERY_REC) -} PyQuery; - -extern PyTypeObject PyQueryType; - -int query_object_init(void); -PyObject *pyquery_new(void *query); -#define pyquery_check(op) PyObject_TypeCheck(op, &PyQueryType) - -#endif diff --git a/objects/rawlog-object.c b/objects/rawlog-object.c deleted file mode 100644 index 340d60a..0000000 --- a/objects/rawlog-object.c +++ /dev/null @@ -1,323 +0,0 @@ -#include -#include "pyirssi_irc.h" -#include "pymodule.h" -#include "rawlog-object.h" -#include "pycore.h" - -/* monitor "????" signal */ -static void rawlog_cleanup(RAWLOG_REC *ban) -{ - /* XXX */ -} - -static void PyRawlog_dealloc(PyRawlog *self) -{ - self->ob_type->tp_free((PyObject*)self); -} - -static PyObject *PyRawlog_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyRawlog *self; - - self = (PyRawlog *)type->tp_alloc(type, 0); - if (!self) - return NULL; - - return (PyObject *)self; -} - -/* XXX: Need function to create the rawlog */ - -/* Getters */ -PyDoc_STRVAR(PyRawlog_logging_doc, - "The raw log is being written to file currently." -); -static PyObject *PyRawlog_logging_get(PyRawlog *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyBool_FromLong(self->data->logging); -} - -PyDoc_STRVAR(PyRawlog_nlines_doc, - "Number of lines in rawlog." -); -static PyObject *PyRawlog_nlines_get(PyRawlog *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyInt_FromLong(self->data->nlines); -} - -/* specialized getters/setters */ -static PyGetSetDef PyRawlog_getseters[] = { - {"logging", (getter)PyRawlog_logging_get, NULL, - PyRawlog_logging_doc, NULL}, - {"nlines", (getter)PyRawlog_nlines_get, NULL, - PyRawlog_nlines_doc, NULL}, - {NULL} -}; - -/* Methods */ -PyDoc_STRVAR(PyRawlog_get_lines_doc, - "get_lines() -> list of str\n" - "\n" - "Return a list of lines for rawlog.\n" -); -static PyObject *PyRawlog_get_lines(PyRawlog *self, PyObject *args) -{ - PyObject *lines = NULL; - GSList *node; - - RET_NULL_IF_INVALID(self->data); - - lines = PyList_New(0); - if (!lines) - return NULL; - - for (node = self->data->lines; node; node = node->next) - { - int ret; - PyObject *line = PyString_FromString(node->data); - - if (!line) - { - Py_XDECREF(lines); - return NULL; - } - - ret = PyList_Append(lines, line); - Py_DECREF(line); - if (ret != 0) - { - Py_XDECREF(lines); - return NULL; - } - } - - return lines; -} - -PyDoc_STRVAR(PyRawlog_destroy_doc, - "destroy() -> None\n" - "\n" - "Destroy rawlog\n" -); -static PyObject *PyRawlog_destroy(PyRawlog *self, PyObject *args) -{ - RET_NULL_IF_INVALID(self->data); - - rawlog_destroy(self->data); - - /*XXX: what about signal handler ? */ - self->data = NULL; - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyRawlog_input_doc, - "input(str) -> None\n" - "\n" - "Send str to rawlog as input text.\n" -); -static PyObject *PyRawlog_input(PyRawlog *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"str", NULL}; - char *str = ""; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &str)) - return NULL; - - rawlog_input(self->data, str); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyRawlog_output_doc, - "output(str) -> None\n" - "\n" - "Send str to rawlog as output text.\n" -); -static PyObject *PyRawlog_output(PyRawlog *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"str", NULL}; - char *str = ""; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &str)) - return NULL; - - rawlog_output(self->data, str); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyRawlog_redirect_doc, - "redirect(str) -> None\n" - "\n" - "Send str to rawlog as redirection text." -); -static PyObject *PyRawlog_redirect(PyRawlog *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"str", NULL}; - char *str = ""; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &str)) - return NULL; - - rawlog_redirect(self->data, str); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyRawlog_open_doc, - "open(fname) -> None\n" - "\n" - "Start logging new messages in rawlog to specified file.\n" -); -static PyObject *PyRawlog_open(PyRawlog *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"fname", NULL}; - char *fname = ""; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &fname)) - return NULL; - - rawlog_open(self->data, fname); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyRawlog_close_doc, - "close() -> None\n" - "\n" - "Stop logging to file\n" -); -static PyObject *PyRawlog_close(PyRawlog *self, PyObject *args) -{ - RET_NULL_IF_INVALID(self->data); - - rawlog_close(self->data); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyRawlog_save_doc, - "save(fname) -> None\n" - "\n" - "Save the current rawlog history to specified file.\n" -); -static PyObject *PyRawlog_save(PyRawlog *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"fname", NULL}; - char *fname = ""; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &fname)) - return NULL; - - rawlog_save(self->data, fname); - - Py_RETURN_NONE; -} -/* Methods for object */ -static PyMethodDef PyRawlog_methods[] = { - {"get_lines", (PyCFunction)PyRawlog_get_lines, METH_NOARGS, - PyRawlog_get_lines_doc}, - {"destroy", (PyCFunction)PyRawlog_destroy, METH_NOARGS, - PyRawlog_destroy_doc}, - {"input", (PyCFunction)PyRawlog_input, METH_VARARGS | METH_KEYWORDS, - PyRawlog_input_doc}, - {"output", (PyCFunction)PyRawlog_output, METH_VARARGS | METH_KEYWORDS, - PyRawlog_output_doc}, - {"redirect", (PyCFunction)PyRawlog_redirect, METH_VARARGS | METH_KEYWORDS, - PyRawlog_redirect_doc}, - {"open", (PyCFunction)PyRawlog_open, METH_VARARGS | METH_KEYWORDS, - PyRawlog_open_doc}, - {"close", (PyCFunction)PyRawlog_close, METH_NOARGS, - PyRawlog_close_doc}, - {"save", (PyCFunction)PyRawlog_save, METH_VARARGS | METH_KEYWORDS, - PyRawlog_save_doc}, - {NULL} /* Sentinel */ -}; - -PyTypeObject PyRawlogType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "Rawlog", /*tp_name*/ - sizeof(PyRawlog), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)PyRawlog_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - "PyRawlog objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - PyRawlog_methods, /* tp_methods */ - 0, /* tp_members */ - PyRawlog_getseters, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - PyRawlog_new, /* tp_new */ -}; - - -/* window item wrapper factory function */ -PyObject *pyrawlog_new(void *rlog) -{ - PyRawlog *pyrlog; - - pyrlog = py_inst(PyRawlog, PyRawlogType); - if (!pyrlog) - return NULL; - - pyrlog->data = rlog; - - return (PyObject *)pyrlog; -} - -int rawlog_object_init(void) -{ - g_return_val_if_fail(py_module != NULL, 0); - - if (PyType_Ready(&PyRawlogType) < 0) - return 0; - - Py_INCREF(&PyRawlogType); - PyModule_AddObject(py_module, "Rawlog", (PyObject *)&PyRawlogType); - - return 1; -} diff --git a/objects/rawlog-object.h b/objects/rawlog-object.h deleted file mode 100644 index d2a9a2d..0000000 --- a/objects/rawlog-object.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef _RAWLOG_OBJECT_H_ -#define _RAWLOG_OBJECT_H_ - -#include -#include "base-objects.h" - -/* forward */ -struct _RAWLOG_REC; - -typedef struct -{ - PyIrssiFinal_HEAD(struct _RAWLOG_REC) - int owned; -} PyRawlog; - -extern PyTypeObject PyRawlogType; - -int rawlog_object_init(void); -PyObject *pyrawlog_new(void *rlog); -#define pyrawlog_check(op) PyObject_TypeCheck(op, &PyRawlogType) - -#endif diff --git a/objects/reconnect-object.c b/objects/reconnect-object.c deleted file mode 100644 index 6483242..0000000 --- a/objects/reconnect-object.c +++ /dev/null @@ -1,151 +0,0 @@ -#include -#include "pyirssi.h" -#include "pymodule.h" -#include "pycore.h" -#include "factory.h" -#include "reconnect-object.h" - -/*XXX: no Reconnect cleanup/destroy sig. Maybe value copy the two members? */ - -static void PyReconnect_dealloc(PyReconnect *self) -{ - Py_XDECREF(self->connect); - self->ob_type->tp_free((PyObject*)self); -} - -static PyObject *PyReconnect_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyReconnect *self; - - self = (PyReconnect *)type->tp_alloc(type, 0); - if (!self) - return NULL; - - return (PyObject *)self; -} - -/* Getters */ -PyDoc_STRVAR(PyReconnect_tag_doc, - "Unique numeric tag" -); -static PyObject *PyReconnect_tag_get(PyReconnect *self, void *closure) -{ - RECONNECT_REC *data = self->data; - RET_NULL_IF_INVALID(self->data); - - return PyInt_FromLong(data->tag); -} - -PyDoc_STRVAR(PyReconnect_next_connect_doc, - "Unix time stamp when the next connection occurs" -); -static PyObject *PyReconnect_next_connect_get(PyReconnect *self, void *closure) -{ - RECONNECT_REC *data = self->data; - RET_NULL_IF_INVALID(self->data); - - return PyLong_FromUnsignedLong(data->next_connect); -} - -PyDoc_STRVAR(PyReconnect_connect_doc, - "Connection object" -); -static PyObject *PyReconnect_connect_get(PyReconnect *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_OBJ_OR_NONE(self->connect); -} - -/* specialized getters/setters */ -static PyGetSetDef PyReconnect_getseters[] = { - {"tag", (getter)PyReconnect_tag_get, NULL, - PyReconnect_tag_doc, NULL}, - {"next_connect", (getter)PyReconnect_next_connect_get, NULL, - PyReconnect_next_connect_doc, NULL}, - {"connect", (getter)PyReconnect_connect_get, NULL, - PyReconnect_connect_doc, NULL}, - {NULL} -}; - -/* Methods for object */ -static PyMethodDef PyReconnect_methods[] = { - {NULL} /* Sentinel */ -}; - -PyTypeObject PyReconnectType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "Reconnect", /*tp_name*/ - sizeof(PyReconnect), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)PyReconnect_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - "PyReconnect objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - PyReconnect_methods, /* tp_methods */ - 0, /* tp_members */ - PyReconnect_getseters, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - PyReconnect_new, /* tp_new */ -}; - - -/* window item wrapper factory function */ -PyObject *pyreconnect_new(void *recon) -{ - RECONNECT_REC *rec = recon; - PyObject *connect; - PyReconnect *pyrecon; - - /* XXX: get a managed connect because there's no signals to manage reconnect */ - connect = py_irssi_chat_new(rec->conn, 1); - if (!connect) - return NULL; - - pyrecon = py_inst(PyReconnect, PyReconnectType); - if (!pyrecon) - return NULL; - - pyrecon->data = recon; - pyrecon->connect = connect; - - return (PyObject *)pyrecon; -} - -int reconnect_object_init(void) -{ - g_return_val_if_fail(py_module != NULL, 0); - - if (PyType_Ready(&PyReconnectType) < 0) - return 0; - - Py_INCREF(&PyReconnectType); - PyModule_AddObject(py_module, "Reconnect", (PyObject *)&PyReconnectType); - - return 1; -} diff --git a/objects/reconnect-object.h b/objects/reconnect-object.h deleted file mode 100644 index ec0b094..0000000 --- a/objects/reconnect-object.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef _RECONNECT_OBJECT_H_ -#define _RECONNECT_OBJECT_H_ - -#include -#include "base-objects.h" - -/*XXX: no Reconnect cleanup/destroy sig. Maybe value copy the two members? */ -typedef struct -{ - PyIrssiFinal_HEAD(void) - PyObject *connect; -} PyReconnect; - -extern PyTypeObject PyReconnectType; - -int reconnect_object_init(void); -PyObject *pyreconnect_new(void *recon); -#define pyreconnect_check(op) PyObject_TypeCheck(op, &PyReconnectType) - -#endif diff --git a/objects/server-object.c b/objects/server-object.c deleted file mode 100644 index 31415b8..0000000 --- a/objects/server-object.c +++ /dev/null @@ -1,807 +0,0 @@ -#include -#include "pymodule.h" -#include "factory.h" -#include "pyirssi.h" -#include "pycore.h" -#include "pyutils.h" - -static void server_cleanup(SERVER_REC *server) -{ - PyServer *pyserver = signal_get_user_data(); - - if (server == pyserver->data) - { - if (pyserver->connect) - ((PyConnect *)pyserver->connect)->data = NULL; - - if (pyserver->rawlog) - ((PyRawlog *)pyserver->rawlog)->data = NULL; - - pyserver->data = NULL; - pyserver->cleanup_installed = 0; - signal_remove_data("server disconnected", server_cleanup, pyserver); - } -} - -static void PyServer_dealloc(PyServer *self) -{ - if (self->cleanup_installed) - signal_remove_data("server disconnected", server_cleanup, self); - - Py_XDECREF(self->connect); - Py_XDECREF(self->rawlog); - - self->ob_type->tp_free((PyObject*)self); -} - -/* Getters */ -PyDoc_STRVAR(PyServer_connect_time_doc, - "Time when connect() to server finished" -); -static PyObject *PyServer_connect_time_get(PyServer *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyLong_FromLong(self->data->connect_time); -} - -PyDoc_STRVAR(PyServer_real_connect_time_doc, - "Time when server sent 'connected' message" -); -static PyObject *PyServer_real_connect_time_get(PyServer *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyLong_FromLong(self->data->real_connect_time); -} - -PyDoc_STRVAR(PyServer_tag_doc, - "Unique server tag" -); -static PyObject *PyServer_tag_get(PyServer *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->tag); -} - -PyDoc_STRVAR(PyServer_nick_doc, - "Current nick" -); -static PyObject *PyServer_nick_get(PyServer *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->nick); -} - -PyDoc_STRVAR(PyServer_connected_doc, - "Is connection finished? 1|0" -); -static PyObject *PyServer_connected_get(PyServer *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyBool_FromLong(self->data->connected); -} - -PyDoc_STRVAR(PyServer_connection_lost_doc, - "Did we lose the connection (1) or was the connection just /DISCONNECTed (0)" -); -static PyObject *PyServer_connection_lost_get(PyServer *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyBool_FromLong(self->data->connection_lost); -} - -PyDoc_STRVAR(PyServer_rawlog_doc, - "Rawlog object for the server" -); -static PyObject *PyServer_rawlog_get(PyServer *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_OBJ_OR_NONE(self->rawlog); -} - -PyDoc_STRVAR(PyServer_connect_doc, - "Connect object for the server" -); -static PyObject *PyServer_connect_get(PyServer *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_OBJ_OR_NONE(self->connect); -} - -PyDoc_STRVAR(PyServer_version_doc, - "Server version" -); -static PyObject *PyServer_version_get(PyServer *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->version); -} - -PyDoc_STRVAR(PyServer_last_invite_doc, - "Last channel we were invited to" -); -static PyObject *PyServer_last_invite_get(PyServer *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->last_invite); -} - -PyDoc_STRVAR(PyServer_server_operator_doc, - "Are we server operator (IRC op) 1|0" -); -static PyObject *PyServer_server_operator_get(PyServer *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyBool_FromLong(self->data->server_operator); -} - -PyDoc_STRVAR(PyServer_usermode_away_doc, - "Are we marked as away? 1|0" -); -static PyObject *PyServer_usermode_away_get(PyServer *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyBool_FromLong(self->data->usermode_away); -} - -PyDoc_STRVAR(PyServer_away_reason_doc, - "Away reason message" -); -static PyObject *PyServer_away_reason_get(PyServer *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->away_reason); -} - -PyDoc_STRVAR(PyServer_banned_doc, - "Were we banned from this server? 1|0" -); -static PyObject *PyServer_banned_get(PyServer *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyBool_FromLong(self->data->banned); -} - -PyDoc_STRVAR(PyServer_lag_doc, - "Current lag to server in milliseconds" -); -static PyObject *PyServer_lag_get(PyServer *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyInt_FromLong(self->data->lag); -} - -static PyGetSetDef PyServer_getseters[] = { - {"connect_time", (getter)PyServer_connect_time_get, NULL, - PyServer_connect_time_doc, NULL}, - {"real_connect_time", (getter)PyServer_real_connect_time_get, NULL, - PyServer_real_connect_time_doc, NULL}, - {"tag", (getter)PyServer_tag_get, NULL, - PyServer_tag_doc, NULL}, - {"nick", (getter)PyServer_nick_get, NULL, - PyServer_nick_doc, NULL}, - {"connected", (getter)PyServer_connected_get, NULL, - PyServer_connected_doc, NULL}, - {"connection_lost", (getter)PyServer_connection_lost_get, NULL, - PyServer_connection_lost_doc, NULL}, - {"rawlog", (getter)PyServer_rawlog_get, NULL, - PyServer_rawlog_doc, NULL}, - {"connect", (getter)PyServer_connect_get, NULL, - PyServer_connect_doc, NULL}, - {"version", (getter)PyServer_version_get, NULL, - PyServer_version_doc, NULL}, - {"last_invite", (getter)PyServer_last_invite_get, NULL, - PyServer_last_invite_doc, NULL}, - {"server_operator", (getter)PyServer_server_operator_get, NULL, - PyServer_server_operator_doc, NULL}, - {"usermode_away", (getter)PyServer_usermode_away_get, NULL, - PyServer_usermode_away_doc, NULL}, - {"away_reason", (getter)PyServer_away_reason_get, NULL, - PyServer_away_reason_doc, NULL}, - {"banned", (getter)PyServer_banned_get, NULL, - PyServer_banned_doc, NULL}, - {"lag", (getter)PyServer_lag_get, NULL, - PyServer_lag_doc, NULL}, - {NULL} -}; - -/* Methods */ -PyDoc_STRVAR(print_doc, - "prnt(channel, str, level) -> None\n" - "\n" - "Print to server\n" -); -static PyObject *PyServer_prnt(PyServer *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"channel", "str", "level", NULL}; - char *str, *channel; - int level = MSGLEVEL_CLIENTNOTICE; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss|i", kwlist, &channel, &str, &level)) - return NULL; - - printtext_string(self->data, channel, level, str); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(command_doc, - "command(cmd) -> None\n" - "\n" - "Send command\n" -); -static PyObject *PyServer_command(PyServer *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"cmd", NULL}; - char *cmd; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &cmd)) - return NULL; - - py_command(cmd, self->data, NULL); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(disconnect_doc, - "disconnect() -> None\n" - "\n" - "Disconnect from server\n" -); -static PyObject *PyServer_disconnect(PyServer *self, PyObject *args) -{ - RET_NULL_IF_INVALID(self->data); - - server_disconnect(self->data); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(isnickflag_doc, - "isnickflag(flag) -> bool\n" - "\n" - "Returns True if flag is a nick mode flag (@, + or % in IRC)\n" -); -static PyObject *PyServer_isnickflag(PyServer *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"flag", NULL}; - char flag; - int ret; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "c", kwlist, &flag)) - return NULL; - - ret = self->data->isnickflag(self->data, flag); - - return PyBool_FromLong(ret); -} - -PyDoc_STRVAR(ischannel_doc, - "ischannel(data) -> bool\n" - "\n" - "Returns True if start of `data' seems to mean channel.\n" -); -static PyObject *PyServer_ischannel(PyServer *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"data", NULL}; - char *data; - int ret; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &data)) - return NULL; - - ret = self->data->ischannel(self->data, data); - - return PyBool_FromLong(ret); -} - -PyDoc_STRVAR(get_nick_flags_doc, - "get_nick_flags() -> str\n" - "\n" - "Returns nick flag characters in order: op, voice, halfop (\"@+%\") in IRC\n" -); -static PyObject *PyServer_get_nick_flags(PyServer *self, PyObject *args) -{ - char *ret; - - RET_NULL_IF_INVALID(self->data); - - ret = (char *)self->data->get_nick_flags(self->data); - - return PyString_FromString(ret); -} - -PyDoc_STRVAR(send_message_doc, - "send_message(target, msg, target_type) -> None\n" - "\n" - "Sends a message to nick/channel. target_type 0 = channel, 1 = nick\n" -); -static PyObject *PyServer_send_message(PyServer *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"target", "msg", "target_type", NULL}; - char *target, *msg; - int target_type; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "ssi", kwlist, &target, &msg, &target_type)) - return NULL; - - self->data->send_message(self->data, target, msg, target_type); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(channels_join_doc, - "channels_join(channels, automatic=False) -> None\n" - "\n" - "Join to channels in server. `channels' may also contain keys for\n" - "channels just like with /JOIN command. `automatic' specifies if this\n" - "channel was joined 'automatically' or if it was joined because join\n" - "was requested by user. If channel join is 'automatic', irssi doesn't\n" - "jump to the window where the channel was joined.\n" -); -static PyObject *PyServer_channels_join(PyServer *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"channels", "automatic", NULL}; - char *channels; - int automatic = 0; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|i", kwlist, &channels, &automatic)) - return NULL; - - self->data->channels_join(self->data, channels, automatic); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyServer_window_item_find_doc, - "window_item_find(name) -> WindowItem object or None\n" - "\n" - "Find window item that matches best to given arguments\n" -); -static PyObject *PyServer_window_item_find(PyServer *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"name", NULL}; - char *name = ""; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &name)) - return NULL; - - return py_irssi_chat_new(window_item_find(self->data, name), 1); -} - -PyDoc_STRVAR(PyServer_window_find_item_doc, - "window_find_item(name) -> Window object or None\n" - "\n" - "Find window which contains window item with specified name/server\n" -); -static PyObject *PyServer_window_find_item(PyServer *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"name", NULL}; - char *name = ""; - WINDOW_REC *win; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &name)) - return NULL; - - win = window_find_item(self->data, name); - if (win) - return pywindow_new(win); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyServer_window_find_level_doc, - "window_find_level(level) -> Window object or None\n" - "\n" - "Find window with level\n" -); -static PyObject *PyServer_window_find_level(PyServer *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"level", NULL}; - int level = 0; - WINDOW_REC *win; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, - &level)) - return NULL; - - win = window_find_level(self->data, level); - if (win) - return pywindow_new(win); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyServer_window_find_closest_doc, - "window_find_closest(name, level) -> Window object or None\n" - "\n" - "Find window that matches best to given arguments. `name' can be either\n" - "window name or name of one of the window items.\n" -); -static PyObject *PyServer_window_find_closest(PyServer *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"name", "level", NULL}; - char *name = ""; - int level = 0; - WINDOW_REC *win; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "si", kwlist, - &name, &level)) - return NULL; - - win = window_find_closest(self->data, name, level); - if (win) - return pywindow_new(win); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyServer_channels_doc, - "channels() -> list of Channel objects\n" - "\n" - "Return list of channels for server\n" -); -static PyObject *PyServer_channels(PyServer *self, PyObject *args) -{ - RET_NULL_IF_INVALID(self->data); - - return py_irssi_chatlist_new(self->data->channels, 1); -} - -PyDoc_STRVAR(PyServer_channel_find_doc, - "channel_find(name) -> Channel object or None\n" - "\n" - "Find channel from this server\n" -); -static PyObject *PyServer_channel_find(PyServer *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"name", NULL}; - char *name = ""; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &name)) - return NULL; - - return py_irssi_chat_new(channel_find(self->data, name), 1); -} - -PyDoc_STRVAR(PyServer_nicks_get_same_doc, - "nicks_get_same(nick)\n" - "\n" - "Return all nick objects in all channels in server. List is in format:\n" - "[(Channel, Nick), (Channel, Nick), ...]\n" -); -static PyObject *PyServer_nicks_get_same(PyServer *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"nick", NULL}; - char *nick = ""; - GSList *list, *node; - PyObject *pylist = NULL; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &nick)) - return NULL; - - pylist = PyList_New(0); - if (!pylist) - return NULL; - - list = nicklist_get_same(self->data, nick); - for (node = list; node != NULL; node = node->next->next) - { - int ret; - PyObject *tup; - - tup = Py_BuildValue("(NN)", - py_irssi_chat_new(node->data, 1), - py_irssi_chat_new(node->next->data, 1)); - if (!tup) - { - Py_XDECREF(pylist); - return NULL; - } - - ret = PyList_Append(pylist, tup); - Py_DECREF(tup); - if (ret != 0) - { - Py_XDECREF(pylist); - return NULL; - } - } - - return pylist; -} - -PyDoc_STRVAR(PyServer_queries_doc, - "queries() -> list of Query objects\n" - "\n" - "Return a list of queries for server.\n" -); -static PyObject *PyServer_queries(PyServer *self, PyObject *args) -{ - RET_NULL_IF_INVALID(self->data); - - return py_irssi_chatlist_new(self->data->queries, 1); -} - -PyDoc_STRVAR(PyServer_query_find_doc, - "query_find(nick) -> Query object or None\n" - "\n" - "Find a query on this server.\n" -); -static PyObject *PyServer_query_find(PyServer *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"nick", NULL}; - char *nick = ""; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &nick)) - return NULL; - - return py_irssi_chat_new(query_find(self->data, nick), 1); -} - -PyDoc_STRVAR(PyServer_mask_match_doc, - "mask_match(mask, nick, user, host) -> bool\n" - "\n" - "Return true if mask matches nick!user@host\n" -); -static PyObject *PyServer_mask_match(PyServer *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"mask", "nick", "user", "host", NULL}; - char *mask = ""; - char *nick = ""; - char *user = ""; - char *host = ""; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "ssss", kwlist, - &mask, &nick, &user, &host)) - return NULL; - - return PyBool_FromLong(mask_match(self->data, mask, nick, user, host)); -} - -PyDoc_STRVAR(PyServer_mask_match_address_doc, - "mask_match_address(mask, nick, address) -> bool\n" - "\n" - "Return True if mask matches nick!address\n" -); -static PyObject *PyServer_mask_match_address(PyServer *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"mask", "nick", "address", NULL}; - char *mask = ""; - char *nick = ""; - char *address = ""; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "sss", kwlist, - &mask, &nick, &address)) - return NULL; - - return PyBool_FromLong(mask_match_address(self->data, mask, nick, address)); -} - -PyDoc_STRVAR(PyServer_masks_match_doc, - "masks_match(masks, nick, address) -> bool\n" - "\n" - "Return True if any mask in the masks (string separated by spaces)\n" - "matches nick!address\n" -); -static PyObject *PyServer_masks_match(PyServer *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"masks", "nick", "address", NULL}; - char *masks = ""; - char *nick = ""; - char *address = ""; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "sss", kwlist, - &masks, &nick, &address)) - return NULL; - - return PyBool_FromLong(masks_match(self->data, masks, nick, address)); -} - -PyDoc_STRVAR(PyServer_ignore_check_doc, - "ignore_check(nick, host, channel, text, level) -> bool\n" - "\n" - "Return True if ignore matches\n" -); -static PyObject *PyServer_ignore_check(PyServer *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"nick", "host", "channel", "text", "level", NULL}; - char *nick = ""; - char *host = ""; - char *channel = ""; - char *text = ""; - int level = 0; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "ssssi", kwlist, - &nick, &host, &channel, &text, &level)) - return NULL; - - return PyBool_FromLong(ignore_check(self->data, - nick, host, channel, text, level)); -} - -/* Methods for object */ -static PyMethodDef PyServer_methods[] = { - {"prnt", (PyCFunction)PyServer_prnt, METH_VARARGS | METH_KEYWORDS, - print_doc}, - {"command", (PyCFunction)PyServer_command, METH_VARARGS | METH_KEYWORDS, - command_doc}, - {"disconnect", (PyCFunction)PyServer_disconnect, METH_NOARGS, - disconnect_doc}, - {"isnickflag", (PyCFunction)PyServer_isnickflag, METH_VARARGS | METH_KEYWORDS, - isnickflag_doc}, - {"ischannel", (PyCFunction)PyServer_ischannel, METH_VARARGS | METH_KEYWORDS, - ischannel_doc}, - {"get_nick_flags", (PyCFunction)PyServer_get_nick_flags, METH_NOARGS, - get_nick_flags_doc}, - {"send_message", (PyCFunction)PyServer_send_message, METH_VARARGS | METH_KEYWORDS, - send_message_doc}, - {"channels_join", (PyCFunction)PyServer_channels_join, METH_VARARGS | METH_KEYWORDS, - channels_join_doc}, - {"window_item_find", (PyCFunction)PyServer_window_item_find, METH_VARARGS | METH_KEYWORDS, - PyServer_window_item_find_doc}, - {"window_find_item", (PyCFunction)PyServer_window_find_item, METH_VARARGS | METH_KEYWORDS, - PyServer_window_find_item_doc}, - {"window_find_level", (PyCFunction)PyServer_window_find_level, METH_VARARGS | METH_KEYWORDS, - PyServer_window_find_level_doc}, - {"window_find_closest", (PyCFunction)PyServer_window_find_closest, METH_VARARGS | METH_KEYWORDS, - PyServer_window_find_closest_doc}, - {"channels", (PyCFunction)PyServer_channels, METH_NOARGS, - PyServer_channels_doc}, - {"channel_find", (PyCFunction)PyServer_channel_find, METH_VARARGS | METH_KEYWORDS, - PyServer_channel_find_doc}, - {"nicks_get_same", (PyCFunction)PyServer_nicks_get_same, METH_VARARGS | METH_KEYWORDS, - PyServer_nicks_get_same_doc}, - {"queries", (PyCFunction)PyServer_queries, METH_NOARGS, - PyServer_queries_doc}, - {"query_find", (PyCFunction)PyServer_query_find, METH_VARARGS | METH_KEYWORDS, - PyServer_query_find_doc}, - {"mask_match", (PyCFunction)PyServer_mask_match, METH_VARARGS | METH_KEYWORDS, - PyServer_mask_match_doc}, - {"mask_match_address", (PyCFunction)PyServer_mask_match_address, METH_VARARGS | METH_KEYWORDS, - PyServer_mask_match_address_doc}, - {"masks_match", (PyCFunction)PyServer_masks_match, METH_VARARGS | METH_KEYWORDS, - PyServer_masks_match_doc}, - {"ignore_check", (PyCFunction)PyServer_ignore_check, METH_VARARGS | METH_KEYWORDS, - PyServer_ignore_check_doc}, - {NULL} /* Sentinel */ -}; - -PyTypeObject PyServerType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "Server", /*tp_name*/ - sizeof(PyServer), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)PyServer_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - "PyServer objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - PyServer_methods, /* tp_methods */ - 0, /* tp_members */ - PyServer_getseters, /* tp_getset */ - &PyIrssiChatBaseType, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ -}; - - -/* server factory function - connect arg should point to a wrapped SERVER_CONNECT */ -PyObject *pyserver_sub_new(void *server, PyTypeObject *subclass) -{ - static const char *SERVER_TYPE = "SERVER"; - SERVER_REC *srec = server; - PyServer *pyserver = NULL; - PyObject *rawlog = NULL; - PyObject *connect = NULL; - - g_return_val_if_fail(server != NULL, NULL); - - connect = py_irssi_chat_new(srec->connrec, 0); - if (!connect) - return NULL; - - /* FIXME */ - /* - if (srec->rawlog) - { - rawlog = pyrawlog_new(srec->rawlog); - if (!rawlog) - return NULL; - } - */ - - pyserver = py_instp(PyServer, subclass); - if (!pyserver) - return NULL; - - pyserver->base_name = SERVER_TYPE; - pyserver->data = server; - signal_add_last_data("server disconnected", server_cleanup, pyserver); - pyserver->cleanup_installed = 1; - pyserver->rawlog = rawlog; - pyserver->connect = connect; - - return (PyObject *)pyserver; -} - -PyObject *pyserver_new(void *server) -{ - return pyserver_sub_new(server, &PyServerType); -} - -int server_object_init(void) -{ - g_return_val_if_fail(py_module != NULL, 0); - - if (PyType_Ready(&PyServerType) < 0) - return 0; - - Py_INCREF(&PyServerType); - PyModule_AddObject(py_module, "Server", (PyObject *)&PyServerType); - - return 1; -} diff --git a/objects/server-object.h b/objects/server-object.h deleted file mode 100644 index 0703f47..0000000 --- a/objects/server-object.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef _SERVER_OBJECT_H_ -#define _SERVER_OBJECT_H_ - -#include -#include "base-objects.h" - -/* forward */ -struct _SERVER_REC; - -#define PyServer_HEAD(type) \ - PyIrssi_HEAD(type) \ - PyObject *connect; \ - PyObject *rawlog; - -typedef struct -{ - PyServer_HEAD(struct _SERVER_REC) -} PyServer; - -extern PyTypeObject PyServerType; - -int server_object_init(void); -PyObject *pyserver_sub_new(void *server, PyTypeObject *subclass); -PyObject *pyserver_new(void *server); - -#define pyserver_check(op) PyObject_TypeCheck(op, &PyServerType) - -#endif diff --git a/objects/statusbar-item-object.c b/objects/statusbar-item-object.c deleted file mode 100644 index f6768af..0000000 --- a/objects/statusbar-item-object.c +++ /dev/null @@ -1,253 +0,0 @@ -#include -#include "pyirssi.h" -#include "pymodule.h" -#include "factory.h" -#include "statusbar-item-object.h" - -/* monitor "statusbar item destroyed" signal */ -static void statusbar_item_cleanup(SBAR_ITEM_REC *sbar_item) -{ - PyStatusbarItem *pysbar_item = signal_get_user_data(); - - if (sbar_item == pysbar_item->data) - { - pysbar_item->data = NULL; - pysbar_item->cleanup_installed = 0; - signal_remove_data("statusbar item_destroy", statusbar_item_cleanup, pysbar_item); - } -} - -static void PyStatusbarItem_dealloc(PyStatusbarItem *self) -{ - if (self->cleanup_installed) - signal_remove_data("sbar_itemlist remove", statusbar_item_cleanup, self); - - self->ob_type->tp_free((PyObject*)self); -} - -static PyObject *PyStatusbarItem_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyStatusbarItem *self; - - self = (PyStatusbarItem *)type->tp_alloc(type, 0); - if (!self) - return NULL; - - return (PyObject *)self; -} - -/* Getter */ -PyDoc_STRVAR(PyStatusbarItem_min_size_doc, - "min size" -); -static PyObject *PyStatusbarItem_min_size_get(PyStatusbarItem *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyInt_FromLong(self->data->min_size); -} - -PyDoc_STRVAR(PyStatusbarItem_max_size_doc, - "max size" -); -static PyObject *PyStatusbarItem_max_size_get(PyStatusbarItem *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyInt_FromLong(self->data->max_size); -} - -PyDoc_STRVAR(PyStatusbarItem_xpos_doc, - "x position" -); -static PyObject *PyStatusbarItem_xpos_get(PyStatusbarItem *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyInt_FromLong(self->data->xpos); -} - -PyDoc_STRVAR(PyStatusbarItem_size_doc, - "size" -); -static PyObject *PyStatusbarItem_size_get(PyStatusbarItem *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyInt_FromLong(self->data->size); -} - -PyDoc_STRVAR(PyStatusbarItem_window_doc, - "parent window for statusbar item" -); -static PyObject *PyStatusbarItem_window_get(PyStatusbarItem *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_OBJ_OR_NONE(self->window); -} - -/* setters */ -static int py_setint(int *iv, PyObject *value) -{ - int tmp; - - if (value == NULL) - { - PyErr_SetString(PyExc_AttributeError, "can't delete member"); - return -1; - } - - if (!PyInt_Check(value)) - { - PyErr_SetString(PyExc_TypeError, "value must be int"); - return -1; - } - - tmp = PyInt_AsLong(value); - if (PyErr_Occurred()) - return -1; - - *iv = tmp; - - return 0; -} - -static int PyStatusbarItem_min_size_set(PyStatusbarItem *self, PyObject *value, void *closure) -{ - return py_setint(&self->data->min_size, value); -} - -static int PyStatusbarItem_max_size_set(PyStatusbarItem *self, PyObject *value, void *closure) -{ - return py_setint(&self->data->max_size, value); -} - -/* specialized getters/setters */ -static PyGetSetDef PyStatusbarItem_getseters[] = { - {"min_size", (getter)PyStatusbarItem_min_size_get, (setter)PyStatusbarItem_min_size_set, - PyStatusbarItem_min_size_doc, NULL}, - {"max_size", (getter)PyStatusbarItem_max_size_get, (setter)PyStatusbarItem_max_size_set, - PyStatusbarItem_max_size_doc, NULL}, - {"xpos", (getter)PyStatusbarItem_xpos_get, NULL, - PyStatusbarItem_xpos_doc, NULL}, - {"size", (getter)PyStatusbarItem_size_get, NULL, - PyStatusbarItem_size_doc, NULL}, - {"window", (getter)PyStatusbarItem_window_get, NULL, - PyStatusbarItem_window_doc, NULL}, - {NULL} -}; - -/* Methods */ -PyDoc_STRVAR(PyStatusbarItem_default_handler_doc, - "default_handler(get_size_only, str=None, data="", escape_vars=True) -> None\n" - "\n" - "Run default handler of item to print to statusbar\n" -); -static PyObject *PyStatusbarItem_default_handler(PyStatusbarItem *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"get_size_only", "str", "data", "escape_vars", NULL}; - int get_size_only = 0; - char *str = NULL; - char *data = ""; - int escape_vars = TRUE; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "i|zsi", kwlist, - &get_size_only, &str, &data, &escape_vars)) - return NULL; - - if (str && !*str) - str = NULL; - - statusbar_item_default_handler(self->data, get_size_only, str, data, escape_vars); - - Py_RETURN_NONE; -} - -/* Methods for object */ -static PyMethodDef PyStatusbarItem_methods[] = { - {"default_handler", (PyCFunction)PyStatusbarItem_default_handler, METH_VARARGS | METH_KEYWORDS, - PyStatusbarItem_default_handler_doc}, - {NULL} /* Sentinel */ -}; - -PyTypeObject PyStatusbarItemType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "StatusbarItem", /*tp_name*/ - sizeof(PyStatusbarItem), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)PyStatusbarItem_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - "PyStatusbarItem objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - PyStatusbarItem_methods, /* tp_methods */ - 0, /* tp_members */ - PyStatusbarItem_getseters, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - PyStatusbarItem_new, /* tp_new */ -}; - - -/* sbar_item factory function */ -PyObject *pystatusbar_item_new(void *sbar_item) -{ - SBAR_ITEM_REC *si; - PyStatusbarItem *pysbar_item; - PyObject *window = NULL; - - si = sbar_item; - if (si->bar->parent_window) - { - window = pywindow_new(si->bar->parent_window); - if (!window) - return NULL; - } - - pysbar_item = py_inst(PyStatusbarItem, PyStatusbarItemType); - if (!pysbar_item) - return NULL; - - pysbar_item->window = window; - - pysbar_item->data = sbar_item; - pysbar_item->cleanup_installed = 1; - signal_add_last_data("statusbar item destroyed", statusbar_item_cleanup, pysbar_item); - - return (PyObject *)pysbar_item; -} - -int statusbar_item_object_init(void) -{ - g_return_val_if_fail(py_module != NULL, 0); - - if (PyType_Ready(&PyStatusbarItemType) < 0) - return 0; - - Py_INCREF(&PyStatusbarItemType); - PyModule_AddObject(py_module, "StatusbarItem", (PyObject *)&PyStatusbarItemType); - - return 1; -} diff --git a/objects/statusbar-item-object.h b/objects/statusbar-item-object.h deleted file mode 100644 index 19243f4..0000000 --- a/objects/statusbar-item-object.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef _SBAR_ITEM_OBJECT_H_ -#define _SBAR_ITEM_OBJECT_H_ - -#include -#include "base-objects.h" - -/* forward */ -struct SBAR_ITEM_REC; - -typedef struct -{ - PyIrssiFinal_HEAD(struct SBAR_ITEM_REC) - PyObject *window; -} PyStatusbarItem; - -extern PyTypeObject PyStatusbarItemType; - -int statusbar_item_object_init(void); -PyObject *pystatusbar_item_new(void *sbar_item); -#define pystatusbar_item_check(op) PyObject_TypeCheck(op, &PyStatusbarItemType) - -#endif diff --git a/objects/textdest-object.c b/objects/textdest-object.c deleted file mode 100644 index 2ad6523..0000000 --- a/objects/textdest-object.c +++ /dev/null @@ -1,285 +0,0 @@ -#include -#include "pyirssi_irc.h" -#include "pymodule.h" -#include "textdest-object.h" -#include "factory.h" -#include "pycore.h" - -static int pytextdest_setup(PyTextDest *pytdest, void *td, int owned); - -/* XXX: no cleanup signal for textdest */ -static void PyTextDest_dealloc(PyTextDest *self) -{ - Py_XDECREF(self->window); - Py_XDECREF(self->server); - - if (self->owned) - { - g_free((char*)self->data->target); - g_free(self->data); - } - - self->ob_type->tp_free((PyObject*)self); -} - -static PyObject *PyTextDest_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyTextDest *self; - - self = (PyTextDest *)type->tp_alloc(type, 0); - if (!self) - return NULL; - - return (PyObject *)self; -} - -/* init function to create the textdest */ -PyDoc_STRVAR(PyTextDest_doc, - "__init__(target, level=MSGLEVEL_CLIENTNOTICE, server=None, window=None)\n" - "\n" - "Create a TextDest\n" -); -static int PyTextDest_init(PyTextDest *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"target", "level", "server", "window", NULL}; - char *target; - int level = MSGLEVEL_CLIENTNOTICE; - PyObject *server = NULL, *window = NULL; - TEXT_DEST_REC *dest; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|ioo", kwlist, - &target, &level, &server, &window)) - return -1; - - if (server == Py_None) - server = NULL; - if (window == Py_None) - window = NULL; - - if (server && !pyserver_check(server)) - { - PyErr_Format(PyExc_TypeError, "arg 3 isnt server"); - return -1; - } - - if (window && !pywindow_check(window)) - { - PyErr_Format(PyExc_TypeError, "arg 4 isnt window"); - return -1; - } - - if (self->data) - { - PyErr_Format(PyExc_RuntimeError, "TextDest already wrapped"); - return -1; - } - - dest = g_new0(TEXT_DEST_REC, 1); - format_create_dest(dest, DATA(server), g_strdup(target), level, DATA(window)); - - if (!pytextdest_setup(self, dest, 1)) - return -1; - - return 0; -} - -/* Getters */ -PyDoc_STRVAR(PyTextDest_window_doc, - "Window where the text will be written" -); -static PyObject *PyTextDest_window_get(PyTextDest *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_OBJ_OR_NONE(self->window); -} - -PyDoc_STRVAR(PyTextDest_server_doc, - "Target server" -); -static PyObject *PyTextDest_server_get(PyTextDest *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_OBJ_OR_NONE(self->server); -} - -PyDoc_STRVAR(PyTextDest_target_doc, - "Target channel/query/etc name" -); -static PyObject *PyTextDest_target_get(PyTextDest *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->target); -} - -PyDoc_STRVAR(PyTextDest_level_doc, - "Text level" -); -static PyObject *PyTextDest_level_get(PyTextDest *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyInt_FromLong(self->data->level); -} - -PyDoc_STRVAR(PyTextDest_hilight_priority_doc, - "Priority for the hilighted text" -); -static PyObject *PyTextDest_hilight_priority_get(PyTextDest *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyInt_FromLong(self->data->hilight_priority); -} - -PyDoc_STRVAR(PyTextDest_hilight_color_doc, - "Color for the hilighted text" -); -static PyObject *PyTextDest_hilight_color_get(PyTextDest *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->hilight_color); -} - -/* specialized getters/setters */ -static PyGetSetDef PyTextDest_getseters[] = { - {"window", (getter)PyTextDest_window_get, NULL, - PyTextDest_window_doc, NULL}, - {"server", (getter)PyTextDest_server_get, NULL, - PyTextDest_server_doc, NULL}, - {"target", (getter)PyTextDest_target_get, NULL, - PyTextDest_target_doc, NULL}, - {"level", (getter)PyTextDest_level_get, NULL, - PyTextDest_level_doc, NULL}, - {"hilight_priority", (getter)PyTextDest_hilight_priority_get, NULL, - PyTextDest_hilight_priority_doc, NULL}, - {"hilight_color", (getter)PyTextDest_hilight_color_get, NULL, - PyTextDest_hilight_color_doc, NULL}, - {NULL} -}; - -/* Methods */ -PyDoc_STRVAR(PyTextDest_prnt_doc, - "prnt(str) -> None\n" - "\n" - "Print str to TextDest\n" -); -static PyObject *PyTextDest_prnt(PyTextDest *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"str", NULL}; - char *str = ""; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &str)) - return NULL; - - printtext_dest(self->data, "%s", str); - - Py_RETURN_NONE; -} - -/* Methods for object */ -static PyMethodDef PyTextDest_methods[] = { - {"prnt", (PyCFunction)PyTextDest_prnt, METH_VARARGS | METH_KEYWORDS, - PyTextDest_prnt_doc}, - {NULL} /* Sentinel */ -}; - -PyTypeObject PyTextDestType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "TextDest", /*tp_name*/ - sizeof(PyTextDest), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)PyTextDest_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - PyTextDest_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - PyTextDest_methods, /* tp_methods */ - 0, /* tp_members */ - PyTextDest_getseters, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)PyTextDest_init, /* tp_init */ - 0, /* tp_alloc */ - PyTextDest_new, /* tp_new */ -}; - -static int pytextdest_setup(PyTextDest *pytdest, void *td, int owned) -{ - PyObject *window, *server; - TEXT_DEST_REC *tdest = td; - - if (tdest->window) - { - window = pywindow_new(tdest->window); - if (!window) - return 0; - } - - server = py_irssi_chat_new(tdest->server, 1); - if (!server) - { - Py_DECREF(window); - return 0; - } - - pytdest->data = td; - pytdest->window = window; - pytdest->server = server; - pytdest->owned = owned; - - return 1; -} - -/* TextDest factory function */ -PyObject *pytextdest_new(void *td) -{ - PyTextDest *pytdest; - - pytdest = py_inst(PyTextDest, PyTextDestType); - if (!pytdest) - return NULL; - - if (!pytextdest_setup(pytdest, td, 0)) - { - Py_DECREF(pytdest); - return NULL; - } - - return (PyObject *)pytdest; -} - -int textdest_object_init(void) -{ - g_return_val_if_fail(py_module != NULL, 0); - - if (PyType_Ready(&PyTextDestType) < 0) - return 0; - - Py_INCREF(&PyTextDestType); - PyModule_AddObject(py_module, "TextDest", (PyObject *)&PyTextDestType); - - return 1; -} diff --git a/objects/textdest-object.h b/objects/textdest-object.h deleted file mode 100644 index 3e273e6..0000000 --- a/objects/textdest-object.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef _TEXTDEST_OBJECT_H_ -#define _TEXTDEST_OBJECT_H_ - -#include -#include "base-objects.h" - -/* forward */ -struct _TEXT_DEST_REC; - -typedef struct -{ - PyIrssiFinal_HEAD(struct _TEXT_DEST_REC) - PyObject *window; - PyObject *server; - int owned; -} PyTextDest; - -extern PyTypeObject PyTextDestType; - -int textdest_object_init(void); -PyObject *pytextdest_new(void *td); -#define pytextdest_check(op) PyObject_TypeCheck(op, &PyTextDestType) - -#endif diff --git a/objects/theme-object.c b/objects/theme-object.c deleted file mode 100644 index 0f12217..0000000 --- a/objects/theme-object.c +++ /dev/null @@ -1,195 +0,0 @@ -#include -#include "pyirssi.h" -#include "pymodule.h" -#include "theme-object.h" -#include "factory.h" -#include "pycore.h" - -/* monitor "theme destroyed" signal */ -static void theme_cleanup(THEME_REC *rec) -{ - PyTheme *pytheme = signal_get_user_data(); - if (pytheme->data == rec) - { - pytheme->data = NULL; - pytheme->cleanup_installed = 0; - signal_remove_data("theme destroyed", theme_cleanup, pytheme); - } -} - -static void PyTheme_dealloc(PyTheme *self) -{ - if (self->cleanup_installed) - signal_remove_data("theme destroyed", theme_cleanup, self); - - self->ob_type->tp_free((PyObject*)self); -} - -static PyObject *PyTheme_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyTheme *self; - - self = (PyTheme *)type->tp_alloc(type, 0); - if (!self) - return NULL; - - return (PyObject *)self; -} - -/* Getters */ -/* specialized getters/setters */ -static PyGetSetDef PyTheme_getseters[] = { - {NULL} -}; - -/* Methods */ -PyDoc_STRVAR(PyTheme_format_expand_doc, - "format_expand(format, flags=0) -> str or None\n" -); -static PyObject *PyTheme_format_expand(PyTheme *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"format", "flags", NULL}; - char *format = ""; - int flags = 0; - char *ret; - PyObject *pyret; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|i", kwlist, - &format, &flags)) - return NULL; - - if (flags == 0) - ret = theme_format_expand(self->data, format); - else - ret = theme_format_expand_data(self->data, (const char **)&format, 'n', 'n', - NULL, NULL, EXPAND_FLAG_ROOT | flags); - - if (ret) - { - pyret = PyString_FromString(ret); - g_free(ret); - return pyret; - } - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyTheme_get_format_doc, - "get_format(module, tag) -> str\n" -); -static PyObject *PyTheme_get_format(PyTheme *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"module", "tag", NULL}; - char *module = ""; - char *tag = ""; - THEME_REC *theme = self->data; - FORMAT_REC *formats; - MODULE_THEME_REC *modtheme; - int i; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss", kwlist, - &module, &tag)) - return NULL; - - formats = g_hash_table_lookup(default_formats, module); - if (!formats) - return PyErr_Format(PyExc_KeyError, "unknown module, %s", module); - - for (i = 0; formats[i].def; i++) - { - if (formats[i].tag && !g_strcasecmp(formats[i].tag, tag)) - { - modtheme = g_hash_table_lookup(theme->modules, module); - if (modtheme && modtheme->formats[i]) - return PyString_FromString(modtheme->formats[i]); - else - return PyString_FromString(formats[i].def); - } - } - - return PyErr_Format(PyExc_KeyError, "unknown format tag, %s", tag); -} - -/* Methods for object */ -static PyMethodDef PyTheme_methods[] = { - {"format_expand", (PyCFunction)PyTheme_format_expand, METH_VARARGS | METH_KEYWORDS, - PyTheme_format_expand_doc}, - {"get_format", (PyCFunction)PyTheme_get_format, METH_VARARGS | METH_KEYWORDS, - PyTheme_get_format_doc}, - {NULL} /* Sentinel */ -}; - -PyTypeObject PyThemeType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "Theme", /*tp_name*/ - sizeof(PyTheme), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)PyTheme_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - 0, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - PyTheme_methods, /* tp_methods */ - 0, /* tp_members */ - PyTheme_getseters, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - PyTheme_new, /* tp_new */ -}; - -/* Theme factory function */ -PyObject *pytheme_new(void *td) -{ - PyTheme *pytheme; - - pytheme = py_inst(PyTheme, PyThemeType); - if (!pytheme) - return NULL; - - pytheme->data = td; - signal_add_last_data("theme destroyed", theme_cleanup, pytheme); - pytheme->cleanup_installed = 1; - - return (PyObject *)pytheme; -} - -int theme_object_init(void) -{ - g_return_val_if_fail(py_module != NULL, 0); - - if (PyType_Ready(&PyThemeType) < 0) - return 0; - - Py_INCREF(&PyThemeType); - PyModule_AddObject(py_module, "Theme", (PyObject *)&PyThemeType); - - return 1; -} diff --git a/objects/theme-object.h b/objects/theme-object.h deleted file mode 100644 index 299d54d..0000000 --- a/objects/theme-object.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef _THEME_OBJECT_H_ -#define _THEME_OBJECT_H_ - -#include -#include "base-objects.h" - -typedef struct -{ - PyIrssiFinal_HEAD(void) -} PyTheme; - -extern PyTypeObject PyThemeType; - -int theme_object_init(void); -PyObject *pytheme_new(void *td); -#define pytheme_check(op) PyObject_TypeCheck(op, &PyThemeType) - -#endif diff --git a/objects/window-item-object.c b/objects/window-item-object.c deleted file mode 100644 index 2f18f7d..0000000 --- a/objects/window-item-object.c +++ /dev/null @@ -1,334 +0,0 @@ -#include -#include "pymodule.h" -#include "base-objects.h" -#include "window-item-object.h" -#include "pyirssi.h" -#include "pycore.h" -#include "pyutils.h" -#include "factory.h" - -/* Dealloc is overridden by sub types */ - -PyDoc_STRVAR(PyWindowItem_server_doc, - "Active name for item" -); -static PyObject *PyWindowItem_server_get(PyWindowItem *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_OBJ_OR_NONE(self->server); -} - -PyDoc_STRVAR(PyWindowItem_name_doc, - "Name of the item" -); -static PyObject *PyWindowItem_name_get(PyWindowItem *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->visible_name); -} - -PyDoc_STRVAR(PyWindowItem_createtime_doc, - "Time the witem was created" -); -static PyObject *PyWindowItem_createtime_get(PyWindowItem *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyLong_FromLong(self->data->createtime); -} - -PyDoc_STRVAR(PyWindowItem_data_level_doc, - "0=no new data, 1=text, 2=msg, 3=highlighted text" -); -static PyObject *PyWindowItem_data_level_get(PyWindowItem *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyInt_FromLong(self->data->data_level); -} - -PyDoc_STRVAR(PyWindowItem_hilight_color_doc, - "Color of the last highlighted text" -); -static PyObject *PyWindowItem_hilight_color_get(PyWindowItem *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->hilight_color); -} - -/* specialized getters/setters */ -static PyGetSetDef PyWindowItem_getseters[] = { - {"server", (getter)PyWindowItem_server_get, NULL, - PyWindowItem_server_doc, NULL}, - {"name", (getter)PyWindowItem_name_get, NULL, - PyWindowItem_name_doc, NULL}, - {"createtime", (getter)PyWindowItem_createtime_get, NULL, - PyWindowItem_createtime_doc, NULL}, - {"data_level", (getter)PyWindowItem_data_level_get, NULL, - PyWindowItem_data_level_doc, NULL}, - {"hilight_color", (getter)PyWindowItem_hilight_color_get, NULL, - PyWindowItem_hilight_color_doc, NULL}, - {NULL} -}; - -/* Methods */ -PyDoc_STRVAR(PyWindowItem_prnt_doc, - "prnt(str, level) -> None\n" - "\n" - "Print to window item\n" -); -static PyObject *PyWindowItem_prnt(PyWindowItem *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"str", "level", NULL}; - char *str; - int level = MSGLEVEL_CLIENTNOTICE; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|i", kwlist, &str, &level)) - return NULL; - - printtext_string(self->data->server, self->data->visible_name, level, str); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyWindowItem_command_doc, - "command(cmd) -> None\n" - "\n" - "Send command to window item\n" -); -static PyObject *PyWindowItem_command(PyWindowItem *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"cmd", NULL}; - char *cmd; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &cmd)) - return NULL; - - py_command(cmd, self->data->server, self->data); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyWindowItem_window_doc, - "window() -> Window object or None\n" - "\n" - "Return parent window for window item\n" -); -static PyObject *PyWindowItem_window(PyWindowItem *self, PyObject *args) -{ - WINDOW_REC *win; - - RET_NULL_IF_INVALID(self->data); - - win = window_item_window(self->data); - if (win) - return pywindow_new(win); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyWindowItem_change_server_doc, - "change_server(server) -> None\n" - "\n" - "Change server for window item\n" -); -static PyObject *PyWindowItem_change_server(PyWindowItem *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"server", NULL}; - PyObject *server = NULL; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, - &server)) - return NULL; - - if (!pyserver_check(server)) - return PyErr_Format(PyExc_TypeError, "arg must be server"); - - window_item_change_server(self->data, ((PyServer*)server)->data); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyWindowItem_is_active_doc, - "is_active() -> bool\n" - "\n" - "Returns true if window item is active\n" -); -static PyObject *PyWindowItem_is_active(PyWindowItem *self, PyObject *args) -{ - RET_NULL_IF_INVALID(self->data); - - return PyBool_FromLong(window_item_is_active(self->data)); -} - -PyDoc_STRVAR(PyWindowItem_set_active_doc, - "set_active() -> None\n" - "\n" - "Set window item active\n" -); -static PyObject *PyWindowItem_set_active(PyWindowItem *self, PyObject *args) -{ - RET_NULL_IF_INVALID(self->data); - - window_item_set_active(window_item_window(self->data), self->data); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyWindowItem_activity_doc, - "activity(data_level, hilight_color) -> None\n" - "\n" -); -static PyObject *PyWindowItem_activity(PyWindowItem *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"data_level", "hilight_color", NULL}; - int data_level = 0; - char *hilight_color = NULL; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "is", kwlist, - &data_level, &hilight_color)) - return NULL; - - window_item_activity(self->data, data_level, hilight_color); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyWindowItem_destroy_doc, - "destroy() -> None\n" - "\n" - "Destroy channel or query\n" -); -static PyObject *PyWindowItem_destroy(PyWindowItem *self, PyObject *args) -{ - RET_NULL_IF_INVALID(self->data); - - window_item_destroy(self->data); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyWindowItem_get_dcc_doc, - "get_dcc() -> DccChat object or None\n" - "\n" - "If item is a query of a =nick, return DCC chat record of nick\n" -); -static PyObject *PyWindowItem_get_dcc(PyWindowItem *self, PyObject *args) -{ - RET_NULL_IF_INVALID(self->data); - return py_irssi_new(self->data, 1); -} - -/* Methods for object */ -static PyMethodDef PyWindowItem_methods[] = { - {"prnt", (PyCFunction)PyWindowItem_prnt, METH_VARARGS | METH_KEYWORDS, - PyWindowItem_prnt_doc}, - {"command", (PyCFunction)PyWindowItem_command, METH_VARARGS | METH_KEYWORDS, - PyWindowItem_command_doc}, - {"window", (PyCFunction)PyWindowItem_window, METH_NOARGS, - PyWindowItem_window_doc}, - {"change_server", (PyCFunction)PyWindowItem_change_server, METH_VARARGS | METH_KEYWORDS, - PyWindowItem_change_server_doc}, - {"is_active", (PyCFunction)PyWindowItem_is_active, METH_NOARGS, - PyWindowItem_is_active_doc}, - {"set_active", (PyCFunction)PyWindowItem_set_active, METH_NOARGS, - PyWindowItem_set_active_doc}, - {"activity", (PyCFunction)PyWindowItem_activity, METH_VARARGS | METH_KEYWORDS, - PyWindowItem_activity_doc}, - {"destroy", (PyCFunction)PyWindowItem_destroy, METH_NOARGS, - PyWindowItem_destroy_doc}, - {"get_dcc", (PyCFunction)PyWindowItem_get_dcc, METH_NOARGS, - PyWindowItem_get_dcc_doc}, - {NULL} /* Sentinel */ -}; - -PyTypeObject PyWindowItemType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "WindowItem", /*tp_name*/ - sizeof(PyWindowItem), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - 0, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - "PyWindowItem objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - PyWindowItem_methods, /* tp_methods */ - 0, /* tp_members */ - PyWindowItem_getseters, /* tp_getset */ - &PyIrssiChatBaseType, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ -}; - - -/* window item wrapper factory function */ -PyObject *pywindow_item_sub_new(void *witem, const char *name, PyTypeObject *subclass) -{ - WI_ITEM_REC *rec = witem; - PyWindowItem *pywitem = NULL; - PyObject *server; - - g_return_val_if_fail(witem != NULL, NULL); - - server = py_irssi_chat_new(rec->server, 1); - if (!server) - return NULL; - - pywitem = py_instp(PyWindowItem, subclass); - if (!pywitem) - return NULL; - - pywitem->data = witem; - pywitem->base_name = name; - pywitem->server = server; - - return (PyObject *)pywitem; -} - -PyObject *pywindow_item_new(void *witem) -{ - return pywindow_item_sub_new(witem, NULL, &PyWindowItemType); -} - -int window_item_object_init(void) -{ - g_return_val_if_fail(py_module != NULL, 0); - - if (PyType_Ready(&PyWindowItemType) < 0) - return 0; - - Py_INCREF(&PyWindowItemType); - PyModule_AddObject(py_module, "WindowItem", (PyObject *)&PyWindowItemType); - - return 1; -} diff --git a/objects/window-item-object.h b/objects/window-item-object.h deleted file mode 100644 index e205ebe..0000000 --- a/objects/window-item-object.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef _WITEM_OBJECT_H_ -#define _WITEM_OBJECT_H_ - -#include -#include "base-objects.h" - -#define PyWindowItem_HEAD(type) \ - PyIrssi_HEAD(type) \ - PyObject *server; - -/* forward */ -struct _WI_ITEM_REC; - -typedef struct -{ - PyWindowItem_HEAD(struct _WI_ITEM_REC) -} PyWindowItem; - -extern PyTypeObject PyWindowItemType; - -int window_item_object_init(void); -PyObject *pywindow_item_sub_new(void *witem, const char *name, PyTypeObject *subclass); -PyObject *pywindow_item_new(void *witem); -#define pywindow_item_check(op) PyObject_TypeCheck(op, &PyWindowItemType) - -#endif diff --git a/objects/window-object.c b/objects/window-object.c deleted file mode 100644 index d5aa475..0000000 --- a/objects/window-object.c +++ /dev/null @@ -1,678 +0,0 @@ -#include -#include "pyirssi_irc.h" -#include "pymodule.h" -#include "window-object.h" -#include "factory.h" -#include "pycore.h" -#include "pyutils.h" - -/* monitor "window destroyed" signal */ -static void window_cleanup(WINDOW_REC *win) -{ - PyWindow *pywindow = signal_get_user_data(); - - if (win == pywindow->data) - { - pywindow->data = NULL; - pywindow->cleanup_installed = 0; - signal_remove_data("window destroyed", window_cleanup, pywindow); - } -} - -static void PyWindow_dealloc(PyWindow *self) -{ - if (self->cleanup_installed) - signal_remove_data("window destroyed", window_cleanup, self); - - self->ob_type->tp_free((PyObject*)self); -} - -static PyObject *PyWindow_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyWindow *self; - - self = (PyWindow *)type->tp_alloc(type, 0); - if (!self) - return NULL; - - return (PyObject *)self; -} - -/* Getters */ -PyDoc_STRVAR(PyWindow_refnum_doc, - "Reference number" -); -static PyObject *PyWindow_refnum_get(PyWindow *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyInt_FromLong(self->data->refnum); -} - -PyDoc_STRVAR(PyWindow_name_doc, - "Name" -); -static PyObject *PyWindow_name_get(PyWindow *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->name); -} - -PyDoc_STRVAR(PyWindow_width_doc, - "Width" -); -static PyObject *PyWindow_width_get(PyWindow *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyInt_FromLong(self->data->width); -} - -PyDoc_STRVAR(PyWindow_height_doc, - "Height" -); -static PyObject *PyWindow_height_get(PyWindow *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyInt_FromLong(self->data->height); -} - -PyDoc_STRVAR(PyWindow_history_name_doc, - "Name of named historylist for this window" -); -static PyObject *PyWindow_history_name_get(PyWindow *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->history_name); -} - -PyDoc_STRVAR(PyWindow_active_doc, - "Active window item" -); -static PyObject *PyWindow_active_get(PyWindow *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return py_irssi_chat_new(self->data->active, 1); -} - -PyDoc_STRVAR(PyWindow_active_server_doc, - "Active server" -); -static PyObject *PyWindow_active_server_get(PyWindow *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return py_irssi_chat_new(self->data->active_server, 1); -} - -PyDoc_STRVAR(PyWindow_servertag_doc, - "active_server must be either None or have this same tag" - "(unless there's items in this window). This is used by" - "/WINDOW SERVER -sticky" -); -static PyObject *PyWindow_servertag_get(PyWindow *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->servertag); -} - -PyDoc_STRVAR(PyWindow_level_doc, - "Current window level" -); -static PyObject *PyWindow_level_get(PyWindow *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyInt_FromLong(self->data->level); -} - -PyDoc_STRVAR(PyWindow_sticky_refnum_doc, - "True if reference number is sticky" -); -static PyObject *PyWindow_sticky_refnum_get(PyWindow *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyBool_FromLong(self->data->sticky_refnum); -} - -PyDoc_STRVAR(PyWindow_data_level_doc, - "Current data level" -); -static PyObject *PyWindow_data_level_get(PyWindow *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyInt_FromLong(self->data->data_level); -} - -PyDoc_STRVAR(PyWindow_hilight_color_doc, - "Current activity hilight color" -); -static PyObject *PyWindow_hilight_color_get(PyWindow *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->hilight_color); -} - -PyDoc_STRVAR(PyWindow_last_timestamp_doc, - "Last time timestamp was written in window" -); -static PyObject *PyWindow_last_timestamp_get(PyWindow *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyLong_FromUnsignedLong(self->data->last_timestamp); -} - -PyDoc_STRVAR(PyWindow_last_line_doc, - "Last time text was written in window" -); -static PyObject *PyWindow_last_line_get(PyWindow *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - return PyLong_FromUnsignedLong(self->data->last_line); -} - -PyDoc_STRVAR(PyWindow_theme_name_doc, - "Active theme in window, None = default" -); -static PyObject *PyWindow_theme_name_get(PyWindow *self, void *closure) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(self->data->theme_name); -} - -/* specialized getters/setters */ -static PyGetSetDef PyWindow_getseters[] = { - {"refnum", (getter)PyWindow_refnum_get, NULL, - PyWindow_refnum_doc, NULL}, - {"name", (getter)PyWindow_name_get, NULL, - PyWindow_name_doc, NULL}, - {"width", (getter)PyWindow_width_get, NULL, - PyWindow_width_doc, NULL}, - {"height", (getter)PyWindow_height_get, NULL, - PyWindow_height_doc, NULL}, - {"history_name", (getter)PyWindow_history_name_get, NULL, - PyWindow_history_name_doc, NULL}, - {"active", (getter)PyWindow_active_get, NULL, - PyWindow_active_doc, NULL}, - {"active_server", (getter)PyWindow_active_server_get, NULL, - PyWindow_active_server_doc, NULL}, - {"servertag", (getter)PyWindow_servertag_get, NULL, - PyWindow_servertag_doc, NULL}, - {"level", (getter)PyWindow_level_get, NULL, - PyWindow_level_doc, NULL}, - {"sticky_refnum", (getter)PyWindow_sticky_refnum_get, NULL, - PyWindow_sticky_refnum_doc, NULL}, - {"data_level", (getter)PyWindow_data_level_get, NULL, - PyWindow_data_level_doc, NULL}, - {"hilight_color", (getter)PyWindow_hilight_color_get, NULL, - PyWindow_hilight_color_doc, NULL}, - {"last_timestamp", (getter)PyWindow_last_timestamp_get, NULL, - PyWindow_last_timestamp_doc, NULL}, - {"last_line", (getter)PyWindow_last_line_get, NULL, - PyWindow_last_line_doc, NULL}, - {"theme_name", (getter)PyWindow_theme_name_get, NULL, - PyWindow_theme_name_doc, NULL}, - {NULL} -}; - -/* Methods */ -PyDoc_STRVAR(PyWindow_items_doc, - "items() -> list of WindowItem objects\n" - "\n" - "Return a list of items in window.\n" -); -static PyObject *PyWindow_items(PyWindow *self, PyObject *args) -{ - RET_NULL_IF_INVALID(self->data); - return py_irssi_chatlist_new(self->data->items, 1); -} - -PyDoc_STRVAR(PyWindow_prnt_doc, - "prnt(str, level=MSGLEVEL_CLIENTNOTICE) -> None\n" - "\n" - "Print to window\n" -); -static PyObject *PyWindow_prnt(PyWindow *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"str", "level", NULL}; - char *str = ""; - int level = MSGLEVEL_CLIENTNOTICE; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|i", kwlist, - &str, &level)) - return NULL; - - printtext_string_window(self->data, level, str); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyWindow_command_doc, - "command(cmd) -> None\n" - "\n" - "Send command to window\n" -); -static PyObject *PyWindow_command(PyWindow *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"cmd", NULL}; - char *cmd = ""; - WINDOW_REC *old; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &cmd)) - return NULL; - - old = active_win; - active_win = self->data; - py_command(cmd, active_win->active_server, active_win->active); - if (g_slist_find(windows, old) != NULL) - active_win = old; - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyWindow_item_add_doc, - "item_add(item, automatic=False) -> None\n" - "\n" - "Add window item\n" -); -static PyObject *PyWindow_item_add(PyWindow *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"item", "automatic", NULL}; - PyObject *item = NULL; - int automatic = 0; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|i", kwlist, - &item, &automatic)) - return NULL; - - if (!pywindow_item_check(item)) - return PyErr_Format(PyExc_TypeError, "item must be window item"); - - window_item_add(self->data, ((PyWindowItem*)item)->data, automatic); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyWindow_item_remove_doc, - "item_remove(item) -> None\n" - "\n" - "Remove window item\n" -); -static PyObject *PyWindow_item_remove(PyWindow *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"item", NULL}; - PyObject *item = NULL; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, - &item)) - return NULL; - - if (!pywindow_item_check(item)) - return PyErr_Format(PyExc_TypeError, "item must be window item"); - - window_item_remove(((PyWindowItem*)item)->data); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyWindow_item_destroy_doc, - "item_destroy(item) -> None\n" - "\n" - "Destroy window item\n" -); -static PyObject *PyWindow_item_destroy(PyWindow *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"item", NULL}; - PyObject *item = NULL; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, - &item)) - return NULL; - - if (!pywindow_item_check(item)) - return PyErr_Format(PyExc_TypeError, "item must be window item"); - - window_item_destroy(((PyWindowItem*)item)->data); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyWindow_item_prev_doc, - "item_prev() -> None\n" - "\n" - "Change to previous window item\n" -); -static PyObject *PyWindow_item_prev(PyWindow *self, PyObject *args) -{ - RET_NULL_IF_INVALID(self->data); - - window_item_prev(self->data); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyWindow_item_next_doc, - "item_next() -> None\n" - "\n" - "Change to next window item\n" -); -static PyObject *PyWindow_item_next(PyWindow *self, PyObject *args) -{ - RET_NULL_IF_INVALID(self->data); - - window_item_next(self->data); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyWindow_destroy_doc, - "destroy() -> None\n" - "\n" - "Destroy the window.\n" -); -static PyObject *PyWindow_destroy(PyWindow *self, PyObject *args) -{ - RET_NULL_IF_INVALID(self->data); - - window_destroy(self->data); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyWindow_set_active_doc, - "set_active() -> None\n" - "\n" - "Set window active.\n" -); -static PyObject *PyWindow_set_active(PyWindow *self, PyObject *args) -{ - RET_NULL_IF_INVALID(self->data); - - window_set_active(self->data); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyWindow_change_server_doc, - "change_server(server) -> None\n" - "\n" - "Change server in window\n" -); -static PyObject *PyWindow_change_server(PyWindow *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"server", NULL}; - PyObject *server = NULL; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, - &server)) - return NULL; - - if (!pyserver_check(server)) - return PyErr_Format(PyExc_TypeError, "arg must be server"); - - window_change_server(self->data, ((PyServer*)server)->data); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyWindow_set_refnum_doc, - "set_refnum(refnum) -> None\n" - "\n" - "Set window refnum\n" -); -static PyObject *PyWindow_set_refnum(PyWindow *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"refnum", NULL}; - int refnum = 0; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, - &refnum)) - return NULL; - - window_set_refnum(self->data, refnum); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyWindow_set_name_doc, - "set_name(name) -> None\n" - "\n" - "Set window name\n" -); -static PyObject *PyWindow_set_name(PyWindow *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"name", NULL}; - char *name = ""; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &name)) - return NULL; - - window_set_name(self->data, name); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyWindow_set_history_doc, - "set_history(history) -> None\n" - "\n" - "Set window history\n" -); -static PyObject *PyWindow_set_history(PyWindow *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"history", NULL}; - char *history = ""; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &history)) - return NULL; - - window_set_history(self->data, history); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyWindow_set_level_doc, - "set_level(level) -> None\n" - "\n" - "Set window level\n" -); -static PyObject *PyWindow_set_level(PyWindow *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"level", NULL}; - int level = 0; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, - &level)) - return NULL; - - window_set_level(self->data, level); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyWindow_activity_doc, - "activity(data_level, hilight_color) -> None\n" - "\n" -); -static PyObject *PyWindow_activity(PyWindow *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"data_level", "hilight_color", NULL}; - int data_level = 0; - char *hilight_color = NULL; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "i|s", kwlist, - &data_level, &hilight_color)) - return NULL; - - window_activity(self->data, data_level, hilight_color); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PyWindow_get_active_name_doc, - "get_active_name() -> str or None\n" - "\n" - "Return active item's name, or if none is active, window's name.\n" -); -static PyObject *PyWindow_get_active_name(PyWindow *self, PyObject *args) -{ - RET_NULL_IF_INVALID(self->data); - RET_AS_STRING_OR_NONE(window_get_active_name(self->data)); -} - -PyDoc_STRVAR(PyWindow_item_find_doc, - "item_find(server, name) -> WindowItem or None\n" - "\n" - "Find window item that matches best to given arguments\n" -); -static PyObject *PyWindow_item_find(PyWindow *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"server", "name", NULL}; - PyObject *server = NULL; - char *name = ""; - WI_ITEM_REC *witem; - - RET_NULL_IF_INVALID(self->data); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "Os", kwlist, - &server, &name)) - return NULL; - - if (!pyserver_check(server)) - return PyErr_Format(PyExc_TypeError, "arg 1 must be server"); - - witem = window_item_find_window(self->data, ((PyServer*)server)->data, name); - return py_irssi_chat_new(witem, 1); -} - -static PyMethodDef PyWindow_methods[] = { - {"items", (PyCFunction)PyWindow_items, METH_NOARGS, - PyWindow_items_doc}, - {"prnt", (PyCFunction)PyWindow_prnt, METH_VARARGS | METH_KEYWORDS, - PyWindow_prnt_doc}, - {"command", (PyCFunction)PyWindow_command, METH_VARARGS | METH_KEYWORDS, - PyWindow_command_doc}, - {"item_add", (PyCFunction)PyWindow_item_add, METH_VARARGS | METH_KEYWORDS, - PyWindow_item_add_doc}, - {"item_remove", (PyCFunction)PyWindow_item_remove, METH_VARARGS | METH_KEYWORDS, - PyWindow_item_remove_doc}, - {"item_destroy", (PyCFunction)PyWindow_item_destroy, METH_VARARGS | METH_KEYWORDS, - PyWindow_item_destroy_doc}, - {"item_prev", (PyCFunction)PyWindow_item_prev, METH_NOARGS, - PyWindow_item_prev_doc}, - {"item_next", (PyCFunction)PyWindow_item_next, METH_NOARGS, - PyWindow_item_next_doc}, - {"destroy", (PyCFunction)PyWindow_destroy, METH_NOARGS, - PyWindow_destroy_doc}, - {"set_active", (PyCFunction)PyWindow_set_active, METH_NOARGS, - PyWindow_set_active_doc}, - {"change_server", (PyCFunction)PyWindow_change_server, METH_VARARGS | METH_KEYWORDS, - PyWindow_change_server_doc}, - {"set_refnum", (PyCFunction)PyWindow_set_refnum, METH_VARARGS | METH_KEYWORDS, - PyWindow_set_refnum_doc}, - {"set_name", (PyCFunction)PyWindow_set_name, METH_VARARGS | METH_KEYWORDS, - PyWindow_set_name_doc}, - {"set_history", (PyCFunction)PyWindow_set_history, METH_VARARGS | METH_KEYWORDS, - PyWindow_set_history_doc}, - {"set_level", (PyCFunction)PyWindow_set_level, METH_VARARGS | METH_KEYWORDS, - PyWindow_set_level_doc}, - {"activity", (PyCFunction)PyWindow_activity, METH_VARARGS | METH_KEYWORDS, - PyWindow_activity_doc}, - {"get_active_name", (PyCFunction)PyWindow_get_active_name, METH_NOARGS, - PyWindow_get_active_name_doc}, - {"item_find", (PyCFunction)PyWindow_item_find, METH_VARARGS | METH_KEYWORDS, - PyWindow_item_find_doc}, - {NULL} /* Sentinel */ -}; - -PyTypeObject PyWindowType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "Window", /*tp_name*/ - sizeof(PyWindow), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)PyWindow_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - "PyWindow objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - PyWindow_methods, /* tp_methods */ - 0, /* tp_members */ - PyWindow_getseters, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - PyWindow_new, /* tp_new */ -}; - - -/* window item wrapper factory function */ -PyObject *pywindow_new(void *win) -{ - PyWindow *pywindow; - - pywindow = py_inst(PyWindow, PyWindowType); - if (!pywindow) - return NULL; - - pywindow->data = win; - pywindow->cleanup_installed = 1; - signal_add_last_data("window destroyed", window_cleanup, pywindow); - - return (PyObject *)pywindow; -} - -int window_object_init(void) -{ - g_return_val_if_fail(py_module != NULL, 0); - - if (PyType_Ready(&PyWindowType) < 0) - return 0; - - Py_INCREF(&PyWindowType); - PyModule_AddObject(py_module, "Window", (PyObject *)&PyWindowType); - - return 1; -} diff --git a/objects/window-object.h b/objects/window-object.h deleted file mode 100644 index b9860af..0000000 --- a/objects/window-object.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef _WINDOW_OBJECT_H_ -#define _WINDOW_OBJECT_H_ - -#include -#include "base-objects.h" - -/* forward */ -struct _WINDOW_REC; - -typedef struct -{ - PyIrssiFinal_HEAD(struct _WINDOW_REC) -} PyWindow; - -extern PyTypeObject PyWindowType; - -int window_object_init(void); -PyObject *pywindow_new(void *win); -#define pywindow_check(op) PyObject_TypeCheck(op, &PyWindowType) - -#endif diff --git a/pyconstants.h b/pyconstants.h deleted file mode 100644 index f898ded..0000000 --- a/pyconstants.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _PYCONSTANTS_H_ -#define _PYCONSTANTS_H_ - -void pyconstants_init(void); - -#endif - diff --git a/pycore.c b/pycore.c deleted file mode 100644 index f9e4c3d..0000000 --- a/pycore.c +++ /dev/null @@ -1,160 +0,0 @@ -#include -#include -#include -#include -#include "pyirssi.h" -#include "pycore.h" -#include "pyloader.h" -#include "pymodule.h" -#include "pysignals.h" -#include "pythemes.h" -#include "pystatusbar.h" -#include "pyconstants.h" -#include "factory.h" - -/*XXX: copy parse into utils */ -static void cmd_exec(const char *data) -{ - PyObject *co; - PyObject *ret; - PyObject *d; - PyObject *m; - char *cmd; - - if (!*data) - cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS); - - cmd = g_strconcat(data, "\n", NULL); - - m = PyImport_AddModule("__main__"); - if (!m) - goto error; - - d = PyModule_GetDict(m); - if (!d) - goto error; - - co = Py_CompileString(cmd, "", Py_single_input); - if (!co) - goto error; - - ret = PyEval_EvalCode((PyCodeObject *)co, d, d); - Py_DECREF(co); - Py_XDECREF(ret); - -error: - g_free(cmd); - if (PyErr_Occurred()) - PyErr_Print(); -} - -static void cmd_load(const char *data) -{ - char **argv; - - argv = g_strsplit(data, " ", -1); - if (*argv == NULL || **argv == '\0') - { - g_strfreev(argv); - cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS); - } - - pyloader_load_script_argv(argv); - g_strfreev(argv); -} - -static void cmd_unload(const char *data) -{ - void *free_arg; - char *script; - - if (!cmd_get_params(data, &free_arg, 1, &script)) - return; - - if (*script == '\0') - cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); - - pyloader_unload_script(script); - - cmd_params_free(free_arg); -} - -static void cmd_list() -{ - char buf[128]; - GSList *list; - - list = pyloader_list(); - - g_snprintf(buf, sizeof(buf), "%-15s %s", "Name", "File"); - - if (list != NULL) - { - GSList *node; - - printtext_string(NULL, NULL, MSGLEVEL_CLIENTCRAP, buf); - for (node = list; node != NULL; node = node->next) - { - PY_LIST_REC *item = node->data; - g_snprintf(buf, sizeof(buf), "%-15s %s", item->name, item->file); - - printtext_string(NULL, NULL, MSGLEVEL_CLIENTCRAP, buf); - } - } - else - printtext_string(NULL, NULL, MSGLEVEL_CLIENTERROR, "No python scripts are loaded"); - - pyloader_list_destroy(&list); -} - -#if 0 -/* why doesn't this get called? */ -static void intr_catch(int sig) -{ - printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "got sig %d", sig); - PyErr_SetInterrupt(); -} -#endif - -void irssi_python_init(void) -{ - Py_InitializeEx(0); - - pysignals_init(); - pystatusbar_init(); - if (!pyloader_init() || !pymodule_init() || !factory_init() || !pythemes_init()) - { - printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "Failed to load Python"); - return; - } - pyconstants_init(); - - /*PyImport_ImportModule("irssi_startup");*/ - /* Install the custom output handlers, import hook and reload function */ - /* XXX: handle import error */ - PyRun_SimpleString( - "import irssi_startup\n" - ); - - //assert(signal(SIGINT, intr_catch) != SIG_ERR); - - command_bind("pyload", NULL, (SIGNAL_FUNC) cmd_load); - command_bind("pyunload", NULL, (SIGNAL_FUNC) cmd_unload); - command_bind("pylist", NULL, (SIGNAL_FUNC) cmd_list); - command_bind("pyexec", NULL, (SIGNAL_FUNC) cmd_exec); - module_register(MODULE_NAME, "core"); -} - -void irssi_python_deinit(void) -{ - command_unbind("pyload", (SIGNAL_FUNC) cmd_load); - command_unbind("pyunload", (SIGNAL_FUNC) cmd_unload); - command_unbind("pylist", (SIGNAL_FUNC) cmd_list); - command_unbind("pyexec", (SIGNAL_FUNC) cmd_exec); - - pymodule_deinit(); - pyloader_deinit(); - pystatusbar_deinit(); - pysignals_deinit(); - Py_Finalize(); -} diff --git a/pycore.h b/pycore.h deleted file mode 100644 index ae51924..0000000 --- a/pycore.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _PYCORE_H -#define _PYCORE_H - -void irssi_python_init(void); -void irssi_python_deinit(void); - -#endif diff --git a/pyirssi.h b/pyirssi.h deleted file mode 100644 index 3fc4223..0000000 --- a/pyirssi.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef _PYIRSSI_H_ -#define _PYIRSSI_H_ - -#define MODULE_NAME "irssi_python" -#include "config.h" -#include "core.h" -#include "common.h" -#include "modules.h" -#include "commands.h" -#include "settings.h" -#include "printtext.h" -#include "statusbar.h" -#include "mainwindows.h" -#include "window-items.h" -#include "window-activity.h" -#include "levels.h" -#include "servers.h" -#include "chat-protocols.h" -#include "channels.h" -#include "queries.h" -#include "nicklist.h" -#include "chatnets.h" -#include "servers-reconnect.h" -#include "masks.h" -#include "misc.h" -#include "rawlog.h" -#include "log.h" -#include "ignore.h" -#include "fe-exec.h" -#include "pidwait.h" - -#endif diff --git a/pyirssi_irc.h b/pyirssi_irc.h deleted file mode 100644 index 0ebd617..0000000 --- a/pyirssi_irc.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef _PY_IRSSI_IRC_H_ -#define _PY_IRSSI_IRC_H_ - -#include "pyirssi.h" -#include "irc.h" -#include "irc-servers.h" -#include "servers-redirect.h" -#include "irc-channels.h" -#include "ctcp.h" -#include "mode-lists.h" -#include "bans.h" -#include "dcc.h" -#include "dcc-get.h" -#include "dcc-send.h" -#include "dcc-chat.h" -#include "netsplit.h" -#include "notifylist.h" -#include "irc-masks.h" - -#endif diff --git a/pyloader.c b/pyloader.c deleted file mode 100644 index a087827..0000000 --- a/pyloader.c +++ /dev/null @@ -1,358 +0,0 @@ -#include -#include -#include -#include "pyirssi.h" -#include "pyloader.h" -#include "pyutils.h" -#include "pyscript-object.h" - -/* List of loaded modules */ -static PyObject *script_modules; - -/* List of load paths for scripts */ -static GSList *script_paths = NULL; - -static PyObject *py_get_script(const char *name, int *id); -static int py_load_module(PyObject *module, const char *path); -static char *py_find_script(const char *name); - -/* Add to the list of script load paths */ -void pyloader_add_script_path(const char *path) -{ - PyObject *ppath = PySys_GetObject("path"); - if (ppath) - { - PyList_Append(ppath, PyString_FromString(path)); - script_paths = g_slist_append(script_paths, g_strdup(path)); - } -} - -/* Loads a file into a module; it is not inserted into sys.modules */ -static int py_load_module(PyObject *module, const char *path) -{ - PyObject *dict, *ret, *fp; - - if (PyModule_AddStringConstant(module, "__file__", (char *)path) < 0) - return 0; - - dict = PyModule_GetDict(module); - - if (PyDict_SetItemString(dict, "__builtins__", PyEval_GetBuiltins()) < 0) - return 0; - - /* Dont use the standard library to avoid incompatabilities with - the FILE structure and Python */ - fp = PyFile_FromString((char *)path, "r"); - if (!fp) - return 0; - - ret = PyRun_File(PyFile_AsFile(fp), path, Py_file_input, dict, dict); - Py_DECREF(fp); /* XXX: I assume that the file is closed when refs drop to zero? */ - if (!ret) - return 0; - - Py_DECREF(ret); - return 1; - -} - -/* looks up name in Irssi script directories - returns full path or NULL if not found */ -static char *py_find_script(const char *name) -{ - GSList *node; - char *fname; - char *path = NULL; - - //XXX: what if there's another ext? - if (!file_has_ext(name, "py")) - fname = g_strdup_printf("%s.py", name); - else - fname = (char *)name; - - /*XXX: use case insensitive path search? */ - for (node = script_paths; node && !path; node = node->next) - { - path = g_strdup_printf("%s/%s", (char *)node->data, fname); - - if (!g_file_test(path, G_FILE_TEST_IS_REGULAR)) - { - g_free(path); - path = NULL; - } - } - - if (fname != name) - g_free(fname); - - return path; -} - -/* Load a script manually using PyRun_File. - * This expects a null terminated array of strings - * (such as from g_strsplit) of the command line. - * The array needs at least one item - */ -int pyloader_load_script_argv(char **argv) -{ - PyObject *module = NULL, *script = NULL; - char *name = NULL, *path = NULL; - - if (py_get_script(argv[0], NULL) != NULL) - { - printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "script %s already loaded", argv[0]); - return 0; - } - - path = py_find_script(argv[0]); - if (!path) - { - printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "script %s does not exist", argv[0]); - return 0; - } - - name = file_get_filename(path); - module = PyModule_New(name); - g_free(name); - if (!module) - goto error; - - script = pyscript_new(module, argv); - Py_DECREF(module); - if (!script) - goto error; - - /* insert script obj into module dict, load file */ - if (PyModule_AddObject(module, "_script", script) != 0) - goto error; - - Py_INCREF(script); - - if (!py_load_module(module, path)) - goto error; - - if (PyList_Append(script_modules, script) != 0) - goto error; - - printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "loaded script %s", argv[0]); - /* PySys_WriteStdout("load %s, script -> 0x%x\n", argv[0], script); */ - - Py_DECREF(script); - g_free(path); - - return 1; - -error: - if (PyErr_Occurred()) - PyErr_Print(); - else - printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "error loading script %s", argv[0]); - - if (script) - { - /* make sure to clean up any formats, signals, commands that may have been - attached before the exception took place */ - pyscript_cleanup(script); - Py_DECREF(script); - } - - g_free(path); - - return 0; -} - -int pyloader_load_script(char *name) -{ - char *argv[2]; - - argv[0] = name; - argv[1] = NULL; - - return pyloader_load_script_argv(argv); -} - -static PyObject *py_get_script(const char *name, int *id) -{ - int i; - - g_return_val_if_fail(script_modules != NULL, NULL); - - for (i = 0; i < PyList_Size(script_modules); i++) - { - PyObject *script; - char *sname; - - script = PyList_GET_ITEM(script_modules, i); - sname = pyscript_get_name(script); - - if (sname && !strcmp(sname, name)) - { - if (id) - *id = i; - return script; - } - } - - return NULL; -} - -int pyloader_unload_script(const char *name) -{ - int id; - PyObject *script = py_get_script(name, &id); - - if (!script) - { - printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "%s is not loaded", name); - return 0; - } - - PySys_WriteStdout("unload %s, script -> 0x%x\n", name, script); - - pyscript_cleanup(script); - - if (PySequence_DelItem(script_modules, id) < 0) - { - PyErr_Print(); - printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "error unloading script %s", name); - return 0; - } - - /* Probably a good time to call the garbage collecter to clean up reference cycles */ - PyGC_Collect(); - printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "unloaded script %s", name); - - return 1; -} - -/* Traverse stack backwards to find the nearest valid _script object in globals */ -PyObject *pyloader_find_script_obj(void) -{ - PyFrameObject *frame; - - for (frame = PyEval_GetFrame(); frame != NULL; frame = frame->f_back) - { - g_return_val_if_fail(frame->f_globals != NULL, NULL); - PyObject *script = PyDict_GetItemString(frame->f_globals, "_script"); - if (script && pyscript_check(script)) - { - /* - PySys_WriteStdout("Found script at %s in %s, script -> 0x%x\n", - PyString_AS_STRING(frame->f_code->co_name), - PyString_AS_STRING(frame->f_code->co_filename), script); - */ - return script; - } - } - - return NULL; -} - -char *pyloader_find_script_name(void) -{ - PyObject *script = pyloader_find_script_obj(); - - if (!script) - return NULL; - - return pyscript_get_name(script); -} - -GSList *pyloader_list(void) -{ - int i; - GSList *list = NULL; - - g_return_val_if_fail(script_modules != NULL, NULL); - - for (i = 0; i < PyList_Size(script_modules); i++) - { - PyObject *scr; - char *name, *file; - - scr = PyList_GET_ITEM(script_modules, i); - name = pyscript_get_name(scr); - file = pyscript_get_filename(scr); - - if (name && file) - { - PY_LIST_REC *rec; - rec = g_new0(PY_LIST_REC, 1); - - rec->name = g_strdup(name); - rec->file = g_strdup(file); - list = g_slist_append(list, rec); - } - } - - return list; -} - -void pyloader_list_destroy(GSList **list) -{ - GSList *node; - - if (*list == NULL) - return; - - for (node = *list; node != NULL; node = node->next) - { - PY_LIST_REC *rec = node->data; - - g_free(rec->name); - g_free(rec->file); - g_free(rec); - } - - g_slist_free(*list); - - *list = NULL; -} - -int pyloader_init(void) -{ - char *pyhome; - - g_return_val_if_fail(script_paths == NULL, 0); - g_return_val_if_fail(script_modules == NULL, 0); - - script_modules = PyList_New(0); - if (!script_modules) - return 0; - - /* XXX: load autorun scripts here */ - /* Add script location to the load path (add more paths later) */ - pyhome = g_strdup_printf("%s/scripts", get_irssi_dir()); - pyloader_add_script_path(pyhome); - g_free(pyhome); - - return 1; -} - -static void py_clear_scripts() -{ - int i; - - for (i = 0; i < PyList_Size(script_modules); i++) - { - PyObject *scr = PyList_GET_ITEM(script_modules, i); - pyscript_cleanup(scr); - } - - Py_DECREF(script_modules); -} - -void pyloader_deinit(void) -{ - GSList *node; - - g_return_if_fail(script_paths != NULL); - g_return_if_fail(script_modules != NULL); - - for (node = script_paths; node != NULL; node = node->next) - g_free(node->data); - g_slist_free(script_paths); - script_paths = NULL; - - py_clear_scripts(); -} diff --git a/pyloader.h b/pyloader.h deleted file mode 100644 index b7befd3..0000000 --- a/pyloader.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef _PYLOADER_H_ -#define _PYLOADER_H_ - -typedef struct -{ - char *name; - char *file; -} PY_LIST_REC; - -void pyloader_add_script_path(const char *path); -int pyloader_load_script_argv(char **argv); -int pyloader_load_script(char *name); -int pyloader_unload_script(const char *name); -PyObject *pyloader_find_script_obj(void); -char *pyloader_find_script_name(void); - -GSList *pyloader_list(void); -void pyloader_list_destroy(GSList **list); - -int pyloader_init(void); -void pyloader_deinit(void); - -#endif diff --git a/pymodule.c b/pymodule.c deleted file mode 100644 index 7795c1a..0000000 --- a/pymodule.c +++ /dev/null @@ -1,1909 +0,0 @@ -#include -#include "pymodule.h" -#include "pyirssi_irc.h" -#include "factory.h" -#include "pyutils.h" -#include "pysignals.h" -#include "pyloader.h" -#include "pythemes.h" -#include "pystatusbar.h" - -/* - * This module is some what different than the Perl's. - * Script specific operations are handled by the Script object - * instead of by a function in this module. command_bind, - * signal_add, etc require data to be saved about the script - * for cleanup purposes, so I moved those functions to the script - * object. - */ - -/* Main embedded module */ -PyObject *py_module = NULL; - -/* Module functions */ -/*XXX: prefix PY to avoid ambiguity with py_command function */ -PyDoc_STRVAR(PY_command_doc, - "command(cmd) -> None\n" - "\n" - "Execute command\n" -); -static PyObject *PY_command(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"cmd", NULL}; - char *cmd = ""; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &cmd)) - return NULL; - - py_command(cmd, NULL, NULL); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(py_prnt_doc, - "prnt(text, msglvl=MSGLEVEL_CLIENTNOTICE) -> None\n" - "\n" - "print output\n" -); -/*XXX: print is a python keyword, so abbreviate it */ -static PyObject *py_prnt(PyObject *self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = {"text", "msglvl", NULL}; - int msglvl = MSGLEVEL_CLIENTNOTICE; - char *text = NULL; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:prnt", kwlist, - &text, &msglvl)) - return NULL; - - printtext_string(NULL, NULL, msglvl, text); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(py_get_script_doc, - "get_script() -> Script object\n" - "\n" - "Find current Irssi script object\n" -); -static PyObject *py_get_script(PyObject *self, PyObject *args) -{ - PyObject *ret = pyloader_find_script_obj(); - - /* XXX: type check */ - - if (!ret) - PyErr_SetString(PyExc_RuntimeError, "unable to find script object"); - else - Py_INCREF(ret); - - return ret; -} - -PyDoc_STRVAR(py_chatnet_find_doc, - "chatnet_find(name) -> Chatnet object or None\n" - "\n" - "Find chat network with name\n" -); -static PyObject *py_chatnet_find(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"name", NULL}; - char *name = ""; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &name)) - return NULL; - - return py_irssi_chat_new(chatnet_find(name), 1); -} - -PyDoc_STRVAR(py_chatnets_doc, - "chatnets() -> list of Chatnet objects\n" - "\n" - "Return a list of all chatnets\n" -); -static PyObject *py_chatnets(PyObject *self, PyObject *args) -{ - return py_irssi_chatlist_new(chatnets, 1); -} - -PyDoc_STRVAR(py_reconnects_doc, - "reconnects() -> list of Reconnect objects\n" - "\n" - "Return a list of all reconnects\n" -); -static PyObject *py_reconnects(PyObject *self, PyObject *args) -{ - return py_irssi_objlist_new(reconnects, 1, (InitFunc)pyreconnect_new); -} - -PyDoc_STRVAR(py_servers_doc, - "servers() -> list of Server objects\n" - "\n" - "Return a list of all servers\n" -); -static PyObject *py_servers(PyObject *self, PyObject *args) -{ - return py_irssi_chatlist_new(servers, 1); -} - -PyDoc_STRVAR(py_channels_doc, - "channels() -> list of Channel objects\n" - "\n" - "Return channel list\n" -); -static PyObject *py_channels(PyObject *self, PyObject *args) -{ - return py_irssi_chatlist_new(channels, 1); -} - -PyDoc_STRVAR(py_channel_find_doc, - "channel_find(name) -> Channel object or None\n" - "\n" - "Find channel from any server\n" -); -static PyObject *py_channel_find(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"name", NULL}; - char *name = ""; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &name)) - return NULL; - - return py_irssi_chat_new(channel_find(NULL, name), 1); -} - -PyDoc_STRVAR(py_windows_doc, - "windows() -> list of Window objects\n" - "\n" - "Get a list of all windows\n" -); -static PyObject *py_windows(PyObject *self, PyObject *args) -{ - return py_irssi_objlist_new(windows, 1, (InitFunc)pywindow_new); -} - -PyDoc_STRVAR(py_active_win_doc, - "active_win() -> Window object\n" - "\n" - "Return active window\n" -); -static PyObject *py_active_win(PyObject *self, PyObject *args) -{ - if (active_win) - return pywindow_new(active_win); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(py_active_server_doc, - "active_server() -> Server object or None\n" - "\n" - "Return active server\n" -); -static PyObject *py_active_server(PyObject *self, PyObject *args) -{ - if (active_win) - return py_irssi_chat_new(active_win->active_server, 1); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(py_window_find_name_doc, - "window_find_name(name) -> Window object or None\n" - "\n" - "Find window with name\n" -); -static PyObject *py_window_find_name(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"name", NULL}; - char *name = ""; - WINDOW_REC *win; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &name)) - return NULL; - - win = window_find_name(name); - if (win) - return pywindow_new(win); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(py_window_find_refnum_doc, - "window_find_refnum(refnum) -> Window object or None\n" - "\n" - "Find window with reference number\n" -); -static PyObject *py_window_find_refnum(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"refnum", NULL}; - int refnum = 0; - WINDOW_REC *win; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, - &refnum)) - return NULL; - - win = window_find_refnum(refnum); - if (win) - return pywindow_new(win); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(py_window_refnum_prev_doc, - "window_refnum_prev(refnum, wrap) -> int\n" - "\n" - "Return refnum for window that's previous in window list\n" -); -static PyObject *py_window_refnum_prev(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"refnum", "wrap", NULL}; - int refnum = 0; - int wrap = 0; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwlist, - &refnum, &wrap)) - return NULL; - - return PyInt_FromLong(window_refnum_prev(refnum, wrap)); -} - -PyDoc_STRVAR(py_window_refnum_next_doc, - "window_refnum_next(refnum, wrap) -> int\n" - "\n" - "Return refnum for window that's next in window list\n" -); -static PyObject *py_window_refnum_next(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"refnum", "wrap", NULL}; - int refnum = 0; - int wrap = 0; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwlist, - &refnum, &wrap)) - return NULL; - - return PyInt_FromLong(window_refnum_next(refnum, wrap)); -} - -PyDoc_STRVAR(py_windows_refnum_last_doc, - "windows_refnum_last() -> int\n" - "\n" - "Return refnum for last window.\n" -); -static PyObject *py_windows_refnum_last(PyObject *self, PyObject *args) -{ - return PyInt_FromLong(windows_refnum_last()); -} - -PyDoc_STRVAR(py_window_find_level_doc, - "window_find_level(level) -> Window object or None\n" - "\n" - "Find window with level.\n" -); -static PyObject *py_window_find_level(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"level", NULL}; - int level = 0; - WINDOW_REC *win; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, - &level)) - return NULL; - - win = window_find_level(NULL, level); - if (win) - return pywindow_new(win); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(py_window_find_item_doc, - "window_find_item(name) -> Window object or None\n" - "\n" - "Find window which contains window item with specified name.\n" -); -static PyObject *py_window_find_item(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"name", NULL}; - char *name = ""; - WINDOW_REC *win; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &name)) - return NULL; - - win = window_find_item(NULL, name); - if (win) - return pywindow_new(win); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(py_window_find_closest_doc, - "window_find_closest(name, level) -> Window object or None\n" - "\n" - "Find window that matches best to given arguments. `name' can be either\n" - "window name or name of one of the window items.\n" -); -static PyObject *py_window_find_closest(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"name", "level", NULL}; - char *name = ""; - int level = 0; - WINDOW_REC *win; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "si", kwlist, - &name, &level)) - return NULL; - - win = window_find_closest(NULL, name, level); - if (win) - return pywindow_new(win); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(py_window_item_find_doc, - "window_item_find(name) -> WindowItem object or None\n" - "\n" - "Find window item that matches best to given arguments.\n" -); -static PyObject *py_window_item_find(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"name", NULL}; - char *name = ""; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &name)) - return NULL; - - return py_irssi_chat_new(window_item_find(NULL, name), 1); -} - -/*XXX: this could be __init__ for Window */ -PyDoc_STRVAR(py_window_create_doc, - "window_create(item=None, automatic=False) -> Window object\n" - "\n" - "Create a new window\n" -); -static PyObject *py_window_create(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"item", "automatic", NULL}; - PyObject *item = NULL; - int automatic = 0; - WI_ITEM_REC *witem = NULL; - WINDOW_REC *win; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oi", kwlist, - &item, &automatic)) - return NULL; - - if (item) - { - if (pywindow_item_check(item)) - { - witem = ((PyWindowItem*)item)->data; - if (!witem) - return PyErr_Format(PyExc_TypeError, "invalid window item"); - else if (witem->server != NULL) - return PyErr_Format(PyExc_TypeError, "window item already assigned to window"); - } - else if (item == Py_None) - ; - else - return PyErr_Format(PyExc_TypeError, "item must be window item or None"); - } - - win = window_create(witem, automatic); - if (win) - return pywindow_new(win); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(py_server_find_tag_doc, - "server_find_tag(tag) -> Server object or None\n" - "\n" - "Find server with tag\n" -); -static PyObject *py_server_find_tag(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"tag", NULL}; - char *tag = ""; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &tag)) - return NULL; - - return py_irssi_chat_new(server_find_tag(tag), 1); -} - -PyDoc_STRVAR(py_server_find_chatnet_doc, - "server_find_chatnet(chatnet) -> Server object or None\n" - "\n" - "Find first server that is in chatnet\n" -); -static PyObject *py_server_find_chatnet(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"chatnet", NULL}; - char *chatnet = ""; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &chatnet)) - return NULL; - - return py_irssi_chat_new(server_find_chatnet(chatnet), 1); -} - -PyDoc_STRVAR(py_queries_doc, - "queries() -> list of Query objects\n" - "\n" - "Return a list of open queries.\n" -); -static PyObject *py_queries(PyObject *self, PyObject *args) -{ - return py_irssi_chatlist_new(queries, 1); -} - -PyDoc_STRVAR(py_query_find_doc, - "query_find(nick) -> Query object or None\n" - "\n" - "Find a query from any server.\n" -); -static PyObject *py_query_find(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"nick", NULL}; - char *nick = ""; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &nick)) - return NULL; - - return py_irssi_chat_new(query_find(NULL, nick), 1); -} - -PyDoc_STRVAR(py_mask_match_doc, - "mask_match(mask, nick, user, host) -> bool\n" - "\n" - "Return true if mask matches nick!user@host\n" -); -static PyObject *py_mask_match(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"mask", "nick", "user", "host", NULL}; - char *mask = ""; - char *nick = ""; - char *user = ""; - char *host = ""; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "ssss", kwlist, - &mask, &nick, &user, &host)) - return NULL; - - return PyBool_FromLong(mask_match(NULL, mask, nick, user, host)); -} - -PyDoc_STRVAR(py_mask_match_address_doc, - "mask_match_address(mask, nick, address) -> bool\n" - "\n" - "Return True if mask matches nick!address\n" -); -static PyObject *py_mask_match_address(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"mask", "nick", "address", NULL}; - char *mask = ""; - char *nick = ""; - char *address = ""; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "sss", kwlist, - &mask, &nick, &address)) - return NULL; - - return PyBool_FromLong(mask_match_address(NULL, mask, nick, address)); -} - -PyDoc_STRVAR(py_masks_match_doc, - "masks_match(masks, nick, address) -> bool\n" - "\n" - "Return True if any mask in the masks (string separated by spaces)\n" - "matches nick!address\n" -); -static PyObject *py_masks_match(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"masks", "nick", "address", NULL}; - char *masks = ""; - char *nick = ""; - char *address = ""; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "sss", kwlist, - &masks, &nick, &address)) - return NULL; - - return PyBool_FromLong(masks_match(NULL, masks, nick, address)); -} - -PyDoc_STRVAR(py_rawlog_set_size_doc, - "rawlog_set_size(lines) -> None\n" - "\n" - "Set the default rawlog size for new rawlogs.\n" -); -static PyObject *py_rawlog_set_size(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"lines", NULL}; - int lines = 0; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, - &lines)) - return NULL; - - rawlog_set_size(lines); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(py_logs_doc, - "logs() -> list of Log objects\n" - "\n" - "Return list of logs.\n" -); -static PyObject *py_logs(PyObject *self, PyObject *args) -{ - return py_irssi_objlist_new(logs, 1, (InitFunc)pylog_new); -} - -PyDoc_STRVAR(py_log_find_doc, - "log_find(fname) -> Log object or None\n" - "\n" - "Find log by file name.\n" -); -static PyObject *py_log_find(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"fname", NULL}; - char *fname = ""; - LOG_REC *log; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &fname)) - return NULL; - - log = log_find(fname); - if (log) - return pylog_new(log); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(py_ignores_doc, - "ignores() -> list of Ignore objects\n" - "\n" - "Return a list of ignore entries\n" -); -static PyObject *py_ignores(PyObject *self, PyObject *args) -{ - return py_irssi_objlist_new(ignores, 1, (InitFunc)pyignore_new); -} - -PyDoc_STRVAR(py_ignore_check_doc, - "ignore_check(nick, host, channel, text, level) -> bool\n" - "\n" - "Return True if ignore matches\n" -); -static PyObject *py_ignore_check(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"nick", "host", "channel", "text", "level", NULL}; - char *nick = ""; - char *host = ""; - char *channel = ""; - char *text = ""; - int level = 0; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "ssssi", kwlist, - &nick, &host, &channel, &text, &level)) - return NULL; - - return PyBool_FromLong(ignore_check(NULL, nick, host, channel, text, level)); -} - -PyDoc_STRVAR(py_dccs_doc, - "dccs() -> list of Dcc objects\n" - "\n" - "Return list of active DCCs\n" -); -static PyObject *py_dccs(PyObject *self, PyObject *args) -{ - return py_irssi_list_new(dcc_conns, 1); -} - -PyDoc_STRVAR(py_dcc_register_type_doc, - "dcc_register_type(type) -> None\n" - "\n" - "???\n" -); -static PyObject *py_dcc_register_type(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"type", NULL}; - char *type = ""; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &type)) - return NULL; - - dcc_register_type(type); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(py_dcc_unregister_type_doc, - "dcc_unregister_type(type) -> None\n" - "\n" - "???\n" -); -static PyObject *py_dcc_unregister_type(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"type", NULL}; - char *type = ""; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &type)) - return NULL; - - dcc_unregister_type(type); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(py_dcc_find_request_latest_doc, - "dcc_find_request_latest(type) -> Dcc object or None\n" - "\n" - "???\n" -); -static PyObject *py_dcc_find_request_latest(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"type", NULL}; - int type = 0; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, - &type)) - return NULL; - - return py_irssi_new(dcc_find_request_latest(type), 1); -} - -PyDoc_STRVAR(py_dcc_find_request_doc, - "dcc_find_request(type, nick, arg) -> Dcc object or None\n" - "\n" - "???\n" -); -static PyObject *py_dcc_find_request(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"type", "nick", "arg", NULL}; - int type = 0; - char *nick = ""; - char *arg = ""; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "iss", kwlist, - &type, &nick, &arg)) - return NULL; - - return py_irssi_new(dcc_find_request(type, nick, arg), 1); -} - -PyDoc_STRVAR(py_dcc_chat_find_id_doc, - "dcc_chat_find_id(id) -> Dcc object or None\n" - "\n" - "???\n" -); -static PyObject *py_dcc_chat_find_id(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"id", NULL}; - char *id = ""; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &id)) - return NULL; - - return py_irssi_new(dcc_chat_find_id(id), 1); -} - -PyDoc_STRVAR(py_dcc_str2type_doc, - "dcc_str2type(type) -> int\n" - "\n" - "???\n" -); -static PyObject *py_dcc_str2type(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"type", NULL}; - char *type = ""; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &type)) - return NULL; - - return PyInt_FromLong(dcc_str2type(type)); -} - -PyDoc_STRVAR(py_dcc_type2str_doc, - "dcc_type2str(type) -> str or None\n" - "\n" - "???\n" -); -static PyObject *py_dcc_type2str(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"type", NULL}; - int type = 0; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, - &type)) - return NULL; - - RET_AS_STRING_OR_NONE(dcc_type2str(type)); -} - -PyDoc_STRVAR(py_dcc_get_download_path_doc, - "dcc_get_download(fname) -> str\n" - "\n" - "???\n" -); -static PyObject *py_dcc_get_download_path(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"fname", NULL}; - char *fname = ""; - char *path; - PyObject *pypath; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &fname)) - return NULL; - - path = dcc_get_download_path(fname); - if (!path) - Py_RETURN_NONE; /*XXX: how to handle? */ - - pypath = PyString_FromString(path); - g_free(path); - - return pypath; -} - -PyDoc_STRVAR(py_notifies_doc, - "notifies() -> list of Notifylist objects\n" - "\n" - "Return list of notifies\n" -); -static PyObject *py_notifies(PyObject *self, PyObject *args) -{ - return py_irssi_objlist_new(notifies, 1, (InitFunc)pynotifylist_new); -} - -PyDoc_STRVAR(py_notifylist_add_doc, - "notifylist_add(mask, ircnets=None, away_check=0, idle_time_check=0) -> Notifylist object\n" - "\n" - "Add new item to notify list\n" -); -static PyObject *py_notifylist_add(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"mask", "ircnets", "away_check", "idle_check_time", NULL}; - char *mask = ""; - char *ircnets = NULL; - int away_check = 0; - int idle_check_time = 0; - NOTIFYLIST_REC *rec; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|zii", kwlist, - &mask, &ircnets, &away_check, &idle_check_time)) - return NULL; - - rec = notifylist_add(mask, ircnets, away_check, idle_check_time); - if (rec) - return pynotifylist_new(rec); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(py_notifylist_remove_doc, - "notifylist_remove(mask) -> None\n" - "\n" - "Remove notify item from notify list\n" -); -static PyObject *py_notifylist_remove(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"mask", NULL}; - char *mask = ""; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &mask)) - return NULL; - - notifylist_remove(mask); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(py_notifylist_ison_doc, - "notifylist_ison(nick, serverlist=\"\") -> IrcServer object\n" - "\n" - "Check if nick is in IRC. serverlist is a space separated list of server tags.\n" - "If it's empty string, all servers will be checked\n" -); -static PyObject *py_notifylist_ison(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"nick", "serverlist", NULL}; - char *nick = ""; - char *serverlist = ""; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|s", kwlist, - &nick, &serverlist)) - return NULL; - - return py_irssi_chat_new(notifylist_ison(nick, serverlist), 1); -} - -PyDoc_STRVAR(py_notifylist_find_doc, - "notifylist_find(mask, ircnet=None) -> Notifylist object\n" - "\n" - "Find notify\n" -); -static PyObject *py_notifylist_find(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"mask", "ircnet", NULL}; - char *mask = ""; - char *ircnet = NULL; - NOTIFYLIST_REC *rec; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|z", kwlist, - &mask, &ircnet)) - return NULL; - - rec = notifylist_find(mask, ircnet); - if (rec) - return pynotifylist_new(rec); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(py_commands_doc, - "commands() -> list of Command objects\n" - "\n" - "Return a list of all commands.\n" -); -static PyObject *py_commands(PyObject *self, PyObject *args) -{ - return py_irssi_objlist_new(commands, 1, (InitFunc)pycommand_new); -} - -PyDoc_STRVAR(py_level2bits_doc, - "level2bits(level) -> long\n" - "\n" - "Level string -> number\n" -); -static PyObject *py_level2bits(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"level", NULL}; - char *level = ""; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &level)) - return NULL; - - return PyLong_FromUnsignedLong(level2bits(level)); -} - -PyDoc_STRVAR(py_bits2level_doc, - "bits2level(bits) -> str\n" - "\n" - "Level number -> string\n" -); -static PyObject *py_bits2level(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"bits", NULL}; - unsigned bits; - char *str; - PyObject *ret; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "I", kwlist, - &bits)) - return NULL; - - str = bits2level(bits); - if (str) - { - ret = PyString_FromString(str); - g_free(str); - return ret; - } - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(py_combine_level_doc, - "combine_level(level, str) -> long\n" - "\n" - "Combine level number to level string ('+level -level'). Return new level number.\n" -); -static PyObject *py_combine_level(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"level", "str", NULL}; - int level = 0; - char *str = ""; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "is", kwlist, - &level, &str)) - return NULL; - - return PyLong_FromUnsignedLong(combine_level(level, str)); -} - -PyDoc_STRVAR(py_signal_emit_doc, - "signal_emit(signal, *args) -> None\n" - "\n" - "Emit an Irssi signal with up to 6 arguments\n" -); -static PyObject *py_signal_emit(PyObject *self, PyObject *args) -{ - PyObject *pysig; - PyObject *sigargs; - char *name; - int ret; - - if (PyTuple_Size(args) < 1) - return PyErr_Format(PyExc_TypeError, "signal name required"); - - if (PyTuple_Size(args) > SIGNAL_MAX_ARGUMENTS+1) - return PyErr_Format(PyExc_TypeError, - "no more than %d arguments for signal accepted", SIGNAL_MAX_ARGUMENTS); - - pysig = PyTuple_GET_ITEM(args, 0); - if (!PyString_Check(pysig)) - return PyErr_Format(PyExc_TypeError, "signal must be string"); - - name = PyString_AsString(pysig); - if (!name) - return NULL; - - sigargs = PySequence_GetSlice(args, 1, PyTuple_Size(args)); - if (!sigargs) - return NULL; - - ret = pysignals_emit(name, sigargs); - Py_DECREF(sigargs); - if (!ret) - return NULL; - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(py_signal_continue_doc, - "signal_continue(*args) -> None\n" - "\n" - "Continue (reemit?) the current Irssi signal with up to 6 arguments\n" -); -static PyObject *py_signal_continue(PyObject *self, PyObject *args) -{ - if (PyTuple_Size(args) > SIGNAL_MAX_ARGUMENTS) - return PyErr_Format(PyExc_TypeError, - "no more than %d arguments for signal accepted", SIGNAL_MAX_ARGUMENTS); - - if (!pysignals_continue(args)) - return NULL; - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(py_signal_stop_doc, - "signal_stop() -> None\n" - "\n" - "Stop the signal that's currently being emitted.\n" -); -static PyObject *py_signal_stop(PyObject *self, PyObject *args) -{ - signal_stop(); - Py_RETURN_NONE; -} - -PyDoc_STRVAR(py_signal_stop_by_name_doc, - "signal_stop_by_name(signal) -> None\n" - "\n" - "Stop the signal, 'signal', thats currently being emitted by name\n" -); -static PyObject *py_signal_stop_by_name(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"signal", NULL}; - char *signal = ""; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &signal)) - return NULL; - - signal_stop_by_name(signal); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(py_signal_get_emitted_doc, - "signal_get_emmited() -> signal name string\n" - "\n" - "Get name of current signal\n" -); -static PyObject *py_signal_get_emitted(PyObject *self, PyObject *args) -{ - RET_AS_STRING_OR_NONE(signal_get_emitted()); -} - -PyDoc_STRVAR(py_signal_get_emitted_id_doc, - "signal_get_emmited_id() -> signal id int\n" - "\n" - "Get id of current signal\n" -); -static PyObject *py_signal_get_emitted_id(PyObject *self, PyObject *args) -{ - return PyInt_FromLong(signal_get_emitted_id()); -} - -PyDoc_STRVAR(py_settings_get_str_doc, - "settings_get_str(key) -> str\n" - "\n" - "Get value for setting.\n" -); -static PyObject *py_settings_get_str(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"key", NULL}; - char *key = ""; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &key)) - return NULL; - - RET_AS_STRING_OR_NONE(settings_get_str(key)); -} - -PyDoc_STRVAR(py_settings_get_int_doc, - "settings_get_int(key) -> int\n" - "\n" - "Get value for setting." -); -static PyObject *py_settings_get_int(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"key", NULL}; - char *key = ""; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &key)) - return NULL; - - return PyInt_FromLong(settings_get_int(key)); -} - -PyDoc_STRVAR(py_settings_get_bool_doc, - "settings_get_bool(key) -> bool\n" - "\n" - "Get value for setting.\n" -); -static PyObject *py_settings_get_bool(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"key", NULL}; - char *key = ""; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &key)) - return NULL; - - return PyBool_FromLong(settings_get_bool(key)); -} - -PyDoc_STRVAR(py_settings_get_time_doc, - "settings_get_time(key) -> long\n" - "\n" - "Get value for setting.\n" -); -static PyObject *py_settings_get_time(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"key", NULL}; - char *key = ""; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &key)) - return NULL; - - return PyLong_FromLong(settings_get_time(key)); -} - -PyDoc_STRVAR(py_settings_get_level_doc, - "settings_get_level(key) -> int\n" - "\n" - "Get value for setting.\n" -); -static PyObject *py_settings_get_level(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"key", NULL}; - char *key = ""; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &key)) - return NULL; - - return PyInt_FromLong(settings_get_level(key)); -} - -PyDoc_STRVAR(py_settings_get_size_doc, - "settings_get_size(key) -> long\n" - "\n" - "Get value for setting.\n" -); -static PyObject *py_settings_get_size(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"key", NULL}; - char *key = ""; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &key)) - return NULL; - - return PyLong_FromLong(settings_get_size(key)); -} - -PyDoc_STRVAR(py_settings_set_str_doc, - "settings_set_str(key, value) -> None\n" - "\n" - "Set string value for setting\n" -); -static PyObject *py_settings_set_str(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"key", "value", NULL}; - char *key = ""; - char *value = ""; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss", kwlist, - &key, &value)) - return NULL; - - settings_set_str(key, value); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(py_settings_set_int_doc, - "settings_set_int(key, value) -> None\n" - "\n" - "Set int value for setting" -); -static PyObject *py_settings_set_int(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"key", "value", NULL}; - char *key = ""; - int value = 0; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "si", kwlist, - &key, &value)) - return NULL; - - settings_set_int(key, value); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(py_settings_set_bool_doc, - "settings_set_bool(key, value) -> None\n" - "\n" - "Set bool value for setting\n" -); -static PyObject *py_settings_set_bool(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"key", "value", NULL}; - char *key = ""; - int value = 0; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "si", kwlist, - &key, &value)) - return NULL; - - settings_set_bool(key, value); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(py_settings_set_time_doc, - "settings_set_time(key, value) -> bool\n" - "\n" - "Set string value for setting\n" -); -static PyObject *py_settings_set_time(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"key", "value", NULL}; - char *key = ""; - char *value = ""; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss", kwlist, - &key, &value)) - return NULL; - - return PyBool_FromLong(settings_set_time(key, value)); -} - -PyDoc_STRVAR(py_settings_set_level_doc, - "settings_set_level(key, value) -> bool\n" - "\n" - "Set string value for setting\n" -); -static PyObject *py_settings_set_level(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"key", "value", NULL}; - char *key = ""; - char *value = ""; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss", kwlist, - &key, &value)) - return NULL; - - return PyBool_FromLong(settings_set_level(key, value)); -} - -PyDoc_STRVAR(py_settings_set_size_doc, - "settings_set_size(key, value) -> bool\n" - "\n" - "Set string value for setting\n" -); -static PyObject *py_settings_set_size(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"key", "value", NULL}; - char *key = ""; - char *value = ""; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss", kwlist, - &key, &value)) - return NULL; - - return PyBool_FromLong(settings_set_size(key, value)); -} - -PyDoc_STRVAR(py_pidwait_add_doc, - "pidwait_add(pid) -> None\n" - "\n" - "Add pid to wait list\n" -); -static PyObject *py_pidwait_add(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"pid", NULL}; - int pid = 0; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, - &pid)) - return NULL; - - pidwait_add(pid); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(py_pidwait_remove_doc, - "pidwait_remove(pid) -> None\n" - "\n" - "Remove pid from wait list\n" -); -static PyObject *py_pidwait_remove(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"pid", NULL}; - int pid = 0; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, - &pid)) - return NULL; - - pidwait_remove(pid); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(py_format_get_length_doc, - "format_get_length(str) -> int length\n" -); -static PyObject *py_format_get_length(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"str", NULL}; - char *str = ""; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &str)) - return NULL; - - return PyInt_FromLong(format_get_length(str)); -} - -PyDoc_STRVAR(py_format_real_length_doc, - "format_real_length(str, len) -> int length\n" -); -static PyObject *py_format_real_length(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"str", "len", NULL}; - char *str = ""; - int len; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "sl", kwlist, - &str, &len)) - return NULL; - - return PyInt_FromLong(format_real_length(str, len)); -} - -PyDoc_STRVAR(py_strip_codes_doc, - "strip_codes(input) -> str\n" -); -static PyObject *py_strip_codes(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"input", NULL}; - char *input = ""; - char *ret; - PyObject *pyret; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &input)) - return NULL; - - ret = strip_codes(input); - if (ret) - { - pyret = PyString_FromString(ret); - g_free(ret); - return pyret; - } - - Py_RETURN_NONE; -} - -#if 0 -PyDoc_STRVAR(py_format_get_text_doc, - "format_get_text(textdest, module, formatnum, ...) -> str\n" - "\n" - "Return a substituted format string from module and formatnum.\n" - "module is a string.\n" - "\n" - "Example:\n" - "TODO\n" -); -static PyObject *py_format_get_text(PyObject *self, PyObject *varargs) -{ - PyTextDest *textdest = NULL; - char *module = ""; - unsigned int formatnum = 0; - PyObject *args = NULL, *pycharargs = NULL; - THEME_REC *theme; - MODULE_THEME_REC *modtheme; - char **charargs = NULL; - char *ret; - int i; - - args = PySequence_GetSlice(varargs, 0, 3); - if (!args) - goto error; - - pycharargs = PySequence_GetSlice(varargs, 3, PyTuple_Size(varargs)); - if (!pycharargs) - goto error; - - if (!PyArg_ParseTuple(args, "OsI", - &textdest, &module, &formatnum)) - goto error; - - if (!pytextdest_check((PyObject *)textdest)) - { - PyErr_Format(PyExc_TypeError, "arg 1 must be TextDest"); - goto error; - } - - /* Bleh, check that formatnum is within range */ - theme = window_get_theme(textdest->data->window); - - /* FIXME: how to boundscheck formatnum ?? */ - - /* size + 1 for terminating NULL ptr */ - charargs = g_new0(char *, PyTuple_Size(pycharargs) + 1); - - for (i = 0; i < PyTuple_Size(pycharargs); i++) - { - PyObject *obj = PyTuple_GET_ITEM(pycharargs, i); - char *str; - - if (!PyString_Check(obj)) - { - PyErr_Format(PyExc_TypeError, - "non string in string argument list (arg %d)", - i + 4); - goto error; - } - - str = PyString_AsString(obj); - if (!str) - goto error; - - charargs[i] = str; - } - - /* return string, or if string is NULL, return None */ - ret = format_get_text_theme_charargs(theme, module, DATA(textdest), formatnum, charargs); - Py_DECREF(args); - Py_DECREF(pycharargs); - g_free(charargs); - - if (ret) - { - PyObject *pyret; - - pyret = PyString_FromString(ret); - g_free(ret); - - return pyret; - } - - Py_RETURN_NONE; - -error: - Py_XDECREF(args); - Py_XDECREF(pycharargs); - g_free(charargs); - - return NULL; -} -#endif - -PyDoc_STRVAR(py_themes_reload_doc, - "themes_reload() -> None\n" -); -static PyObject *py_themes_reload(PyObject *self, PyObject *args) -{ - themes_reload(); - Py_RETURN_NONE; -} - -PyDoc_STRVAR(py_current_theme_doc, - "current_theme() -> Theme object\n" -); -static PyObject *py_current_theme(PyObject *self, PyObject *args) -{ - if (current_theme) - return pytheme_new(current_theme); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(py_statusbar_items_redraw_doc, - "statusbar_items_redraw(name) -> None\n" -); -static PyObject *py_statusbar_items_redraw(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"name", NULL}; - char *name = ""; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &name)) - return NULL; - - statusbar_items_redraw(name); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(py_statusbars_recreate_items_doc, - "statusbars_recreate_items() -> None" -); -static PyObject *py_statusbars_recreate_items(PyObject *self, PyObject *args) -{ - statusbars_recreate_items(); - - Py_RETURN_NONE; -} - -/* XXX: we can unregister any statusbar items, not just the ones from this script */ -PyDoc_STRVAR(py_statusbar_item_unregister_doc, - "statusbar_item_unregister(name) -> None" -); -static PyObject *py_statusbar_item_unregister(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"name", NULL}; - char *name = ""; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &name)) - return NULL; - - pystatusbar_item_unregister(name); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(py_active_mainwin_doc, - "active_mainwin() -> MainWindow object\n" - "\n" - "return active main window\n" -); -static PyObject *py_active_mainwin(PyObject *self, PyObject *args) -{ - if (!active_mainwin) - Py_RETURN_NONE; - - return pymain_window_new(active_mainwin); -} - -PyDoc_STRVAR(py_mainwindows_doc, - "mainwindows() -> list of MainWindow objects\n" - "\n" - "return a list of mainwindows\n" -); -static PyObject *py_mainwindows(PyObject *self, PyObject *args) -{ - return py_irssi_objlist_new(mainwindows, 1, (InitFunc)pymain_window_new); -} - -/* expect a list of tuples [('str', 0), ...] */ -static GSList *py_register_conv(PyObject *list) -{ - int i; - GSList *ret = NULL; - - if (list == Py_None) - return NULL; - - if (!PyList_Check(list)) - { - PyErr_Format(PyExc_TypeError, "expect a list of tuples of string and int"); - return NULL; - } - - for (i = 0; i < PyList_Size(list); i++) - { - char *key; - int val; - PyObject *tup = PyList_GET_ITEM(list, i); - - if (!PyTuple_Check(tup) || !PyArg_ParseTuple(tup, "si", &key, &val)) - { - if (!PyErr_Occurred() || PyErr_ExceptionMatches(PyExc_TypeError)) - { - PyErr_Clear(); - PyErr_SetString(PyExc_TypeError, "expect a list of tuples of string and int"); - } - - /* return the list so far; caller will clear it on error */ - break; - } - - ret = g_slist_append(ret, g_strdup(key)); - ret = g_slist_append(ret, GINT_TO_POINTER(val)); - } - - return ret; -} - -PyDoc_STRVAR(py_server_redirect_register_doc, - "server_redirect_register(command, stop, start=None, opt=None, remote=False, timeout=0) -> None\n" - "\n" - "Register new redirection command. By default irssi has already\n" - "registered at least: whois, whowas, who, list, ison, userhost, ping,\n" - "\"mode channel\" (/MODE #channel), \"mode b\" (/MODE #channel b), \"mode e\"\n" - "and \"mode I\".\n" - "\n" - "`command' specifies the name of the command to register, it doesn't\n" - "have to be a real command name, but something you just specify to\n" - "Server.redirect_event() when using this redirection.\n" - "\n" - "`start', `stop', `opt' - lists of ('event', argpos) tuples.\n" - "List of events that start and stop this redirection.\n" - "Start event list may be empty, but there must be at least one\n" - "stop event. Optional events are checked only if they are received\n" - "immediately after one of the stop-events. `argpos' specifies the\n" - "word number in event string which is compared to wanted argument,\n" - "-1 = don't compare, TRUE always.\n" - "\n" - "`remote' specifies if the command is by default a remote command\n" - "(eg. sent to another server). Server.redirect_event() may override this.\n" - "\n" - "`timeout' - If remote is TRUE, specifies how many seconds to wait for\n" - "reply before aborting.\n" - "\n" - "Example (already done by irssi):\n" - "\n" - "server_redirect_register('mode channel',\n" - " start = None,\n" - " stop = [ \n" - " ('event 324', 1), # MODE-reply\n" - " ('event 403', 1), # no such channel\n" - " ('event 442', 1), # \"you're not on that channel\"\n" - " ('event 479', 1) # \"Cannot join channel (illegal name)\"\n" - " ], \n" - " opt = [ \n" - " ('event 329', 1) # Channel create time\n" - " ] \n" - ")\n" -); -static PyObject *py_server_redirect_register(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"command", "stop", "start", "opt", "remote", "timeout", NULL}; - char *command = ""; - int remote = 0; - int timeout = 0; - PyObject *start = NULL; - PyObject *stop = NULL; - PyObject *opt = NULL; - GSList *node; - GSList *gstart = NULL; - GSList *gstop = NULL; - GSList *gopt = NULL; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "sO|OOii", kwlist, - &command, &stop, &start, &opt, &remote, &timeout)) - return NULL; - - gstart = py_register_conv(start); - if (PyErr_Occurred()) - goto error; - - gstop = py_register_conv(stop); - if (!gstop || PyErr_Occurred()) - { - if (!PyErr_Occurred()) - PyErr_SetString(PyExc_TypeError, "stop list must be provided"); - - goto error; - } - - gopt = py_register_conv(opt); - if (PyErr_Occurred()) - goto error; - - server_redirect_register_list(command, remote, timeout, gstart, gstop, gopt); - - Py_RETURN_NONE; - -error: - /* clean up all lists */ - for (node = gstart; node; node = node->next->next) - g_free(node->data); - for (node = gstop; node; node = node->next->next) - g_free(node->data); - for (node = gopt; node; node = node->next->next) - g_free(node->data); - - g_slist_free(gstart); - g_slist_free(gstop); - g_slist_free(gopt); - - return NULL; - -} - -PyDoc_STRVAR(py_command_runsub_doc, - "command_runsub(cmd, data, server=None, item=None) -> None\n" - "\n" - "Run subcommands for `cmd'. First word in `data' is parsed as\n" - "subcommand. `server' is Server object for current\n" - "WindowItem `item'.\n" - "\n" - "Call command_runsub in handler function for `cmd' and bind\n" - "with command_bind(\"`cmd' `subcmd'\", subcmdfunc[, category]);\n" -); -static PyObject *py_command_runsub(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"cmd", "data", "server", "item", NULL}; - char *cmd = ""; - char *data = ""; - PyObject *pserver = Py_None; - PyObject *pitem = Py_None; - SERVER_REC *server = NULL; - WI_ITEM_REC *item = NULL; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss|OO", kwlist, - &cmd, &data, &pserver, &pitem)) - return NULL; - - if (pserver != Py_None && !pyserver_check(pserver)) - return PyErr_Format(PyExc_TypeError, "server must be a server"); - - if (pitem != Py_None && !pywindow_item_check(pitem)) - return PyErr_Format(PyExc_TypeError, "item must be a window item"); - - if (pserver != Py_None) - server = DATA(pserver); - - if (pitem != Py_None) - item = DATA(pitem); - - command_runsub(cmd, data, server, item); - - Py_RETURN_NONE; -} - -static PyMethodDef ModuleMethods[] = { - {"prnt", (PyCFunction)py_prnt, METH_VARARGS | METH_KEYWORDS, - py_prnt_doc}, - {"get_script", (PyCFunction)py_get_script, METH_NOARGS, - py_get_script_doc}, - {"chatnet_find", (PyCFunction)py_chatnet_find, METH_VARARGS | METH_KEYWORDS, - py_chatnet_find_doc}, - {"chatnets", (PyCFunction)py_chatnets, METH_NOARGS, - py_chatnets_doc}, - {"reconnects", (PyCFunction)py_reconnects, METH_NOARGS, - py_reconnects_doc}, - {"servers", (PyCFunction)py_servers, METH_NOARGS, - py_servers_doc}, - {"windows", (PyCFunction)py_windows, METH_NOARGS, - py_windows_doc}, - {"active_win", (PyCFunction)py_active_win, METH_NOARGS, - py_active_win_doc}, - {"active_server", (PyCFunction)py_active_server, METH_NOARGS, - py_active_server_doc}, - {"window_find_name", (PyCFunction)py_window_find_name, METH_VARARGS | METH_KEYWORDS, - py_window_find_name_doc}, - {"window_find_refnum", (PyCFunction)py_window_find_refnum, METH_VARARGS | METH_KEYWORDS, - py_window_find_refnum_doc}, - {"window_refnum_prev", (PyCFunction)py_window_refnum_prev, METH_VARARGS | METH_KEYWORDS, - py_window_refnum_prev_doc}, - {"window_refnum_next", (PyCFunction)py_window_refnum_next, METH_VARARGS | METH_KEYWORDS, - py_window_refnum_next_doc}, - {"windows_refnum_last", (PyCFunction)py_windows_refnum_last, METH_NOARGS, - py_windows_refnum_last_doc}, - {"window_find_level", (PyCFunction)py_window_find_level, METH_VARARGS | METH_KEYWORDS, - py_window_find_level_doc}, - {"window_find_item", (PyCFunction)py_window_find_item, METH_VARARGS | METH_KEYWORDS, - py_window_find_item_doc}, - {"window_find_closest", (PyCFunction)py_window_find_closest, METH_VARARGS | METH_KEYWORDS, - py_window_find_closest_doc}, - {"window_item_find", (PyCFunction)py_window_item_find, METH_VARARGS | METH_KEYWORDS, - py_window_item_find_doc}, - {"window_create", (PyCFunction)py_window_create, METH_VARARGS | METH_KEYWORDS, - py_window_create_doc}, - {"server_find_tag", (PyCFunction)py_server_find_tag, METH_VARARGS | METH_KEYWORDS, - py_server_find_tag_doc}, - {"server_find_chatnet", (PyCFunction)py_server_find_chatnet, METH_VARARGS | METH_KEYWORDS, - py_server_find_chatnet_doc}, - {"command", (PyCFunction)PY_command, METH_VARARGS | METH_KEYWORDS, - PY_command_doc}, - {"channels", (PyCFunction)py_channels, METH_NOARGS, - py_channels_doc}, - {"channel_find", (PyCFunction)py_channel_find, METH_VARARGS | METH_KEYWORDS, - py_channel_find_doc}, - {"query_find", (PyCFunction)py_query_find, METH_VARARGS | METH_KEYWORDS, - py_query_find_doc}, - {"queries", (PyCFunction)py_queries, METH_NOARGS, - py_queries_doc}, - {"mask_match", (PyCFunction)py_mask_match, METH_VARARGS | METH_KEYWORDS, - py_mask_match_doc}, - {"mask_match_address", (PyCFunction)py_mask_match_address, METH_VARARGS | METH_KEYWORDS, - py_mask_match_address_doc}, - {"masks_match", (PyCFunction)py_masks_match, METH_VARARGS | METH_KEYWORDS, - py_masks_match_doc}, - {"rawlog_set_size", (PyCFunction)py_rawlog_set_size, METH_VARARGS | METH_KEYWORDS, - py_rawlog_set_size_doc}, - {"logs", (PyCFunction)py_logs, METH_NOARGS, - py_logs_doc}, - {"log_find", (PyCFunction)py_log_find, METH_VARARGS | METH_KEYWORDS, - py_log_find_doc}, - {"ignores", (PyCFunction)py_ignores, METH_NOARGS, - py_ignores_doc}, - {"ignore_check", (PyCFunction)py_ignore_check, METH_VARARGS | METH_KEYWORDS, - py_ignore_check_doc}, - {"dccs", (PyCFunction)py_dccs, METH_NOARGS, - py_dccs_doc}, - {"dcc_register_type", (PyCFunction)py_dcc_register_type, METH_VARARGS | METH_KEYWORDS, - py_dcc_register_type_doc}, - {"dcc_unregister_type", (PyCFunction)py_dcc_unregister_type, METH_VARARGS | METH_KEYWORDS, - py_dcc_unregister_type_doc}, - {"dcc_find_request_latest", (PyCFunction)py_dcc_find_request_latest, METH_VARARGS | METH_KEYWORDS, - py_dcc_find_request_latest_doc}, - {"dcc_find_request", (PyCFunction)py_dcc_find_request, METH_VARARGS | METH_KEYWORDS, - py_dcc_find_request_doc}, - {"dcc_chat_find_id", (PyCFunction)py_dcc_chat_find_id, METH_VARARGS | METH_KEYWORDS, - py_dcc_chat_find_id_doc}, - {"dcc_str2type", (PyCFunction)py_dcc_str2type, METH_VARARGS | METH_KEYWORDS, - py_dcc_str2type_doc}, - {"dcc_type2str", (PyCFunction)py_dcc_type2str, METH_VARARGS | METH_KEYWORDS, - py_dcc_type2str_doc}, - {"dcc_get_download_path", (PyCFunction)py_dcc_get_download_path, METH_VARARGS | METH_KEYWORDS, - py_dcc_get_download_path_doc}, - {"notifies", (PyCFunction)py_notifies, METH_NOARGS, - py_notifies_doc}, - {"notifylist_add", (PyCFunction)py_notifylist_add, METH_VARARGS | METH_KEYWORDS, - py_notifylist_add_doc}, - {"notifylist_remove", (PyCFunction)py_notifylist_remove, METH_VARARGS | METH_KEYWORDS, - py_notifylist_remove_doc}, - {"notifylist_ison", (PyCFunction)py_notifylist_ison, METH_VARARGS | METH_KEYWORDS, - py_notifylist_ison_doc}, - {"notifylist_find", (PyCFunction)py_notifylist_find, METH_VARARGS | METH_KEYWORDS, - py_notifylist_find_doc}, - {"commands", (PyCFunction)py_commands, METH_NOARGS, - py_commands_doc}, - {"level2bits", (PyCFunction)py_level2bits, METH_VARARGS | METH_KEYWORDS, - py_level2bits_doc}, - {"bits2level", (PyCFunction)py_bits2level, METH_VARARGS | METH_KEYWORDS, - py_bits2level_doc}, - {"combine_level", (PyCFunction)py_combine_level, METH_VARARGS | METH_KEYWORDS, - py_combine_level_doc}, - {"signal_emit", (PyCFunction)py_signal_emit, METH_VARARGS, - py_signal_emit_doc}, - {"signal_stop", (PyCFunction)py_signal_stop, METH_NOARGS, - py_signal_stop_doc}, - {"signal_stop_by_name", (PyCFunction)py_signal_stop_by_name, METH_VARARGS | METH_KEYWORDS, - py_signal_stop_by_name_doc}, - {"signal_get_emitted", (PyCFunction)py_signal_get_emitted, METH_NOARGS, - py_signal_get_emitted_doc}, - {"signal_get_emitted_id", (PyCFunction)py_signal_get_emitted_id, METH_NOARGS, - py_signal_get_emitted_id_doc}, - {"signal_continue", (PyCFunction)py_signal_continue, METH_VARARGS, - py_signal_continue_doc}, - {"settings_get_str", (PyCFunction)py_settings_get_str, METH_VARARGS | METH_KEYWORDS, - py_settings_get_str_doc}, - {"settings_get_int", (PyCFunction)py_settings_get_int, METH_VARARGS | METH_KEYWORDS, - py_settings_get_int_doc}, - {"settings_get_bool", (PyCFunction)py_settings_get_bool, METH_VARARGS | METH_KEYWORDS, - py_settings_get_bool_doc}, - {"settings_get_time", (PyCFunction)py_settings_get_time, METH_VARARGS | METH_KEYWORDS, - py_settings_get_time_doc}, - {"settings_get_level", (PyCFunction)py_settings_get_level, METH_VARARGS | METH_KEYWORDS, - py_settings_get_level_doc}, - {"settings_get_size", (PyCFunction)py_settings_get_size, METH_VARARGS | METH_KEYWORDS, - py_settings_get_size_doc}, - {"settings_set_str", (PyCFunction)py_settings_set_str, METH_VARARGS | METH_KEYWORDS, - py_settings_set_str_doc}, - {"settings_set_int", (PyCFunction)py_settings_set_int, METH_VARARGS | METH_KEYWORDS, - py_settings_set_int_doc}, - {"settings_set_bool", (PyCFunction)py_settings_set_bool, METH_VARARGS | METH_KEYWORDS, - py_settings_set_bool_doc}, - {"settings_set_time", (PyCFunction)py_settings_set_time, METH_VARARGS | METH_KEYWORDS, - py_settings_set_time_doc}, - {"settings_set_level", (PyCFunction)py_settings_set_level, METH_VARARGS | METH_KEYWORDS, - py_settings_set_level_doc}, - {"settings_set_size", (PyCFunction)py_settings_set_size, METH_VARARGS | METH_KEYWORDS, - py_settings_set_size_doc}, - {"pidwait_add", (PyCFunction)py_pidwait_add, METH_VARARGS | METH_KEYWORDS, - py_pidwait_add_doc}, - {"pidwait_remove", (PyCFunction)py_pidwait_remove, METH_VARARGS | METH_KEYWORDS, - py_pidwait_remove_doc}, - {"format_get_length", (PyCFunction)py_format_get_length, METH_VARARGS | METH_KEYWORDS, - py_format_get_length_doc}, - {"format_real_length", (PyCFunction)py_format_real_length, METH_VARARGS | METH_KEYWORDS, - py_format_real_length_doc}, - {"strip_codes", (PyCFunction)py_strip_codes, METH_VARARGS | METH_KEYWORDS, - py_strip_codes_doc}, - /*{"format_get_text", (PyCFunction)py_format_get_text, METH_VARARGS, - py_format_get_text_doc},*/ - {"themes_reload", (PyCFunction)py_themes_reload, METH_NOARGS, - py_themes_reload_doc}, - {"current_theme", (PyCFunction)py_current_theme, METH_NOARGS, - py_current_theme_doc}, - {"statusbar_items_redraw", (PyCFunction)py_statusbar_items_redraw, METH_VARARGS | METH_KEYWORDS, - py_statusbar_items_redraw_doc}, - {"statusbars_recreate_items", (PyCFunction)py_statusbars_recreate_items, METH_NOARGS, - py_statusbars_recreate_items_doc}, - {"statusbar_item_unregister", (PyCFunction)py_statusbar_item_unregister, METH_VARARGS | METH_KEYWORDS, - py_statusbar_item_unregister_doc}, - {"active_mainwin", (PyCFunction)py_active_mainwin, METH_NOARGS, - py_active_mainwin_doc}, - {"mainwindows", (PyCFunction)py_mainwindows, METH_NOARGS, - py_mainwindows_doc}, - {"server_redirect_register", (PyCFunction)py_server_redirect_register, METH_VARARGS | METH_KEYWORDS, - py_server_redirect_register_doc}, - {"command_runsub", (PyCFunction)py_command_runsub, METH_VARARGS | METH_KEYWORDS, - py_command_runsub_doc}, - {NULL, NULL, 0, NULL} /* Sentinel */ -}; - -int pymodule_init(void) -{ - g_return_val_if_fail(py_module == NULL, 0); - - py_module = Py_InitModule("_irssi", ModuleMethods); - if (!py_module) - return 0; - - return 1; -} - -void pymodule_deinit(void) -{ - g_return_if_fail(py_module != NULL); - - Py_DECREF(py_module); - py_module = NULL; -} diff --git a/pymodule.h b/pymodule.h deleted file mode 100644 index 242eecf..0000000 --- a/pymodule.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef _PY_MODULE_H_ -#define _PY_MODULE_H_ - -#include - -/* This is global so that type objects and such can be easily attached */ -extern PyObject *py_module; -int pymodule_init(void); -void pymodule_deinit(void); - -#endif diff --git a/pysigmap.h b/pysigmap.h deleted file mode 100644 index c34fbf7..0000000 --- a/pysigmap.h +++ /dev/null @@ -1,188 +0,0 @@ -/* Include in your C module */ -static PY_SIGNAL_SPEC_REC py_sigmap[] = { - {"gui exit", "", 0, 0, 0}, - {"gui dialog", "ss", 0, 0, 0}, - {"send command", "sSW", 0, 0, 0}, - {"chat protocol created", "?", 0, 0, 0}, - {"chat protocol updated", "?", 0, 0, 0}, - {"chat protocol destroyed", "?", 0, 0, 0}, - {"channel created", "Ci", 0, 0, 0}, - {"channel destroyed", "C", 0, 0, 0}, - {"chatnet created", "c", 0, 0, 0}, - {"chatnet destroyed", "c", 0, 0, 0}, - {"commandlist new", "o", 0, 0, 0}, - {"commandlist remove", "o", 0, 0, 0}, - {"error command", "is", 0, 0, 0}, - {"send command", "sSW", 0, 0, 0}, - {"send text", "sSW", 0, 0, 0}, - {"command ", "sSW", 0, 0, 1}, - {"default command", "sSW", 0, 0, 0}, - {"ignore created", "g", 0, 0, 0}, - {"ignore destroyed", "g", 0, 0, 0}, - {"ignore changed", "g", 0, 0, 0}, - {"log new", "l", 0, 0, 0}, - {"log remove", "l", 0, 0, 0}, - {"log create failed", "l", 0, 0, 0}, - {"log locked", "l", 0, 0, 0}, - {"log started", "l", 0, 0, 0}, - {"log stopped", "l", 0, 0, 0}, - {"log rotated", "l", 0, 0, 0}, - {"log written", "ls", 0, 0, 0}, - {"module loaded", "??", 0, 0, 0}, - {"module unloaded", "??", 0, 0, 0}, - {"module error", "isss", 0, 0, 0}, - {"nicklist new", "Cn", 0, 0, 0}, - {"nicklist remove", "Cn", 0, 0, 0}, - {"nicklist changed", "Cns", 0, 0, 0}, - {"nicklist host changed", "Cn", 0, 0, 0}, - {"nicklist gone changed", "Cn", 0, 0, 0}, - {"nicklist serverop changed", "Cn", 0, 0, 0}, - {"pidwait", "ii", 0, 0, 0}, - {"query created", "qi", 0, 0, 0}, - {"query destroyed", "q", 0, 0, 0}, - {"query nick changed", "qs", 0, 0, 0}, - {"window item name changed", "W", 0, 0, 0}, - {"query address changed", "q", 0, 0, 0}, - {"query server changed", "qS", 0, 0, 0}, - {"rawlog", "ls", 0, 0, 0}, - {"server looking", "S", 0, 0, 0}, - {"server connected", "S", 0, 0, 0}, - {"server connecting", "Su", 0, 0, 0}, - {"server connect failed", "S", 0, 0, 0}, - {"server disconnected", "S", 0, 0, 0}, - {"server quit", "Ss", 0, 0, 0}, - {"server sendmsg", "Sssi", 0, 0, 0}, - {"setup changed", "", 0, 0, 0}, - {"setup reread", "s", 0, 0, 0}, - {"setup saved", "si", 0, 0, 0}, - {"ban type changed", "s", 0, 0, 0}, - {"channel joined", "C", 0, 0, 0}, - {"channel wholist", "C", 0, 0, 0}, - {"channel sync", "C", 0, 0, 0}, - {"channel topic changed", "C", 0, 0, 0}, - {"ctcp msg", "Sssss", 0, 0, 0}, - {"ctcp msg ", "Sssss", 0, 0, 1}, - {"default ctcp msg", "Sssss", 0, 0, 0}, - {"ctcp reply", "Sssss", 0, 0, 0}, - {"ctcp reply ", "Sssss", 0, 0, 1}, - {"default ctcp reply", "Sssss", 0, 0, 0}, - {"ctcp action", "Sssss", 0, 0, 0}, - {"awaylog show", "lii", 0, 0, 0}, - {"server nick changed", "S", 0, 0, 0}, - {"event connected", "S", 0, 0, 0}, - {"server event", "Ssss", 0, 0, 0}, - {"event ", "Ssss", 0, 0, 1}, - {"default event", "Ssss", 0, 0, 0}, - {"whois default event", "Ssss", 0, 0, 0}, - {"server incoming", "Ss", 0, 0, 0}, - {"redir ", "Ssss", 0, 0, 1}, - {"server lag", "S", 0, 0, 0}, - {"server lag disconnect", "S", 0, 0, 0}, - {"massjoin", "CL", 0, 0, 0}, - {"ban new", "Cb", 0, 0, 0}, - {"ban remove", "Cbs", 0, 0, 0}, - {"channel mode changed", "Cs", 0, 0, 0}, - {"nick mode changed", "Cnsss", 0, 0, 0}, - {"user mode changed", "Ss", 0, 0, 0}, - {"away mode changed", "S", 0, 0, 0}, - {"netsplit server new", "SS", 0, 0, 0}, - {"netsplit server remove", "SS", 0, 0, 0}, - {"netsplit new", "N", 0, 0, 0}, - {"netsplit remove", "N", 0, 0, 0}, - {"dcc ctcp ", "sd", 0, 0, 1}, - {"default dcc ctcp", "sd", 0, 0, 0}, - {"dcc unknown ctcp", "sss", 0, 0, 0}, - {"dcc reply ", "sd", 0, 0, 1}, - {"default dcc reply", "sd", 0, 0, 0}, - {"dcc unknown reply", "sss", 0, 0, 0}, - {"dcc chat message", "ds", 0, 0, 0}, - {"dcc created", "d", 0, 0, 0}, - {"dcc destroyed", "d", 0, 0, 0}, - {"dcc connected", "d", 0, 0, 0}, - {"dcc rejecting", "d", 0, 0, 0}, - {"dcc closed", "d", 0, 0, 0}, - {"dcc request", "ds", 0, 0, 0}, - {"dcc request send", "d", 0, 0, 0}, - {"dcc chat message", "ds", 0, 0, 0}, - {"dcc transfer update", "d", 0, 0, 0}, - {"dcc get receive", "d", 0, 0, 0}, - {"dcc error connect", "d", 0, 0, 0}, - {"dcc error file create", "ds", 0, 0, 0}, - {"dcc error file open", "ssi", 0, 0, 0}, - {"dcc error get not found", "s", 0, 0, 0}, - {"dcc error send exists", "ss", 0, 0, 0}, - {"dcc error unknown type", "s", 0, 0, 0}, - {"dcc error close not found", "sss", 0, 0, 0}, - {"autoignore new", "S?", 0, 0, 0}, - {"autoignore remove", "S?", 0, 0, 0}, - {"flood", "Sssis", 0, 0, 0}, - {"notifylist new", "O", 0, 0, 0}, - {"notifylist remove", "O", 0, 0, 0}, - {"notifylist joined", "Ssssss", 0, 0, 0}, - {"notifylist away changed", "Ssssss", 0, 0, 0}, - {"notifylist unidle", "Ssssss", 0, 0, 0}, - {"notifylist left", "Ssssss", 0, 0, 0}, - {"proxy client connected", "?", 0, 0, 0}, - {"proxy client disconnected", "?", 0, 0, 0}, - {"gui print text", "wiiist", 0, 0, 0}, - {"gui print text finished", "w", 0, 0, 0}, - {"complete word", "?wssi", 0, 0, 0}, - {"irssi init read settings", "", 0, 0, 0}, - {"exec new", "p", 0, 0, 0}, - {"exec remove", "pi", 0, 0, 0}, - {"exec input", "ps", 0, 0, 0}, - {"message public", "Sssss", 0, 0, 0}, - {"message private", "Ssss", 0, 0, 0}, - {"message own_public", "Sss", 0, 0, 0}, - {"message own_private", "Ssss", 0, 0, 0}, - {"message join", "Ssss", 0, 0, 0}, - {"message part", "Sssss", 0, 0, 0}, - {"message quit", "Ssss", 0, 0, 0}, - {"message kick", "Ssssss", 0, 0, 0}, - {"message nick", "Ssss", 0, 0, 0}, - {"message own_nick", "Ssss", 0, 0, 0}, - {"message invite", "Ssss", 0, 0, 0}, - {"message topic", "Sssss", 0, 0, 0}, - {"keyinfo created", "?", 0, 0, 0}, - {"keyinfo destroyed", "?", 0, 0, 0}, - {"print text", "tss", 0, 0, 0}, - {"theme created", "?", 0, 0, 0}, - {"theme destroyed", "?", 0, 0, 0}, - {"window hilight", "w", 0, 0, 0}, - {"window activity", "wi", 0, 0, 0}, - {"window item hilight", "W", 0, 0, 0}, - {"window item activity", "Wi", 0, 0, 0}, - {"window item new", "wW", 0, 0, 0}, - {"window item remove", "wW", 0, 0, 0}, - {"window item changed", "wW", 0, 0, 0}, - {"window item server changed", "wW", 0, 0, 0}, - {"window created", "w", 0, 0, 0}, - {"window destroyed", "w", 0, 0, 0}, - {"window changed", "ww", 0, 0, 0}, - {"window changed automatic", "w", 0, 0, 0}, - {"window server changed", "wS", 0, 0, 0}, - {"window refnum changed", "wi", 0, 0, 0}, - {"window name changed", "w", 0, 0, 0}, - {"window history changed", "ws", 0, 0, 0}, - {"window level changed", "w", 0, 0, 0}, - {"message irc op_public", "Sssss", 0, 0, 0}, - {"message irc own_wall", "Sss", 0, 0, 0}, - {"message irc own_action", "Sss", 0, 0, 0}, - {"message irc action", "Sssss", 0, 0, 0}, - {"message irc own_notice", "Sss", 0, 0, 0}, - {"message irc notice", "Sssss", 0, 0, 0}, - {"message irc own_ctcp", "Ssss", 0, 0, 0}, - {"message irc ctcp", "Ssssss", 0, 0, 0}, - {"message irc mode", "Sssss", 0, 0, 0}, - {"message dcc own", "ds", 0, 0, 0}, - {"message dcc own_action", "ds", 0, 0, 0}, - {"message dcc own_ctcp", "dss", 0, 0, 0}, - {"message dcc", "ds", 0, 0, 0}, - {"message dcc action", "ds", 0, 0, 0}, - {"message dcc ctcp", "dss", 0, 0, 0}, - {"gui key pressed", "i", 0, 0, 0}, - {"beep", "", 0, 0, 0}, - {NULL} -}; - -#define py_sigmap_len() (sizeof(py_sigmap) / sizeof(py_sigmap[0]) - 1) diff --git a/pysignals.c b/pysignals.c deleted file mode 100644 index 95718aa..0000000 --- a/pysignals.c +++ /dev/null @@ -1,805 +0,0 @@ -#include -#include "pyirssi.h" -#include "pysignals.h" -#include "factory.h" - -/* NOTE: - * There are two different records used to store signal related data: - * PY_SIGNAL_SPEC_REC and PY_SIGNAL_REC. Each SPEC_REC declares a "plain" - * signal, or a type of "variable" signal. Each PY_SIGNAL_REC stores data - * about a handler for a signal. - * - * Plain signals are emitted using the same text every time. They are never - * extended or altered in any way. Plain signals make up the vast majority - * of Irssi signals. These include (some random examples): "beep", - * "printtext", "log new", "ban new", etc. - * - * Variable signals are emitted by joining a common prefix with text that - * varies from emit to emit. These are signals that have a "" suffix - * in Irssi's signal listing. irssi-python uses the trailing space to - * distinguish between plain signals and variable signals. Example prefixes: - * "redir ", "command ", "event ". "command nick" would be emitted when the - * user types /nick yournick at the prompt. - * - * While PY_SIGNAL_SPEC_REC stores data about each individual signal, - * PY_SIGNAL_REC stores data about each handler of a signal (or command). - * A listing of SPEC_REC entries is stored globally in this module for each - * signal known to irssi-python. Each Script holds a list of PY_SIGNAL_REC - * entries to remember signals and commands bound by the script. The - * PY_SIGNAL_REC data includes references to a callable PyObject and a - * PY_SIGNAL_SPEC_REC entry for the argument type list of the signal. - * - * Signals must be registered to be accessible to Python scripts. - * Registering a dynamic signal adds a new SPEC_REC with a refcount of 1. - * If another script registers the same signal, the original entry's refcount - * is incremented. Binding to the signal also increments its reference count. - * Likewise, unregistering or unbinding a dynamic signal will decrement its - * refcount. When refcount hits 0, the dynamic signal is removed from the list, - * and scripts can no longer bind to or emit the signal untill it is - * re-registered. Built-in signals in the sigmap are not from the heap and are - * never removed; it is an error for the refcount of any such signal entry to - * drop to 0. - */ - -typedef struct _PY_SIGNAL_SPEC_REC -{ - char *name; - char *arglist; - int refcount; - int dynamic; - int is_var; /* is this entry a prefix for a variable signal? */ -} PY_SIGNAL_SPEC_REC; - -#include "pysigmap.h" - -#define SIGNAME(sig) (sig->command? sig->command : sig->signal->name) -/* This macro is useful for PY_SIGNAL_REC entries bound to "variable" signals, - * whose names extend the name prefix stored in the SPEC_REC entry. - * - * Example: - * sig->command == "command nick" - * sig->signal->name == "command " - * - * The exact signal text differs from the prefix, so the text must be stored - * separately in each PY_SIGNAL_REC entry. - * - * However, entries for "plain" signals do not require any extra data stored, - * so sig->command is NULL. - * - * Example: - * sig->command == NULL; - * sig->signal->name == "massjoin"; - * - * "massjoin" is not a prefix for any signal, so any PY_SIGNAL_REC - * referencing the "massjoin" SPEC_REC entry will have a NULL command. - */ - -/* hashtable for normal signals, tree for variable signal prefixes. */ -static GHashTable *py_sighash = NULL; -static GTree *py_sigtree = NULL; - -static void py_run_handler(PY_SIGNAL_REC *rec, void **args); -static void py_sig_proxy(void *p1, void *p2, void *p3, void *p4, void *p5, void *p6); -static void py_signal_ref(PY_SIGNAL_SPEC_REC *sig); -static int py_signal_unref(PY_SIGNAL_SPEC_REC *sig); -static void py_signal_add(PY_SIGNAL_SPEC_REC *sig); -static PY_SIGNAL_REC *py_signal_rec_new(const char *signal, PyObject *func, const char *command); -static void py_signal_rec_destroy(PY_SIGNAL_REC *sig); -static PyObject *py_mkstrlist(void *iobj); -static PyObject *py_i2py(char code, void *iobj); -static void *py_py2i(char code, PyObject *pobj, int arg, const char *signal); -static void py_getstrlist(GList **list, PyObject *pylist); -static int precmp(const char *spec, const char *test); -static PY_SIGNAL_SPEC_REC *py_signal_lookup(const char *name); -static void py_signal_remove(PY_SIGNAL_SPEC_REC *sig); -static int py_convert_args(void **args, PyObject *argtup, const char *signal); - -PY_SIGNAL_REC *pysignals_command_bind(const char *cmd, PyObject *func, - const char *category, int priority) -{ - PY_SIGNAL_REC *rec = py_signal_rec_new("send command", func, cmd); - g_return_val_if_fail(rec != NULL, NULL); - - command_bind_full(MODULE_NAME, priority, cmd, - -1, category, (SIGNAL_FUNC)py_sig_proxy, rec); - - return rec; -} - -int pysignals_command_bind_list(GSList **list, const char *command, - PyObject *func, const char *category, int priority) -{ - PY_SIGNAL_REC *rec = pysignals_command_bind(command, func, category, priority); - if (!rec) - return 0; - - *list = g_slist_append(*list, rec); - return 1; -} - -/* return NULL if signal is invalid */ -PY_SIGNAL_REC *pysignals_signal_add(const char *signal, PyObject *func, int priority) -{ - PY_SIGNAL_REC *rec = py_signal_rec_new(signal, func, NULL); - - if (rec == NULL) - return NULL; - - signal_add_full(MODULE_NAME, priority, SIGNAME(rec), - (SIGNAL_FUNC)py_sig_proxy, rec); - - return rec; -} - -int pysignals_signal_add_list(GSList **list, const char *signal, - PyObject *func, int priority) -{ - PY_SIGNAL_REC *rec = pysignals_signal_add(signal, func, priority); - if (!rec) - return 0; - - *list = g_slist_append(*list, rec); - return 1; -} - -void pysignals_command_unbind(PY_SIGNAL_REC *rec) -{ - g_return_if_fail(rec->is_signal == FALSE); - g_return_if_fail(rec->command != NULL); - - command_unbind_full(rec->command, (SIGNAL_FUNC)py_sig_proxy, rec); - py_signal_rec_destroy(rec); -} - -void pysignals_signal_remove(PY_SIGNAL_REC *rec) -{ - g_return_if_fail(rec->is_signal == TRUE); - - signal_remove_full(SIGNAME(rec), (SIGNAL_FUNC)py_sig_proxy, rec); - py_signal_rec_destroy(rec); -} - -void pysignals_remove_generic(PY_SIGNAL_REC *rec) -{ - if (rec->is_signal) - pysignals_signal_remove(rec); - else - pysignals_command_unbind(rec); -} - -/* returns 1 when found and removed successfully */ -int pysignals_remove_search(GSList **siglist, const char *name, - PyObject *func, PSG_TYPE type) -{ - GSList *node; - - for (node = *siglist; node != NULL; node = node->next) - { - PY_SIGNAL_REC *sig = node->data; - - if ((sig->is_signal && type == PSG_COMMAND) || - (!sig->is_signal && type == PSG_SIGNAL)) - continue; - - if ((strcmp(SIGNAME(sig), name) == 0) && - (func == NULL || func == sig->handler)) - { - pysignals_remove_generic(sig); - *siglist = g_slist_delete_link(*siglist, node); - - /* deleting node won't harm iteration because it quits here */ - return 1; - } - } - - return 0; -} - -void pysignals_remove_list(GSList *siglist) -{ - GSList *node = siglist; - - for (node = siglist; node != NULL; node = node->next) - pysignals_remove_generic(node->data); -} - -static PyObject *py_mkstrlist(void *iobj) -{ - PyObject *list; - GList *node, **ptr; - ptr = iobj; - - list = PyList_New(0); - if (!list) - return NULL; - - for (node = *ptr; node != NULL; node = node->next) - { - int ret; - PyObject *str; - - str = PyString_FromString(node->data); - if (!str) - { - Py_DECREF(list); - return NULL; - } - - ret = PyList_Append(list, str); - Py_DECREF(str); - if (ret != 0) - { - Py_DECREF(list); - return NULL; - } - } - - return list; -} - -/* irssi obj -> PyObject */ -static PyObject *py_i2py(char code, void *iobj) -{ - if (iobj == NULL) - Py_RETURN_NONE; - - switch (code) - { - case '?': - Py_RETURN_NONE; - - case 's': - return PyString_FromString((char *)iobj); - case 'u': - return PyLong_FromUnsignedLong(*(unsigned long*)iobj); - case 'I': - return PyInt_FromLong(*(int *)iobj); - case 'i': - return PyInt_FromLong((int)iobj); - - case 'G': - return py_mkstrlist(iobj); - case 'L': /* list of nicks */ - return py_irssi_chatlist_new((GSList *)iobj, 1); - - case 'c': - case 'S': - case 'C': - case 'q': - case 'n': - case 'W': - return py_irssi_chat_new(iobj, 1); - - case 'd': - return py_irssi_new(iobj, 1); - - case 'r': - return pyreconnect_new(iobj); - case 'o': - return pycommand_new(iobj); - case 'l': - return pylog_new(iobj); - case 'a': - return pyrawlog_new(iobj); - case 'g': - return pyignore_new(iobj); - case 'b': - return pyban_new(iobj); - case 'N': - return pynetsplit_new(iobj); - case 'e': - return pynetsplit_server_new(iobj); - case 'O': - return pynotifylist_new(iobj); - case 'p': - return pyprocess_new(iobj); - case 't': - return pytextdest_new(iobj); - case 'w': - return pywindow_new(iobj); - } - - return PyErr_Format(PyExc_TypeError, "unknown code %c", code); -} - -/* PyObject -> irssi obj*/ -static void *py_py2i(char code, PyObject *pobj, int arg, const char *signal) -{ - char *type; - - if (pobj == Py_None) - return NULL; - - switch (code) - { - /* XXX: string doesn't persist */ - case 's': - type = "str"; - if (PyString_Check(pobj)) return PyString_AsString(pobj); - break; - case 'i': - type = "int"; - if (PyInt_Check(pobj)) return (void*)PyInt_AsLong(pobj); - break; - - case 'L': /* list of nicks */ - /*FIXME*/ - return NULL; - - case 'c': - type = "Chatnet"; - if (pychatnet_check(pobj)) return DATA(pobj); - break; - case 'S': - type = "Server"; - if (pyserver_check(pobj)) return DATA(pobj); - break; - case 'C': - type = "Channel"; - if (pychannel_check(pobj)) return DATA(pobj); - break; - case 'q': - type = "Query"; - if (pyquery_check(pobj)) return DATA(pobj); - break; - case 'n': - type = "Nick"; - if (pynick_check(pobj)) return DATA(pobj); - break; - case 'W': - type = "WindowItem"; - if (pywindow_item_check(pobj)) return DATA(pobj); - break; - - case 'd': - type = "DCC"; - if (pydcc_check(pobj)) return DATA(pobj); - break; - - case 'r': - type = "Reconnect"; - if (pyreconnect_check(pobj)) return DATA(pobj); - break; - case 'o': - type = "Command"; - if (pycommand_check(pobj)) return DATA(pobj); - break; - case 'l': - type = "Log"; - if (pylog_check(pobj)) return DATA(pobj); - break; - case 'a': - type = "Rawlog"; - if (pyrawlog_check(pobj)) return DATA(pobj); - break; - case 'g': - type = "Ignore"; - if (pyignore_check(pobj)) return DATA(pobj); - break; - case 'b': - type = "Ban"; - if (pyban_check(pobj)) return DATA(pobj); - break; - case 'N': - type = "Netsplit"; - if (pynetsplit_check(pobj)) return DATA(pobj); - break; - case 'e': - type = "NetsplitServer"; - if (pynetsplit_server_check(pobj)) return DATA(pobj); - break; - case 'O': - type = "Notifylist"; - if (pynotifylist_check(pobj)) return DATA(pobj); - break; - case 'p': - type = "Process"; - if (pyprocess_check(pobj)) return DATA(pobj); - break; - case 't': - type = "TextDest"; - if (pytextdest_check(pobj)) return DATA(pobj); - break; - case 'w': - type = "Window"; - if (pywindow_check(pobj)) return DATA(pobj); - break; - default: - PyErr_Format(PyExc_TypeError, "don't know type code %c", code); - return NULL; - } - - PyErr_Format(PyExc_TypeError, "signal `%s': expected type %s for arg %d, but got %s", - signal, type, arg, pobj->ob_type->tp_name); - return NULL; -} - -static void py_getstrlist(GList **list, PyObject *pylist) -{ - GList *out = NULL; - int i; - PyObject *str; - char *cstr; - - for (i = 0; i < PyList_Size(pylist); i++) - { - str = PyList_GET_ITEM(pylist, i); - if (!PyString_Check(str)) - { - PyErr_SetString(PyExc_TypeError, "string list contains invalid elements"); - PyErr_Print(); - return; - } - - cstr = g_strdup(PyString_AS_STRING(str)); - out = g_list_append(out, cstr); - } - - g_list_foreach(*list, (GFunc)g_free, NULL); - g_list_free(*list); - *list = out; -} - -static void py_run_handler(PY_SIGNAL_REC *rec, void **args) -{ - PyObject *argtup, *ret; - char *arglist = rec->signal->arglist; - int arglen, i, j; - - arglen = strlen(arglist); - g_return_if_fail(arglen <= SIGNAL_MAX_ARGUMENTS); - - argtup = PyTuple_New(arglen); - if (!argtup) - goto error; - - for (i = 0; i < arglen; i++) - { - PyObject *arg = py_i2py(arglist[i], args[i]); - if (!arg) - goto error; - - PyTuple_SET_ITEM(argtup, i, arg); - } - - ret = PyObject_CallObject(rec->handler, argtup); - if (!ret) - goto error; - - /*XXX: IN/OUT arg handling not well tested */ - for (i = 0, j = 0; i < arglen; i++) - { - GList **list; - PyObject *pyarg = PyTuple_GET_ITEM(argtup, i); - - switch (arglist[i]) - { - case 'G': - list = args[i]; - py_getstrlist(list, pyarg); - break; - - case 'I': - if (ret != Py_None) - { - PyObject *value; - int *intarg = args[i]; - - /* expect a proper return value to set reference arg. - * if return is a tuple, find the next item - */ - if (PyTuple_Check(ret)) - value = PyTuple_GET_ITEM(ret, j++); - else - value = ret; - - if (!PyInt_Check(value)) - continue; - - *intarg = PyInt_AS_LONG(value); - } - break; - } - } - - Py_XDECREF(ret); - -error: - Py_XDECREF(argtup); - if (PyErr_Occurred()) - PyErr_Print(); -} - -static void py_sig_proxy(void *p1, void *p2, void *p3, void *p4, void *p5, void *p6) -{ - PY_SIGNAL_REC *rec = signal_get_user_data(); - void *args[6]; - - args[0] = p1; args[1] = p2; args[2] = p3; - args[3] = p4; args[4] = p5; args[5] = p6; - py_run_handler(rec, args); -} - -static int py_convert_args(void **args, PyObject *argtup, const char *signal) -{ - char *arglist; - PY_SIGNAL_SPEC_REC *spec; - int i; - int maxargs; - - spec = py_signal_lookup(signal); - if (!spec) - { - PyErr_Format(PyExc_KeyError, "signal not found"); - return 0; - } - - /*XXX: specifying fewer signal args than in the format implicitly - sets overlooked args to NULL or 0 */ - - arglist = spec->arglist; - maxargs = strlen(arglist); - for (i = 0; i < maxargs && i < PyTuple_Size(argtup); i++) - { - args[i] = py_py2i(arglist[i], - PyTuple_GET_ITEM(argtup, i), - i+1, signal); - - if (PyErr_Occurred()) /* XXX: any cleanup needed? */ - return -1; - } - - return maxargs; -} - -int pysignals_emit(const char *signal, PyObject *argtup) -{ - int arglen; - void *args[6]; - - memset(args, 0, sizeof args); - - arglen = py_convert_args(args, argtup, signal); - if (arglen < 0) - return 0; - - signal_emit(signal, arglen, - args[0], args[1], args[2], - args[3], args[4], args[5]); - - return 1; -} - -int pysignals_continue(PyObject *argtup) -{ - const char *signal; - int arglen; - void *args[6]; - - memset(args, 0, sizeof args); - - signal = signal_get_emitted(); - if (!signal) - { - PyErr_Format(PyExc_LookupError, "cannot determine current signal"); - return 0; - } - - arglen = py_convert_args(args, argtup, signal); - if (arglen < 0) - return 0; - - signal_continue(arglen, - args[0], args[1], args[2], - args[3], args[4], args[5]); - - return 1; -} - -/* returns NULL if signal is invalid, incr reference to func */ -static PY_SIGNAL_REC *py_signal_rec_new(const char *signal, PyObject *func, const char *command) -{ - PY_SIGNAL_REC *rec; - PY_SIGNAL_SPEC_REC *spec; - - g_return_val_if_fail(func != NULL, NULL); - - spec = py_signal_lookup(signal); - if (!spec) - return NULL; - - rec = g_new0(PY_SIGNAL_REC, 1); - rec->signal = spec; - rec->handler = func; - Py_INCREF(func); - - if (command) - { - rec->is_signal = FALSE; - rec->command = g_strdup(command); - } - else - { - rec->is_signal = TRUE; - /* handle variable signal. requested signal will be longer than spec->name, ie - * signal = "var signal POOOM", spec->name = "var signal " - */ - if (strcmp(signal, spec->name) != 0) - rec->command = g_strdup(signal); - } - - py_signal_ref(spec); - - return rec; -} - -static void py_signal_rec_destroy(PY_SIGNAL_REC *sig) -{ - py_signal_unref(sig->signal); - Py_DECREF(sig->handler); - g_free(sig->command); - g_free(sig); -} - -static void py_signal_add(PY_SIGNAL_SPEC_REC *sig) -{ - if (sig->is_var) - g_tree_insert(py_sigtree, sig->name, sig); - else - g_hash_table_insert(py_sighash, sig->name, sig); -} - -static void py_signal_remove(PY_SIGNAL_SPEC_REC *sig) -{ - int ret; - - if (sig->is_var) - g_tree_remove(py_sigtree, sig->name); - else - { - ret = g_hash_table_remove(py_sighash, sig->name); - g_return_if_fail(ret != FALSE); - } -} - -static int precmp(const char *spec, const char *test) -{ - while (*spec == *test++) - if (*spec++ == '\0') - return 0; - - /* Variable event prefix matches (spec must never be empty string)*/ - /* precmp("var event ", "var event POOOM") -> 0 */ - if (*spec == '\0' && *(spec-1) == ' ') - return 0; - - return *(const unsigned char *)(test - 1) - *(const unsigned char *)spec; -} - -static PY_SIGNAL_SPEC_REC *py_signal_lookup(const char *name) -{ - PY_SIGNAL_SPEC_REC *ret; - - /* First check the normal signals hash, then check the variable signal prefixes in the tree */ - ret = g_hash_table_lookup(py_sighash, name); - if (!ret) - ret = g_tree_search(py_sigtree, (GCompareFunc)precmp, name); - - return ret; -} - -static void py_signal_ref(PY_SIGNAL_SPEC_REC *sig) -{ - g_return_if_fail(sig->refcount >= 0); - - sig->refcount++; -} - -static int py_signal_unref(PY_SIGNAL_SPEC_REC *sig) -{ - g_return_val_if_fail(sig->refcount >= 1, 0); - g_return_val_if_fail(sig->refcount > 1 || sig->dynamic, 0); - - sig->refcount--; - - if (sig->refcount == 0) - { - py_signal_remove(sig); - - /* freeing name also takes care of the key */ - g_free(sig->name); - g_free(sig->arglist); - g_free(sig); - - return 1; - } - - return 0; -} - -/* returns 0 when signal already exists, but with different args, or when - similar signal prefix is already present. */ -int pysignals_register(const char *name, const char *arglist) -{ - int len; - PY_SIGNAL_SPEC_REC *spec; - - len = strlen(name); - g_return_val_if_fail(len > 0, 0); - - spec = py_signal_lookup(name); - if (!spec) - { - spec = g_new0(PY_SIGNAL_SPEC_REC, 1); - spec->is_var = name[len-1] == ' '; /* trailing space means signal prefix */ - spec->dynamic = 1; - spec->refcount = 0; - spec->name = g_strdup(name); - spec->arglist = g_strdup(arglist); - - py_signal_add(spec); - } - else if (strcmp(spec->arglist, arglist) || strcmp(spec->name, name)) - return 0; - - spec->refcount++; - - return 1; -} - -/* returns 0 when name doesn't exist */ -int pysignals_unregister(const char *name) -{ - PY_SIGNAL_SPEC_REC *spec; - - spec = py_signal_lookup(name); - if (!spec) - return 0; - - py_signal_unref(spec); - return 1; -} - -void pysignals_init(void) -{ - int i; - - g_return_if_fail(py_sighash == NULL); - g_return_if_fail(py_sigtree == NULL); - - py_sigtree = g_tree_new((GCompareFunc)strcmp); - py_sighash = g_hash_table_new(g_str_hash, g_str_equal); - - for (i = 0; i < py_sigmap_len(); i++) - { - py_sigmap[i].refcount = 1; - py_sigmap[i].dynamic = 0; - py_signal_add(&py_sigmap[i]); - } -} - -static int py_check_sig(char *key, PY_SIGNAL_SPEC_REC *value, void *data) -{ - /* shouldn't need to deallocate any script recs -- all remaining at - this point should not be dynamic. non dynamic signals should have - no outstanding references */ - g_return_val_if_fail(value->dynamic == 0, FALSE); - g_return_val_if_fail(value->refcount == 1, FALSE); - - return FALSE; -} - -/* XXX: remember to remove all scripts before calling this deinit */ -void pysignals_deinit(void) -{ - g_return_if_fail(py_sighash != NULL); - g_return_if_fail(py_sigtree != NULL); - - g_tree_foreach(py_sigtree, (GTraverseFunc)py_check_sig, NULL); - g_hash_table_foreach_remove(py_sighash, (GHRFunc)py_check_sig, NULL); - - g_tree_destroy(py_sigtree); - g_hash_table_destroy(py_sighash); - py_sigtree = NULL; - py_sighash = NULL; -} diff --git a/pysignals.h b/pysignals.h deleted file mode 100644 index bec72c9..0000000 --- a/pysignals.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef _PYSIGNALS_H_ -#define _PYSIGNALS_H_ -#include - -/* forward */ -struct _PY_SIGNAL_SPEC_REC; - -typedef struct _PY_SIGNAL_REC -{ - struct _PY_SIGNAL_SPEC_REC *signal; - char *command; /* used for command and variable signal */ - PyObject *handler; - int is_signal; -} PY_SIGNAL_REC; - -typedef enum -{ - PSG_COMMAND, - PSG_SIGNAL, - PSG_ALL, -} PSG_TYPE; - -PY_SIGNAL_REC *pysignals_command_bind(const char *cmd, PyObject *func, - const char *category, int priority); -PY_SIGNAL_REC *pysignals_signal_add(const char *signal, PyObject *func, - int priority); -int pysignals_command_bind_list(GSList **list, const char *command, - PyObject *func, const char *category, int priority); -int pysignals_signal_add_list(GSList **list, const char *signal, - PyObject *func, int priority); -void pysignals_command_unbind(PY_SIGNAL_REC *rec); -void pysignals_signal_remove(PY_SIGNAL_REC *rec); -void pysignals_remove_generic(PY_SIGNAL_REC *rec); -int pysignals_remove_search(GSList **siglist, const char *name, - PyObject *func, PSG_TYPE type); -void pysignals_remove_list(GSList *siglist); -int pysignals_emit(const char *signal, PyObject *argtup); -int pysignals_continue(PyObject *argtup); -int pysignals_register(const char *name, const char *arglist); -int pysignals_unregister(const char *name); -void pysignals_init(void); -void pysignals_deinit(void); - -#endif diff --git a/pysource.c b/pysource.c deleted file mode 100644 index 413ab2c..0000000 --- a/pysource.c +++ /dev/null @@ -1,130 +0,0 @@ -#include -#include "pyirssi.h" -#include "pysource.h" - -typedef struct _PY_SOURCE_REC -{ - int tag; - GSList **tag_list; - int fd; - PyObject *func; - PyObject *data; -} PY_SOURCE_REC; - -static PY_SOURCE_REC *py_source_rec_new(GSList **tag_list, int fd, PyObject *func, PyObject *data) -{ - PY_SOURCE_REC *rec; - - rec = g_new0(PY_SOURCE_REC, 1); - rec->tag_list = tag_list; - rec->fd = fd; - rec->func = func; - rec->data = data; - - Py_INCREF(func); - Py_XINCREF(data); - - return rec; -} - -static int py_remove_tag(GSList **list, int handle) -{ - GSList *node; - - node = g_slist_find(*list, GINT_TO_POINTER(handle)); - if (!node) - return 0; - - *list = g_slist_delete_link(*list, node); - - return 1; -} - -static void py_source_destroy(PY_SOURCE_REC *rec) -{ - g_return_if_fail(py_remove_tag(rec->tag_list, rec->tag) == 1); - Py_DECREF(rec->func); - Py_XDECREF(rec->data); - g_free(rec); -} - -static int py_handle_ret(PyObject *ret) -{ - int res; - - if (!ret) - { - PyErr_Print(); - res = FALSE; - } - else - { - res = PyObject_IsTrue(ret); - Py_DECREF(ret); - } - - return res; -} - -static int py_timeout_proxy(PY_SOURCE_REC *rec) -{ - PyObject *ret; - - g_return_val_if_fail(rec != NULL, FALSE); - - if (rec->data) - ret = PyObject_CallFunction(rec->func, "O", rec->data); - else - ret = PyObject_CallFunction(rec->func, ""); - - return py_handle_ret(ret); -} - -static int py_io_proxy(GIOChannel *src, GIOCondition condition, PY_SOURCE_REC *rec) -{ - PyObject *ret; - - g_return_val_if_fail(rec != NULL, FALSE); - - if (rec->data) - ret = PyObject_CallFunction(rec->func, "iiO", rec->fd, condition, rec->data); - else - ret = PyObject_CallFunction(rec->func, "ii", rec->fd, condition); - - return py_handle_ret(ret); -} - -int pysource_timeout_add_list(GSList **list, int msecs, PyObject *func, PyObject *data) -{ - PY_SOURCE_REC *rec; - - g_return_val_if_fail(func != NULL, -1); - - rec = py_source_rec_new(list, -1, func, data); - rec->tag = g_timeout_add_full(G_PRIORITY_DEFAULT, msecs, - (GSourceFunc)py_timeout_proxy, rec, - (GDestroyNotify)py_source_destroy); - - *list = g_slist_append(*list, GINT_TO_POINTER(rec->tag)); - - return rec->tag; -} - -int pysource_io_add_watch_list(GSList **list, int fd, int cond, PyObject *func, PyObject *data) -{ - PY_SOURCE_REC *rec; - GIOChannel *channel; - - g_return_val_if_fail(func != NULL, 1); - - rec = py_source_rec_new(list, fd, func, data); - channel = g_io_channel_unix_new(fd); - rec->tag = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, cond, - (GIOFunc)py_io_proxy, rec, - (GDestroyNotify)py_source_destroy); - g_io_channel_unref(channel); - - *list = g_slist_append(*list, GINT_TO_POINTER(rec->tag)); - - return rec->tag; -} diff --git a/pysource.h b/pysource.h deleted file mode 100644 index 78b55ec..0000000 --- a/pysource.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _PYSOURCE_H_ -#define _PYSOURCE_H_ - -#include - -/* condition is G_INPUT_READ or G_INPUT_WRITE */ -int pysource_io_add_watch_list(GSList **list, int fd, int cond, PyObject *func, PyObject *data); -int pysource_timeout_add_list(GSList **list, int msecs, PyObject *func, PyObject *data); - -#endif diff --git a/pystatusbar.c b/pystatusbar.c deleted file mode 100644 index 8537718..0000000 --- a/pystatusbar.c +++ /dev/null @@ -1,132 +0,0 @@ -#include "pystatusbar.h" -#include "pyirssi.h" -#include "factory.h" - -typedef struct -{ - char *name; - PyObject *script; - PyObject *handler; -} PY_BAR_ITEM_REC; - -/* Map: item name -> bar item obj */ -static GHashTable *py_bar_items = NULL; - -static void py_add_bar_handler(const char *iname, PyObject *script, PyObject *handler) -{ - PY_BAR_ITEM_REC *sitem; - - sitem = g_new0(PY_BAR_ITEM_REC, 1); - sitem->name = g_strdup(iname); - sitem->script = script; - sitem->handler = handler; - Py_INCREF(script); - Py_INCREF(handler); - - g_hash_table_insert(py_bar_items, sitem->name, sitem); -} - -static void py_destroy_handler(PY_BAR_ITEM_REC *sitem) -{ - statusbar_item_unregister(sitem->name); - - g_free(sitem->name); /* destroy key */ - Py_DECREF(sitem->script); - Py_DECREF(sitem->handler); - g_free(sitem); -} - -static void py_statusbar_proxy_call(SBAR_ITEM_REC *item, int sizeonly, PY_BAR_ITEM_REC *sitem) -{ - PyObject *pybaritem; - PyObject *ret; - - g_return_if_fail(PyCallable_Check(sitem->handler)); - - pybaritem = pystatusbar_item_new(item); - if (!pybaritem) - { - PyErr_Print(); - pystatusbar_item_unregister(sitem->name); - } - - ret = PyObject_CallFunction(sitem->handler, "Oi", pybaritem, sizeonly); - if (!ret) - { - PyErr_Print(); - pystatusbar_item_unregister(sitem->name); - } - else - Py_DECREF(ret); -} - -static void py_statusbar_proxy(SBAR_ITEM_REC *item, int sizeonly) -{ - PY_BAR_ITEM_REC *sitem; - - sitem = g_hash_table_lookup(py_bar_items, item->config->name); - if (sitem) - py_statusbar_proxy_call(item, sizeonly, sitem); - else - { - statusbar_item_default_handler(item, sizeonly, NULL, "", TRUE); - g_critical("unknown handler for Python statusbar proxy: %s", item->config->name); - } -} - -void pystatusbar_item_register(PyObject *script, const char *sitem, - const char *value, PyObject *func) -{ - if (func) - { - g_return_if_fail(PyCallable_Check(func)); - py_add_bar_handler(sitem, script, func); - } - - statusbar_item_register(sitem, value, func? py_statusbar_proxy : NULL); -} - -/* remove selected status bar item handler */ -void pystatusbar_item_unregister(const char *iname) -{ - if (!g_hash_table_remove(py_bar_items, iname)) - statusbar_item_unregister(iname); -} - -/* remove all statusbar item handlers for script */ -/* XXX: Only status bar items registered with a handler are stored in the hash table. - * Items registered with only a value are not stored, so there is no way to unregister - * them when the script is unloaded. - */ -static int py_check_clean(char *key, PY_BAR_ITEM_REC *value, PyObject *script) -{ - if (value->script == script) - return 1; - - return 0; -} - -void pystatusbar_cleanup_script(PyObject *script) -{ - g_hash_table_foreach_remove(py_bar_items, (GHRFunc)py_check_clean, script); -} - -void pystatusbar_init(void) -{ - g_return_if_fail(py_bar_items == NULL); - - /* key is freed by destroy_handler */ - py_bar_items = g_hash_table_new_full(g_str_hash, g_str_equal, - NULL, (GDestroyNotify)py_destroy_handler); -} - -/* XXX: this must be called after cleaning up all the loaded scripts */ -void pystatusbar_deinit(void) -{ - g_return_if_fail(py_bar_items != NULL); - g_return_if_fail(g_hash_table_size(py_bar_items) == 0); - - g_hash_table_destroy(py_bar_items); - py_bar_items = NULL; -} - diff --git a/pystatusbar.h b/pystatusbar.h deleted file mode 100644 index 9749c9f..0000000 --- a/pystatusbar.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef _PYSTATUSBAR_H_ -#define _PYSTATUSBAR_H_ - -#include - -void pystatusbar_item_register(PyObject *script, const char *sitem, - const char *value, PyObject *func); -void pystatusbar_item_unregister(const char *iname); -void pystatusbar_cleanup_script(PyObject *script); -void pystatusbar_init(void); -void pystatusbar_deinit(void); - -#endif diff --git a/pythemes.c b/pythemes.c deleted file mode 100644 index a3e8927..0000000 --- a/pythemes.c +++ /dev/null @@ -1,287 +0,0 @@ -#include -#include "pythemes.h" -#include "pyirssi.h" -#include "factory.h" -#include "pymodule.h" -#include "pyloader.h" - -static void py_get_mod(char *full, int fullsz, const char *script) -{ - g_snprintf(full, fullsz, "irssi_python/%s.py", script); -} - -/* Edited from Perl Themes.xs */ -int pythemes_printformat(TEXT_DEST_REC *dest, const char *name, const char *format, PyObject *argtup) -{ - char *arglist[MAX_FORMAT_PARAMS + 1]; - THEME_REC *theme; - char *str; - char script[256]; - int formatnum; - int i; - - py_get_mod(script, sizeof script, name); - - formatnum = format_find_tag(script, format); - if (formatnum < 0) { - PyErr_Format(PyExc_KeyError, "unregistered format '%s'", format); - return 0; - } - - memset(arglist, 0, sizeof arglist); - for (i = 0; i < MAX_FORMAT_PARAMS && i < PyTuple_Size(argtup); i++) { - PyObject *obj = PyTuple_GET_ITEM(argtup, i); - char *str; - - if (!PyString_Check(obj)) { - PyErr_Format(PyExc_TypeError, "format argument list contains non-string data"); - return 0; - } - - str = PyString_AsString(obj); - if (!str) - return 0; - - arglist[i] = str; - } - - theme = window_get_theme(dest->window); - signal_emit("print format", 5, theme, script, - dest, GINT_TO_POINTER(formatnum), arglist); - - str = format_get_text_theme_charargs(theme, script, dest, formatnum, arglist); - if (*str != '\0') printtext_dest(dest, "%s", str); - g_free(str); - - return 1; -} - -static void py_destroy_format_list(FORMAT_REC *recs) -{ - int i; - - for (i = 0; recs[i].def; i++) - { - g_free(recs[i].def); - g_free(recs[i].tag); - } - - g_free(recs); -} - -/* register a list of formats in this format: - * [ (name, format), ... ] - */ -int pythemes_register(const char *name, PyObject *list) -{ - char script[256]; - FORMAT_REC *formatrecs; - int i; - - py_get_mod(script, sizeof script, name); - - if (!PyList_Check(list)) - { - PyErr_Format(PyExc_TypeError, "arg must be list"); - return 0; - } - - if (PyList_Size(list) == 0) - { - PyErr_Format(PyExc_TypeError, "cannot register empty list"); - return 0; - } - - if (g_hash_table_lookup(default_formats, script)) - { - PyErr_Format(PyExc_KeyError, "format list already registered by script"); - return 0; - } - - formatrecs = g_new0(FORMAT_REC, PyList_Size(list) + 2); - formatrecs[0].tag = g_strdup(script); - formatrecs[0].def = g_strdup("Python script"); - - for (i = 0; i < PyList_Size(list); i++) - { - FORMAT_REC *rec; - PyObject *item; - char *key, *value; - - rec = &formatrecs[i + 1]; - item = PyList_GET_ITEM(list, i); - if (!PyTuple_Check(item) || !PyArg_ParseTuple(item, "ss", &key, &value)) - { - if (!PyErr_Occurred() || PyErr_ExceptionMatches(PyExc_TypeError)) - { - PyErr_Clear(); - PyErr_Format(PyExc_TypeError, "format list must contain tuples of two strings"); - } - py_destroy_format_list(formatrecs); - return 0; - } - - rec->tag = g_strdup(key); - rec->def = g_strdup(value); - rec->params = MAX_FORMAT_PARAMS; - } - - theme_register_module(script, formatrecs); - - return 1; -} - -void pythemes_unregister(const char *name) -{ - char script[256]; - FORMAT_REC *formats; - - py_get_mod(script, sizeof script, name); - - formats = g_hash_table_lookup(default_formats, script); - if (!formats) - return; - - py_destroy_format_list(formats); - theme_unregister_module(script); -} - -/* XXX: test binding a PyCFunction to different sources. Not sure - if this is a good thing or not, but it seems to work */ -PyDoc_STRVAR(py_printformat_doc, - "for Server objects:\n" - "printformat(target, level, format, ...) -> None\n" - "\n" - "For all else:\n" - "printformat(level, format, ...) -> None\n" -); -static PyObject *py_printformat(PyObject *self, PyObject *all) -{ - int level; - char *format; - char *target; - PyObject *args = NULL, *varargs = NULL; - TEXT_DEST_REC dest; - char *script; - int formatstart; - - if (self && pyserver_check(self)) - formatstart = 3; - else - formatstart = 2; - - args = PySequence_GetSlice(all, 0, formatstart); - if (!args) - goto error; - - varargs = PySequence_GetSlice(all, formatstart, PyTuple_Size(all)); - if (!varargs) - goto error; - - if (self && pyserver_check(self)) - { - if (!PyArg_ParseTuple(args, "sis", &target, &level, &format)) - goto error; - } - else - { - if (!PyArg_ParseTuple(args, "is", &level, &format)) - goto error; - } - - script = pyloader_find_script_name(); - if (!script) - { - PyErr_Format(PyExc_RuntimeError, "No script found"); - goto error; - } - - /* create the text dest depending on whether this function is called from - module level or as a method of one of the objects */ - if (self == NULL) /* module */ - format_create_dest(&dest, NULL, NULL, level, NULL); - else if (pyserver_check(self)) - format_create_dest(&dest, DATA(self), target, level, NULL); - else if (pywindow_check(self)) - format_create_dest(&dest, NULL, NULL, level, DATA(self)); - else if (pywindow_item_check(self)) - { - PyWindowItem *pywi = (PyWindowItem *)self; - format_create_dest(&dest, pywi->data->server, pywi->data->visible_name, level, NULL); - } - - if (!pythemes_printformat(&dest, script, format, varargs)) - goto error; - - Py_DECREF(args); - Py_DECREF(varargs); - - Py_RETURN_NONE; - -error: - Py_XDECREF(args); - Py_XDECREF(varargs); - - return NULL; -} - -/* XXX: these funcs could be moved to pyutils.c */ -static int py_add_module_func(PyMethodDef *mdef) -{ - PyObject *func; - - g_return_val_if_fail(py_module != NULL, 0); - - func = PyCFunction_New(mdef, NULL); - if (!func) - return 0; - - if (PyModule_AddObject(py_module, mdef->ml_name, func) != 0) - { - Py_DECREF(func); - return 0; - } - - return 1; -} - -static int py_add_method(PyTypeObject *type, PyMethodDef *mdef) -{ - int ret; - PyObject *func; - - g_return_val_if_fail(type->tp_dict != NULL, 0); - - func = PyDescr_NewMethod(type, mdef); - if (!func) - return 0; - - ret = PyDict_SetItemString(type->tp_dict, mdef->ml_name, func); - Py_DECREF(func); - if (ret != 0) - return 0; - - return 1; -} - -int pythemes_init(void) -{ - static PyMethodDef pfdef = {"printformat", (PyCFunction)py_printformat, - METH_VARARGS, py_printformat_doc}; - - /* add function to main module and as member some types */ - - if (!py_add_module_func(&pfdef)) - return 0; - - if (!py_add_method(&PyServerType, &pfdef)) - return 0; - - if (!py_add_method(&PyWindowType, &pfdef)) - return 0; - - if (!py_add_method(&PyWindowItemType, &pfdef)) - return 0; - - return 1; -} diff --git a/pythemes.h b/pythemes.h deleted file mode 100644 index 92af965..0000000 --- a/pythemes.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef _PYTHEMES_H_ -#define _PYTHEMES_H_ - -#include - -struct _TEXT_DEST_REC; - -int pythemes_printformat(struct _TEXT_DEST_REC *dest, const char *script, const char *format, PyObject *argtup); -int pythemes_register(const char *script, PyObject *list); -void pythemes_unregister(const char *script); -int pythemes_init(void); - -#endif diff --git a/pyutils.c b/pyutils.c deleted file mode 100644 index 05e1f31..0000000 --- a/pyutils.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include "pyirssi.h" -#include "pyutils.h" -#include "settings.h" -#include "servers.h" - -/* copy paste from perl bindings */ -void py_command(const char *cmd, SERVER_REC *server, WI_ITEM_REC *item) -{ - const char *cmdchars; - char *sendcmd = (char *) cmd; - - if (*cmd == '\0') - return; - - cmdchars = settings_get_str("cmdchars"); - if (strchr(cmdchars, *cmd) == NULL) { - /* no command char - let's put it there.. */ - sendcmd = g_strdup_printf("%c%s", *cmdchars, cmd); - } - - signal_emit("send command", 3, sendcmd, server, item); - if (sendcmd != cmd) g_free(sendcmd); -} - -/* return the file extension for a file, or empty string - don't free result */ -char *file_get_ext(const char *file) -{ - const char *dot = NULL; - - while (*file) - { - if (*file == '.') - dot = file; - - file++; - } - - if (dot) - return (char *) dot + 1; - - return (char *) file; -} - -int file_has_ext(const char *file, const char *ext) -{ - const char *fext = file_get_ext(file); - - return !strcmp(fext, ext); -} - - -/* return whats in the braces -> /path/to/{filename}.py - result must be freed */ -char *file_get_filename(const char *path) -{ - const char *begin; - const char *end; - char *name; - size_t len; - - begin = strrchr(path, '/'); - if (!begin) - begin = path; - else - begin++; - - end = strrchr(begin, '.'); - if (end != NULL && end > begin) - len = end - begin; - else - len = strlen(begin); - - name = g_strnfill(len, 0); - - strncpy(name, begin, len); - - return name; -} - diff --git a/pyutils.h b/pyutils.h deleted file mode 100644 index 7b2ca7b..0000000 --- a/pyutils.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef _PYUTILS_H_ -#define _PYUTILS_H_ - -#include "servers.h" - -void py_command(const char *cmd, SERVER_REC *server, WI_ITEM_REC *item); -char *file_get_ext(const char *file); -int file_has_ext(const char *file, const char *ext); -char *file_get_filename(const char *path); - - -#endif diff --git a/sig2code.awk b/sig2code.awk deleted file mode 100644 index d6bdb0d..0000000 --- a/sig2code.awk +++ /dev/null @@ -1,61 +0,0 @@ -BEGIN { - FS = "[ \t]*->[ \t]*"; - - #read in codes - while (getline < "sig2code.txt") - { - sub(/^[ \t]*/, ""); - if (NF < 2) - continue; - - #print $1, $2 - sigmap[$2] = $1 - } - - close("sig2code.txt"); - - FS = "[ \t]*,[ \t]*"; - - print "/* Include in your C module */"; - print "static PY_SIGNAL_SPEC_REC py_sigmap[] = {"; -} - -function match_type(t) -{ - for (type in sigmap) - { - if (index(t, type) != 0) - return sigmap[type]; - } - - return "?"; -} - -$1 ~ /^[ \t]*"/ && $1 !~ /"script error"/ { - sub(/^[ \t]*/, ""); - - signal = $1 - if (signal ~ /.*$/) - { - varsig = 1; - sub(//, "", signal); - } - else - varsig = 0; - - args = ""; - for (i = 2; i <= NF; i++) - { - args = args""match_type($i); - } - - printf(" {%s, \"%s\", 0, 0, %d},\n", signal, args, varsig); -} - -END { - print " {NULL}" ; - print "};"; - print ""; - print "#define py_sigmap_len() (sizeof(py_sigmap) / sizeof(py_sigmap[0]) - 1)"; -} - diff --git a/sig2code.txt b/sig2code.txt deleted file mode 100644 index 379e88e..0000000 --- a/sig2code.txt +++ /dev/null @@ -1,44 +0,0 @@ - Conversion codes notes - I = int *arg IN/OUT - G = string GList **arg IN/OUT (list must be reconstructed) - L = list of nicks - - Scalars - s -> char * - u -> ulong * - I -> int * - i -> int - - Lists of things (completion.c and massjoin.c) - G -> GList * of char* - L -> GSList of NICK_RECs - - Chat objects - c -> CHATNET_REC - S -> SERVER_REC - C -> CHANNEL_REC - q -> QUERY_REC - n -> NICK_REC - W -> WI_ITEM_REC - - Irssi objects - d -> DCC_REC - - Other objects - r -> RECONNECT_REC - o -> COMMAND_REC - l -> LOG_REC - a -> RAWLOG_REC - g -> IGNORE_REC - ? -> MODULE_REC - b -> BAN_REC - N -> NETSPLIT_REC - e -> NETSPLIT_SERVER_REC - ? -> AUTOIGNORE_REC - O -> NOTIFYLIST_REC - ? -> THEME_REC - ? -> KEYINFO_REC - p -> PROCESS_REC - t -> TEXT_DEST_REC - w -> WINDOW_REC - diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..123e0ed --- /dev/null +++ b/src/Makefile @@ -0,0 +1,35 @@ +CC = gcc + +PYTHON = /usr/include/python2.4 +IRSSI = /home/chrisd/irssi-0.8.10 + +CFLAGS = -fpic -ggdb -Wall -I$(PYTHON) -I$(IRSSI) -I$(IRSSI)/src \ +-I$(IRSSI)/src/fe-common/core -I$(IRSSI)/src/core -I$(IRSSI)/src/fe-text \ +-I$(IRSSI)/src/irc -I$(IRSSI)/src/irc/core -I$(IRSSI)/src/irc/dcc \ +-I$(IRSSI)/src/irc/notifylist -I.. -I. -Iobjects \ +`pkg-config glib-2.0 --cflags` + +LDFLAGS = -fpic /usr/lib/libpython2.4.so + +OBJ = pycore.o pyutils.o pymodule.o pyloader.o pysignals.o pysource.o \ +pythemes.o pystatusbar.o pyconstants.o + +pyirssi: pyobjects.a $(OBJ) + $(CC) -shared -o libirssi_python.so $(OBJ) objects/pyobjects.a $(LDFLAGS) + +pyobjects.a: + cd objects/ && make + +%.o: %.c + $(CC) -c $< $(CFLAGS) + +signalmap: + awk -f sig2code.awk ~/irssi-0.8.10/docs/signals.txt > pysigmap.h + +constants: + awk -f constants.awk constants.txt > pyconstants.c + +clean: + rm -f *.o *.so + cd objects/ && make clean + diff --git a/src/constants.awk b/src/constants.awk new file mode 100644 index 0000000..3aa5034 --- /dev/null +++ b/src/constants.awk @@ -0,0 +1,20 @@ +BEGIN { + print "#include \"pymodule.h\""; + print "#include \"pyirssi_irc.h\""; + print + print "void pyconstants_init(void)" + print "{" +} + +{ + if (NF >= 2) + constant = $2; + else + constant = $1; + + printf(" PyModule_AddIntConstant(py_module, \"%s\", %s);\n", $1, constant); +} + +END { + print "}" +} diff --git a/src/constants.txt b/src/constants.txt new file mode 100644 index 0000000..a3b8917 --- /dev/null +++ b/src/constants.txt @@ -0,0 +1,45 @@ +IO_IN G_IO_IN +IO_OUT G_IO_OUT +IO_PRI G_IO_PRI +IO_ERR G_IO_ERR +IO_HUP G_IO_HUP +IRSSI_GUI_GNOME +IRSSI_GUI_GTK +IRSSI_GUI_KDE +IRSSI_GUI_NONE +IRSSI_GUI_QT +IRSSI_GUI_TEXT +IRC_MASK_DOMAIN +IRC_MASK_HOST +IRC_MASK_NICK +IRC_MASK_USER +MSGLEVEL_ACTIONS +MSGLEVEL_ALL +MSGLEVEL_CLIENTCRAP +MSGLEVEL_CLIENTERROR +MSGLEVEL_CLIENTNOTICE +MSGLEVEL_CRAP +MSGLEVEL_CTCPS +MSGLEVEL_DCC +MSGLEVEL_DCCMSGS +MSGLEVEL_HILIGHT +MSGLEVEL_INVITES +MSGLEVEL_JOINS +MSGLEVEL_KICKS +MSGLEVEL_LASTLOG +MSGLEVEL_MODES +MSGLEVEL_MSGS +MSGLEVEL_NEVER +MSGLEVEL_NICKS +MSGLEVEL_NO_ACT +MSGLEVEL_NOHILIGHT +MSGLEVEL_NOTICES +MSGLEVEL_PARTS +MSGLEVEL_PUBLIC +MSGLEVEL_QUITS +MSGLEVEL_SNOTES +MSGLEVEL_TOPICS +MSGLEVEL_WALLOPS +SIGNAL_PRIORITY_DEFAULT +SIGNAL_PRIORITY_HIGH +SIGNAL_PRIORITY_LOW diff --git a/src/irssi.py b/src/irssi.py new file mode 100644 index 0000000..3f193ad --- /dev/null +++ b/src/irssi.py @@ -0,0 +1,31 @@ +""" +""" + +import sys +import _irssi +from _irssi import * + +def command_bind(*args, **kwargs): + """ see Script.command_bind """ + get_script().command_bind(*args, **kwargs) + +def command_unbind(*args, **kwargs): + """ see Script.command_unbind """ + get_script().command_unbind(*args, **kwargs) + +def signal_add(*args, **kwargs): + """ see Script.signal_add """ + get_script().signal_add(*args, **kwargs) + +def signal_remove(*args, **kwargs): + """ see Script.signal_remove """ + get_script().signal_remove(*args, **kwargs) + +def timeout_add(*args, **kwargs): + """ see Script.timeout_add """ + get_script().timeout_add(*args, **kwargs) + +def io_add_watch(*args, **kwargs): + """ see Script.io_add_watch """ + get_script().io_add_watch(*args, **kwargs) + diff --git a/src/irssi_startup.py b/src/irssi_startup.py new file mode 100644 index 0000000..ee8dbdd --- /dev/null +++ b/src/irssi_startup.py @@ -0,0 +1,202 @@ +import sys, imp, __builtin__ +import _irssi + +class Output: + def __init__(self, level): + self.level = level + self.buf = [] + def write(self, text): + if not text: + return + self.buf.append(text) + if '\n' == text[-1]: + text = ''.join(self.buf)[:-1] + for line in text.split('\\n'): + _irssi.active_win().prnt(line, self.level) + self.buf = [] + +#XXX: hardcode +#try: +sys.stdout = Output(level = 0x0080000) +sys.stderr = Output(level = 0x0100000) +#except Exception, e: +# print 'Cant set output', e +# sys.stdout = sys.__stdout__ +# sys.stderr = sys.__stderr__ + +""" +#Import stuff modified from /Demo/imputil/knee.py +#If a script instance is available, it's module dictionary +#is used in place of sys.modules +#XXX: needs testing +#XXX: copyright? + +# Save the original hooks +original_import = __builtin__.__import__ +original_reload = __builtin__.reload + +# Replacement for __import__() +def import_hook(name, globals=None, locals=None, fromlist=None): + print 'LOADING', name + if name == 'sys': + return sys + #if name == '_irssi': + # return _irssi + + try: + script = _irssi.get_script() + except RuntimeError: + print 'ORIG IMPORT', name + return original_import(name, globals, locals, fromlist) + + parent = determine_parent(globals, script) + q, tail = find_head_package(parent, name, script) + m = load_tail(q, tail, script) + if not fromlist: + return q + + if hasattr(m, "__path__"): + ensure_fromlist(m, fromlist, script) + + recur -= 1 + return m + +def determine_parent(globals, script): + if not globals or not globals.has_key("__name__"): + print 'DP no __name__ in globals' + return None + pname = globals['__name__'] + print 'DP pname', pname + if globals.has_key("__path__"): + parent = script.modules[pname] + assert globals is parent.__dict__ + return parent + if '.' in pname: + i = pname.rfind('.') + pname = pname[:i] + parent = script.modules[pname] + assert parent.__name__ == pname + return parent + return None + +def find_head_package(parent, name, script): + if '.' in name: + i = name.find('.') + head = name[:i] + tail = name[i+1:] + else: + head = name + tail = "" + if parent: + qname = "%s.%s" % (parent.__name__, head) + else: + qname = head + q = import_module(head, qname, parent, script) + if q: + return q, tail + else: + print 'FHP (1) no q module for', name + + if parent: + qname = head + parent = None + q = import_module(head, qname, parent, script) + if q: + return q, tail + else: + print 'FHP (2) no q module for', name + + raise ImportError, "No module named " + qname + +def load_tail(q, tail, script): + m = q + while tail: + i = tail.find('.') + if i < 0: i = len(tail) + head, tail = tail[:i], tail[i+1:] + mname = "%s.%s" % (m.__name__, head) + m = import_module(head, mname, m, script) + if not m: + raise ImportError, "No module named " + mname + return m + +def ensure_fromlist(m, fromlist, script, recursive=0): + for sub in fromlist: + if sub == "*": + if not recursive: + try: + all = m.__all__ + except AttributeError: + pass + else: + assert recursive == 0 + ensure_fromlist(m, all, script, 1) + continue + if sub != "*" and not hasattr(m, sub): + subname = "%s.%s" % (m.__name__, sub) + submod = import_module(sub, subname, m, script) + if not submod: + raise ImportError, "No module named " + subname + +def import_module(partname, fqname, parent, script): + try: + m = script.modules[fqname] + #if hasattr(m, '_script'): + # assert m._script == script + + _irssi.prnt('LOADING CACHED %s script -> %s' % (fqname, repr(script))) + + return m + except KeyError: + print 'IM no cached moddule for', fqname + pass + + try: + fp, pathname, stuff = imp.find_module(partname, + parent and parent.__path__) + except ImportError, e: + print 'IM import error', e + return None + + try: + m = imp.load_module(fqname, fp, pathname, stuff) + finally: + if fp: fp.close() + if parent: + setattr(parent, partname, m) + + #don't load script into builtins, extensions, or this wrapper + if hasattr(m, '__file__') and fqname != 'irssi': + m._script = script + script.modules[fqname] = m + + #if hasattr(m, '__file__') and fqname not in ('__builtin__', 'sys', '__main__', '_irssi'): + # del sys.modules[fqname] + + _irssi.prnt('GOT -> %s, SCRIPT -> %s' % (m, repr(script))) + + return m + + +# Replacement for reload() +def reload_hook(module): + _irssi.prnt('reloading ' + repr(module)) + try: + script = _irssi.get_script() + except RuntimeError: + return original_reload(module) + + name = module.__name__ + if '.' not in name: + return import_module(name, name, None, script) + i = name.rfind('.') + pname = name[:i] + parent = script.modules[pname] + return import_module(name[i+1:], name, parent, script) + + +# Now install our hooks +__builtin__.__import__ = import_hook +__builtin__.reload = reload_hook +""" + diff --git a/src/objects/Makefile b/src/objects/Makefile new file mode 100644 index 0000000..6cc56fb --- /dev/null +++ b/src/objects/Makefile @@ -0,0 +1,28 @@ +CC = gcc + +PYTHON = /usr/include/python2.4 +IRSSI = /home/chrisd/irssi-0.8.10 +CFLAGS = -fpic -ggdb -Wall -I$(PYTHON) -I$(IRSSI) -I$(IRSSI)/src \ +-I$(IRSSI)/src/fe-common/core -I$(IRSSI)/src/core -I$(IRSSI)/src/fe-text \ +-I$(IRSSI)/src/irc -I$(IRSSI)/src/irc/core -I$(IRSSI)/src/irc/dcc \ +-I$(IRSSI)/src/irc/notifylist -I.. \ +`pkg-config glib-2.0 --cflags` + +OBJ = pyscript-object.o base-objects.o window-item-object.o channel-object.o \ +query-object.o server-object.o connect-object.o irc-server-object.o \ +irc-connect-object.o irc-channel-object.o ban-object.o nick-object.o \ +chatnet-object.o reconnect-object.o window-object.o textdest-object.o \ +rawlog-object.o log-object.o logitem-object.o ignore-object.o \ +dcc-object.o dcc-chat-object.o dcc-get-object.o dcc-send-object.o \ +netsplit-object.o netsplit-server-object.o netsplit-channel-object.o \ +notifylist-object.o process-object.o command-object.o theme-object.o \ +statusbar-item-object.o main-window-object.o factory.o + +pyobjects.a: $(OBJ) + ar r pyobjects.a $(OBJ) + +%.o: %.c + $(CC) -c $< $(CFLAGS) + +clean: + rm -f *.o *.so *.a diff --git a/src/objects/ban-object.c b/src/objects/ban-object.c new file mode 100644 index 0000000..908bae2 --- /dev/null +++ b/src/objects/ban-object.c @@ -0,0 +1,155 @@ +#include +#include "pyirssi_irc.h" +#include "pymodule.h" +#include "ban-object.h" +#include "pycore.h" + +/* monitor "ban remove" signal */ +static void ban_cleanup(CHANNEL_REC *chan, BAN_REC *ban) +{ + PyBan *pyban = signal_get_user_data(); + + if (ban == pyban->data) + { + pyban->data = NULL; + pyban->cleanup_installed = 0; + signal_remove_data("ban remove", ban_cleanup, pyban); + } +} + +static void PyBan_dealloc(PyBan *self) +{ + if (self->cleanup_installed) + signal_remove_data("ban remove", ban_cleanup, self); + + self->ob_type->tp_free((PyObject*)self); +} + +static PyObject *PyBan_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyBan *self; + + self = (PyBan *)type->tp_alloc(type, 0); + if (!self) + return NULL; + + return (PyObject *)self; +} + +PyDoc_STRVAR(PyBan_ban_doc, + "The ban" +); +static PyObject *PyBan_ban_get(PyBan *self, void *closure) +{ + BAN_REC *data = self->data; + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(data->ban); +} + +PyDoc_STRVAR(PyBan_setby_doc, + "Nick of who set the ban" +); +static PyObject *PyBan_setby_get(PyBan *self, void *closure) +{ + BAN_REC *data = self->data; + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(data->setby); +} + +PyDoc_STRVAR(PyBan_time_doc, + "Timestamp when ban was set" +); +static PyObject *PyBan_time_get(PyBan *self, void *closure) +{ + BAN_REC *data = self->data; + RET_NULL_IF_INVALID(self->data); + return PyLong_FromUnsignedLong(data->time); +} + +/* specialized getters/setters */ +static PyGetSetDef PyBan_getseters[] = { + {"ban", (getter)PyBan_ban_get, NULL, + PyBan_ban_doc, NULL}, + {"setby", (getter)PyBan_setby_get, NULL, + PyBan_setby_doc, NULL}, + {"time", (getter)PyBan_time_get, NULL, + PyBan_time_doc, NULL}, + {NULL} +}; + +/* Methods for object */ +static PyMethodDef PyBan_methods[] = { + {NULL} /* Sentinel */ +}; + +PyTypeObject PyBanType = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "Ban", /*tp_name*/ + sizeof(PyBan), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)PyBan_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + "PyBan objects", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + PyBan_methods, /* tp_methods */ + 0, /* tp_members */ + PyBan_getseters, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + PyBan_new, /* tp_new */ +}; + + +/* window item wrapper factory function */ +PyObject *pyban_new(void *ban) +{ + PyBan *pyban; + + pyban = py_inst(PyBan, PyBanType); + if (!pyban) + return NULL; + + pyban->data = ban; + pyban->cleanup_installed = 1; + signal_add_last_data("ban remove", ban_cleanup, pyban); + + return (PyObject *)pyban; +} + +int ban_object_init(void) +{ + g_return_val_if_fail(py_module != NULL, 0); + + if (PyType_Ready(&PyBanType) < 0) + return 0; + + Py_INCREF(&PyBanType); + PyModule_AddObject(py_module, "Ban", (PyObject *)&PyBanType); + + return 1; +} diff --git a/src/objects/ban-object.h b/src/objects/ban-object.h new file mode 100644 index 0000000..59ec9e7 --- /dev/null +++ b/src/objects/ban-object.h @@ -0,0 +1,18 @@ +#ifndef _BAN_OBJECT_H_ +#define _BAN_OBJECT_H_ + +#include +#include "base-objects.h" + +typedef struct +{ + PyIrssiFinal_HEAD(void) +} PyBan; + +extern PyTypeObject PyBanType; + +int ban_object_init(void); +PyObject *pyban_new(void *ban); +#define pyban_check(op) PyObject_TypeCheck(op, &PyBanType) + +#endif diff --git a/src/objects/base-objects.c b/src/objects/base-objects.c new file mode 100644 index 0000000..42f5cac --- /dev/null +++ b/src/objects/base-objects.c @@ -0,0 +1,235 @@ +#include +#include "structmember.h" +#include "pymodule.h" +#include "base-objects.h" +#include "pyirssi.h" + +/* This is the base type for Irssi objects with a type id. The user can find + * the type name, type id, and check if the object is wrapping a valid Irssi + * record. + */ + +static void PyIrssiBase_dealloc(PyIrssiBase *self) +{ + self->ob_type->tp_free((PyObject*)self); +} + +static PyObject *PyIrssiBase_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyIrssiBase *self; + + self = (PyIrssiBase *)type->tp_alloc(type, 0); + if (!self) + return NULL; + + return (PyObject *)self; +} + +/* Getters */ +PyDoc_STRVAR(PyIrssiBase_type_id_doc, + "Irssi's type id for object" +); +static PyObject *PyIrssiBase_type_id_get(PyIrssiBase *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyInt_FromLong(self->data->type); +} + +PyDoc_STRVAR(PyIrssiBase_type_doc, + "Irssi's name for object" +); +static PyObject *PyIrssiBase_type_get(PyIrssiBase *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->base_name); +} + +PyDoc_STRVAR(PyIrssiBase_valid_doc, + "True if the object is valid" +); +static PyObject *PyIrssiBase_valid_get(PyIrssiBase *self, void *closure) +{ + if (self->data != NULL) + Py_RETURN_TRUE; + + Py_RETURN_FALSE; +} + +/* specialized getters/setters */ +static PyGetSetDef PyIrssiBase_getseters[] = { + {"type_id", (getter)PyIrssiBase_type_id_get, NULL, + PyIrssiBase_type_id_doc, NULL}, + {"type", (getter)PyIrssiBase_type_get, NULL, + PyIrssiBase_type_doc, NULL}, + {"valid", (getter)PyIrssiBase_valid_get, NULL, + PyIrssiBase_valid_doc, NULL}, + {NULL} +}; + +/* Methods for object */ +static PyMethodDef PyIrssiBase_methods[] = { + {NULL} +}; + +PyTypeObject PyIrssiBaseType = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "IrssiBase", /*tp_name*/ + sizeof(PyIrssiBase), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)PyIrssiBase_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + "PyIrssiBase objects", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + PyIrssiBase_methods, /* tp_methods */ + 0, /* tp_members */ + PyIrssiBase_getseters, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + PyIrssiBase_new, /* tp_new */ +}; + + +/* IrssiChatBase is a base type for any object with a chat type. The user + can find the chat type string name with the chat_type member or + the type id with the chat_type_id member. It inherits from IrssiBase + so the type, valid, and type_id members are visible to the user, too */ + +static void PyIrssiChatBase_dealloc(PyIrssiChatBase *self) +{ + self->ob_type->tp_free((PyObject*)self); +} + +static PyObject *PyIrssiChatBase_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyIrssiChatBase *self; + + self = (PyIrssiChatBase *)type->tp_alloc(type, 0); + if (!self) + return NULL; + + return (PyObject *)self; +} + +/* Getters */ +PyDoc_STRVAR(PyIrssiChatBase_chat_type_id_doc, + "Chat Type id (int)" +); +static PyObject *PyIrssiChatBase_chat_type_id_get(PyIrssiChatBase *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyInt_FromLong(self->data->chat_type); +} + +PyDoc_STRVAR(PyIrssiChatBase_chat_type_doc, + "Chat name (str)" +); +static PyObject *PyIrssiChatBase_chat_type_get(PyIrssiChatBase *self, void *closure) +{ + CHAT_PROTOCOL_REC *rec; + + RET_NULL_IF_INVALID(self->data); + + rec = chat_protocol_find_id(self->data->chat_type); + if (rec) + RET_AS_STRING_OR_NONE(rec->name); + else + Py_RETURN_NONE; +} + +/* specialized getters/setters */ +static PyGetSetDef PyIrssiChatBase_getseters[] = { + {"chat_type_id", (getter)PyIrssiChatBase_chat_type_id_get, NULL, + PyIrssiChatBase_chat_type_id_doc, NULL}, + {"chat_type", (getter)PyIrssiChatBase_chat_type_get, NULL, + PyIrssiChatBase_chat_type_doc, NULL}, + {NULL} +}; + +/* Methods */ +static PyMethodDef PyIrssiChatBase_methods[] = { + {NULL} +}; + +PyTypeObject PyIrssiChatBaseType = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "IrssiChatBase", /*tp_name*/ + sizeof(PyIrssiChatBase), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)PyIrssiChatBase_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + "PyIrssiChatBase objects", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + PyIrssiChatBase_methods, /* tp_methods */ + 0, /* tp_members */ + PyIrssiChatBase_getseters, /* tp_getset */ + &PyIrssiBaseType, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + PyIrssiChatBase_new, /* tp_new */ +}; + +int base_objects_init(void) +{ + g_return_val_if_fail(py_module != NULL, 0); + + if (PyType_Ready(&PyIrssiBaseType) < 0) + return 0; + if (PyType_Ready(&PyIrssiChatBaseType) < 0) + return 0; + + Py_INCREF(&PyIrssiBaseType); + Py_INCREF(&PyIrssiChatBaseType); + PyModule_AddObject(py_module, "IrssiBase", (PyObject *)&PyIrssiBaseType); + PyModule_AddObject(py_module, "IrssiChatBase", (PyObject *)&PyIrssiChatBaseType); + + return 1; +} diff --git a/src/objects/base-objects.h b/src/objects/base-objects.h new file mode 100644 index 0000000..5351ead --- /dev/null +++ b/src/objects/base-objects.h @@ -0,0 +1,105 @@ +#ifndef _BASE_OBJECTS_H_ +#define _BASE_OBJECTS_H_ + +#include + +/* data is a pointer to the underlying Irssi record */ +/* base_name is the type name of the object returned from the type member + it can be SERVER, CHANNEL, QUERY, etc. Note: base_name isn't freed, so + it cannot point to heap memory */ +/* cleanup_installed: 1 = a cleanup signal handler is installed, 0 = not installed */ +#define PyIrssi_HEAD(type) \ + PyObject_HEAD \ + type *data; \ + const char *base_name; \ + int cleanup_installed; + +/* for uninheritable objects without a type id (Ban, Log, etc) */ +#define PyIrssiFinal_HEAD(type) \ + PyObject_HEAD \ + type *data; \ + int cleanup_installed; + +/* to access data from any irssi object */ +typedef struct +{ + PyObject_HEAD + void *data; +} PyIrssiObject; + +#define DATA(obj) (obj? ((PyIrssiObject *)obj)->data : NULL) + +/* base for classes with a type */ +typedef struct +{ + int type; +} IRSSI_BASE_REC; + +typedef struct +{ + PyIrssi_HEAD(IRSSI_BASE_REC) +} PyIrssiBase; + + +/* base for classes with type and a chat type */ +typedef struct +{ + int type; + int chat_type; +} IRSSI_CHAT_REC; + +typedef struct +{ + PyIrssi_HEAD(IRSSI_CHAT_REC) +} PyIrssiChatBase; + +extern PyTypeObject PyIrssiBaseType; +extern PyTypeObject PyIrssiChatBaseType; + +#define pybase_check(op) PyObject_TypeCheck(op, &PyIrssiBaseType) +#define pychatbase_check(op) PyObject_TypeCheck(op, &PyIrssiChatBaseType) +#define py_instp(tp, to) ((tp *) (to)->tp_alloc(to, 0)) +#define py_inst(tp, to) py_instp(tp, &to) + +int base_objects_init(void); + +#define RET_NULL_IF_INVALID(data) \ + if (data == NULL) \ + return PyErr_Format(PyExc_RuntimeError, "wrapped object is invalid") + +#define RET_N1_IF_INVALID(data) \ +do { \ + if (data == NULL) \ + { \ + PyErr_Format(PyExc_RuntimeError, "wrapped object is invalid"); \ + return -1; \ + } \ +} while (0) + +#define RET_AS_STRING_OR_NONE(str) \ +do { \ + if (str) \ + return PyString_FromString(str); \ + else \ + { \ + Py_INCREF(Py_None); \ + return Py_None; \ + } \ +} while (0) + + +#define RET_AS_STRING_OR_EMPTY(str) return PyString_FromString(str? str : "") + +#define RET_AS_OBJ_OR_NONE(obj) \ +do { \ + PyObject *tmp = obj; \ + if (!tmp) \ + tmp = Py_None; \ + Py_INCREF(tmp); \ + return tmp; \ +} while (0) + +#define INVALID_MEMBER(member) \ + return PyErr_Format(PyExc_RuntimeError, "invalid member id, %d", member) + +#endif diff --git a/src/objects/channel-object.c b/src/objects/channel-object.c new file mode 100644 index 0000000..fa4edd4 --- /dev/null +++ b/src/objects/channel-object.c @@ -0,0 +1,379 @@ +#include +#include "pyirssi.h" +#include "pymodule.h" +#include "factory.h" +#include "channel-object.h" +#include "pycore.h" + +/* monitor "channel destroyed" signal */ +static void chan_cleanup(CHANNEL_REC *chan) +{ + PyChannel *pychan = signal_get_user_data(); + + if (chan == pychan->data) + { + pychan->data = NULL; + pychan->cleanup_installed = 0; + signal_remove_data("channel destroyed", chan_cleanup, pychan); + } +} + +static void PyChannel_dealloc(PyChannel *self) +{ + if (self->cleanup_installed) + signal_remove_data("channel destroyed", chan_cleanup, self); + + self->ob_type->tp_free((PyObject*)self); +} + +/* Getters */ +PyDoc_STRVAR(PyChannel_topic_doc, + "Channel topic" +); +static PyObject *PyChannel_topic_get(PyChannel *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->topic); +} + +PyDoc_STRVAR(PyChannel_topic_by_doc, + "Nick who set the topic" +); +static PyObject *PyChannel_topic_by_get(PyChannel *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->topic_by); +} + +PyDoc_STRVAR(PyChannel_topic_time_doc, + "Timestamp when the topic was set" +); +static PyObject *PyChannel_topic_time_get(PyChannel *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyLong_FromLong(self->data->topic_time); +} + +PyDoc_STRVAR(PyChannel_no_modes_doc, + "Channel is modeless" +); +static PyObject *PyChannel_no_modes_get(PyChannel *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyBool_FromLong(self->data->no_modes); +} + +PyDoc_STRVAR(PyChannel_mode_doc, + "Channel mode" +); +static PyObject *PyChannel_mode_get(PyChannel *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->mode); +} + +PyDoc_STRVAR(PyChannel_limit_doc, + "Max. users in channel (+l mode)" +); +static PyObject *PyChannel_limit_get(PyChannel *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyInt_FromLong(self->data->limit); +} + +PyDoc_STRVAR(PyChannel_key_doc, + "Channel key (password)" +); +static PyObject *PyChannel_key_get(PyChannel *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->key); +} + +PyDoc_STRVAR(PyChannel_chanop_doc, + "You are channel operator" +); +static PyObject *PyChannel_chanop_get(PyChannel *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyBool_FromLong(self->data->chanop); +} + +PyDoc_STRVAR(PyChannel_names_got_doc, + "/NAMES list has been received" +); +static PyObject *PyChannel_names_got_get(PyChannel *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyBool_FromLong(self->data->names_got); +} + +PyDoc_STRVAR(PyChannel_wholist_doc, + "/WHO list has been received" +); +static PyObject *PyChannel_wholist_get(PyChannel *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyBool_FromLong(self->data->wholist); +} + +PyDoc_STRVAR(PyChannel_synced_doc, + "Channel is fully synchronized" +); +static PyObject *PyChannel_synced_get(PyChannel *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyBool_FromLong(self->data->synced); +} + +PyDoc_STRVAR(PyChannel_joined_doc, + "JOIN event for this channel has been received" +); +static PyObject *PyChannel_joined_get(PyChannel *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyBool_FromLong(self->data->joined); +} + +PyDoc_STRVAR(PyChannel_left_doc, + "You just left the channel (for 'channel destroyed' event)" +); +static PyObject *PyChannel_left_get(PyChannel *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyBool_FromLong(self->data->left); +} + +PyDoc_STRVAR(PyChannel_kicked_doc, + "You were just kicked out of the channel (for 'channel destroyed' event)" +); +static PyObject *PyChannel_kicked_get(PyChannel *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyBool_FromLong(self->data->kicked); +} + +/* specialized getters/setters */ +static PyGetSetDef PyChannel_getseters[] = { + {"topic", (getter)PyChannel_topic_get, NULL, + PyChannel_topic_doc, NULL}, + {"topic_by", (getter)PyChannel_topic_by_get, NULL, + PyChannel_topic_by_doc, NULL}, + {"topic_time", (getter)PyChannel_topic_time_get, NULL, + PyChannel_topic_time_doc, NULL}, + {"no_modes", (getter)PyChannel_no_modes_get, NULL, + PyChannel_no_modes_doc, NULL}, + {"mode", (getter)PyChannel_mode_get, NULL, + PyChannel_mode_doc, NULL}, + {"limit", (getter)PyChannel_limit_get, NULL, + PyChannel_limit_doc, NULL}, + {"key", (getter)PyChannel_key_get, NULL, + PyChannel_key_doc, NULL}, + {"chanop", (getter)PyChannel_chanop_get, NULL, + PyChannel_chanop_doc, NULL}, + {"names_got", (getter)PyChannel_names_got_get, NULL, + PyChannel_names_got_doc, NULL}, + {"wholist", (getter)PyChannel_wholist_get, NULL, + PyChannel_wholist_doc, NULL}, + {"synced", (getter)PyChannel_synced_get, NULL, + PyChannel_synced_doc, NULL}, + {"joined", (getter)PyChannel_joined_get, NULL, + PyChannel_joined_doc, NULL}, + {"left", (getter)PyChannel_left_get, NULL, + PyChannel_left_doc, NULL}, + {"kicked", (getter)PyChannel_kicked_get, NULL, + PyChannel_kicked_doc, NULL}, + {NULL} +}; + +/* Methods */ +PyDoc_STRVAR(PyChannel_nicks_doc, + "nicks() -> list of Nick objects\n" + "\n" + "Return a list of nicks in the channel.\n" +); +static PyObject *PyChannel_nicks(PyChannel *self, PyObject *args) +{ + RET_NULL_IF_INVALID(self->data); + + return py_irssi_chatlist_new(nicklist_getnicks(self->data), 1); +} + +PyDoc_STRVAR(PyChannel_nicks_find_mask_doc, + "nicks_find_mask(mask) -> Nick object or None\n" + "\n" + "Find nick mask from nicklist, wildcards allowed.\n" +); +static PyObject *PyChannel_nicks_find_mask(PyChannel *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"mask", NULL}; + char *mask = ""; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &mask)) + return NULL; + + return py_irssi_chat_new(nicklist_find_mask(self->data, mask), 1); +} + +PyDoc_STRVAR(PyChannel_nick_find_doc, + "nick_find(nick) -> Nick object or None\n" + "\n" + "Find nick from nicklist.\n" +); +static PyObject *PyChannel_nick_find(PyChannel *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"nick", NULL}; + char *nick = ""; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &nick)) + return NULL; + + return py_irssi_chat_new(nicklist_find(self->data, nick), 1); +} + +PyDoc_STRVAR(PyChannel_nick_remove_doc, + "nick_remove(nick) -> None\n" + "\n" + "Remove nick from nicklist.\n" +); +static PyObject *PyChannel_nick_remove(PyChannel *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"nick", NULL}; + PyObject *nick = NULL; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, + &nick)) + return NULL; + + if (!pynick_check(nick)) + return PyErr_Format(PyExc_TypeError, "arg must be nick"); + + nicklist_remove(self->data, ((PyNick*)nick)->data); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyChannel_nick_insert_obj_doc, + "nick_insert(nick) -> None\n" + "\n" + "Insert nick object into nicklist.\n" +); +static PyObject *PyChannel_nick_insert_obj(PyChannel *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"nick", NULL}; + PyObject *nick = NULL; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, + &nick)) + return NULL; + + if (!pynick_check(nick)) + return PyErr_Format(PyExc_TypeError, "arg must be nick"); + + nicklist_insert(self->data, ((PyNick*)nick)->data); + + Py_RETURN_NONE; +} + +/* Methods for object */ +static PyMethodDef PyChannel_methods[] = { + {"nicks", (PyCFunction)PyChannel_nicks, METH_NOARGS, + PyChannel_nicks_doc}, + {"nicks_find_mask", (PyCFunction)PyChannel_nicks_find_mask, METH_VARARGS | METH_KEYWORDS, + PyChannel_nicks_find_mask_doc}, + {"nick_find", (PyCFunction)PyChannel_nick_find, METH_VARARGS | METH_KEYWORDS, + PyChannel_nick_find_doc}, + {"nick_remove", (PyCFunction)PyChannel_nick_remove, METH_VARARGS | METH_KEYWORDS, + PyChannel_nick_remove_doc}, + {"nick_insert_obj", (PyCFunction)PyChannel_nick_insert_obj, METH_VARARGS | METH_KEYWORDS, + PyChannel_nick_insert_obj_doc}, + {NULL} /* Sentinel */ +}; + +PyTypeObject PyChannelType = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "Channel", /*tp_name*/ + sizeof(PyChannel), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)PyChannel_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + "PyChannel objects", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + PyChannel_methods, /* tp_methods */ + 0, /* tp_members */ + PyChannel_getseters, /* tp_getset */ + &PyWindowItemType, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + + +/* window item wrapper factory function */ +PyObject *pychannel_sub_new(void *chan, const char *name, PyTypeObject *type) +{ + PyObject *pychan; + + pychan = pywindow_item_sub_new(chan, name, type); + if (pychan) + { + PyChannel *pych = (PyChannel *)pychan; + signal_add_last_data("channel destroyed", chan_cleanup, pych); + pych->cleanup_installed = 1; + } + + return pychan; +} + +PyObject *pychannel_new(void *chan) +{ + static const char *name = "CHANNEL"; + return pychannel_sub_new(chan, name, &PyChannelType); +} + +int channel_object_init(void) +{ + g_return_val_if_fail(py_module != NULL, 0); + + if (PyType_Ready(&PyChannelType) < 0) + return 0; + + Py_INCREF(&PyChannelType); + PyModule_AddObject(py_module, "Channel", (PyObject *)&PyChannelType); + + return 1; +} diff --git a/src/objects/channel-object.h b/src/objects/channel-object.h new file mode 100644 index 0000000..0858e7b --- /dev/null +++ b/src/objects/channel-object.h @@ -0,0 +1,22 @@ +#ifndef _CHANNEL_OBJECT_H_ +#define _CHANNEL_OBJECT_H_ + +#include +#include "window-item-object.h" + +/* forward */ +struct _CHANNEL_REC; + +typedef struct +{ + PyWindowItem_HEAD(struct _CHANNEL_REC) +} PyChannel; + +extern PyTypeObject PyChannelType; + +int channel_object_init(void); +PyObject *pychannel_sub_new(void *chan, const char *name, PyTypeObject *type); +PyObject *pychannel_new(void *chan); +#define pychannel_check(op) PyObject_TypeCheck(op, &PyChannelType) + +#endif diff --git a/src/objects/chatnet-object.c b/src/objects/chatnet-object.c new file mode 100644 index 0000000..c22f0cb --- /dev/null +++ b/src/objects/chatnet-object.c @@ -0,0 +1,182 @@ +#include +#include "pymodule.h" +#include "base-objects.h" +#include "chatnet-object.h" +#include "pyirssi.h" +#include "pycore.h" +#include "pyutils.h" + +static void chatnet_cleanup(CHATNET_REC *cn) +{ + PyChatnet *pycn = signal_get_user_data(); + + if (cn == pycn->data) + { + pycn->data = NULL; + pycn->cleanup_installed = 0; + signal_remove_data("chatnet destroyed", chatnet_cleanup, pycn); + } +} + +static void PyChatnet_dealloc(PyChatnet *self) +{ + if (self->cleanup_installed) + signal_remove_data("chatnet destroyed", chatnet_cleanup, self); + + self->ob_type->tp_free((PyObject*)self); +} + +/* Getters */ +PyDoc_STRVAR(PyChatnet_name_doc, + "name of chat network" +); +static PyObject *PyChatnet_name_get(PyChatnet *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->name); +} + +PyDoc_STRVAR(PyChatnet_nick_doc, + "if not empty, nick preferred in this network" +); +static PyObject *PyChatnet_nick_get(PyChatnet *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->nick); +} + +PyDoc_STRVAR(PyChatnet_username_doc, + "if not empty, username preferred in this network" +); +static PyObject *PyChatnet_username_get(PyChatnet *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->username); +} + +PyDoc_STRVAR(PyChatnet_realname_doc, + "if not empty, realname preferred in this network" +); +static PyObject *PyChatnet_realname_get(PyChatnet *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->realname); +} + +PyDoc_STRVAR(PyChatnet_own_host_doc, + "address to use when connecting to this network" +); +static PyObject *PyChatnet_own_host_get(PyChatnet *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->own_host); +} + +PyDoc_STRVAR(PyChatnet_autosendcmd_doc, + "command to send after connecting to this network" +); +static PyObject *PyChatnet_autosendcmd_get(PyChatnet *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->autosendcmd); +} + +/* specialized getters/setters */ +static PyGetSetDef PyChatnet_getseters[] = { + {"name", (getter)PyChatnet_name_get, NULL, + PyChatnet_name_doc, NULL}, + {"nick", (getter)PyChatnet_nick_get, NULL, + PyChatnet_nick_doc, NULL}, + {"username", (getter)PyChatnet_username_get, NULL, + PyChatnet_username_doc, NULL}, + {"realname", (getter)PyChatnet_realname_get, NULL, + PyChatnet_realname_doc, NULL}, + {"own_host", (getter)PyChatnet_own_host_get, NULL, + PyChatnet_own_host_doc, NULL}, + {"autosendcmd", (getter)PyChatnet_autosendcmd_get, NULL, + PyChatnet_autosendcmd_doc, NULL}, + {NULL} +}; + +static PyMethodDef PyChatnet_methods[] = { + {NULL} /* Sentinel */ +}; + +PyTypeObject PyChatnetType = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "Chatnet", /*tp_name*/ + sizeof(PyChatnet), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)PyChatnet_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + "PyChatnet objects", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + PyChatnet_methods, /* tp_methods */ + 0, /* tp_members */ + PyChatnet_getseters, /* tp_getset */ + &PyIrssiChatBaseType, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + + +/* chatnet factory function */ +PyObject *pychatnet_sub_new(void *cn, PyTypeObject *subclass) +{ + static const char *name = "CHATNET"; + PyChatnet *pycn = NULL; + + pycn = py_instp(PyChatnet, subclass); + if (!pycn) + return NULL; + + pycn->data = cn; + pycn->base_name = name; + signal_add_last_data("chatnet destroyed", chatnet_cleanup, pycn); + pycn->cleanup_installed = 1; + + return (PyObject *)pycn; +} + +PyObject *pychatnet_new(void *cn) +{ + return pychatnet_sub_new(cn, &PyChatnetType); +} + +int chatnet_object_init(void) +{ + g_return_val_if_fail(py_module != NULL, 0); + + if (PyType_Ready(&PyChatnetType) < 0) + return 0; + + Py_INCREF(&PyChatnetType); + PyModule_AddObject(py_module, "Chatnet", (PyObject *)&PyChatnetType); + + return 1; +} diff --git a/src/objects/chatnet-object.h b/src/objects/chatnet-object.h new file mode 100644 index 0000000..8a6d1fc --- /dev/null +++ b/src/objects/chatnet-object.h @@ -0,0 +1,22 @@ +#ifndef _CHATNET_OBJECT_H_ +#define _CHATNET_OBJECT_H_ + +#include +#include "base-objects.h" + +/* forward */ +struct _CHATNET_REC; + +typedef struct +{ + PyIrssi_HEAD(struct _CHATNET_REC) +} PyChatnet; + +extern PyTypeObject PyChatnetType; + +int chatnet_object_init(void); +PyObject *pychatnet_sub_new(void *cn, PyTypeObject *subclass); +PyObject *pychatnet_new(void *cn); +#define pychatnet_check(op) PyObject_TypeCheck(op, &PyChatnetType) + +#endif diff --git a/src/objects/command-object.c b/src/objects/command-object.c new file mode 100644 index 0000000..ad60012 --- /dev/null +++ b/src/objects/command-object.c @@ -0,0 +1,145 @@ +#include +#include "pyirssi.h" +#include "pymodule.h" +#include "command-object.h" +#include "pycore.h" + +#define COMMAND(cmd) ((COMMAND_REC *)cmd) + +/* monitor "commandlist remove" signal */ +static void command_cleanup(COMMAND_REC *command) +{ + PyCommand *pycommand = signal_get_user_data(); + + if (command == pycommand->data) + { + pycommand->data = NULL; + pycommand->cleanup_installed = 0; + signal_remove_data("commandlist remove", command_cleanup, pycommand); + } +} + +static void PyCommand_dealloc(PyCommand *self) +{ + if (self->cleanup_installed) + signal_remove_data("commandlist remove", command_cleanup, self); + + self->ob_type->tp_free((PyObject*)self); +} + +static PyObject *PyCommand_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyCommand *self; + + self = (PyCommand *)type->tp_alloc(type, 0); + if (!self) + return NULL; + + return (PyObject *)self; +} + +/* Getters */ +PyDoc_STRVAR(PyCommand_cmd_doc, + "Command name" +); +static PyObject *PyCommand_cmd_get(PyCommand *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(COMMAND(self->data)->cmd); +} + +PyDoc_STRVAR(PyCommand_category_doc, + "Category" +); +static PyObject *PyCommand_category_get(PyCommand *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(COMMAND(self->data)->category); +} + +/* specialized getters/setters */ +static PyGetSetDef PyCommand_getseters[] = { + {"cmd", (getter)PyCommand_cmd_get, NULL, + PyCommand_cmd_doc, NULL}, + {"category", (getter)PyCommand_category_get, NULL, + PyCommand_category_doc, NULL}, + {NULL} +}; + +/* Methods */ +/* Methods for object */ +static PyMethodDef PyCommand_methods[] = { + {NULL} /* Sentinel */ +}; + +PyTypeObject PyCommandType = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "Command", /*tp_name*/ + sizeof(PyCommand), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)PyCommand_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + "PyCommand objects", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + PyCommand_methods, /* tp_methods */ + 0, /* tp_members */ + PyCommand_getseters, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + PyCommand_new, /* tp_new */ +}; + + +/* command factory function */ +PyObject *pycommand_new(void *command) +{ + PyCommand *pycommand; + + pycommand = py_inst(PyCommand, PyCommandType); + if (!pycommand) + return NULL; + + pycommand->data = command; + pycommand->cleanup_installed = 1; + signal_add_last_data("commandlist remove", command_cleanup, pycommand); + + return (PyObject *)pycommand; +} + +int command_object_init(void) +{ + g_return_val_if_fail(py_module != NULL, 0); + + if (PyType_Ready(&PyCommandType) < 0) + return 0; + + Py_INCREF(&PyCommandType); + PyModule_AddObject(py_module, "Command", (PyObject *)&PyCommandType); + + return 1; +} diff --git a/src/objects/command-object.h b/src/objects/command-object.h new file mode 100644 index 0000000..e6402cf --- /dev/null +++ b/src/objects/command-object.h @@ -0,0 +1,18 @@ +#ifndef _COMMAND_OBJECT_H_ +#define _COMMAND_OBJECT_H_ + +#include +#include "base-objects.h" + +typedef struct +{ + PyIrssiFinal_HEAD(void) +} PyCommand; + +extern PyTypeObject PyCommandType; + +int command_object_init(void); +PyObject *pycommand_new(void *command); +#define pycommand_check(op) PyObject_TypeCheck(op, &PyCommandType) + +#endif diff --git a/src/objects/connect-object.c b/src/objects/connect-object.c new file mode 100644 index 0000000..8ef9a29 --- /dev/null +++ b/src/objects/connect-object.c @@ -0,0 +1,198 @@ +#include +#include "pymodule.h" +#include "base-objects.h" +#include "connect-object.h" +#include "pyirssi.h" +#include "pycore.h" +#include "pyutils.h" + +static void connect_cleanup(SERVER_CONNECT_REC *connect) +{ + PyConnect *pyconn = signal_get_user_data(); + + /* + if (server == pyconn->data) + { + pyserver->data = NULL; + pyserver->cleanup_installed = 0; + signal_remove_data("server disconnected", connect_cleanup, pyserver); + } + */ +} + +static void PyConnect_dealloc(PyConnect *self) +{ + if (self->cleanup_installed) + signal_remove_data("server disconnected", connect_cleanup, self); + + self->ob_type->tp_free((PyObject*)self); +} + +/* Getters */ +PyDoc_STRVAR(PyConnect_address_doc, + "Address where we connected (irc.blah.org)" +); +static PyObject *PyConnect_address_get(PyConnect *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->address); +} + +PyDoc_STRVAR(PyConnect_port_doc, + "Port where we're connected" +); +static PyObject *PyConnect_port_get(PyConnect *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyInt_FromLong(self->data->port); +} + +PyDoc_STRVAR(PyConnect_chatnet_doc, + "Chat network" +); +static PyObject *PyConnect_chatnet_get(PyConnect *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->chatnet); +} + +PyDoc_STRVAR(PyConnect_password_doc, + "Password we used in connection." +); +static PyObject *PyConnect_password_get(PyConnect *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->password); +} + +PyDoc_STRVAR(PyConnect_wanted_nick_doc, + "Nick which we would prefer to use" +); +static PyObject *PyConnect_wanted_nick_get(PyConnect *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->nick); +} + +PyDoc_STRVAR(PyConnect_username_doc, + "User name" +); +static PyObject *PyConnect_username_get(PyConnect *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->username); +} + +PyDoc_STRVAR(PyConnect_realname_doc, + "Real name" +); +static PyObject *PyConnect_realname_get(PyConnect *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->realname); +} + +/* Get/Set */ +static PyGetSetDef PyConnect_getseters[] = { + {"address", (getter)PyConnect_address_get, NULL, + PyConnect_address_doc, NULL}, + {"port", (getter)PyConnect_port_get, NULL, + PyConnect_port_doc, NULL}, + {"chatnet", (getter)PyConnect_chatnet_get, NULL, + PyConnect_chatnet_doc, NULL}, + {"password", (getter)PyConnect_password_get, NULL, + PyConnect_password_doc, NULL}, + {"wanted_nick", (getter)PyConnect_wanted_nick_get, NULL, + PyConnect_wanted_nick_doc, NULL}, + {"username", (getter)PyConnect_username_get, NULL, + PyConnect_username_doc, NULL}, + {"realname", (getter)PyConnect_realname_get, NULL, + PyConnect_realname_doc, NULL}, + {NULL} +}; + +PyTypeObject PyConnectType = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "Connect", /*tp_name*/ + sizeof(PyConnect), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)PyConnect_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + "PyConnect objects", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + PyConnect_getseters, /* tp_getset */ + &PyIrssiChatBaseType, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + + +/* server connect factory function (managed == 0, don't do signal cleanup, 1 == do sig cleanup */ +PyObject *pyconnect_sub_new(void *connect, PyTypeObject *subclass, int managed) +{ + static const char *CONNECT_TYPE = "SERVER CONNECT"; + PyConnect *pyconn = NULL; + + g_return_val_if_fail(connect != NULL, NULL); + + pyconn = py_instp(PyConnect, subclass); + if (!pyconn) + return NULL; + + pyconn->base_name = CONNECT_TYPE; + pyconn->data = connect; + + if (managed) + { + //XXX: how to handle cleanup? + //signal_add_last_data("server disconnected", connect_cleanup, pyconn); + //pyconn->cleanup_installed = 1; + } + + return (PyObject *)pyconn; +} + +PyObject *pyconnect_new(void *connect, int managed) +{ + return pyconnect_sub_new(connect, &PyConnectType, managed); +} + +int connect_object_init(void) +{ + g_return_val_if_fail(py_module != NULL, 0); + + if (PyType_Ready(&PyConnectType) < 0) + return 0; + + Py_INCREF(&PyConnectType); + PyModule_AddObject(py_module, "Connect", (PyObject *)&PyConnectType); + + return 1; +} diff --git a/src/objects/connect-object.h b/src/objects/connect-object.h new file mode 100644 index 0000000..53bd509 --- /dev/null +++ b/src/objects/connect-object.h @@ -0,0 +1,22 @@ +#ifndef _CONNECT_OBJECT_H_ +#define _CONNECT_OBJECT_H_ + +#include +#include "base-objects.h" + +/* forward */ +struct _SERVER_CONNECT_REC; + +typedef struct +{ + PyIrssi_HEAD(struct _SERVER_CONNECT_REC) +} PyConnect; + +extern PyTypeObject PyConnectType; + +int connect_object_init(void); +PyObject *pyconnect_sub_new(void *connect, PyTypeObject *subtype, int managed); +PyObject *pyconnect_new(void *connect, int managed); +#define pyconnect_check(op) PyObject_TypeCheck(op, &PyConnectType) + +#endif diff --git a/src/objects/dcc-chat-object.c b/src/objects/dcc-chat-object.c new file mode 100644 index 0000000..5cfe796 --- /dev/null +++ b/src/objects/dcc-chat-object.c @@ -0,0 +1,137 @@ +#include +#include "pyirssi_irc.h" +#include "pymodule.h" +#include "dcc-chat-object.h" +#include "factory.h" +#include "pycore.h" + +/* inherit destroy and cleanup from DccChat type */ + +/* Getters */ +PyDoc_STRVAR(PyDccChat_id_doc, + "Unique identifier - usually same as nick" +); +static PyObject *PyDccChat_id_get(PyDccChat *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->id); +} + +PyDoc_STRVAR(PyDccChat_mirc_ctcp_doc, + "Send CTCPs without the CTCP_MESSAGE prefix" +); +static PyObject *PyDccChat_mirc_ctcp_get(PyDccChat *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyBool_FromLong(self->data->mirc_ctcp); +} + +PyDoc_STRVAR(PyDccChat_connection_lost_doc, + "Other side closed connection" +); +static PyObject *PyDccChat_connection_lost_get(PyDccChat *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyBool_FromLong(self->data->connection_lost); +} + +/* specialized getters/setters */ +static PyGetSetDef PyDccChat_getseters[] = { + {"id", (getter)PyDccChat_id_get, NULL, + PyDccChat_id_doc, NULL}, + {"mirc_ctcp", (getter)PyDccChat_mirc_ctcp_get, NULL, + PyDccChat_mirc_ctcp_doc, NULL}, + {"connection_lost", (getter)PyDccChat_connection_lost_get, NULL, + PyDccChat_connection_lost_doc, NULL}, + {NULL} +}; + +/* Methods */ +PyDoc_STRVAR(PyDccChat_chat_send_doc, + "chat_send(data) -> None\n" + "\n" + "Send data to a dcc chat session.\n" +); +static PyObject *PyDccChat_chat_send(PyDccChat *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"data", NULL}; + char *data = ""; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &data)) + return NULL; + + dcc_chat_send(self->data, data); + + Py_RETURN_NONE; +} + +/* Methods for object */ +static PyMethodDef PyDccChat_methods[] = { + {"chat_send", (PyCFunction)PyDccChat_chat_send, METH_VARARGS | METH_KEYWORDS, + PyDccChat_chat_send_doc}, + {NULL} /* Sentinel */ +}; + +PyTypeObject PyDccChatType = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "DccChat", /*tp_name*/ + sizeof(PyDccChat), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + 0, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + "PyDccChat objects", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + PyDccChat_methods, /* tp_methods */ + 0, /* tp_members */ + PyDccChat_getseters, /* tp_getset */ + &PyDccType, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +PyObject *pydcc_chat_new(void *dcc) +{ + static const char *name = "DCC CHAT"; + return pydcc_sub_new(dcc, name, &PyDccChatType); +} + +int dcc_chat_object_init(void) +{ + g_return_val_if_fail(py_module != NULL, 0); + + if (PyType_Ready(&PyDccChatType) < 0) + return 0; + + Py_INCREF(&PyDccChatType); + PyModule_AddObject(py_module, "DccChat", (PyObject *)&PyDccChatType); + + return 1; +} diff --git a/src/objects/dcc-chat-object.h b/src/objects/dcc-chat-object.h new file mode 100644 index 0000000..955e6be --- /dev/null +++ b/src/objects/dcc-chat-object.h @@ -0,0 +1,21 @@ +#ifndef _DCC_CHAT_OBJECT_H_ +#define _DCC_CHAT_OBJECT_H_ + +#include +#include "dcc-object.h" + +/* forward */ +struct CHAT_DCC_REC; + +typedef struct +{ + PyDcc_HEAD(struct CHAT_DCC_REC) +} PyDccChat; + +extern PyTypeObject PyDccChatType; + +PyObject *pydcc_chat_new(void *dcc); +#define pydcc_chat_check(op) PyObject_TypeCheck(op, &PyDccChatType) +int dcc_chat_object_init(void); + +#endif diff --git a/src/objects/dcc-get-object.c b/src/objects/dcc-get-object.c new file mode 100644 index 0000000..fa7c13a --- /dev/null +++ b/src/objects/dcc-get-object.c @@ -0,0 +1,138 @@ +#include +#include "pyirssi_irc.h" +#include "pymodule.h" +#include "dcc-get-object.h" +#include "factory.h" +#include "pycore.h" + +#define DCC_GET_CAST(rec) ((GET_DCC_REC *)rec) + +/* inherit destroy and cleanup from Dcc type */ + +/* Getters */ +PyDoc_STRVAR(PyDccGet_size_doc, + "File size" +); +static PyObject *PyDccGet_size_get(PyDccGet *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyLong_FromUnsignedLong(DCC_GET_CAST(self->data)->size); +} + +PyDoc_STRVAR(PyDccGet_skipped_doc, + "Bytes skipped from start (resuming file)" +); +static PyObject *PyDccGet_skipped_get(PyDccGet *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyLong_FromUnsignedLong(DCC_GET_CAST(self->data)->skipped); +} + +PyDoc_STRVAR(PyDccGet_get_type_doc, + "What to do if file exists? 0=default, 1=rename, 2=overwrite, 3=resume" +); +static PyObject *PyDccGet_get_type_get(PyDccGet *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyInt_FromLong(DCC_GET_CAST(self->data)->get_type); +} + +PyDoc_STRVAR(PyDccGet_file_doc, + "The real file name which we use." +); +static PyObject *PyDccGet_file_get(PyDccGet *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(DCC_GET_CAST(self->data)->file); +} + +PyDoc_STRVAR(PyDccGet_file_quoted_doc, + "true if file name was received quoted (\"file name\")" +); +static PyObject *PyDccGet_file_quoted_get(PyDccGet *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyBool_FromLong(DCC_GET_CAST(self->data)->file_quoted); +} + +/* specialized getters/setters */ +static PyGetSetDef PyDccGet_getseters[] = { + {"size", (getter)PyDccGet_size_get, NULL, + PyDccGet_size_doc, NULL}, + {"skipped", (getter)PyDccGet_skipped_get, NULL, + PyDccGet_skipped_doc, NULL}, + {"get_type", (getter)PyDccGet_get_type_get, NULL, + PyDccGet_get_type_doc, NULL}, + {"file", (getter)PyDccGet_file_get, NULL, + PyDccGet_file_doc, NULL}, + {"file_quoted", (getter)PyDccGet_file_quoted_get, NULL, + PyDccGet_file_quoted_doc, NULL}, + {NULL} +}; + +/* Methods */ +/* Methods for object */ +static PyMethodDef PyDccGet_methods[] = { + {NULL} /* Sentinel */ +}; + +PyTypeObject PyDccGetType = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "DccGet", /*tp_name*/ + sizeof(PyDccGet), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + 0, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + "PyDccGet objects", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + PyDccGet_methods, /* tp_methods */ + 0, /* tp_members */ + PyDccGet_getseters, /* tp_getset */ + &PyDccType, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +PyObject *pydcc_get_new(void *dcc) +{ + static const char *name = "DCC GET"; + return pydcc_sub_new(dcc, name, &PyDccGetType); +} + +int dcc_get_object_init(void) +{ + g_return_val_if_fail(py_module != NULL, 0); + + if (PyType_Ready(&PyDccGetType) < 0) + return 0; + + Py_INCREF(&PyDccGetType); + PyModule_AddObject(py_module, "DccGet", (PyObject *)&PyDccGetType); + + return 1; +} diff --git a/src/objects/dcc-get-object.h b/src/objects/dcc-get-object.h new file mode 100644 index 0000000..532b854 --- /dev/null +++ b/src/objects/dcc-get-object.h @@ -0,0 +1,18 @@ +#ifndef _DCC_GET_OBJECT_H_ +#define _DCC_GET_OBJECT_H_ + +#include +#include "dcc-object.h" + +typedef struct +{ + PyDcc_HEAD(void) +} PyDccGet; + +extern PyTypeObject PyDccGetType; + +PyObject *pydcc_get_new(void *dcc); +#define pydcc_get_check(op) PyObject_TypeCheck(op, &PyDccGetType) +int dcc_get_object_init(void); + +#endif diff --git a/src/objects/dcc-object.c b/src/objects/dcc-object.c new file mode 100644 index 0000000..95a3a4a --- /dev/null +++ b/src/objects/dcc-object.c @@ -0,0 +1,347 @@ +#include +#include "pyirssi_irc.h" +#include "pymodule.h" +#include "dcc-object.h" +#include "factory.h" +#include "pycore.h" + + +/* monitor "dcc destroyed signal" */ +static void dcc_cleanup(DCC_REC *dcc) +{ + PyDcc *pydcc = signal_get_user_data(); + + if (dcc == pydcc->data) + { + pydcc->data = NULL; + pydcc->cleanup_installed = 0; + signal_remove_data("dcc destroyed", dcc_cleanup, pydcc); + } +} + +static void PyDcc_dealloc(PyDcc *self) +{ + if (self->cleanup_installed) + signal_remove_data("dcc destroyed", dcc_cleanup, self); + + Py_XDECREF(self->server); + Py_XDECREF(self->chat); + + self->ob_type->tp_free((PyObject*)self); +} + +/* Getters */ +PyDoc_STRVAR(PyDcc_orig_type_doc, + "Original DCC type that was sent to us - same as type except GET and SEND are swapped" +); +static PyObject *PyDcc_orig_type_get(PyDcc *self, void *closure) +{ + const char *type; + + RET_NULL_IF_INVALID(self->data); + + type = module_find_id_str("DCC", DCC(self->data)->orig_type); + RET_AS_STRING_OR_NONE(type); +} + +PyDoc_STRVAR(PyDcc_created_doc, + "Time stamp when the DCC record was created" +); +static PyObject *PyDcc_created_get(PyDcc *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyLong_FromUnsignedLong(DCC(self->data)->created); +} + +PyDoc_STRVAR(PyDcc_server_doc, + "Server record where the DCC was initiated." +); +static PyObject *PyDcc_server_get(PyDcc *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_OBJ_OR_NONE(self->server); +} + +PyDoc_STRVAR(PyDcc_servertag_doc, + "Tag of the server where the DCC was initiated." +); +static PyObject *PyDcc_servertag_get(PyDcc *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(DCC(self->data)->servertag); +} + +PyDoc_STRVAR(PyDcc_mynick_doc, + "Our nick to use in DCC chat." +); +static PyObject *PyDcc_mynick_get(PyDcc *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(DCC(self->data)->mynick); +} + +PyDoc_STRVAR(PyDcc_nick_doc, + "Other side's nick name." +); +static PyObject *PyDcc_nick_get(PyDcc *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(DCC(self->data)->nick); +} + +PyDoc_STRVAR(PyDcc_chat_doc, + "Dcc chat record if the request came through DCC chat" +); +static PyObject *PyDcc_chat_get(PyDcc *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_OBJ_OR_NONE(self->chat); +} + +PyDoc_STRVAR(PyDcc_target_doc, + "Who the request was sent to - your nick, channel or empty if you sent the request" +); +static PyObject *PyDcc_target_get(PyDcc *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(DCC(self->data)->target); +} + +PyDoc_STRVAR(PyDcc_arg_doc, + "Given argument .. file name usually" +); +static PyObject *PyDcc_arg_get(PyDcc *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(DCC(self->data)->arg); +} + +PyDoc_STRVAR(PyDcc_addr_doc, + "Other side's IP address." +); +static PyObject *PyDcc_addr_get(PyDcc *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(DCC(self->data)->addrstr); +} + +PyDoc_STRVAR(PyDcc_port_doc, + "Port we're connecting in." +); +static PyObject *PyDcc_port_get(PyDcc *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyInt_FromLong(DCC(self->data)->port); +} + +PyDoc_STRVAR(PyDcc_starttime_doc, + "Unix time stamp when the DCC transfer was started" +); +static PyObject *PyDcc_starttime_get(PyDcc *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyLong_FromUnsignedLong(DCC(self->data)->starttime); +} + +PyDoc_STRVAR(PyDcc_transfd_doc, + "Bytes transferred" +); +static PyObject *PyDcc_transfd_get(PyDcc *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyLong_FromUnsignedLong(DCC(self->data)->transfd); +} + +/* specialized getters/setters */ +static PyGetSetDef PyDcc_getseters[] = { + {"orig_type", (getter)PyDcc_orig_type_get, NULL, + PyDcc_orig_type_doc, NULL}, + {"created", (getter)PyDcc_created_get, NULL, + PyDcc_created_doc, NULL}, + {"server", (getter)PyDcc_server_get, NULL, + PyDcc_server_doc, NULL}, + {"servertag", (getter)PyDcc_servertag_get, NULL, + PyDcc_servertag_doc, NULL}, + {"mynick", (getter)PyDcc_mynick_get, NULL, + PyDcc_mynick_doc, NULL}, + {"nick", (getter)PyDcc_nick_get, NULL, + PyDcc_nick_doc, NULL}, + {"chat", (getter)PyDcc_chat_get, NULL, + PyDcc_chat_doc, NULL}, + {"target", (getter)PyDcc_target_get, NULL, + PyDcc_target_doc, NULL}, + {"arg", (getter)PyDcc_arg_get, NULL, + PyDcc_arg_doc, NULL}, + {"addr", (getter)PyDcc_addr_get, NULL, + PyDcc_addr_doc, NULL}, + {"port", (getter)PyDcc_port_get, NULL, + PyDcc_port_doc, NULL}, + {"starttime", (getter)PyDcc_starttime_get, NULL, + PyDcc_starttime_doc, NULL}, + {"transfd", (getter)PyDcc_transfd_get, NULL, + PyDcc_transfd_doc, NULL}, + {NULL} +}; + +/* Methods */ +PyDoc_STRVAR(PyDcc_destroy_doc, + "destroy() -> None\n" + "\n" + "Destroy DCC connection\n" +); +static PyObject *PyDcc_destroy(PyDcc *self, PyObject *args) +{ + RET_NULL_IF_INVALID(self->data); + + dcc_destroy(DCC(self->data)); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyDcc_reject_doc, + "reject() -> None\n" + "\n" + "?\n" +); +static PyObject *PyDcc_reject(PyDcc *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"server", NULL}; + PyObject *server = NULL; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, + &server)) + return NULL; + + if (!pyirc_server_check(server)) + return PyErr_Format(PyExc_TypeError, "arg must be IRC server object"); + + dcc_reject(self->data, ((PyIrcServer*)server)->data); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyDcc_close_doc, + "close() -> None\n" + "\n" + "Close and destroy DCC connection.\n" +); +static PyObject *PyDcc_close(PyDcc *self, PyObject *args) +{ + RET_NULL_IF_INVALID(self->data); + + dcc_close(self->data); + + Py_RETURN_NONE; +} + +/* Methods for object */ +static PyMethodDef PyDcc_methods[] = { + {"destroy", (PyCFunction)PyDcc_destroy, METH_NOARGS, + PyDcc_destroy_doc}, + {"reject", (PyCFunction)PyDcc_reject, METH_VARARGS | METH_KEYWORDS, + PyDcc_reject_doc}, + {"close", (PyCFunction)PyDcc_close, METH_NOARGS, + PyDcc_close_doc}, + {NULL} /* Sentinel */ +}; + +PyTypeObject PyDccType = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "Dcc", /*tp_name*/ + sizeof(PyDcc), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)PyDcc_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + "PyDcc objects", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + PyDcc_methods, /* tp_methods */ + 0, /* tp_members */ + PyDcc_getseters, /* tp_getset */ + &PyIrssiBaseType, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + + +/* Dcc factory function */ +PyObject *pydcc_sub_new(void *dcc, const char *name, PyTypeObject *subclass) +{ + PyObject *chat = NULL, *server = NULL; + PyDcc *pydcc; + DCC_REC *rec = dcc; + + server = py_irssi_chat_new(rec->server, 1); + if (!server) + return NULL; + + chat = py_irssi_chat_new(rec->chat, 1); + if (!chat) + { + Py_DECREF(server); + return NULL; + } + + pydcc = py_instp(PyDcc, subclass); + if (!pydcc) + { + Py_DECREF(server); + Py_DECREF(chat); + return NULL; + } + + pydcc->data = dcc; + pydcc->server = server; + pydcc->chat = chat; + pydcc->base_name = name; + + pydcc->cleanup_installed = 1; + signal_add_last_data("dcc destroyed", dcc_cleanup, pydcc); + + return (PyObject *)pydcc; +} + +PyObject *pydcc_new(void *dcc) +{ + static const char *name = "DCC"; + return pydcc_sub_new(dcc, name, &PyDccType); +} + +int dcc_object_init(void) +{ + g_return_val_if_fail(py_module != NULL, 0); + + if (PyType_Ready(&PyDccType) < 0) + return 0; + + Py_INCREF(&PyDccType); + PyModule_AddObject(py_module, "Dcc", (PyObject *)&PyDccType); + + return 1; +} diff --git a/src/objects/dcc-object.h b/src/objects/dcc-object.h new file mode 100644 index 0000000..d44d3db --- /dev/null +++ b/src/objects/dcc-object.h @@ -0,0 +1,24 @@ +#ifndef _DCC_OBJECT_H_ +#define _DCC_OBJECT_H_ + +#include +#include "base-objects.h" + +#define PyDcc_HEAD(type) \ + PyIrssi_HEAD(type) \ + PyObject *server; \ + PyObject *chat; + +typedef struct +{ + PyDcc_HEAD(void) +} PyDcc; + +extern PyTypeObject PyDccType; + +PyObject *pydcc_sub_new(void *dcc, const char *name, PyTypeObject *subclass); +PyObject *pydcc_new(void *dcc); +#define pydcc_check(op) PyObject_TypeCheck(op, &PyDccType) +int dcc_object_init(void); + +#endif diff --git a/src/objects/dcc-send-object.c b/src/objects/dcc-send-object.c new file mode 100644 index 0000000..643f741 --- /dev/null +++ b/src/objects/dcc-send-object.c @@ -0,0 +1,138 @@ +#include +#include "pyirssi_irc.h" +#include "pymodule.h" +#include "dcc-send-object.h" +#include "factory.h" +#include "pycore.h" + +#define DCC_SEND_CAST(rec) ((SEND_DCC_REC *)rec) + +/* inherit destroy and cleanup from Dcc type */ + +/* Getters */ +PyDoc_STRVAR(PyDccSend_size_doc, + "File size" +); +static PyObject *PyDccSend_size_get(PyDccSend *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyLong_FromUnsignedLong(DCC_SEND_CAST(self->data)->size); +} + +PyDoc_STRVAR(PyDccSend_skipped_doc, + "Bytes skipped from start (resuming file)" +); +static PyObject *PyDccSend_skipped_get(PyDccSend *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyLong_FromUnsignedLong(DCC_SEND_CAST(self->data)->skipped); +} + +PyDoc_STRVAR(PyDccSend_file_quoted_doc, + "True if file name was received quoted (\"file name\")" +); +static PyObject *PyDccSend_file_quoted_get(PyDccSend *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyBool_FromLong(DCC_SEND_CAST(self->data)->file_quoted); +} + +PyDoc_STRVAR(PyDccSend_waitforend_doc, + "File is sent, just wait for the replies from the other side" +); +static PyObject *PyDccSend_waitforend_get(PyDccSend *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyBool_FromLong(DCC_SEND_CAST(self->data)->waitforend); +} + +PyDoc_STRVAR(PyDccSend_gotalldata_doc, + "Got all acks from the other end" +); +static PyObject *PyDccSend_gotalldata_get(PyDccSend *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyBool_FromLong(DCC_SEND_CAST(self->data)->gotalldata); +} + +/* specialized getters/setters */ +static PyGetSetDef PyDccSend_getseters[] = { + {"size", (getter)PyDccSend_size_get, NULL, + PyDccSend_size_doc, NULL}, + {"skipped", (getter)PyDccSend_skipped_get, NULL, + PyDccSend_skipped_doc, NULL}, + {"file_quoted", (getter)PyDccSend_file_quoted_get, NULL, + PyDccSend_file_quoted_doc, NULL}, + {"waitforend", (getter)PyDccSend_waitforend_get, NULL, + PyDccSend_waitforend_doc, NULL}, + {"gotalldata", (getter)PyDccSend_gotalldata_get, NULL, + PyDccSend_gotalldata_doc, NULL}, + {NULL} +}; + +/* Methods */ +/* Methods for object */ +static PyMethodDef PyDccSend_methods[] = { + {NULL} /* Sentinel */ +}; + +PyTypeObject PyDccSendType = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "DccSend", /*tp_name*/ + sizeof(PyDccSend), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + 0, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + "PyDccSend objects", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + PyDccSend_methods, /* tp_methods */ + 0, /* tp_members */ + PyDccSend_getseters, /* tp_getset */ + &PyDccType, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +PyObject *pydcc_send_new(void *dcc) +{ + static const char *name = "DCC SEND"; + return pydcc_sub_new(dcc, name, &PyDccSendType); +} + +int dcc_send_object_init(void) +{ + g_return_val_if_fail(py_module != NULL, 0); + + if (PyType_Ready(&PyDccSendType) < 0) + return 0; + + Py_INCREF(&PyDccSendType); + PyModule_AddObject(py_module, "DccSend", (PyObject *)&PyDccSendType); + + return 1; +} diff --git a/src/objects/dcc-send-object.h b/src/objects/dcc-send-object.h new file mode 100644 index 0000000..6303f86 --- /dev/null +++ b/src/objects/dcc-send-object.h @@ -0,0 +1,18 @@ +#ifndef _DCC_SEND_OBJECT_H_ +#define _DCC_SEND_OBJECT_H_ + +#include +#include "dcc-object.h" + +typedef struct +{ + PyDcc_HEAD(void) +} PyDccSend; + +extern PyTypeObject PyDccSendType; + +PyObject *pydcc_send_new(void *dcc); +#define pydcc_send_check(op) PyObject_TypeCheck(op, &PyDccSendType) +int dcc_send_object_init(void); + +#endif diff --git a/src/objects/factory.c b/src/objects/factory.c new file mode 100644 index 0000000..49336e6 --- /dev/null +++ b/src/objects/factory.c @@ -0,0 +1,326 @@ +#include +#include "pyirssi.h" +#include "factory.h" + +/* Irssi object factory works for all items with at least a type member. + * + * Use py_irssi_new() or py_irssi_chat_new() to get a new wrapper for an + * IrssiObject or an IrssiChatObject, respectively. + * + * For objects not descending from IrssiObject or IrssiChatObject, you must + * use the object-specific init function directly. + */ + +#define MAKEKEY(type, chat) ((chat << 16 ) | type) +#define GETTYPE(key) (key & 0xffff) +#define GETCHAT(key) ((key >> 16) & 0xffff) + + +GHashTable *init_map = NULL; + +static int init_objects(void); +static void register_chat(CHAT_PROTOCOL_REC *rec); +static void unregister_chat(CHAT_PROTOCOL_REC *rec); +static void insert_map(int type, int chat_type, InitFunc func); +static int remove_chat(void *key, void *value, void *chat_typep); +static void register_nonchat(void); +static InitFunc find_map(int type, int chat_type); + +static int init_objects(void) +{ + if (!pyscript_init()) + return 0; + + /* order is somewhat important here */ + if (!base_objects_init()) + return 0; + + if (!window_item_object_init()) + return 0; + + if (!channel_object_init()) + return 0; + + if (!query_object_init()) + return 0; + + if (!server_object_init()) + return 0; + + if (!connect_object_init()) + return 0; + + if (!irc_server_object_init()) + return 0; + + if (!irc_connect_object_init()) + return 0; + + if (!irc_channel_object_init()) + return 0; + + if (!ban_object_init()) + return 0; + + if (!nick_object_init()) + return 0; + + if (!chatnet_object_init()) + return 0; + + if (!reconnect_object_init()) + return 0; + + if (!window_object_init()) + return 0; + + if (!textdest_object_init()) + return 0; + + if (!rawlog_object_init()) + return 0; + + if (!log_object_init()) + return 0; + + if (!logitem_object_init()) + return 0; + + if (!ignore_object_init()) + return 0; + + if (!dcc_object_init()) + return 0; + + if (!dcc_chat_object_init()) + return 0; + + if (!dcc_get_object_init()) + return 0; + + if (!dcc_send_object_init()) + return 0; + + if (!netsplit_object_init()) + return 0; + + if (!netsplit_server_object_init()) + return 0; + + if (!netsplit_channel_object_init()) + return 0; + + if (!notifylist_object_init()) + return 0; + + if (!process_object_init()) + return 0; + + if (!command_object_init()) + return 0; + + if (!theme_object_init()) + return 0; + + if (!statusbar_item_object_init()) + return 0; + + if (!main_window_object_init()) + return 0; + + return 1; +} + +static InitFunc find_map(int type, int chat_type) +{ + unsigned hash; + + g_return_val_if_fail(type <= 0xffff, NULL); + g_return_val_if_fail(chat_type <= 0xffff, NULL); + + hash = MAKEKEY(type, chat_type); + return g_hash_table_lookup(init_map, GUINT_TO_POINTER(hash)); +} + +static void insert_map(int type, int chat_type, InitFunc func) +{ + unsigned hash; + + g_return_if_fail(type <= 0xffff); + g_return_if_fail(chat_type <= 0xffff); + + hash = MAKEKEY(type, chat_type); + g_hash_table_insert(init_map, GUINT_TO_POINTER(hash), func); +} + +static void register_chat(CHAT_PROTOCOL_REC *rec) +{ + int type; + int chat_type; + int is_irc = 0; + + /* chat_type == rec->id ??? */ + chat_type = chat_protocol_lookup(rec->name); + g_return_if_fail(chat_type >= 0 && chat_type < 0xffff); + + if (!g_strcasecmp(rec->name, "IRC")) + is_irc = 1; + + type = module_get_uniq_id("SERVER", 0); + if (is_irc) + insert_map(type, chat_type, (InitFunc)pyirc_server_new); + else + insert_map(type, chat_type, (InitFunc)pyserver_new); + + type = module_get_uniq_id("SERVER CONNECT", 0); + if (is_irc) + insert_map(type, chat_type, (InitFunc)pyirc_connect_new); + else + insert_map(type, chat_type, (InitFunc)pyconnect_new); + + type = module_get_uniq_id_str("WINDOW ITEM TYPE", "CHANNEL"); + if (is_irc) + insert_map(type, chat_type, (InitFunc)pyirc_channel_new); + else + insert_map(type, chat_type, (InitFunc)pychannel_new); + + type = module_get_uniq_id_str("WINDOW ITEM TYPE", "QUERY"); + insert_map(type, chat_type, (InitFunc)pyquery_new); + + type = module_get_uniq_id("CHATNET", 0); + insert_map(type, chat_type, (InitFunc)pychatnet_new); + + type = module_get_uniq_id("NICK", 0); + insert_map(type, chat_type, (InitFunc)pynick_new); +} + +/* register funcs for objects without a chat type */ +static void register_nonchat(void) +{ + int type; + int chat_type = 0xffff; + + type = module_get_uniq_id_str("DCC", "CHAT"); + insert_map(type, chat_type, (InitFunc)pydcc_chat_new); + + type = module_get_uniq_id_str("DCC", "GET"); + insert_map(type, chat_type, (InitFunc)pydcc_get_new); + + type = module_get_uniq_id_str("DCC", "SEND"); + insert_map(type, chat_type, (InitFunc)pydcc_send_new); + + type = module_get_uniq_id_str("DCC", "SERVER"); + insert_map(type, chat_type, (InitFunc)pydcc_new); +} + +static int remove_chat(void *key, void *value, void *chat_typep) +{ + unsigned hash = GPOINTER_TO_UINT(key); + int chat_type = GPOINTER_TO_INT(chat_type); + + if (GETCHAT(hash) == chat_type) + return TRUE; + + return FALSE; +} + +/* remove all items matching chat_type */ +static void unregister_chat(CHAT_PROTOCOL_REC *rec) +{ + /*int chat_type = chat_protocol_lookup(rec->name);*/ + g_hash_table_foreach_remove(init_map, + (GHRFunc)remove_chat, + GINT_TO_POINTER(rec->id)); +} + +PyObject *py_irssi_new(void *typeobj, int managed) +{ + IRSSI_BASE_REC *base = typeobj; + InitFunc ifunc; + + if (!base) + Py_RETURN_NONE; + + ifunc = find_map(base->type, 0xffff); + + if (ifunc) + return ifunc(typeobj, managed); + + return PyErr_Format(PyExc_RuntimeError, "no initfunc for object type %d", base->type); +} + +PyObject *py_irssi_chat_new(void *typeobj, int managed) +{ + IRSSI_CHAT_REC *chat = typeobj; + InitFunc ifunc; + + if (!chat) + Py_RETURN_NONE; + + ifunc = find_map(chat->type, chat->chat_type); + + if (ifunc) + return ifunc(typeobj, managed); + + return PyErr_Format(PyExc_RuntimeError, "no initfunc for object type %d, chat_type %d", + chat->type, chat->chat_type); +} + +PyObject *py_irssi_objlist_new(GSList *node, int managed, InitFunc init) +{ + PyObject *list = NULL; + + list = PyList_New(0); + if (!list) + goto error; + + for (; node != NULL; node = node->next) + { + int ret; + PyObject *obj = init(node->data, managed); + + if (!obj) + goto error; + + ret = PyList_Append(list, obj); + Py_DECREF(obj); + + if (ret != 0) + goto error; + } + + return list; + +error: + Py_XDECREF(list); + return NULL; +} + +int factory_init(void) +{ + g_return_val_if_fail(init_map == NULL, 0); + + if (!init_objects()) + return 0; + + init_map = g_hash_table_new(g_direct_hash, g_direct_equal); + g_slist_foreach(chat_protocols, (GFunc) register_chat, NULL); + register_nonchat(); + + signal_add("chat protocol created", (SIGNAL_FUNC) register_chat); + signal_add("chat protocol destroyed", (SIGNAL_FUNC) unregister_chat); + + return 1; +} + +void factory_deinit(void) +{ + g_return_if_fail(init_map != NULL); + + g_hash_table_destroy(init_map); + init_map = NULL; + + signal_remove("chat protocol created", (SIGNAL_FUNC) register_chat); + signal_remove("chat protocol destroyed", (SIGNAL_FUNC) unregister_chat); +} + diff --git a/src/objects/factory.h b/src/objects/factory.h new file mode 100644 index 0000000..9d4bd79 --- /dev/null +++ b/src/objects/factory.h @@ -0,0 +1,58 @@ +#ifndef _FACTORY_H_ +#define _FACTORY_H_ + +#include +#include "pyscript-object.h" +#include "base-objects.h" +#include "window-item-object.h" +#include "channel-object.h" +#include "query-object.h" +#include "server-object.h" +#include "connect-object.h" +#include "irc-server-object.h" +#include "irc-connect-object.h" +#include "irc-channel-object.h" +#include "ban-object.h" +#include "nick-object.h" +#include "chatnet-object.h" +#include "reconnect-object.h" +#include "window-object.h" +#include "textdest-object.h" +#include "rawlog-object.h" +#include "log-object.h" +#include "logitem-object.h" +#include "ignore-object.h" +#include "dcc-object.h" +#include "dcc-chat-object.h" +#include "dcc-get-object.h" +#include "dcc-send-object.h" +#include "netsplit-object.h" +#include "netsplit-server-object.h" +#include "netsplit-channel-object.h" +#include "notifylist-object.h" +#include "process-object.h" +#include "command-object.h" +#include "theme-object.h" +#include "statusbar-item-object.h" +#include "main-window-object.h" + +int factory_init(void); +void factory_deinit(void); + +/*managed == 1: object invalidates itself + *managed == 0: caller responsible for invalidating object + *XXX: most objects invalidate themselves, ignoring "managed" switch, + * and some are never managed (Reconnect) + */ + +/* For objects with a type member but no chat_type */ +PyObject *py_irssi_new(void *typeobj, int managed); +/* For objects with both type and chat_type members */ +PyObject *py_irssi_chat_new(void *typeobj, int managed); + +typedef PyObject *(*InitFunc)(void *, int); +PyObject *py_irssi_objlist_new(GSList *node, int managed, InitFunc init); +#define py_irssi_chatlist_new(n, m) py_irssi_objlist_new(n, m, py_irssi_chat_new) +#define py_irssi_list_new(n, m) py_irssi_objlist_new(n, m, py_irssi_new) + +#endif diff --git a/src/objects/ignore-object.c b/src/objects/ignore-object.c new file mode 100644 index 0000000..979c9b1 --- /dev/null +++ b/src/objects/ignore-object.c @@ -0,0 +1,284 @@ +#include +#include "pyirssi_irc.h" +#include "pymodule.h" +#include "ignore-object.h" +#include "factory.h" +#include "pycore.h" + +/* monitor "ignore destroy" signal */ +static void ignore_cleanup(IGNORE_REC *ignore) +{ + PyIgnore *pyignore = signal_get_user_data(); + + if (ignore == pyignore->data) + { + pyignore->data = NULL; + pyignore->cleanup_installed = 0; + signal_remove_data("ignore destroy", ignore_cleanup, pyignore); + } +} + +static void PyIgnore_dealloc(PyIgnore *self) +{ + if (self->cleanup_installed) + signal_remove_data("ignore destroy", ignore_cleanup, self); + + self->ob_type->tp_free((PyObject*)self); +} + +static PyObject *PyIgnore_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyIgnore *self; + + self = (PyIgnore *)type->tp_alloc(type, 0); + if (!self) + return NULL; + + return (PyObject *)self; +} + +/* Getters */ +PyDoc_STRVAR(PyIgnore_mask_doc, + "Ignore mask" +); +static PyObject *PyIgnore_mask_get(PyIgnore *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->mask); +} + +PyDoc_STRVAR(PyIgnore_servertag_doc, + "Ignore only in server" +); +static PyObject *PyIgnore_servertag_get(PyIgnore *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->servertag); +} + +PyDoc_STRVAR(PyIgnore_pattern_doc, + "Ignore text patern" +); +static PyObject *PyIgnore_pattern_get(PyIgnore *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->pattern); +} + +PyDoc_STRVAR(PyIgnore_level_doc, + "Ignore level" +); +static PyObject *PyIgnore_level_get(PyIgnore *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyInt_FromLong(self->data->level); +} + +PyDoc_STRVAR(PyIgnore_exception_doc, + "This is an exception ignore" +); +static PyObject *PyIgnore_exception_get(PyIgnore *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyBool_FromLong(self->data->exception); +} + +PyDoc_STRVAR(PyIgnore_regexp_doc, + "Regexp pattern matching" +); +static PyObject *PyIgnore_regexp_get(PyIgnore *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyBool_FromLong(self->data->regexp); +} + +PyDoc_STRVAR(PyIgnore_fullword_doc, + "Pattern matches only full words" +); +static PyObject *PyIgnore_fullword_get(PyIgnore *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyBool_FromLong(self->data->fullword); +} + +PyDoc_STRVAR(PyIgnore_replies_doc, + "Ignore replies to nick in channel" +); +static PyObject *PyIgnore_replies_get(PyIgnore *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyBool_FromLong(self->data->replies); +} + +/* specialized getters/setters */ +static PyGetSetDef PyIgnore_getseters[] = { + {"mask", (getter)PyIgnore_mask_get, NULL, + PyIgnore_mask_doc, NULL}, + {"servertag", (getter)PyIgnore_servertag_get, NULL, + PyIgnore_servertag_doc, NULL}, + {"pattern", (getter)PyIgnore_pattern_get, NULL, + PyIgnore_pattern_doc, NULL}, + {"level", (getter)PyIgnore_level_get, NULL, + PyIgnore_level_doc, NULL}, + {"exception", (getter)PyIgnore_exception_get, NULL, + PyIgnore_exception_doc, NULL}, + {"regexp", (getter)PyIgnore_regexp_get, NULL, + PyIgnore_regexp_doc, NULL}, + {"fullword", (getter)PyIgnore_fullword_get, NULL, + PyIgnore_fullword_doc, NULL}, + {"replies", (getter)PyIgnore_replies_get, NULL, + PyIgnore_replies_doc, NULL}, + {NULL} +}; + +/* Methods */ +PyDoc_STRVAR(PyIgnore_channels_doc, + "channels() -> list of str\n" + "\n" + "Ignore only in channels (list of names)\n" +); +static PyObject *PyIgnore_channels(PyIgnore *self, PyObject *args) +{ + char **p; + PyObject *list; + + RET_NULL_IF_INVALID(self->data); + + list = PyList_New(0); + if (!list) + return NULL; + + for (p = self->data->channels; *p; p++) + { + int ret; + PyObject *str; + + str = PyString_FromString(*p); + if (!str) + { + Py_XDECREF(list); + return NULL; + } + + ret = PyList_Append(list, str); + Py_DECREF(str); + if (ret != 0) + { + Py_XDECREF(list); + return NULL; + } + } + + return list; +} + +PyDoc_STRVAR(PyIgnore_add_rec_doc, + "add_rec() -> None\n" + "\n" + "Add ignore record" +); +static PyObject *PyIgnore_add_rec(PyIgnore *self, PyObject *args) +{ + RET_NULL_IF_INVALID(self->data); + + ignore_add_rec(self->data); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyIgnore_update_rec_doc, + "update_rec() -> None\n" + "\n" + "Update ignore record in configuration" +); +static PyObject *PyIgnore_update_rec(PyIgnore *self, PyObject *args) +{ + RET_NULL_IF_INVALID(self->data); + + ignore_update_rec(self->data); + + Py_RETURN_NONE; +} + +/* Methods for object */ +static PyMethodDef PyIgnore_methods[] = { + {"add_rec", (PyCFunction)PyIgnore_add_rec, METH_NOARGS, + PyIgnore_add_rec_doc}, + {"update_rec", (PyCFunction)PyIgnore_update_rec, METH_NOARGS, + PyIgnore_update_rec_doc}, + {"channels", (PyCFunction)PyIgnore_channels, METH_NOARGS, + PyIgnore_channels_doc}, + {NULL} /* Sentinel */ +}; + +PyTypeObject PyIgnoreType = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "Ignore", /*tp_name*/ + sizeof(PyIgnore), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)PyIgnore_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + "PyIgnore objects", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + PyIgnore_methods, /* tp_methods */ + 0, /* tp_members */ + PyIgnore_getseters, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + PyIgnore_new, /* tp_new */ +}; + + +/* ignore factory function */ +PyObject *pyignore_new(void *ignore) +{ + PyIgnore *pyignore; + + pyignore = py_inst(PyIgnore, PyIgnoreType); + if (!pyignore) + return NULL; + + pyignore->data = ignore; + pyignore->cleanup_installed = 1; + signal_add_last_data("ignore destroy", ignore_cleanup, pyignore); + + return (PyObject *)pyignore; +} + +int ignore_object_init(void) +{ + g_return_val_if_fail(py_module != NULL, 0); + + if (PyType_Ready(&PyIgnoreType) < 0) + return 0; + + Py_INCREF(&PyIgnoreType); + PyModule_AddObject(py_module, "Ignore", (PyObject *)&PyIgnoreType); + + return 1; +} diff --git a/src/objects/ignore-object.h b/src/objects/ignore-object.h new file mode 100644 index 0000000..39f7425 --- /dev/null +++ b/src/objects/ignore-object.h @@ -0,0 +1,21 @@ +#ifndef _IGNORE_OBJECT_H_ +#define _IGNORE_OBJECT_H_ + +#include +#include "base-objects.h" + +/* forward */ +struct _IGNORE_REC; + +typedef struct +{ + PyIrssiFinal_HEAD(struct _IGNORE_REC) +} PyIgnore; + +extern PyTypeObject PyIgnoreType; + +int ignore_object_init(void); +PyObject *pyignore_new(void *ignore); +#define pyignore_check(op) PyObject_TypeCheck(op, &PyIgnoreType) + +#endif diff --git a/src/objects/irc-channel-object.c b/src/objects/irc-channel-object.c new file mode 100644 index 0000000..5e9531d --- /dev/null +++ b/src/objects/irc-channel-object.c @@ -0,0 +1,173 @@ +#include +#include "pyirssi_irc.h" +#include "pymodule.h" +#include "pycore.h" +#include "irc-channel-object.h" +#include "factory.h" + +/* PyIrcChannel destructor is inherited from PyChannel */ + +/* specialized getters/setters */ +static PyGetSetDef PyIrcChannel_getseters[] = { + {NULL} +}; + +/* Methods */ +PyDoc_STRVAR(bans_doc, + "bans() -> list of Ban objects\n" + "\n" + "Returns a list of bans in the channel.\n" +); +static PyObject *PyIrcChannel_bans(PyIrcChannel *self, PyObject *args) +{ + RET_NULL_IF_INVALID(self->data); + + return py_irssi_objlist_new(self->data->banlist, 1, (InitFunc)pyban_new); +} + +PyDoc_STRVAR(ban_get_mask_doc, + "ban_get_mask(nick, ban_type=0) -> str\n" + "\n" + "Get ban mask for 'nick'.\n" +); +static PyObject *PyIrcChannel_ban_get_mask(PyIrcChannel *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"nick", "ban_type", NULL}; + char *nick, *str; + int ban_type = 0; + PyObject *ret; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|i", kwlist, &nick, &ban_type)) + return NULL; + + str = ban_get_mask(self->data, nick, ban_type); + if (!str) + Py_RETURN_NONE; + + ret = PyString_FromString(str); + g_free(str); + + return ret; +} + +PyDoc_STRVAR(banlist_add_doc, + "banlist_add(ban, nick, time) -> Ban object or None\n" + "\n" + "Add a new ban to channel. Return None if duplicate." +); +static PyObject *PyIrcChannel_banlist_add(PyIrcChannel *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"ban", "nick", "time", NULL}; + char *ban, *nick; + time_t btime; + BAN_REC *newban; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "ssk", kwlist, &ban, &nick, &btime)) + return NULL; + + newban = banlist_add(self->data, ban, nick, btime); + /* XXX: return none or throw error? */ + if (!newban) + Py_RETURN_NONE; + + return pyban_new(newban); +} + +PyDoc_STRVAR(banlist_remove_doc, + "banlist_remove(ban, nick) -> None\n" + "\n" + "Remove a new ban from channel.\n" +); +static PyObject *PyIrcChannel_banlist_remove(PyIrcChannel *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"ban", "nick", NULL}; + char *ban, *nick; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss", kwlist, &ban, &nick)) + return NULL; + + banlist_remove(self->data, ban, nick); + Py_RETURN_NONE; +} + +/* Methods for object */ +static PyMethodDef PyIrcChannel_methods[] = { + {"bans", (PyCFunction)PyIrcChannel_bans, METH_NOARGS, + bans_doc}, + {"ban_get_mask", (PyCFunction)PyIrcChannel_ban_get_mask, METH_VARARGS | METH_KEYWORDS, + ban_get_mask_doc}, + {"banlist_add", (PyCFunction)PyIrcChannel_banlist_add, METH_VARARGS | METH_KEYWORDS, + banlist_add_doc}, + {"banlist_remove", (PyCFunction)PyIrcChannel_banlist_remove, METH_VARARGS | METH_KEYWORDS, + banlist_remove_doc}, + {NULL} /* Sentinel */ +}; + +PyTypeObject PyIrcChannelType = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "IrcChannel", /*tp_name*/ + sizeof(PyIrcChannel), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + 0, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + "PyIrcChannel objects", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + PyIrcChannel_methods, /* tp_methods */ + 0, /* tp_members */ + PyIrcChannel_getseters, /* tp_getset */ + &PyChannelType, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + + +/* irc channel factory function */ +PyObject *pyirc_channel_new(void *chan) +{ + static const char *BASE_NAME = "CHANNEL"; + return pychannel_sub_new(chan, BASE_NAME, &PyIrcChannelType); +} + +int irc_channel_object_init(void) +{ + g_return_val_if_fail(py_module != NULL, 0); + + if (PyType_Ready(&PyIrcChannelType) < 0) + return 0; + + Py_INCREF(&PyIrcChannelType); + PyModule_AddObject(py_module, "IrcChannel", (PyObject *)&PyIrcChannelType); + + return 1; +} diff --git a/src/objects/irc-channel-object.h b/src/objects/irc-channel-object.h new file mode 100644 index 0000000..a1d845a --- /dev/null +++ b/src/objects/irc-channel-object.h @@ -0,0 +1,21 @@ +#ifndef _IRC_CHANNEL_OBJECT_H_ +#define _IRC_CHANNEL_OBJECT_H_ + +#include +#include "window-item-object.h" + +/* forward */ +struct _IRC_CHANNEL_REC; + +typedef struct +{ + PyWindowItem_HEAD(struct _IRC_CHANNEL_REC) +} PyIrcChannel; + +extern PyTypeObject PyIrcChannelType; + +int irc_channel_object_init(void); +PyObject *pyirc_channel_new(void *chan); +#define pyirc_channel_check(op) PyObject_TypeCheck(op, &PyIrcChannelType) + +#endif diff --git a/src/objects/irc-connect-object.c b/src/objects/irc-connect-object.c new file mode 100644 index 0000000..5068dea --- /dev/null +++ b/src/objects/irc-connect-object.c @@ -0,0 +1,86 @@ +#include +#include "pymodule.h" +#include "base-objects.h" +#include "irc-connect-object.h" +#include "pyirssi_irc.h" +#include "pycore.h" +#include "pyutils.h" + +/* cleanup and deallocation handled by Connect base */ + +/* Getters */ +PyDoc_STRVAR(PyIrcConnect_alternate_nick_doc, + "Alternate nick to use if default nick is taken" +); +static PyObject *PyIrcConnect_alternate_nick_get(PyIrcConnect *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->alternate_nick); +} + +/* Get/Set */ +static PyGetSetDef PyIrcConnect_getseters[] = { + {"alternate_nick", (getter)PyIrcConnect_alternate_nick_get, NULL, + PyIrcConnect_alternate_nick_doc, NULL}, + {NULL} +}; + +PyTypeObject PyIrcConnectType = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "IrcConnect", /*tp_name*/ + sizeof(PyIrcConnect), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + 0, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + "PyIrcConnect objects", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + PyIrcConnect_getseters, /* tp_getset */ + &PyConnectType, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +PyObject *pyirc_connect_new(void *connect, int managed) +{ + return pyconnect_sub_new(connect, &PyIrcConnectType, managed); +} + +int irc_connect_object_init(void) +{ + g_return_val_if_fail(py_module != NULL, 0); + + if (PyType_Ready(&PyIrcConnectType) < 0) + return 0; + + Py_INCREF(&PyIrcConnectType); + PyModule_AddObject(py_module, "IrcConnect", (PyObject *)&PyIrcConnectType); + + return 1; +} diff --git a/src/objects/irc-connect-object.h b/src/objects/irc-connect-object.h new file mode 100644 index 0000000..3f6cad4 --- /dev/null +++ b/src/objects/irc-connect-object.h @@ -0,0 +1,21 @@ +#ifndef _IRC_CONNECT_OBJECT_H_ +#define _IRC_CONNECT_OBJECT_H_ + +#include +#include "connect-object.h" + +/* forward */ +struct _IRC_SERVER_CONNECT_REC; + +typedef struct +{ + PyIrssi_HEAD(struct _IRC_SERVER_CONNECT_REC) +} PyIrcConnect; + +extern PyTypeObject PyIrcConnectType; + +int irc_connect_object_init(void); +PyObject *pyirc_connect_new(void *connect, int managed); +#define pyirc_connect_check(op) PyObject_TypeCheck(op, &PyIrcConnectType) + +#endif diff --git a/src/objects/irc-server-object.c b/src/objects/irc-server-object.c new file mode 100644 index 0000000..4e9a28e --- /dev/null +++ b/src/objects/irc-server-object.c @@ -0,0 +1,491 @@ +#include +#include "pymodule.h" +#include "base-objects.h" +#include "irc-server-object.h" +#include "factory.h" +#include "pyirssi_irc.h" +#include "pycore.h" +#include "pyutils.h" + +/* cleanup and dealloc inherited from base Server */ + +/* Getters */ +PyDoc_STRVAR(PyIrcServer_real_address_doc, + "Address the IRC server gives" +); +static PyObject *PyIrcServer_real_address_get(PyIrcServer *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->real_address); +} + +PyDoc_STRVAR(PyIrcServer_usermode_doc, + "User mode in server" +); +static PyObject *PyIrcServer_usermode_get(PyIrcServer *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->usermode); +} + +PyDoc_STRVAR(PyIrcServer_userhost_doc, + "Your user host in server" +); +static PyObject *PyIrcServer_userhost_get(PyIrcServer *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->userhost); +} + +static PyGetSetDef PyIrcServer_getseters[] = { + {"real_address", (getter)PyIrcServer_real_address_get, NULL, + PyIrcServer_real_address_doc, NULL}, + {"usermode", (getter)PyIrcServer_usermode_get, NULL, + PyIrcServer_usermode_doc, NULL}, + {"userhost", (getter)PyIrcServer_userhost_get, NULL, + PyIrcServer_userhost_doc, NULL}, + {NULL} +}; + +/* Methods */ +PyDoc_STRVAR(get_channels_doc, + "get_channels() -> str\n" + "\n" + "Return a string of all channels (and keys, if any have them) in server,\n" + "like '#a,#b,#c,#d x,b_chan_key,x,x' or just '#e,#f,#g'\n" +); +static PyObject *PyIrcServer_get_channels(PyIrcServer *self, PyObject *args) +{ + char *list; + PyObject *ret; + + RET_NULL_IF_INVALID(self->data); + + list = irc_server_get_channels(self->data); + ret = PyString_FromString(list); + g_free(list); + + return ret; +} + +PyDoc_STRVAR(send_raw_doc, + "send_raw(cmd) -> None\n" + "\n" + "Send raw message to server, it will be flood protected so you\n" + "don't need to worry about it.\n" +); +static PyObject *PyIrcServer_send_raw(PyIrcServer *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"cmd", NULL}; + char *cmd; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &cmd)) + return NULL; + + irc_send_cmd(self->data, cmd); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(send_raw_now_doc, + "send_raw_now(cmd) -> None\n" + "\n" + "Send raw message to server immediately without flood protection.\n" +); +static PyObject *PyIrcServer_send_raw_now(PyIrcServer *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"cmd", NULL}; + char *cmd; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &cmd)) + return NULL; + + irc_send_cmd_now(self->data, cmd); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(send_raw_split_doc, + "send_raw_split(cmd, nickarg, max_nicks) -> None\n" + "\n" + "Split the `cmd' into several commands so `nickarg' argument has only\n" + "`max_nicks' number of nicks.\n" + "\n" + "Example:\n" + "server.send_raw_split('KICK #channel nick1,nick2,nick3 :byebye', 3, 2)\n" + "\n" + "Irssi will send commands 'KICK #channel nick1,nick2 :byebye' and\n" + "'KICK #channel nick3 :byebye' to server.\n" +); +static PyObject *PyIrcServer_send_raw_split(PyIrcServer *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"cmd", "nickarg", "max_nicks", NULL}; + char *cmd; + int nickarg; + int max_nicks; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "sii", kwlist, &cmd, &nickarg, &max_nicks)) + return NULL; + + irc_send_cmd_split(self->data, cmd, nickarg, max_nicks); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(ctcp_send_reply_doc, + "ctcp_send_reply(data) -> None\n" + "\n" + "Send CTCP reply. This will be 'CTCP flood protected' so if there's too\n" + "many CTCP requests in buffer, this reply might not get sent. The data\n" + "is the full raw command to be sent to server, like\n" + "'NOTICE nick :\001VERSION irssi\001'\n" +); +static PyObject *PyIrcServer_ctcp_send_reply(PyIrcServer *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"data", NULL}; + char *data; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &data)) + return NULL; + + ctcp_send_reply(self->data, data); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(isupport_doc, + "isupport(name) -> str or None\n" + "\n" + "Returns the value of the named item in the ISUPPORT (005) numeric to the\n" + "script. If the item is not present returns undef, if the item has no value\n" + "then '' is returned use defined server.isupport('name') if you need to\n" + "check whether a property is present.\n" + "See http://www.ietf.org/internet-drafts/draft-brocklesby-irc-isupport-01.txt\n" + "for more information on the ISUPPORT numeric.\n" +); +static PyObject *PyIrcServer_isupport(PyIrcServer *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"name", NULL}; + char *name; + char *found; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &name)) + return NULL; + + found = g_hash_table_lookup(self->data->isupport, name); + + RET_AS_STRING_OR_NONE(found); +} + +PyDoc_STRVAR(PyIrcServer_netsplit_find_doc, + "netsplit_find(nick, address) -> Netsplit object or None\n" + "\n" + "Check if nick!address is on the other side of netsplit. Netsplit records\n" + "are automatically removed after 30 minutes (current default)..\n" +); +static PyObject *PyIrcServer_netsplit_find(PyIrcServer *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"nick", "address", NULL}; + char *nick = ""; + char *address = ""; + NETSPLIT_REC *ns; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss", kwlist, + &nick, &address)) + return NULL; + + ns = netsplit_find(self->data, nick, address); + if (ns) + return pynetsplit_new(ns); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyIrcServer_netsplit_find_channel_doc, + "netsplit_find_channel(nick, address, channel) -> NetsplitChannel object or None\n" + "\n" + "Find nick record for nick!address in channel `channel'.\n" +); +static PyObject *PyIrcServer_netsplit_find_channel(PyIrcServer *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"nick", "address", "channel", NULL}; + char *nick = ""; + char *address = ""; + char *channel = ""; + NETSPLIT_CHAN_REC *nsc; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "sss", kwlist, + &nick, &address, &channel)) + return NULL; + + nsc = netsplit_find_channel(self->data, nick, address, channel); + if (nsc) + return pynetsplit_channel_new(nsc); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyIrcServer_notifylist_ison_doc, + "notifylist_ison(nick) -> bool\n" + "\n" + "Check if nick is on server\n" +); +static PyObject *PyIrcServer_notifylist_ison(PyIrcServer *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"nick", NULL}; + char *nick = ""; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &nick)) + return NULL; + + return PyBool_FromLong(notifylist_ison_server(self->data, nick)); +} + +/* expect a list of tuples [('str', 'str'), ...] */ +static GSList *py_event_conv(PyObject *list) +{ + int i; + GSList *ret = NULL; + + if (!PyList_Check(list)) + { + PyErr_Format(PyExc_TypeError, "expect a list of tuples of two strings"); + return NULL; + } + + for (i = 0; i < PyList_Size(list); i++) + { + char *key; + char *val; + PyObject *tup = PyList_GET_ITEM(list, i); + + if (!PyTuple_Check(tup) || !PyArg_ParseTuple(tup, "ss", &key, &val)) + { + GSList *node; + + for (node = ret; node; node = node->next) + g_free(node->data); + + g_slist_free(ret); + + if (!PyErr_Occurred() || PyErr_ExceptionMatches(PyExc_TypeError)) + { + PyErr_Clear(); + PyErr_SetString(PyExc_TypeError, "expect a list of tuples of two strings"); + } + + return NULL; + } + + ret = g_slist_append(ret, g_strdup(key)); + ret = g_slist_append(ret, g_strdup(val)); + } + + return ret; +} + +PyDoc_STRVAR(PyIrcServer_redirect_event_doc, + "redirect_event(command, signals, arg=None, count=1, remote=-1, failure_signal=None) -> None\n" + "\n" + "Specify that the next command sent to server will be redirected.\n" + "NOTE: This command MUST be called before sending the command to server.\n" + "\n" + "`command' - Name of the registered redirection that we're using.\n" + "\n" + "`count' - How many times to execute the redirection. Some commands may\n" + "send multiple stop events, like MODE #a,#b.\n" + "\n" + "`arg' - The argument to be compared in event strings. You can give multiple\n" + "arguments separated with space.\n" + "\n" + "`remote' - Specifies if the command is a remote command, -1 = use default.\n" + "\n" + "`failure_signal' - If irssi can't find the stop signal for the redirection,\n" + "this signal is called.\n" + "\n" + "`signals' - hash reference with \"event\" => \"redir signal\" entries.\n" + "If the event is "", all the events belonging to the redirection but not\n" + "specified here, will be sent there.\n" + "\n" + "Example:\n" + "\n" + "# ignore all events generated by whois query, except 311.\n" + "\n" + "server.redirect_event(\"whois\",\n" + " remote = 0,\n" + " arg = \"cras\",\n" + " signals = [\n" + " ('event 311', 'redir whois'),\n" + " ('', 'event empty') \n" + " ]\n" + ")\n" + "server.send_raw(\"WHOIS :cras\")\n" +); +static PyObject *PyIrcServer_redirect_event(PyIrcServer *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"command", "signals", "arg", "count", "remote", "failure_signal", NULL}; + char *command = ""; + int count = 1; + char *arg = NULL; + int remote = -1; + char *failure_signal = NULL; + PyObject *signals = NULL; + GSList *gsignals; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "sO|ziiz", kwlist, + &command, &signals, &arg, &count, &remote, &failure_signal)) + return NULL; + + gsignals = py_event_conv(signals); + if (!gsignals) + return NULL; + + server_redirect_event(self->data, command, count, arg, remote, failure_signal, gsignals); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyIrcServer_redirect_get_signal_doc, + "redirect_get_signal(event, args) -> str\n" +); +static PyObject *PyIrcServer_redirect_get_signal(PyIrcServer *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"event", "args", NULL}; + char *event = ""; + char *pargs = ""; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss", kwlist, + &event, &pargs)) + return NULL; + + RET_AS_STRING_OR_NONE(server_redirect_get_signal(self->data, event, pargs)); +} + +PyDoc_STRVAR(PyIrcServer_redirect_peek_signal_doc, + "redirect_peek_signal(event, args) -> str\n" +); +static PyObject *PyIrcServer_redirect_peek_signal(PyIrcServer *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"event", "args", NULL}; + char *event = ""; + char *pargs = ""; + int redirection; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss", kwlist, + &event, &pargs)) + return NULL; + + RET_AS_STRING_OR_NONE(server_redirect_peek_signal(self->data, event, pargs, &redirection)); +} + +/* Methods for object */ +static PyMethodDef PyIrcServer_methods[] = { + {"get_channels", (PyCFunction)PyIrcServer_get_channels, METH_NOARGS, + get_channels_doc}, + {"send_raw", (PyCFunction)PyIrcServer_send_raw, METH_VARARGS | METH_KEYWORDS, + send_raw_doc}, + {"send_raw_now", (PyCFunction)PyIrcServer_send_raw_now, METH_VARARGS | METH_KEYWORDS, + send_raw_now_doc}, + {"send_raw_split", (PyCFunction)PyIrcServer_send_raw_split, METH_VARARGS | METH_KEYWORDS, + send_raw_split_doc}, + {"ctcp_send_reply", (PyCFunction)PyIrcServer_ctcp_send_reply, METH_VARARGS | METH_KEYWORDS, + ctcp_send_reply_doc}, + {"isupport", (PyCFunction)PyIrcServer_isupport, METH_VARARGS | METH_KEYWORDS, + isupport_doc}, + {"netsplit_find", (PyCFunction)PyIrcServer_netsplit_find, METH_VARARGS | METH_KEYWORDS, + PyIrcServer_netsplit_find_doc}, + {"netsplit_find_channel", (PyCFunction)PyIrcServer_netsplit_find_channel, METH_VARARGS | METH_KEYWORDS, + PyIrcServer_netsplit_find_channel_doc}, + {"notifylist_ison", (PyCFunction)PyIrcServer_notifylist_ison, METH_VARARGS | METH_KEYWORDS, + PyIrcServer_notifylist_ison_doc}, + {"redirect_event", (PyCFunction)PyIrcServer_redirect_event, METH_VARARGS | METH_KEYWORDS, + PyIrcServer_redirect_event_doc}, + {"redirect_get_signal", (PyCFunction)PyIrcServer_redirect_get_signal, METH_VARARGS | METH_KEYWORDS, + PyIrcServer_redirect_get_signal_doc}, + {"redirect_peek_signal", (PyCFunction)PyIrcServer_redirect_peek_signal, METH_VARARGS | METH_KEYWORDS, + PyIrcServer_redirect_peek_signal_doc}, + {NULL} /* Sentinel */ +}; + +PyTypeObject PyIrcServerType = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "IrcServer", /*tp_name*/ + sizeof(PyIrcServer), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + 0, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + "PyIrcServer objects", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + PyIrcServer_methods, /* tp_methods */ + 0, /* tp_members */ + PyIrcServer_getseters, /* tp_getset */ + &PyServerType, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +PyObject *pyirc_server_new(void *server) +{ + return pyserver_sub_new(server, &PyIrcServerType); +} + +int irc_server_object_init(void) +{ + g_return_val_if_fail(py_module != NULL, 0); + + if (PyType_Ready(&PyIrcServerType) < 0) + return 0; + + Py_INCREF(&PyIrcServerType); + PyModule_AddObject(py_module, "IrcServer", (PyObject *)&PyIrcServerType); + + return 1; +} diff --git a/src/objects/irc-server-object.h b/src/objects/irc-server-object.h new file mode 100644 index 0000000..b3eb76a --- /dev/null +++ b/src/objects/irc-server-object.h @@ -0,0 +1,21 @@ +#ifndef _IRC_SERVER_OBJECT_H_ +#define _IRC_SERVER_OBJECT_H_ + +#include +#include "server-object.h" + +/* forward */ +struct _IRC_SERVER_REC; + +typedef struct +{ + PyServer_HEAD(struct _IRC_SERVER_REC) +} PyIrcServer; + +extern PyTypeObject PyIrcServerType; + +int irc_server_object_init(void); +PyObject *pyirc_server_new(void *server); +#define pyirc_server_check(op) PyObject_TypeCheck(op, &PyIrcServerType) + +#endif diff --git a/src/objects/log-object.c b/src/objects/log-object.c new file mode 100644 index 0000000..b18f826 --- /dev/null +++ b/src/objects/log-object.c @@ -0,0 +1,477 @@ +#include +#include "pyirssi_irc.h" +#include "pymodule.h" +#include "log-object.h" +#include "factory.h" +#include "pycore.h" + +static LOG_ITEM_REC *find_item(LOG_REC *log, PyLogitem *item); +static void log_cleanup(LOG_REC *log); +static int logtype(int *type, int target, int window); + +/* find/convert a py log item */ +static LOG_ITEM_REC *find_item(LOG_REC *log, PyLogitem *item) +{ + int type; + char *name; + char *servertag = NULL; + + if (!item->type || !item->name) + return NULL; + + type = PyInt_AS_LONG(item->type); + name = PyString_AS_STRING(item->name); + if (item->servertag) + servertag = PyString_AS_STRING(item->servertag); + + return log_item_find(log, type, name, servertag); +} + +/* monitor "log remove" signal */ +static void log_cleanup(LOG_REC *log) +{ + PyLog *pylog = signal_get_user_data(); + + if (log == pylog->data) + { + pylog->data = NULL; + pylog->cleanup_installed = 0; + signal_remove_data("log remove", log_cleanup, pylog); + } +} + +static void PyLog_dealloc(PyLog *self) +{ + if (self->cleanup_installed) + signal_remove_data("log remove", log_cleanup, self); + + if (self->data && !g_slist_find(logs, self->data)) + { + printtext(NULL, NULL, MSGLEVEL_CRAP, "destroying orphan log %s", self->data->fname); + log_close(self->data); + } + + self->ob_type->tp_free((PyObject*)self); +} + +static PyObject *PyLog_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyLog *self; + + self = (PyLog *)type->tp_alloc(type, 0); + if (!self) + return NULL; + + return (PyObject *)self; +} + +/* function to create the log */ +PyDoc_STRVAR(PyLog_doc, + "__init__(fname, level=MSGLEVEL_ALL)\n" + "\n" + "Create a log\n" +); +static int PyLog_init(PyLog *self, PyObject *args, PyObject *kwds) +{ + char *fname; + int level = MSGLEVEL_ALL; + LOG_REC *log; + + static char *kwlist[] = {"fname", "level", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|i", kwlist, + &fname, &level)) + return -1; + + /*XXX: anything better than RuntimeError ? */ + if (self->data || self->cleanup_installed) + { + PyErr_Format(PyExc_RuntimeError, "log already opened; close it first"); + return -1; + } + + log = log_create_rec(fname, level); + if (!log) + { + PyErr_Format(PyExc_RuntimeError, "failed to create log"); + return -1; + } + + self->data = log; + self->cleanup_installed = 1; + signal_add_last_data("log remove", log_cleanup, self); + + return 0; +} + +/* Getters */ +PyDoc_STRVAR(PyLog_fname_doc, + "Log file name" +); +static PyObject *PyLog_fname_get(PyLog *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->fname); +} + +PyDoc_STRVAR(PyLog_real_fname_doc, + "The actual opened log file (after %d.%m.Y etc. are expanded)" +); +static PyObject *PyLog_real_fname_get(PyLog *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->real_fname); +} + +PyDoc_STRVAR(PyLog_opened_doc, + "Log file is open" +); +static PyObject *PyLog_opened_get(PyLog *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyLong_FromUnsignedLong(self->data->opened); +} + +PyDoc_STRVAR(PyLog_level_doc, + "Log only these levels" +); +static PyObject *PyLog_level_get(PyLog *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyInt_FromLong(self->data->level); +} + +PyDoc_STRVAR(PyLog_last_doc, + "Timestamp when last message was written" +); +static PyObject *PyLog_last_get(PyLog *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyLong_FromUnsignedLong(self->data->last); +} + +PyDoc_STRVAR(PyLog_autoopen_doc, + "Automatically open log at startup" +); +static PyObject *PyLog_autoopen_get(PyLog *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyBool_FromLong(self->data->autoopen); +} + +PyDoc_STRVAR(PyLog_failed_doc, + "Opening log failed last time" +); +static PyObject *PyLog_failed_get(PyLog *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyBool_FromLong(self->data->failed); +} + +PyDoc_STRVAR(PyLog_temp_doc, + "Log isn't saved to config file" +); +static PyObject *PyLog_temp_get(PyLog *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyBool_FromLong(self->data->temp); +} + +/* specialized getters/setters */ +static PyGetSetDef PyLog_getseters[] = { + {"fname", (getter)PyLog_fname_get, NULL, + PyLog_fname_doc, NULL}, + {"real_fname", (getter)PyLog_real_fname_get, NULL, + PyLog_real_fname_doc, NULL}, + {"opened", (getter)PyLog_opened_get, NULL, + PyLog_opened_doc, NULL}, + {"level", (getter)PyLog_level_get, NULL, + PyLog_level_doc, NULL}, + {"last", (getter)PyLog_last_get, NULL, + PyLog_last_doc, NULL}, + {"autoopen", (getter)PyLog_autoopen_get, NULL, + PyLog_autoopen_doc, NULL}, + {"failed", (getter)PyLog_failed_get, NULL, + PyLog_failed_doc, NULL}, + {"temp", (getter)PyLog_temp_get, NULL, + PyLog_temp_doc, NULL}, + {NULL} +}; + +/* Methods */ +PyDoc_STRVAR(PyLog_items_doc, + "items() -> list of Log objects\n" + "\n" + "Return a list of log items\n" +); +static PyObject *PyLog_items(PyLog *self, PyObject *args) +{ + RET_NULL_IF_INVALID(self->data); + return py_irssi_objlist_new(self->data->items, 1, (InitFunc)pylogitem_new); +} + +PyDoc_STRVAR(PyLog_update_doc, + "update() -> None\n" + "\n" + "Add log to list of logs / save changes to config file.\n" +); +static PyObject *PyLog_update(PyLog *self, PyObject *args) +{ + RET_NULL_IF_INVALID(self->data); + + log_update(self->data); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyLog_close_doc, + "destroy() -> None\n" + "\n" + "Destroy the log file\n" +); +static PyObject *PyLog_close(PyLog *self, PyObject *args) +{ + RET_NULL_IF_INVALID(self->data); + + log_close(self->data); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyLog_start_logging_doc, + "start_logging() -> None\n" + "\n" + "Open log file and start logging.\n" +); +static PyObject *PyLog_start_logging(PyLog *self, PyObject *args) +{ + RET_NULL_IF_INVALID(self->data); + + log_start_logging(self->data); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyLog_stop_logging_doc, + "stop_logging() -> None\n" + "\n" + "Stop and close the log file.\n" +); +static PyObject *PyLog_stop_logging(PyLog *self, PyObject *args) +{ + RET_NULL_IF_INVALID(self->data); + + log_stop_logging(self->data); + + Py_RETURN_NONE; +} + +static int logtype(int *type, int target, int window) +{ + if (target || window) + { + if (target && window) + { + PyErr_SetString(PyExc_TypeError, "must specify target or window, not both"); + return 0; + } + + *type = target? 0 : 1; + } + else if (*type < 0) + { + PyErr_SetString(PyExc_TypeError, "must specify type, target, or window"); + return 0; + } + + return 1; +} + +PyDoc_STRVAR(PyLog_item_add_doc, + "item_add(item, servertag=None, type=0, target=False, window=False) -> None\n" + "\n" + "Add a log item to log.\n" + "\n" + "Add a target item (nick, chan): \n" + " item_add('#linux', target=True)\n" + " item_add('#linux', type=0)\n" + "\n" + "Add a window ref: \n" + " item_add('2', window=True)\n" + " item_add('2', type=1)\n" +); +static PyObject *PyLog_item_add(PyLog *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"item", "servertag", "type", "target", "window", NULL}; + char *item = ""; + char *servertag = NULL; + int type = 0; + int target = 0; + int window = 0; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|ziii", kwlist, + &item, &servertag, &type, &target, &window)) + return NULL; + + if (!logtype(&type, target, window)) + return NULL; + + log_item_add(self->data, type, item, servertag); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyLog_item_destroy_doc, + "item_destroy(item) -> None\n" + "\n" + "Remove log item from log.\n" +); +static PyObject *PyLog_item_destroy(PyLog *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"item", NULL}; + PyObject *item = NULL; + LOG_ITEM_REC *li; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, + &item)) + return NULL; + + if (!pylogitem_check(item)) + return PyErr_Format(PyExc_TypeError, "arg 1 should be log item"); + + li = find_item(self->data, (PyLogitem *)item); + if (!li) + return PyErr_Format(PyExc_TypeError, "log item invalid or not found"); + + log_item_destroy(self->data, li); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyLog_item_find_doc, + "item_find(item, servertag=None, type=-1, target=False, window=False) -> item or None\n" + "\n" + "Find item from log.\n" +); +static PyObject *PyLog_item_find(PyLog *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"item", "servertag", "type", "target", "window", NULL}; + char *item = ""; + char *server = NULL; + int type = 0; + int target = 0; + int window = 0; + LOG_ITEM_REC *li; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|ziii", kwlist, + &item, &server, &type, &target, &window)) + return NULL; + + if (!logtype(&type, target, window)) + return NULL; + + li = log_item_find(self->data, type, item, server); + if (li) + return pylogitem_new(li); + + Py_RETURN_NONE; +} + +/* Methods for object */ +static PyMethodDef PyLog_methods[] = { + {"items", (PyCFunction)PyLog_items, METH_NOARGS, + PyLog_items_doc}, + {"update", (PyCFunction)PyLog_update, METH_NOARGS, + PyLog_update_doc}, + {"close", (PyCFunction)PyLog_close, METH_NOARGS, + PyLog_close_doc}, + {"start_logging", (PyCFunction)PyLog_start_logging, METH_NOARGS, + PyLog_start_logging_doc}, + {"stop_logging", (PyCFunction)PyLog_stop_logging, METH_NOARGS, + PyLog_stop_logging_doc}, + {"item_add", (PyCFunction)PyLog_item_add, METH_VARARGS | METH_KEYWORDS, + PyLog_item_add_doc}, + {"item_destroy", (PyCFunction)PyLog_item_destroy, METH_VARARGS | METH_KEYWORDS, + PyLog_item_destroy_doc}, + {"item_find", (PyCFunction)PyLog_item_find, METH_VARARGS | METH_KEYWORDS, + PyLog_item_find_doc}, + {NULL} /* Sentinel */ +}; + +PyTypeObject PyLogType = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "Log", /*tp_name*/ + sizeof(PyLog), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)PyLog_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + PyLog_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + PyLog_methods, /* tp_methods */ + 0, /* tp_members */ + PyLog_getseters, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)PyLog_init, /* tp_init */ + 0, /* tp_alloc */ + PyLog_new, /* tp_new */ +}; + + +/* window item wrapper factory function */ +PyObject *pylog_new(void *log) +{ + PyLog *pylog; + + pylog = (PyLog *)PyLogType.tp_alloc(&PyLogType, 0); + if (!pylog) + return NULL; + + pylog->data = log; + pylog->cleanup_installed = 1; + signal_add_last_data("log remove", log_cleanup, pylog); + + return (PyObject *)pylog; +} + +int log_object_init(void) +{ + g_return_val_if_fail(py_module != NULL, 0); + + if (PyType_Ready(&PyLogType) < 0) + return 0; + + Py_INCREF(&PyLogType); + PyModule_AddObject(py_module, "Log", (PyObject *)&PyLogType); + + return 1; +} diff --git a/src/objects/log-object.h b/src/objects/log-object.h new file mode 100644 index 0000000..9893bc5 --- /dev/null +++ b/src/objects/log-object.h @@ -0,0 +1,21 @@ +#ifndef _LOG_OBJECT_H_ +#define _LOG_OBJECT_H_ + +#include +#include "base-objects.h" + +/* forward */ +struct _LOG_REC; + +typedef struct +{ + PyIrssiFinal_HEAD(struct _LOG_REC) +} PyLog; + +extern PyTypeObject PyLogType; + +int log_object_init(void); +PyObject *pylog_new(void *log); +#define pylog_check(op) PyObject_TypeCheck(op, &PyLogType) + +#endif diff --git a/src/objects/logitem-object.c b/src/objects/logitem-object.c new file mode 100644 index 0000000..4dc2275 --- /dev/null +++ b/src/objects/logitem-object.c @@ -0,0 +1,156 @@ +#include +#include "pyirssi_irc.h" +#include "pymodule.h" +#include "logitem-object.h" +#include "pycore.h" + +/* no special cleanup -- value copy is made */ + +static void PyLogitem_dealloc(PyLogitem *self) +{ + Py_XDECREF(self->type); + Py_XDECREF(self->name); + Py_XDECREF(self->servertag); + + self->ob_type->tp_free((PyObject*)self); +} + +static PyObject *PyLogitem_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyLogitem *self; + + self = (PyLogitem *)type->tp_alloc(type, 0); + if (!self) + return NULL; + + return (PyObject *)self; +} + +/* Getters */ +PyDoc_STRVAR(PyLogitem_type_doc, + "0=target, 1=window refnum" +); +static PyObject *PyLogitem_type_get(PyLogitem *self, void *closure) +{ + RET_AS_OBJ_OR_NONE(self->type); +} + +PyDoc_STRVAR(PyLogitem_name_doc, + "Name" +); +static PyObject *PyLogitem_name_get(PyLogitem *self, void *closure) +{ + RET_AS_OBJ_OR_NONE(self->name); +} + +PyDoc_STRVAR(PyLogitem_servertag_doc, + "Server tag" +); +static PyObject *PyLogitem_servertag_get(PyLogitem *self, void *closure) +{ + RET_AS_OBJ_OR_NONE(self->servertag); +} + +/* specialized getters/setters */ +static PyGetSetDef PyLogitem_getseters[] = { + {"type", (getter)PyLogitem_type_get, NULL, + PyLogitem_type_doc, NULL}, + {"name", (getter)PyLogitem_name_get, NULL, + PyLogitem_name_doc, NULL}, + {"servertag", (getter)PyLogitem_servertag_get, NULL, + PyLogitem_servertag_doc, NULL}, + {NULL} +}; + +/* Methods for object */ +static PyMethodDef PyLogitem_methods[] = { + {NULL} /* Sentinel */ +}; + +PyTypeObject PyLogitemType = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "Logitem", /*tp_name*/ + sizeof(PyLogitem), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)PyLogitem_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + "PyLogitem objects", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + PyLogitem_methods, /* tp_methods */ + 0, /* tp_members */ + PyLogitem_getseters, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + PyLogitem_new, /* tp_new */ +}; + + +/* log item factory function */ +PyObject *pylogitem_new(void *log) +{ + LOG_ITEM_REC *li = log; + PyLogitem *pylog = NULL; + + pylog = py_inst(PyLogitem, PyLogitemType); + if (!pylog) + return NULL; + + pylog->type = PyInt_FromLong(li->type); + if (!pylog->type) + goto error; + + pylog->name = PyString_FromString(li->name); + if (!pylog->name) + goto error; + + if (li->servertag) + { + pylog->servertag = PyString_FromString(li->servertag); + if (!pylog->servertag) + goto error; + } + + return (PyObject *)pylog; + +error: + Py_XDECREF(pylog); + return NULL; +} + +int logitem_object_init(void) +{ + g_return_val_if_fail(py_module != NULL, 0); + + if (PyType_Ready(&PyLogitemType) < 0) + return 0; + + Py_INCREF(&PyLogitemType); + PyModule_AddObject(py_module, "Logitem", (PyObject *)&PyLogitemType); + + return 1; +} diff --git a/src/objects/logitem-object.h b/src/objects/logitem-object.h new file mode 100644 index 0000000..b7fd588 --- /dev/null +++ b/src/objects/logitem-object.h @@ -0,0 +1,21 @@ +#ifndef _LOG_ITEM_OBJECT_H_ +#define _LOG_ITEM_OBJECT_H_ + +#include +#include "base-objects.h" + +typedef struct +{ + PyObject_HEAD + PyObject *type; + PyObject *name; + PyObject *servertag; +} PyLogitem; + +extern PyTypeObject PyLogitemType; + +int logitem_object_init(void); +PyObject *pylogitem_new(void *log); +#define pylogitem_check(op) PyObject_TypeCheck(op, &PyLogitemType) + +#endif diff --git a/src/objects/main-window-object.c b/src/objects/main-window-object.c new file mode 100644 index 0000000..6541f2b --- /dev/null +++ b/src/objects/main-window-object.c @@ -0,0 +1,199 @@ +#include +#include "pyirssi.h" +#include "pymodule.h" +#include "main-window-object.h" +#include "factory.h" +#include "pycore.h" + +#define MW(data) ((MAIN_WINDOW_REC *) data) + +/* monitor "mainwindow destroyed" signal */ +static void main_window_cleanup(MAIN_WINDOW_REC *mw) +{ + PyMainWindow *pymw = signal_get_user_data(); + + if (mw == pymw->data) + { + pymw->data = NULL; + pymw->cleanup_installed = 0; + signal_remove_data("mainwindow destroyed", main_window_cleanup, pymw); + } +} + +static void PyMainWindow_dealloc(PyMainWindow *self) +{ + if (self->cleanup_installed) + signal_remove_data("mainwindow destroyed", main_window_cleanup, self); + + Py_XDECREF(self->active); + self->ob_type->tp_free((PyObject*)self); +} + +static PyObject *PyMainWindow_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyMainWindow *self; + + self = (PyMainWindow *)type->tp_alloc(type, 0); + if (!self) + return NULL; + + return (PyObject *)self; +} + +/* getters */ +PyDoc_STRVAR(PyMainWindow_active_doc, + "active window object" +); +static PyObject *PyMainWindow_active_get(PyMainWindow *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_OBJ_OR_NONE(self->active); +} + +PyDoc_STRVAR(PyMainWindow_first_line_doc, + "first line used by this window (0..x) (includes statusbars)" +); +static PyObject *PyMainWindow_first_line_get(PyMainWindow *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyInt_FromLong(MW(self->data)->first_line); +} + +PyDoc_STRVAR(PyMainWindow_last_line_doc, + "last line used by this window (0..x) (includes statusbars)" +); +static PyObject *PyMainWindow_last_line_get(PyMainWindow *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyInt_FromLong(MW(self->data)->last_line); +} + +PyDoc_STRVAR(PyMainWindow_width_doc, + "width of the window (includes statusbars)" +); +static PyObject *PyMainWindow_width_get(PyMainWindow *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyInt_FromLong(MW(self->data)->width); +} + +PyDoc_STRVAR(PyMainWindow_height_doc, + "height of the window (includes statusbars)" +); +static PyObject *PyMainWindow_height_get(PyMainWindow *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyInt_FromLong(MW(self->data)->height); +} + +PyDoc_STRVAR(PyMainWindow_statusbar_lines_doc, + "???" +); +static PyObject *PyMainWindow_statusbar_lines_get(PyMainWindow *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyInt_FromLong(MW(self->data)->statusbar_lines); +} + +/* specialized getters/setters */ +static PyGetSetDef PyMainWindow_getseters[] = { + {"active", (getter)PyMainWindow_active_get, NULL, + PyMainWindow_active_doc, NULL}, + {"first_line", (getter)PyMainWindow_first_line_get, NULL, + PyMainWindow_first_line_doc, NULL}, + {"last_line", (getter)PyMainWindow_last_line_get, NULL, + PyMainWindow_last_line_doc, NULL}, + {"width", (getter)PyMainWindow_width_get, NULL, + PyMainWindow_width_doc, NULL}, + {"height", (getter)PyMainWindow_height_get, NULL, + PyMainWindow_height_doc, NULL}, + {"statusbar_lines", (getter)PyMainWindow_statusbar_lines_get, NULL, + PyMainWindow_statusbar_lines_doc, NULL}, + {NULL} +}; + +/* Methods for object */ +static PyMethodDef PyMainWindow_methods[] = { + {NULL} /* Sentinel */ +}; + +PyTypeObject PyMainWindowType = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "MainWindow", /*tp_name*/ + sizeof(PyMainWindow), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)PyMainWindow_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + "PyMainWindow objects", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + PyMainWindow_methods, /* tp_methods */ + 0, /* tp_members */ + PyMainWindow_getseters, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + PyMainWindow_new, /* tp_new */ +}; + + +/* main window wrapper factory function */ +PyObject *pymain_window_new(MAIN_WINDOW_REC *mw) +{ + PyObject *pyactive = NULL; + PyMainWindow *pymw; + + pyactive = pywindow_new(mw->active); + if (!pyactive) + return NULL; + + pymw = py_inst(PyMainWindow, PyMainWindowType); + if (!pymw) + { + Py_DECREF(pyactive); + return NULL; + } + + pymw->active = pyactive; + pymw->data = mw; + pymw->cleanup_installed = 1; + signal_add_last_data("mainwindow destroyed", main_window_cleanup, pymw); + + return (PyObject *)pymw; +} + +int main_window_object_init(void) +{ + g_return_val_if_fail(py_module != NULL, 0); + + if (PyType_Ready(&PyMainWindowType) < 0) + return 0; + + Py_INCREF(&PyMainWindowType); + PyModule_AddObject(py_module, "MainWindow", (PyObject *)&PyMainWindowType); + + return 1; +} diff --git a/src/objects/main-window-object.h b/src/objects/main-window-object.h new file mode 100644 index 0000000..fbbdac0 --- /dev/null +++ b/src/objects/main-window-object.h @@ -0,0 +1,20 @@ +#ifndef _MAIN_WINDOW_OBJECT_H_ +#define _MAIN_WINDOW_OBJECT_H_ + +#include +#include "base-objects.h" +#include "pyirssi.h" + +typedef struct +{ + PyIrssiFinal_HEAD(void) + PyObject *active; +} PyMainWindow; + +extern PyTypeObject PyMainWindowType; + +int main_window_object_init(void); +PyObject *pymain_window_new(MAIN_WINDOW_REC *mw); +#define pymain_window_check(op) PyObject_TypeCheck(op, &PyMainWindowType) + +#endif diff --git a/src/objects/netsplit-channel-object.c b/src/objects/netsplit-channel-object.c new file mode 100644 index 0000000..3e2639b --- /dev/null +++ b/src/objects/netsplit-channel-object.c @@ -0,0 +1,170 @@ +#include +#include "pyirssi_irc.h" +#include "pymodule.h" +#include "netsplit-channel-object.h" +#include "factory.h" +#include "pycore.h" + +/* value copied -- no special cleanup */ + +static void PyNetsplitChannel_dealloc(PyNetsplitChannel *self) +{ + Py_XDECREF(self->name); + + self->ob_type->tp_free((PyObject*)self); +} + +static PyObject *PyNetsplitChannel_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyNetsplitChannel *self; + + self = (PyNetsplitChannel *)type->tp_alloc(type, 0); + if (!self) + return NULL; + + return (PyObject *)self; +} + +/* Getters */ +PyDoc_STRVAR(PyNetsplitChannel_name_doc, + "Channel name" +); +static PyObject *PyNetsplitChannel_name_get(PyNetsplitChannel *self, void *closure) +{ + RET_AS_OBJ_OR_NONE(self->name); +} + +PyDoc_STRVAR(PyNetsplitChannel_op_doc, + "is op" +); +static PyObject *PyNetsplitChannel_op_get(PyNetsplitChannel *self, void *closure) +{ + return PyBool_FromLong(self->op); +} + +PyDoc_STRVAR(PyNetsplitChannel_halfop_doc, + "is halfop" +); +static PyObject *PyNetsplitChannel_halfop_get(PyNetsplitChannel *self, void *closure) +{ + return PyBool_FromLong(self->halfop); +} + +PyDoc_STRVAR(PyNetsplitChannel_voice_doc, + "is voice" +); +static PyObject *PyNetsplitChannel_voice_get(PyNetsplitChannel *self, void *closure) +{ + return PyBool_FromLong(self->voice); +} + +PyDoc_STRVAR(PyNetsplitChannel_other_doc, + "?" +); +static PyObject *PyNetsplitChannel_other_get(PyNetsplitChannel *self, void *closure) +{ + return PyInt_FromLong(self->other); +} + +/* specialized getters/setters */ +static PyGetSetDef PyNetsplitChannel_getseters[] = { + {"name", (getter)PyNetsplitChannel_name_get, NULL, + PyNetsplitChannel_name_doc, NULL}, + {"op", (getter)PyNetsplitChannel_op_get, NULL, + PyNetsplitChannel_op_doc, NULL}, + {"halfop", (getter)PyNetsplitChannel_halfop_get, NULL, + PyNetsplitChannel_halfop_doc, NULL}, + {"voice", (getter)PyNetsplitChannel_voice_get, NULL, + PyNetsplitChannel_voice_doc, NULL}, + {"other", (getter)PyNetsplitChannel_other_get, NULL, + PyNetsplitChannel_other_doc, NULL}, + {NULL} +}; + +/* Methods */ +/* Methods for object */ +static PyMethodDef PyNetsplitChannel_methods[] = { + {NULL} /* Sentinel */ +}; + +PyTypeObject PyNetsplitChannelType = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "NetsplitChannel", /*tp_name*/ + sizeof(PyNetsplitChannel), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)PyNetsplitChannel_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + "PyNetsplitChannel objects", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + PyNetsplitChannel_methods, /* tp_methods */ + 0, /* tp_members */ + PyNetsplitChannel_getseters, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + PyNetsplitChannel_new, /* tp_new */ +}; + + +/* window item wrapper factory function */ +PyObject *pynetsplit_channel_new(void *netsplit) +{ + NETSPLIT_CHAN_REC *rec = netsplit; + PyNetsplitChannel *pynetsplit; + PyObject *name; + + name = PyString_FromString(rec->name); + if (!name) + return NULL; + + pynetsplit = py_inst(PyNetsplitChannel, PyNetsplitChannelType); + if (!pynetsplit) + { + Py_DECREF(name); + return NULL; + } + + pynetsplit->name = name; + pynetsplit->op = rec->op; + pynetsplit->halfop = rec->halfop; + pynetsplit->other = rec->other; + + return (PyObject *)pynetsplit; +} + +int netsplit_channel_object_init(void) +{ + g_return_val_if_fail(py_module != NULL, 0); + + if (PyType_Ready(&PyNetsplitChannelType) < 0) + return 0; + + Py_INCREF(&PyNetsplitChannelType); + PyModule_AddObject(py_module, "NetsplitChannel", (PyObject *)&PyNetsplitChannelType); + + return 1; +} diff --git a/src/objects/netsplit-channel-object.h b/src/objects/netsplit-channel-object.h new file mode 100644 index 0000000..3a00fbb --- /dev/null +++ b/src/objects/netsplit-channel-object.h @@ -0,0 +1,21 @@ +#ifndef _NETSPLIT_CHANNEL_OBJECT_H_ +#define _NETSPLIT_CHANNEL_OBJECT_H_ + +#include +#include "base-objects.h" + +typedef struct +{ + PyObject_HEAD + PyObject *name; + int op, halfop; + int voice, other; +} PyNetsplitChannel; + +extern PyTypeObject PyNetsplitChannelType; + +int netsplit_channel_object_init(void); +PyObject *pynetsplit_channel_new(void *ns); +#define pynetsplit_channel_check(op) PyObject_TypeCheck(op, &PyNetsplitChannelType) + +#endif diff --git a/src/objects/netsplit-object.c b/src/objects/netsplit-object.c new file mode 100644 index 0000000..d64bd97 --- /dev/null +++ b/src/objects/netsplit-object.c @@ -0,0 +1,184 @@ +#include +#include "pyirssi_irc.h" +#include "pymodule.h" +#include "netsplit-object.h" +#include "factory.h" +#include "pycore.h" + +#define NETSPLIT(ns) ((NETSPLIT_REC*)ns) + +/* monitor "netsplit remove" signal */ +static void netsplit_cleanup(NETSPLIT_REC *netsplit) +{ + PyNetsplit *pynetsplit = signal_get_user_data(); + + if (netsplit == pynetsplit->data) + { + pynetsplit->data = NULL; + pynetsplit->cleanup_installed = 0; + signal_remove_data("netsplit remove", netsplit_cleanup, pynetsplit); + } +} + +static void PyNetsplit_dealloc(PyNetsplit *self) +{ + if (self->cleanup_installed) + signal_remove_data("netsplit remove", netsplit_cleanup, self); + + self->ob_type->tp_free((PyObject*)self); +} + +static PyObject *PyNetsplit_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyNetsplit *self; + + self = (PyNetsplit *)type->tp_alloc(type, 0); + if (!self) + return NULL; + + return (PyObject *)self; +} + +/* Getters */ +PyDoc_STRVAR(PyNetsplit_nick_doc, + "Nick" +); +static PyObject *PyNetsplit_nick_get(PyNetsplit *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(NETSPLIT(self->data)->nick); +} + +PyDoc_STRVAR(PyNetsplit_address_doc, + "Nick's host" +); +static PyObject *PyNetsplit_address_get(PyNetsplit *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(NETSPLIT(self->data)->address); +} + +PyDoc_STRVAR(PyNetsplit_destroy_doc, + "Timestamp when this record should be destroyed" +); +static PyObject *PyNetsplit_destroy_get(PyNetsplit *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyLong_FromUnsignedLong(NETSPLIT(self->data)->destroy); +} + +PyDoc_STRVAR(PyNetsplit_server_doc, + "Netsplitserver object" +); +static PyObject *PyNetsplit_server_get(PyNetsplit *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_OBJ_OR_NONE(self->server); +} + +/* specialized getters/setters */ +static PyGetSetDef PyNetsplit_getseters[] = { + {"nick", (getter)PyNetsplit_nick_get, NULL, + PyNetsplit_nick_doc, NULL}, + {"address", (getter)PyNetsplit_address_get, NULL, + PyNetsplit_address_doc, NULL}, + {"destroy", (getter)PyNetsplit_destroy_get, NULL, + PyNetsplit_destroy_doc, NULL}, + {"server", (getter)PyNetsplit_server_get, NULL, + PyNetsplit_server_doc, NULL}, + {NULL} +}; + +/* Methods */ +PyDoc_STRVAR(PyNetsplit_channels_doc, + "channels() -> list of NetsplitChannel objects\n" + "\n" + "Return list of NetsplitChannel objects\n" +); +static PyObject *PyNetsplit_channels(PyNetsplit *self, PyObject *args) +{ + RET_NULL_IF_INVALID(self->data); + return py_irssi_objlist_new(NETSPLIT(self->data)->channels, 1, + (InitFunc)pynetsplit_channel_new); +} + +/* Methods for object */ +static PyMethodDef PyNetsplit_methods[] = { + {"channels", (PyCFunction)PyNetsplit_channels, METH_NOARGS, + PyNetsplit_channels_doc}, + {NULL} /* Sentinel */ +}; + +PyTypeObject PyNetsplitType = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "Netsplit", /*tp_name*/ + sizeof(PyNetsplit), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)PyNetsplit_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + "PyNetsplit objects", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + PyNetsplit_methods, /* tp_methods */ + 0, /* tp_members */ + PyNetsplit_getseters, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + PyNetsplit_new, /* tp_new */ +}; + + +/* window item wrapper factory function */ +PyObject *pynetsplit_new(void *netsplit) +{ + PyNetsplit *pynetsplit; + + //FIXME: add netsplit server + + pynetsplit = py_inst(PyNetsplit, PyNetsplitType); + if (!pynetsplit) + return NULL; + + pynetsplit->data = netsplit; + pynetsplit->cleanup_installed = 1; + signal_add_last_data("netsplit remove", netsplit_cleanup, pynetsplit); + + return (PyObject *)pynetsplit; +} + +int netsplit_object_init(void) +{ + g_return_val_if_fail(py_module != NULL, 0); + + if (PyType_Ready(&PyNetsplitType) < 0) + return 0; + + Py_INCREF(&PyNetsplitType); + PyModule_AddObject(py_module, "Netsplit", (PyObject *)&PyNetsplitType); + + return 1; +} diff --git a/src/objects/netsplit-object.h b/src/objects/netsplit-object.h new file mode 100644 index 0000000..bd166e0 --- /dev/null +++ b/src/objects/netsplit-object.h @@ -0,0 +1,19 @@ +#ifndef _NETSPLIT_OBJECT_H_ +#define _NETSPLIT_OBJECT_H_ + +#include +#include "base-objects.h" + +typedef struct +{ + PyIrssiFinal_HEAD(void) + PyObject *server; +} PyNetsplit; + +extern PyTypeObject PyNetsplitType; + +int netsplit_object_init(void); +PyObject *pynetsplit_new(void *ns); +#define pynetsplit_check(op) PyObject_TypeCheck(op, &PyNetsplitType) + +#endif diff --git a/src/objects/netsplit-server-object.c b/src/objects/netsplit-server-object.c new file mode 100644 index 0000000..7208ae1 --- /dev/null +++ b/src/objects/netsplit-server-object.c @@ -0,0 +1,157 @@ +#include +#include "pyirssi_irc.h" +#include "pymodule.h" +#include "netsplit-object.h" +#include "factory.h" +#include "pycore.h" + +#define NETSPLIT_SERVER(ns) ((NETSPLIT_SERVER_REC*)ns) + +/* monitor "netsplit remove" signal */ +static void netsplit_server_cleanup(NETSPLIT_SERVER_REC *netsplit) +{ + PyNetsplitServer *pynetsplit = signal_get_user_data(); + + if (netsplit == pynetsplit->data) + { + pynetsplit->data = NULL; + pynetsplit->cleanup_installed = 0; + signal_remove_data("netsplit remove", netsplit_server_cleanup, pynetsplit); + } +} + +static void PyNetsplitServer_dealloc(PyNetsplitServer *self) +{ + if (self->cleanup_installed) + signal_remove_data("netsplit remove", netsplit_server_cleanup, self); + + self->ob_type->tp_free((PyObject*)self); +} + +static PyObject *PyNetsplitServer_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyNetsplitServer *self; + + self = (PyNetsplitServer *)type->tp_alloc(type, 0); + if (!self) + return NULL; + + return (PyObject *)self; +} + +/* Getters */ +PyDoc_STRVAR(PyNetsplitServer_server_doc, + "The server nick was in" +); +static PyObject *PyNetsplitServer_server_get(PyNetsplitServer *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(NETSPLIT_SERVER(self->data)->server); +} + +PyDoc_STRVAR(PyNetsplitServer_destserver_doc, + "The other server where split occured." +); +static PyObject *PyNetsplitServer_destserver_get(PyNetsplitServer *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(NETSPLIT_SERVER(self->data)->destserver); +} + +PyDoc_STRVAR(PyNetsplitServer_count_doc, + "Number of splits in server" +); +static PyObject *PyNetsplitServer_count_get(PyNetsplitServer *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyInt_FromLong(NETSPLIT_SERVER(self->data)->count); +} + +/* specialized getters/setters */ +static PyGetSetDef PyNetsplitServer_getseters[] = { + {"server", (getter)PyNetsplitServer_server_get, NULL, + PyNetsplitServer_server_doc, NULL}, + {"destserver", (getter)PyNetsplitServer_destserver_get, NULL, + PyNetsplitServer_destserver_doc, NULL}, + {"count", (getter)PyNetsplitServer_count_get, NULL, + PyNetsplitServer_count_doc, NULL}, + {NULL} +}; + +/* Methods */ +/* Methods for object */ +static PyMethodDef PyNetsplitServer_methods[] = { + {NULL} /* Sentinel */ +}; + +PyTypeObject PyNetsplitServerType = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "NetsplitServer", /*tp_name*/ + sizeof(PyNetsplitServer), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)PyNetsplitServer_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + "PyNetsplitServer objects", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + PyNetsplitServer_methods, /* tp_methods */ + 0, /* tp_members */ + PyNetsplitServer_getseters, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + PyNetsplitServer_new, /* tp_new */ +}; + + +/* window item wrapper factory function */ +PyObject *pynetsplit_server_new(void *nss) +{ + PyNetsplitServer *pynss; + + pynss = py_inst(PyNetsplitServer, PyNetsplitServerType); + if (!pynss) + return NULL; + + pynss->data = nss; + pynss->cleanup_installed = 1; + signal_add_last_data("netsplit server remove", netsplit_server_cleanup, pynss); + + return (PyObject *)pynss; +} + +int netsplit_server_object_init(void) +{ + g_return_val_if_fail(py_module != NULL, 0); + + if (PyType_Ready(&PyNetsplitServerType) < 0) + return 0; + + Py_INCREF(&PyNetsplitServerType); + PyModule_AddObject(py_module, "NetsplitServer", (PyObject *)&PyNetsplitServerType); + + return 1; +} diff --git a/src/objects/netsplit-server-object.h b/src/objects/netsplit-server-object.h new file mode 100644 index 0000000..f1d5fbf --- /dev/null +++ b/src/objects/netsplit-server-object.h @@ -0,0 +1,18 @@ +#ifndef _NETSPLIT_SERVER_OBJECT_H_ +#define _NETSPLIT_SERVER_OBJECT_H_ + +#include +#include "base-objects.h" + +typedef struct +{ + PyIrssiFinal_HEAD(void) +} PyNetsplitServer; + +extern PyTypeObject PyNetsplitServerType; + +int netsplit_server_object_init(void); +PyObject *pynetsplit_server_new(void *nss); +#define pynetsplit_server_check(op) PyObject_TypeCheck(op, &PyNetsplitServerType) + +#endif diff --git a/src/objects/nick-object.c b/src/objects/nick-object.c new file mode 100644 index 0000000..79f3a85 --- /dev/null +++ b/src/objects/nick-object.c @@ -0,0 +1,237 @@ +#include +#include "pymodule.h" +#include "base-objects.h" +#include "nick-object.h" +#include "pyirssi.h" +#include "pycore.h" +#include "pyutils.h" + +static void nick_cleanup(CHANNEL_REC *chan, NICK_REC *nick) +{ + PyNick *pynick = signal_get_user_data(); + + if (nick == pynick->data) + { + pynick->data = NULL; + pynick->cleanup_installed = 0; + signal_remove_data("nicklist remove", nick_cleanup, pynick); + } +} + +static void PyNick_dealloc(PyNick *self) +{ + if (self->cleanup_installed) + signal_remove_data("nicklist remove", nick_cleanup, self); + + self->ob_type->tp_free((PyObject*)self); +} + +/* Getters */ +PyDoc_STRVAR(PyNick_send_massjoin_doc, + "Waiting to be sent in a 'massjoin' signal, True or False" +); +static PyObject *PyNick_send_massjoin_get(PyNick *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyBool_FromLong(self->data->send_massjoin); +} + +PyDoc_STRVAR(PyNick_nick_doc, + "Plain nick" +); +static PyObject *PyNick_nick_get(PyNick *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->nick); +} + +PyDoc_STRVAR(PyNick_host_doc, + "Host address" +); +static PyObject *PyNick_host_get(PyNick *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->host); +} + +PyDoc_STRVAR(PyNick_realname_doc, + "Real name" +); +static PyObject *PyNick_realname_get(PyNick *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->realname); +} + +PyDoc_STRVAR(PyNick_hops_doc, + "Hop count to the server the nick is using" +); +static PyObject *PyNick_hops_get(PyNick *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyInt_FromLong(self->data->hops); +} + +PyDoc_STRVAR(PyNick_gone_doc, + "User status" +); +static PyObject *PyNick_gone_get(PyNick *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyBool_FromLong(self->data->gone); +} + +PyDoc_STRVAR(PyNick_serverop_doc, + "User status" +); +static PyObject *PyNick_serverop_get(PyNick *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyBool_FromLong(self->data->serverop); +} + +PyDoc_STRVAR(PyNick_op_doc, + "User status" +); +static PyObject *PyNick_op_get(PyNick *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyBool_FromLong(self->data->op); +} + +PyDoc_STRVAR(PyNick_voice_doc, + "User status" +); +static PyObject *PyNick_voice_get(PyNick *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyBool_FromLong(self->data->voice); +} + +PyDoc_STRVAR(PyNick_halfop_doc, + "User status" +); +static PyObject *PyNick_halfop_get(PyNick *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyBool_FromLong(self->data->halfop); +} + +PyDoc_STRVAR(PyNick_last_check_doc, + "timestamp when last checked gone/ircop status." +); +static PyObject *PyNick_last_check_get(PyNick *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyLong_FromUnsignedLong(self->data->last_check); +} + +/* specialized getters/setters */ +static PyGetSetDef PyNick_getseters[] = { + {"send_massjoin", (getter)PyNick_send_massjoin_get, NULL, + PyNick_send_massjoin_doc, NULL}, + {"nick", (getter)PyNick_nick_get, NULL, + PyNick_nick_doc, NULL}, + {"host", (getter)PyNick_host_get, NULL, + PyNick_host_doc, NULL}, + {"realname", (getter)PyNick_realname_get, NULL, + PyNick_realname_doc, NULL}, + {"hops", (getter)PyNick_hops_get, NULL, + PyNick_hops_doc, NULL}, + {"gone", (getter)PyNick_gone_get, NULL, + PyNick_gone_doc, NULL}, + {"serverop", (getter)PyNick_serverop_get, NULL, + PyNick_serverop_doc, NULL}, + {"op", (getter)PyNick_op_get, NULL, + PyNick_op_doc, NULL}, + {"voice", (getter)PyNick_voice_get, NULL, + PyNick_voice_doc, NULL}, + {"halfop", (getter)PyNick_halfop_get, NULL, + PyNick_halfop_doc, NULL}, + {"last_check", (getter)PyNick_last_check_get, NULL, + PyNick_last_check_doc, NULL}, + {NULL} +}; + +static PyMethodDef PyNick_methods[] = { + {NULL} /* Sentinel */ +}; + +PyTypeObject PyNickType = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "Nick", /*tp_name*/ + sizeof(PyNick), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)PyNick_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + "PyNick objects", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + PyNick_methods, /* tp_methods */ + 0, /* tp_members */ + PyNick_getseters, /* tp_getset */ + &PyIrssiChatBaseType, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + + +/* nick factory function */ +PyObject *pynick_sub_new(void *nick, PyTypeObject *subclass) +{ + static const char *name = "NICK"; + PyNick *pynick = NULL; + + pynick = py_instp(PyNick, subclass); + if (!pynick) + return NULL; + + pynick->data = nick; + pynick->base_name = name; + signal_add_last_data("nicklist remove", nick_cleanup, pynick); + pynick->cleanup_installed = 1; + + return (PyObject *)pynick; +} + +PyObject *pynick_new(void *nick) +{ + return pynick_sub_new(nick, &PyNickType); +} + +int nick_object_init(void) +{ + g_return_val_if_fail(py_module != NULL, 0); + + if (PyType_Ready(&PyNickType) < 0) + return 0; + + Py_INCREF(&PyNickType); + PyModule_AddObject(py_module, "Nick", (PyObject *)&PyNickType); + + return 1; +} diff --git a/src/objects/nick-object.h b/src/objects/nick-object.h new file mode 100644 index 0000000..6831994 --- /dev/null +++ b/src/objects/nick-object.h @@ -0,0 +1,22 @@ +#ifndef _NICK_OBJECT_H_ +#define _NICK_OBJECT_H_ + +#include +#include "base-objects.h" + +/* forward */ +struct _NICK_REC; + +typedef struct +{ + PyIrssi_HEAD(struct _NICK_REC) +} PyNick; + +extern PyTypeObject PyNickType; + +int nick_object_init(void); +PyObject *pynick_sub_new(void *nick, PyTypeObject *subclass); +PyObject *pynick_new(void *nick); +#define pynick_check(op) PyObject_TypeCheck(op, &PyNickType) + +#endif diff --git a/src/objects/notifylist-object.c b/src/objects/notifylist-object.c new file mode 100644 index 0000000..3366d0f --- /dev/null +++ b/src/objects/notifylist-object.c @@ -0,0 +1,221 @@ +#include +#include "pyirssi_irc.h" +#include "pymodule.h" +#include "notifylist-object.h" +#include "pycore.h" + +#define NOTIFYLIST(nl) ((NOTIFYLIST_REC *)nl) + +/* monitor "notifylist remove" signal */ +static void notifylist_cleanup(NOTIFYLIST_REC *notifylist) +{ + PyNotifylist *pynotifylist = signal_get_user_data(); + + if (notifylist == pynotifylist->data) + { + pynotifylist->data = NULL; + pynotifylist->cleanup_installed = 0; + signal_remove_data("notifylist remove", notifylist_cleanup, pynotifylist); + } +} + +static void PyNotifylist_dealloc(PyNotifylist *self) +{ + if (self->cleanup_installed) + signal_remove_data("notifylist remove", notifylist_cleanup, self); + + self->ob_type->tp_free((PyObject*)self); +} + +static PyObject *PyNotifylist_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyNotifylist *self; + + self = (PyNotifylist *)type->tp_alloc(type, 0); + if (!self) + return NULL; + + return (PyObject *)self; +} + +/* Getters */ +PyDoc_STRVAR(PyNotifylist_mask_doc, + "Notify nick mask" +); +static PyObject *PyNotifylist_mask_get(PyNotifylist *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(NOTIFYLIST(self->data)->mask); +} + +PyDoc_STRVAR(PyNotifylist_away_check_doc, + "Notify away status changes" +); +static PyObject *PyNotifylist_away_check_get(PyNotifylist *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyBool_FromLong(NOTIFYLIST(self->data)->away_check); +} + +PyDoc_STRVAR(PyNotifylist_idle_check_time_doc, + "Notify when idle time is reset and idle was bigger than this (seconds)" +); +static PyObject *PyNotifylist_idle_check_time_get(PyNotifylist *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyLong_FromUnsignedLong(NOTIFYLIST(self->data)->idle_check_time); +} + +/* specialized getters/setters */ +static PyGetSetDef PyNotifylist_getseters[] = { + {"mask", (getter)PyNotifylist_mask_get, NULL, + PyNotifylist_mask_doc, NULL}, + {"away_check", (getter)PyNotifylist_away_check_get, NULL, + PyNotifylist_away_check_doc, NULL}, + {"idle_check_time", (getter)PyNotifylist_idle_check_time_get, NULL, + PyNotifylist_idle_check_time_doc, NULL}, + {NULL} +}; + +/* Methods */ +PyDoc_STRVAR(PyNotifylist_ircnets_doc, + "ircnets() -> list of str\n" + "\n" + "Return list of ircnets the notify is checked\n" +); +static PyObject *PyNotifylist_ircnets(PyNotifylist *self, PyObject *args) +{ + PyObject *list; + char **nets; + + RET_NULL_IF_INVALID(self->data); + + nets = NOTIFYLIST(self->data)->ircnets; + list = PyList_New(0); + if (!list) + return NULL; + + while (nets && *nets) + { + int ret; + PyObject *str = PyString_FromString(*nets); + + if (!str) + { + Py_DECREF(list); + return NULL; + } + + ret = PyList_Append(list, str); + Py_DECREF(str); + if (ret != 0) + { + Py_DECREF(list); + return NULL; + } + + nets++; + } + + return list; +} + +PyDoc_STRVAR(PyNotifylist_ircnets_match_doc, + "ircnets_match(ircnet) -> bool\n" + "\n" + "Return True if notify is checked in ircnet\n" +); +static PyObject *PyNotifylist_ircnets_match(PyNotifylist *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"ircnet", NULL}; + char *ircnet = ""; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &ircnet)) + return NULL; + + return PyBool_FromLong(notifylist_ircnets_match(self->data, ircnet)); +} + +/* Methods for object */ +static PyMethodDef PyNotifylist_methods[] = { + {"ircnets", (PyCFunction)PyNotifylist_ircnets, METH_NOARGS, + PyNotifylist_ircnets_doc}, + {"ircnets_match", (PyCFunction)PyNotifylist_ircnets_match, METH_VARARGS | METH_KEYWORDS, + PyNotifylist_ircnets_match_doc}, + {NULL} /* Sentinel */ +}; + +PyTypeObject PyNotifylistType = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "Notifylist", /*tp_name*/ + sizeof(PyNotifylist), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)PyNotifylist_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + "PyNotifylist objects", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + PyNotifylist_methods, /* tp_methods */ + 0, /* tp_members */ + PyNotifylist_getseters, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + PyNotifylist_new, /* tp_new */ +}; + + +/* window item wrapper factory function */ +PyObject *pynotifylist_new(void *notifylist) +{ + PyNotifylist *pynotifylist; + + pynotifylist = py_inst(PyNotifylist, PyNotifylistType); + if (!pynotifylist) + return NULL; + + pynotifylist->data = notifylist; + pynotifylist->cleanup_installed = 1; + signal_add_last_data("notifylist remove", notifylist_cleanup, pynotifylist); + + return (PyObject *)pynotifylist; +} + +int notifylist_object_init(void) +{ + g_return_val_if_fail(py_module != NULL, 0); + + if (PyType_Ready(&PyNotifylistType) < 0) + return 0; + + Py_INCREF(&PyNotifylistType); + PyModule_AddObject(py_module, "Notifylist", (PyObject *)&PyNotifylistType); + + return 1; +} diff --git a/src/objects/notifylist-object.h b/src/objects/notifylist-object.h new file mode 100644 index 0000000..9db6922 --- /dev/null +++ b/src/objects/notifylist-object.h @@ -0,0 +1,18 @@ +#ifndef _NOTIFYLIST_OBJECT_H_ +#define _NOTIFYLIST_OBJECT_H_ + +#include +#include "base-objects.h" + +typedef struct +{ + PyIrssiFinal_HEAD(void) +} PyNotifylist; + +extern PyTypeObject PyNotifylistType; + +int notifylist_object_init(void); +PyObject *pynotifylist_new(void *notifylist); +#define pynotifylist_check(op) PyObject_TypeCheck(op, &PyNotifylistType) + +#endif diff --git a/src/objects/process-object.c b/src/objects/process-object.c new file mode 100644 index 0000000..43c0fd7 --- /dev/null +++ b/src/objects/process-object.c @@ -0,0 +1,222 @@ +#include +#include "pyirssi_irc.h" +#include "pymodule.h" +#include "process-object.h" +#include "pycore.h" + +/* monitor "exec remove" signal */ +static void process_cleanup(PROCESS_REC *process, int status) +{ + PyProcess *pyprocess = signal_get_user_data(); + + if (process == pyprocess->data) + { + pyprocess->data = NULL; + pyprocess->cleanup_installed = 0; + signal_remove_data("exec remove", process_cleanup, pyprocess); + } +} + +static void PyProcess_dealloc(PyProcess *self) +{ + if (self->cleanup_installed) + signal_remove_data("exec remove", process_cleanup, self); + + Py_XDECREF(self->target_win); + + self->ob_type->tp_free((PyObject*)self); +} + +static PyObject *PyProcess_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyProcess *self; + + self = (PyProcess *)type->tp_alloc(type, 0); + if (!self) + return NULL; + + return (PyObject *)self; +} + +/* Getters */ +PyDoc_STRVAR(PyProcess_id_doc, + "ID for the process" +); +static PyObject *PyProcess_id_get(PyProcess *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyInt_FromLong(self->data->id); +} + +PyDoc_STRVAR(PyProcess_name_doc, + "Name for the process (if given)" +); +static PyObject *PyProcess_name_get(PyProcess *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->name); +} + +PyDoc_STRVAR(PyProcess_args_doc, + "The command that is being executed" +); +static PyObject *PyProcess_args_get(PyProcess *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->args); +} + +PyDoc_STRVAR(PyProcess_pid_doc, + "PID for the executed command" +); +static PyObject *PyProcess_pid_get(PyProcess *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyInt_FromLong(self->data->pid); +} + +PyDoc_STRVAR(PyProcess_target_doc, + "send text with /msg ..." +); +static PyObject *PyProcess_target_get(PyProcess *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->target); +} + +PyDoc_STRVAR(PyProcess_target_win_doc, + "print text to this window" +); +static PyObject *PyProcess_target_win_get(PyProcess *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_OBJ_OR_NONE(self->target_win); +} + +PyDoc_STRVAR(PyProcess_shell_doc, + "start the program via /bin/sh" +); +static PyObject *PyProcess_shell_get(PyProcess *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyBool_FromLong(self->data->shell); +} + +PyDoc_STRVAR(PyProcess_notice_doc, + "send text with /notice, not /msg if target is set" +); +static PyObject *PyProcess_notice_get(PyProcess *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyBool_FromLong(self->data->notice); +} + +PyDoc_STRVAR(PyProcess_silent_doc, + "don't print \"process exited with level xx\"" +); +static PyObject *PyProcess_silent_get(PyProcess *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyBool_FromLong(self->data->silent); +} + +/* specialized getters/setters */ +static PyGetSetDef PyProcess_getseters[] = { + {"id", (getter)PyProcess_id_get, NULL, + PyProcess_id_doc, NULL}, + {"name", (getter)PyProcess_name_get, NULL, + PyProcess_name_doc, NULL}, + {"args", (getter)PyProcess_args_get, NULL, + PyProcess_args_doc, NULL}, + {"pid", (getter)PyProcess_pid_get, NULL, + PyProcess_pid_doc, NULL}, + {"target", (getter)PyProcess_target_get, NULL, + PyProcess_target_doc, NULL}, + {"target_win", (getter)PyProcess_target_win_get, NULL, + PyProcess_target_win_doc, NULL}, + {"shell", (getter)PyProcess_shell_get, NULL, + PyProcess_shell_doc, NULL}, + {"notice", (getter)PyProcess_notice_get, NULL, + PyProcess_notice_doc, NULL}, + {"silent", (getter)PyProcess_silent_get, NULL, + PyProcess_silent_doc, NULL}, + {NULL} +}; + +/* Methods */ +/* Methods for object */ +static PyMethodDef PyProcess_methods[] = { + {NULL} /* Sentinel */ +}; + +PyTypeObject PyProcessType = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "Process", /*tp_name*/ + sizeof(PyProcess), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)PyProcess_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + "PyProcess objects", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + PyProcess_methods, /* tp_methods */ + 0, /* tp_members */ + PyProcess_getseters, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + PyProcess_new, /* tp_new */ +}; + + +/* process factory function */ +PyObject *pyprocess_new(void *process) +{ + PyProcess *pyprocess; + + pyprocess = py_inst(PyProcess, PyProcessType); + if (!pyprocess) + return NULL; + + pyprocess->data = process; + pyprocess->cleanup_installed = 1; + signal_add_last_data("exec remove", process_cleanup, pyprocess); + + return (PyObject *)pyprocess; +} + +int process_object_init(void) +{ + g_return_val_if_fail(py_module != NULL, 0); + + if (PyType_Ready(&PyProcessType) < 0) + return 0; + + Py_INCREF(&PyProcessType); + PyModule_AddObject(py_module, "Process", (PyObject *)&PyProcessType); + + return 1; +} diff --git a/src/objects/process-object.h b/src/objects/process-object.h new file mode 100644 index 0000000..041f187 --- /dev/null +++ b/src/objects/process-object.h @@ -0,0 +1,22 @@ +#ifndef _PROCESS_OBJECT_H_ +#define _PROCESS_OBJECT_H_ + +#include +#include "base-objects.h" + +/* forward */ +struct PROCESS_REC; + +typedef struct +{ + PyIrssiFinal_HEAD(struct PROCESS_REC) + PyObject *target_win; +} PyProcess; + +extern PyTypeObject PyProcessType; + +int process_object_init(void); +PyObject *pyprocess_new(void *process); +#define pyprocess_check(op) PyObject_TypeCheck(op, &PyProcessType) + +#endif diff --git a/src/objects/pyscript-object.c b/src/objects/pyscript-object.c new file mode 100644 index 0000000..ae4770e --- /dev/null +++ b/src/objects/pyscript-object.c @@ -0,0 +1,801 @@ +#include +#include +#include "pyscript-object.h" +#include "pyirssi.h" +#include "pysignals.h" +#include "pymodule.h" +#include "pysource.h" +#include "pythemes.h" +#include "pystatusbar.h" + +/* handle cycles... + Can't think of any reason why the user would put script into one of the lists + but who knows. Call GC after unloading module. +*/ +static int PyScript_traverse(PyScript *self, visitproc visit, void *arg) +{ + Py_VISIT(self->module); + Py_VISIT(self->argv); + Py_VISIT(self->modules); + + return 0; +} + +static int PyScript_clear(PyScript *self) +{ + Py_CLEAR(self->module); + Py_CLEAR(self->argv); + Py_CLEAR(self->modules); + + return 0; +} + +static void PyScript_dealloc(PyScript* self) +{ + PyScript_clear(self); + pyscript_remove_signals((PyObject*)self); + pyscript_remove_sources((PyObject*)self); + + self->ob_type->tp_free((PyObject*)self); +} + +static PyObject *PyScript_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyScript *self; + PyObject *argv = NULL, *modules = NULL; + + argv = PyList_New(0); + if (!argv) + goto error; + + modules = PyDict_New(); + if (!modules) + goto error; + + self = (PyScript *)type->tp_alloc(type, 0); + if (!self) + goto error; + + self->argv = argv; + self->modules = modules; + + return (PyObject *)self; + +error: + Py_XDECREF(argv); + Py_XDECREF(modules); + return NULL; +} + +PyDoc_STRVAR(PyScript_command_bind_doc, + "command_bind(command, func, catetory=None, priority=SIGNAL_PRIORITY_DEFAULT) -> None\n" + "\n" + "Add handler for a command\n" +); +static PyObject *PyScript_command_bind(PyScript *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"cmd", "func", "category", "priority", NULL}; + char *cmd; + PyObject *func; + char *category = NULL; + int priority = SIGNAL_PRIORITY_DEFAULT; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "sO|zi", kwlist, + &cmd, &func, &category, &priority)) + return NULL; + + if (!PyCallable_Check(func)) + return PyErr_Format(PyExc_TypeError, "func must be callable"); + + if (!pysignals_command_bind_list(&self->signals, cmd, func, category, priority)) + return PyErr_Format(PyExc_RuntimeError, "unable to bind command"); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyScript_signal_add_doc, + "signal_add(signal, func, priority=SIGNAL_PRIORITY_DEFAULT) -> None\n" + "\n" + "Add handler for signal" +); +static PyObject *PyScript_signal_add(PyScript *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"signal", "func", "priority", NULL}; + char *signal; + PyObject *func; + int priority = SIGNAL_PRIORITY_DEFAULT; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "sO|i", kwlist, + &signal, &func, &priority)) + return NULL; + + if (!PyCallable_Check(func)) + return PyErr_Format(PyExc_TypeError, "func must be callable"); + + if (!pysignals_signal_add_list(&self->signals, signal, func, priority)) + return PyErr_Format(PyExc_KeyError, "unable to find signal, '%s'", signal); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyScript_signal_remove_doc, + "signal_remove(signal, func=None) -> None\n" + "\n" + "Remove signal handler\n" +); +static PyObject *PyScript_signal_remove(PyScript *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"signal", "func", NULL}; + char *signal = ""; + PyObject *func = Py_None; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|O", kwlist, + &signal, &func)) + return NULL; + + if (!PyCallable_Check(func) && func != Py_None) + return PyErr_Format(PyExc_TypeError, "func must be callable or None"); + + if (func == Py_None) + func = NULL; + + if (!pysignals_remove_search(&self->signals, signal, func, PSG_SIGNAL)) + return PyErr_Format(PyExc_KeyError, "can't find signal"); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyScript_command_unbind_doc, + "command_unbind(command, func=None) -> None\n" + "\n" + "Remove command handler\n" +); +static PyObject *PyScript_command_unbind(PyScript *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"command", "func", NULL}; + char *command = ""; + PyObject *func = Py_None; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|O", kwlist, + &command, &func)) + return NULL; + + if (!PyCallable_Check(func) && func != Py_None) + return PyErr_Format(PyExc_TypeError, "func must be callable or None"); + + if (func == Py_None) + func = NULL; + + if (!pysignals_remove_search(&self->signals, command, func, PSG_COMMAND)) + return PyErr_Format(PyExc_KeyError, "can't find command"); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyScript_signal_register_doc, + "signal_register(signal, arglist) -> None\n" + "\n" + "Register a new dynamic signal for use with irssi_python\n" + "arglist is a string of character codes representing the type of each argument\n" + "of the signal handler function.\n" + "\n" + " Scalars\n" + " s -> char *\n" + " i -> int\n" + "\n" + " Chat objects\n" + " c -> CHATNET_REC\n" + " S -> SERVER_REC\n" + " C -> CHANNEL_REC\n" + " q -> QUERY_REC\n" + " n -> NICK_REC\n" + " W -> WI_ITEM_REC\n" + "\n" + " Irssi objects\n" + " d -> DCC_REC\n" + "\n" + " Other objects\n" + " r -> RECONNECT_REC\n" + " o -> COMMAND_REC\n" + " l -> LOG_REC\n" + " a -> RAWLOG_REC\n" + " g -> IGNORE_REC\n" + " b -> BAN_REC\n" + " N -> NETSPLIT_REC\n" + " e -> NETSPLIT_SERVER_REC\n" + " O -> NOTIFYLIST_REC\n" + " p -> PROCESS_REC\n" + " t -> TEXT_DEST_REC\n" + " w -> WINDOW_REC\n" +); +static PyObject *PyScript_signal_register(PyScript *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"signal", "arglist", NULL}; + static const char *good_codes = "sicSCqnWdrolagbNeOptw"; + char *signal = ""; + char *arglist = ""; + int i; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss", kwlist, + &signal, &arglist)) + return NULL; + + for (i = 0; arglist[i]; i++) + if (!strchr(good_codes, arglist[i])) + return PyErr_Format(PyExc_TypeError, "invalid code, %c", arglist[i]); + + if (i >= SIGNAL_MAX_ARGUMENTS) + return PyErr_Format(PyExc_TypeError, + "arglist greater than SIGNAL_MAX_ARGUMENTS (%d)", + SIGNAL_MAX_ARGUMENTS); + + if (!pysignals_register(signal, arglist)) + return PyErr_Format(PyExc_TypeError, "signal present with different args"); + + self->registered_signals = g_slist_append(self->registered_signals, + g_strdup(signal)); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyScript_signal_unregister_doc, + "signal_unregister(signal) -> None\n" + "\n" + "Unregister dynamic signal\n" +); +static PyObject *PyScript_signal_unregister(PyScript *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"signal", NULL}; + char *signal = ""; + GSList *search; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &signal)) + return NULL; + + search = g_slist_find_custom(self->registered_signals, signal, (GCompareFunc)strcmp); + if (!search) + return PyErr_Format(PyExc_KeyError, "script has not registered that signal"); + + g_free(search->data); + self->registered_signals = g_slist_delete_link(self->registered_signals, search); + + if (!pysignals_unregister(signal)) + return PyErr_Format(PyExc_SystemError, + "script registered signal, but signal does not exist"); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyScript_timeout_add_doc, + "timeout_add(msecs, func, data=None) -> int source tag\n" + "\n" + "Add a timeout handler called every 'msecs' milliseconds until func\n" + "returns False or the source is removed with source_remove().\n" + "\n" + "func is called as func(data) or func(), depending on whether data\n" + "is specified or not.\n" +); +static PyObject *PyScript_timeout_add(PyScript *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"msecs", "func", "data", NULL}; + int msecs = 0; + PyObject *func = NULL; + PyObject *data = NULL; + int ret; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "iO|O", kwlist, + &msecs, &func, &data)) + return NULL; + + if (msecs < 10) + return PyErr_Format(PyExc_ValueError, "msecs must be at least 10"); + + if (!PyCallable_Check(func)) + return PyErr_Format(PyExc_TypeError, "func not callable"); + + ret = pysource_timeout_add_list(&self->sources, msecs, func, data); + + return PyInt_FromLong(ret); +} + +PyDoc_STRVAR(PyScript_io_add_watch_doc, + "io_add_watch(fd, func, data=None, condition=IO_IN|IO_PRI) -> int source tag\n" +); +static PyObject *PyScript_io_add_watch(PyScript *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"fd", "func", "data", "condition", NULL}; + int fd = 0; + PyObject *pyfd = NULL; + PyObject *func = NULL; + PyObject *data = NULL; + int condition = G_IO_IN | G_IO_PRI; + int ret; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO|Oi", kwlist, + &pyfd, &func, &data, &condition)) + return NULL; + + fd = PyObject_AsFileDescriptor(pyfd); + if (fd < 0) + return NULL; + + if (!PyCallable_Check(func)) + return PyErr_Format(PyExc_TypeError, "func not callable"); + + ret = pysource_io_add_watch_list(&self->sources, fd, condition, func, data); + + return PyInt_FromLong(ret); +} + +PyDoc_STRVAR(PyScript_source_remove_doc, + "source_remove(tag) -> bool\n" + "\n" + "Remove IO or timeout source by tag. Return True if tag found and removed.\n" +); +static PyObject *PyScript_source_remove(PyScript *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"tag", NULL}; + int tag = 0; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, + &tag)) + return NULL; + + /* the destroy notify func will remove the list link, but first + check that the tag exists in this Script object */ + if (g_slist_find(self->sources, GINT_TO_POINTER(tag))) + return PyBool_FromLong(g_source_remove(tag)); + + Py_RETURN_FALSE; +} + +static int py_settings_add(PyScript *self, const char *name) +{ + GSList *node; + + node = gslist_find_icase_string(self->settings, name); + if (node) + return 0; + + self->settings = g_slist_append(self->settings, g_strdup(name)); + + return 1; +} + +static int py_settings_remove(PyScript *self, const char *name) +{ + GSList *node; + + node = gslist_find_icase_string(self->settings, name); + if (!node) + return 0; + + settings_remove(node->data); + g_free(node->data); + + self->settings = g_slist_delete_link(self->settings, node); + + return 1; +} + +PyDoc_STRVAR(PyScript_settings_add_str_doc, + "settings_add_str(section, key, def) -> None\n" +); +static PyObject *PyScript_settings_add_str(PyScript *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"section", "key", "def", NULL}; + char *section = ""; + char *key = ""; + char *def = ""; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "sss", kwlist, + §ion, &key, &def)) + return NULL; + + if (!py_settings_add(self, key)) + return PyErr_Format(PyExc_ValueError, "key, %s, already added by script", key); + + settings_add_str_module(MODULE_NAME"/scripts", section, key, def); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyScript_settings_add_int_doc, + "settings_add_int(section, key, def) -> None\n" +); +static PyObject *PyScript_settings_add_int(PyScript *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"section", "key", "def", NULL}; + char *section = ""; + char *key = ""; + int def = 0; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "ssi", kwlist, + §ion, &key, &def)) + return NULL; + + if (!py_settings_add(self, key)) + return PyErr_Format(PyExc_ValueError, "key, %s, already added by script", key); + + settings_add_int_module(MODULE_NAME"/scripts", section, key, def); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyScript_settings_add_bool_doc, + "settings_add_bool(section, key, def) -> None\n" +); +static PyObject *PyScript_settings_add_bool(PyScript *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"section", "key", "def", NULL}; + char *section = ""; + char *key = ""; + int def = 0; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "ssi", kwlist, + §ion, &key, &def)) + return NULL; + + if (!py_settings_add(self, key)) + return PyErr_Format(PyExc_ValueError, "key, %s, already added by script", key); + + settings_add_bool_module(MODULE_NAME"/scripts", section, key, def); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyScript_settings_add_time_doc, + "settings_add_time(section, key, def) -> None\n" +); +static PyObject *PyScript_settings_add_time(PyScript *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"section", "key", "def", NULL}; + char *section = ""; + char *key = ""; + char *def = ""; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "sss", kwlist, + §ion, &key, &def)) + return NULL; + + if (!py_settings_add(self, key)) + return PyErr_Format(PyExc_ValueError, "key, %s, already added by script", key); + + settings_add_time_module(MODULE_NAME"/scripts", section, key, def); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyScript_settings_add_level_doc, + "settings_add_level(section, key, def) -> None\n" +); +static PyObject *PyScript_settings_add_level(PyScript *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"section", "key", "def", NULL}; + char *section = ""; + char *key = ""; + char *def = ""; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "sss", kwlist, + §ion, &key, &def)) + return NULL; + + if (!py_settings_add(self, key)) + return PyErr_Format(PyExc_ValueError, "key, %s, already added by script", key); + + settings_add_level_module(MODULE_NAME"/scripts", section, key, def); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyScript_settings_add_size_doc, + "settings_add_size(section, key, def) -> None\n" +); +static PyObject *PyScript_settings_add_size(PyScript *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"section", "key", "def", NULL}; + char *section = ""; + char *key = ""; + char *def = ""; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "sss", kwlist, + §ion, &key, &def)) + return NULL; + + if (!py_settings_add(self, key)) + return PyErr_Format(PyExc_ValueError, "key, %s, already added by script", key); + + settings_add_size_module(MODULE_NAME"/scripts", section, key, def); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyScript_settings_remove_doc, + "settings_remove(key) -> bool\n" +); +static PyObject *PyScript_settings_remove(PyScript *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"key", NULL}; + char *key = ""; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &key)) + return NULL; + + return PyBool_FromLong(py_settings_remove(self, key)); +} + +PyDoc_STRVAR(PyScript_theme_register_doc, + "theme_register(list) -> None\n" +); +static PyObject *PyScript_theme_register(PyScript *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"list", NULL}; + PyObject *list = NULL; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, + &list)) + return NULL; + + if (!pythemes_register(pyscript_get_name(self), list)) + return NULL; + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyScript_statusbar_item_register_doc, + "statusbar_item_register(name, value=None, func=None) -> None\n" +); +static PyObject *PyScript_statusbar_item_register(PyScript *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"name", "value", "func", NULL}; + char *name = ""; + char *value = NULL; + PyObject *func = NULL; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|zO", kwlist, + &name, &value, &func)) + return NULL; + + pystatusbar_item_register((PyObject *)self, name, value, func); + + Py_RETURN_NONE; +} + +/* Methods for object */ +static PyMethodDef PyScript_methods[] = { + {"command_bind", (PyCFunction)PyScript_command_bind, METH_VARARGS | METH_KEYWORDS, + PyScript_command_bind_doc}, + {"signal_add", (PyCFunction)PyScript_signal_add, METH_VARARGS | METH_KEYWORDS, + PyScript_signal_add_doc}, + {"signal_remove", (PyCFunction)PyScript_signal_remove, METH_VARARGS | METH_KEYWORDS, + PyScript_signal_remove_doc}, + {"command_unbind", (PyCFunction)PyScript_command_unbind, METH_VARARGS | METH_KEYWORDS, + PyScript_command_unbind_doc}, + {"signal_register", (PyCFunction)PyScript_signal_register, METH_VARARGS | METH_KEYWORDS, + PyScript_signal_register_doc}, + {"signal_unregister", (PyCFunction)PyScript_signal_unregister, METH_VARARGS | METH_KEYWORDS, + PyScript_signal_unregister_doc}, + {"timeout_add", (PyCFunction)PyScript_timeout_add, METH_VARARGS | METH_KEYWORDS, + PyScript_timeout_add_doc}, + {"io_add_watch", (PyCFunction)PyScript_io_add_watch, METH_VARARGS | METH_KEYWORDS, + PyScript_io_add_watch_doc}, + {"source_remove", (PyCFunction)PyScript_source_remove, METH_VARARGS | METH_KEYWORDS, + PyScript_source_remove_doc}, + {"settings_add_str", (PyCFunction)PyScript_settings_add_str, METH_VARARGS | METH_KEYWORDS, + PyScript_settings_add_str_doc}, + {"settings_add_int", (PyCFunction)PyScript_settings_add_int, METH_VARARGS | METH_KEYWORDS, + PyScript_settings_add_int_doc}, + {"settings_add_bool", (PyCFunction)PyScript_settings_add_bool, METH_VARARGS | METH_KEYWORDS, + PyScript_settings_add_bool_doc}, + {"settings_add_time", (PyCFunction)PyScript_settings_add_time, METH_VARARGS | METH_KEYWORDS, + PyScript_settings_add_time_doc}, + {"settings_add_level", (PyCFunction)PyScript_settings_add_level, METH_VARARGS | METH_KEYWORDS, + PyScript_settings_add_level_doc}, + {"settings_add_size", (PyCFunction)PyScript_settings_add_size, METH_VARARGS | METH_KEYWORDS, + PyScript_settings_add_size_doc}, + {"settings_remove", (PyCFunction)PyScript_settings_remove, METH_VARARGS | METH_KEYWORDS, + PyScript_settings_remove_doc}, + {"theme_register", (PyCFunction)PyScript_theme_register, METH_VARARGS | METH_KEYWORDS, + PyScript_theme_register_doc}, + {"statusbar_item_register", (PyCFunction)PyScript_statusbar_item_register, METH_VARARGS | METH_KEYWORDS, + PyScript_statusbar_item_register_doc}, + {NULL} /* Sentinel */ +}; + +static PyMemberDef PyScript_members[] = { + {"argv", T_OBJECT, offsetof(PyScript, argv), 0, "Script arguments"}, + {"module", T_OBJECT_EX, offsetof(PyScript, module), RO, "Script module"}, + {"modules", T_OBJECT_EX, offsetof(PyScript, modules), 0, "Imported modules"}, + {NULL} /* Sentinel */ +}; + +PyTypeObject PyScriptType = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "Script", /*tp_name*/ + sizeof(PyScript), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)PyScript_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ + "PyScript objects", /* tp_doc */ + (traverseproc)PyScript_traverse, /* tp_traverse */ + (inquiry)PyScript_clear, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + PyScript_methods, /* tp_methods */ + PyScript_members, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + PyScript_new, /* tp_new */ +}; + +/* PyScript factory function */ +PyObject *pyscript_new(PyObject *module, char **argv) +{ + PyObject *script; + + script = PyObject_CallFunction((PyObject*)&PyScriptType, "()"); + + if (script) + { + PyScript *scr = (PyScript *)script; + + while (*argv) + { + if (**argv != '\0') + { + PyObject *str = PyString_FromString(*argv); + if (!str) + { + /* The destructor should DECREF argv */ + Py_DECREF(script); + return NULL; + } + + PyList_Append(scr->argv, str); + Py_DECREF(str); + } + + *argv++; + } + + Py_INCREF(module); + scr->module = module; + } + + return script; +} + +void pyscript_remove_signals(PyObject *script) +{ + GSList *node; + PyScript *self; + + g_return_if_fail(pyscript_check(script)); + + self = (PyScript *) script; + + /* remove bound signals */ + pysignals_remove_list(self->signals); + g_slist_free(self->signals); + self->signals = NULL; + + /* remove registered signals */ + for (node = self->registered_signals; node; node = node->next) + { + pysignals_unregister(node->data); + g_free(node->data); + } + + g_slist_free(self->registered_signals); + self->registered_signals = NULL; +} + +void pyscript_remove_sources(PyObject *script) +{ + GSList *node; + PyScript *self; + + g_return_if_fail(pyscript_check(script)); + + self = (PyScript *) script; + + node = self->sources; + while (node) + { + /* the notify func will destroy the link so save next */ + GSList *next = node->next; + g_source_remove(GPOINTER_TO_INT(node->data)); + node = next; + } + + g_return_if_fail(self->sources == NULL); +} + +void pyscript_remove_settings(PyObject *script) +{ + PyScript *self; + + g_return_if_fail(pyscript_check(script)); + + self = (PyScript *) script; + + g_slist_foreach(self->settings, (GFunc)settings_remove, NULL); + g_slist_foreach(self->settings, (GFunc)g_free, NULL); + g_slist_free(self->settings); +} + +void pyscript_remove_themes(PyObject *script) +{ + PyScript *self; + + g_return_if_fail(pyscript_check(script)); + + self = (PyScript *) script; + + pythemes_unregister(pyscript_get_name(script)); +} + +void pyscript_remove_statusbars(PyObject *script) +{ + g_return_if_fail(pyscript_check(script)); + + pystatusbar_cleanup_script(script); +} + +void pyscript_clear_modules(PyObject *script) +{ + PyScript *self; + + g_return_if_fail(pyscript_check(script)); + + self = (PyScript *) script; + + PyDict_Clear(self->modules); +} + +void pyscript_cleanup(PyObject *script) +{ + pyscript_remove_signals(script); + pyscript_remove_sources(script); + pyscript_remove_settings(script); + pyscript_remove_themes(script); + pyscript_remove_statusbars(script); + pyscript_clear_modules(script); +} + +int pyscript_init(void) +{ + if (PyType_Ready(&PyScriptType) < 0) + return 0; + + Py_INCREF(&PyScriptType); + PyModule_AddObject(py_module, "Script", (PyObject *)&PyScriptType); + + return 1; +} + diff --git a/src/objects/pyscript-object.h b/src/objects/pyscript-object.h new file mode 100644 index 0000000..624a578 --- /dev/null +++ b/src/objects/pyscript-object.h @@ -0,0 +1,33 @@ +#ifndef _PYSCRIPT_OBJECT_H_ +#define _PYSCRIPT_OBJECT_H_ +#include +#include + +typedef struct { + PyObject_HEAD + PyObject *module; /* module object */ + PyObject *argv; /* list of argument strings from the load command */ + PyObject *modules; /* dict of imported modules for script */ + GSList *signals; /* list of bound signals and commands */ + GSList *registered_signals; /* list of signal names registered */ + GSList *sources; /* list of io and timeout sources */ + GSList *settings; /* list of settings from settings_add_*() */ +} PyScript; + +extern PyTypeObject PyScriptType; + +int pyscript_init(void); +PyObject *pyscript_new(PyObject *module, char **argv); +void pyscript_remove_signals(PyObject *script); +void pyscript_remove_sources(PyObject *script); +void pyscript_remove_settings(PyObject *script); +void pyscript_remove_themes(PyObject *script); +void pyscript_remove_statusbars(PyObject *script); +void pyscript_clear_modules(PyObject *script); +void pyscript_cleanup(PyObject *script); +#define pyscript_check(op) PyObject_TypeCheck(op, &PyScriptType) +#define pyscript_get_name(scr) PyModule_GetName(((PyScript*)scr)->module) +#define pyscript_get_filename(scr) PyModule_GetFilename(((PyScript*)scr)->module) +#define pyscript_get_module(scr) (((PyScript*)scr)->module) + +#endif diff --git a/src/objects/query-object.c b/src/objects/query-object.c new file mode 100644 index 0000000..47badd5 --- /dev/null +++ b/src/objects/query-object.c @@ -0,0 +1,172 @@ +#include +#include "pyirssi.h" +#include "pymodule.h" +#include "base-objects.h" +#include "window-item-object.h" +#include "query-object.h" +#include "server-object.h" +#include "pycore.h" + +/* monitor "query destroyed" signal */ +static void query_cleanup(QUERY_REC *query) +{ + PyQuery *pyquery = signal_get_user_data(); + + if (query == pyquery->data) + { + pyquery->data = NULL; + pyquery->cleanup_installed = 0; + signal_remove_data("query destroyed", query_cleanup, pyquery); + } +} + +static void PyQuery_dealloc(PyQuery *self) +{ + if (self->cleanup_installed) + signal_remove_data("query destroyed", query_cleanup, self); + + self->ob_type->tp_free((PyObject*)self); +} + +/* Getters */ +PyDoc_STRVAR(PyQuery_address_doc, + "Host address of the queries nick" +); +static PyObject *PyQuery_address_get(PyQuery *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->address); +} + +PyDoc_STRVAR(PyQuery_server_tag_doc, + "Server tag used for this nick (doesn't get erased if server gets disconnected)" +); +static PyObject *PyQuery_server_tag_get(PyQuery *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->server_tag); +} + +PyDoc_STRVAR(PyQuery_unwanted_doc, + "1 if the other side closed or some error occured (DCC chats)" +); +static PyObject *PyQuery_unwanted_get(PyQuery *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyBool_FromLong(self->data->unwanted); +} + +/* specialized getters/setters */ +static PyGetSetDef PyQuery_getseters[] = { + {"address", (getter)PyQuery_address_get, NULL, + PyQuery_address_doc, NULL}, + {"server_tag", (getter)PyQuery_server_tag_get, NULL, + PyQuery_server_tag_doc, NULL}, + {"unwanted", (getter)PyQuery_unwanted_get, NULL, + PyQuery_unwanted_doc, NULL}, + {NULL} +}; + +PyDoc_STRVAR(change_server_doc, + "change_server(server) -> None\n" + "\n" + "Change the active server for the query.\n" +); +static PyObject *PyQuery_change_server(PyQuery *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"server", NULL}; + PyObject *server; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &server)) + return NULL; + + if (!pyserver_check(server)) + return PyErr_Format(PyExc_TypeError, "argument must be server object"); + + query_change_server(self->data, ((PyServer*)server)->data); + + Py_RETURN_NONE; +} + +/* Methods for object */ +static PyMethodDef PyQuery_methods[] = { + {"change_server", (PyCFunction)PyQuery_change_server, METH_VARARGS | METH_KEYWORDS, + change_server_doc}, + + {NULL} /* Sentinel */ +}; + +PyTypeObject PyQueryType = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "Query", /*tp_name*/ + sizeof(PyQuery), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)PyQuery_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + "PyQuery objects", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + PyQuery_methods, /* tp_methods */ + 0, /* tp_members */ + PyQuery_getseters, /* tp_getset */ + &PyWindowItemType, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + + +/* query factory function */ +PyObject *pyquery_new(void *query) +{ + static const char *BASE_NAME = "QUERY"; + PyObject *pyquery; + + pyquery = pywindow_item_sub_new(query, BASE_NAME, &PyQueryType); + if (pyquery) + { + PyQuery *pyq = (PyQuery *)pyquery; + signal_add_last_data("query destroyed", query_cleanup, pyq); + pyq->cleanup_installed = 1; + } + + return pyquery; +} + +int query_object_init(void) +{ + g_return_val_if_fail(py_module != NULL, 0); + + if (PyType_Ready(&PyQueryType) < 0) + return 0; + + Py_INCREF(&PyQueryType); + PyModule_AddObject(py_module, "Query", (PyObject *)&PyQueryType); + + return 1; +} diff --git a/src/objects/query-object.h b/src/objects/query-object.h new file mode 100644 index 0000000..844ce55 --- /dev/null +++ b/src/objects/query-object.h @@ -0,0 +1,21 @@ +#ifndef _QUERY_OBJECT_H_ +#define _QUERY_OBJECT_H_ + +#include +#include "window-item-object.h" + +/* forward */ +struct _QUERY_REC; + +typedef struct +{ + PyWindowItem_HEAD(struct _QUERY_REC) +} PyQuery; + +extern PyTypeObject PyQueryType; + +int query_object_init(void); +PyObject *pyquery_new(void *query); +#define pyquery_check(op) PyObject_TypeCheck(op, &PyQueryType) + +#endif diff --git a/src/objects/rawlog-object.c b/src/objects/rawlog-object.c new file mode 100644 index 0000000..340d60a --- /dev/null +++ b/src/objects/rawlog-object.c @@ -0,0 +1,323 @@ +#include +#include "pyirssi_irc.h" +#include "pymodule.h" +#include "rawlog-object.h" +#include "pycore.h" + +/* monitor "????" signal */ +static void rawlog_cleanup(RAWLOG_REC *ban) +{ + /* XXX */ +} + +static void PyRawlog_dealloc(PyRawlog *self) +{ + self->ob_type->tp_free((PyObject*)self); +} + +static PyObject *PyRawlog_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyRawlog *self; + + self = (PyRawlog *)type->tp_alloc(type, 0); + if (!self) + return NULL; + + return (PyObject *)self; +} + +/* XXX: Need function to create the rawlog */ + +/* Getters */ +PyDoc_STRVAR(PyRawlog_logging_doc, + "The raw log is being written to file currently." +); +static PyObject *PyRawlog_logging_get(PyRawlog *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyBool_FromLong(self->data->logging); +} + +PyDoc_STRVAR(PyRawlog_nlines_doc, + "Number of lines in rawlog." +); +static PyObject *PyRawlog_nlines_get(PyRawlog *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyInt_FromLong(self->data->nlines); +} + +/* specialized getters/setters */ +static PyGetSetDef PyRawlog_getseters[] = { + {"logging", (getter)PyRawlog_logging_get, NULL, + PyRawlog_logging_doc, NULL}, + {"nlines", (getter)PyRawlog_nlines_get, NULL, + PyRawlog_nlines_doc, NULL}, + {NULL} +}; + +/* Methods */ +PyDoc_STRVAR(PyRawlog_get_lines_doc, + "get_lines() -> list of str\n" + "\n" + "Return a list of lines for rawlog.\n" +); +static PyObject *PyRawlog_get_lines(PyRawlog *self, PyObject *args) +{ + PyObject *lines = NULL; + GSList *node; + + RET_NULL_IF_INVALID(self->data); + + lines = PyList_New(0); + if (!lines) + return NULL; + + for (node = self->data->lines; node; node = node->next) + { + int ret; + PyObject *line = PyString_FromString(node->data); + + if (!line) + { + Py_XDECREF(lines); + return NULL; + } + + ret = PyList_Append(lines, line); + Py_DECREF(line); + if (ret != 0) + { + Py_XDECREF(lines); + return NULL; + } + } + + return lines; +} + +PyDoc_STRVAR(PyRawlog_destroy_doc, + "destroy() -> None\n" + "\n" + "Destroy rawlog\n" +); +static PyObject *PyRawlog_destroy(PyRawlog *self, PyObject *args) +{ + RET_NULL_IF_INVALID(self->data); + + rawlog_destroy(self->data); + + /*XXX: what about signal handler ? */ + self->data = NULL; + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyRawlog_input_doc, + "input(str) -> None\n" + "\n" + "Send str to rawlog as input text.\n" +); +static PyObject *PyRawlog_input(PyRawlog *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"str", NULL}; + char *str = ""; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &str)) + return NULL; + + rawlog_input(self->data, str); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyRawlog_output_doc, + "output(str) -> None\n" + "\n" + "Send str to rawlog as output text.\n" +); +static PyObject *PyRawlog_output(PyRawlog *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"str", NULL}; + char *str = ""; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &str)) + return NULL; + + rawlog_output(self->data, str); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyRawlog_redirect_doc, + "redirect(str) -> None\n" + "\n" + "Send str to rawlog as redirection text." +); +static PyObject *PyRawlog_redirect(PyRawlog *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"str", NULL}; + char *str = ""; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &str)) + return NULL; + + rawlog_redirect(self->data, str); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyRawlog_open_doc, + "open(fname) -> None\n" + "\n" + "Start logging new messages in rawlog to specified file.\n" +); +static PyObject *PyRawlog_open(PyRawlog *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"fname", NULL}; + char *fname = ""; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &fname)) + return NULL; + + rawlog_open(self->data, fname); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyRawlog_close_doc, + "close() -> None\n" + "\n" + "Stop logging to file\n" +); +static PyObject *PyRawlog_close(PyRawlog *self, PyObject *args) +{ + RET_NULL_IF_INVALID(self->data); + + rawlog_close(self->data); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyRawlog_save_doc, + "save(fname) -> None\n" + "\n" + "Save the current rawlog history to specified file.\n" +); +static PyObject *PyRawlog_save(PyRawlog *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"fname", NULL}; + char *fname = ""; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &fname)) + return NULL; + + rawlog_save(self->data, fname); + + Py_RETURN_NONE; +} +/* Methods for object */ +static PyMethodDef PyRawlog_methods[] = { + {"get_lines", (PyCFunction)PyRawlog_get_lines, METH_NOARGS, + PyRawlog_get_lines_doc}, + {"destroy", (PyCFunction)PyRawlog_destroy, METH_NOARGS, + PyRawlog_destroy_doc}, + {"input", (PyCFunction)PyRawlog_input, METH_VARARGS | METH_KEYWORDS, + PyRawlog_input_doc}, + {"output", (PyCFunction)PyRawlog_output, METH_VARARGS | METH_KEYWORDS, + PyRawlog_output_doc}, + {"redirect", (PyCFunction)PyRawlog_redirect, METH_VARARGS | METH_KEYWORDS, + PyRawlog_redirect_doc}, + {"open", (PyCFunction)PyRawlog_open, METH_VARARGS | METH_KEYWORDS, + PyRawlog_open_doc}, + {"close", (PyCFunction)PyRawlog_close, METH_NOARGS, + PyRawlog_close_doc}, + {"save", (PyCFunction)PyRawlog_save, METH_VARARGS | METH_KEYWORDS, + PyRawlog_save_doc}, + {NULL} /* Sentinel */ +}; + +PyTypeObject PyRawlogType = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "Rawlog", /*tp_name*/ + sizeof(PyRawlog), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)PyRawlog_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + "PyRawlog objects", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + PyRawlog_methods, /* tp_methods */ + 0, /* tp_members */ + PyRawlog_getseters, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + PyRawlog_new, /* tp_new */ +}; + + +/* window item wrapper factory function */ +PyObject *pyrawlog_new(void *rlog) +{ + PyRawlog *pyrlog; + + pyrlog = py_inst(PyRawlog, PyRawlogType); + if (!pyrlog) + return NULL; + + pyrlog->data = rlog; + + return (PyObject *)pyrlog; +} + +int rawlog_object_init(void) +{ + g_return_val_if_fail(py_module != NULL, 0); + + if (PyType_Ready(&PyRawlogType) < 0) + return 0; + + Py_INCREF(&PyRawlogType); + PyModule_AddObject(py_module, "Rawlog", (PyObject *)&PyRawlogType); + + return 1; +} diff --git a/src/objects/rawlog-object.h b/src/objects/rawlog-object.h new file mode 100644 index 0000000..d2a9a2d --- /dev/null +++ b/src/objects/rawlog-object.h @@ -0,0 +1,22 @@ +#ifndef _RAWLOG_OBJECT_H_ +#define _RAWLOG_OBJECT_H_ + +#include +#include "base-objects.h" + +/* forward */ +struct _RAWLOG_REC; + +typedef struct +{ + PyIrssiFinal_HEAD(struct _RAWLOG_REC) + int owned; +} PyRawlog; + +extern PyTypeObject PyRawlogType; + +int rawlog_object_init(void); +PyObject *pyrawlog_new(void *rlog); +#define pyrawlog_check(op) PyObject_TypeCheck(op, &PyRawlogType) + +#endif diff --git a/src/objects/reconnect-object.c b/src/objects/reconnect-object.c new file mode 100644 index 0000000..6483242 --- /dev/null +++ b/src/objects/reconnect-object.c @@ -0,0 +1,151 @@ +#include +#include "pyirssi.h" +#include "pymodule.h" +#include "pycore.h" +#include "factory.h" +#include "reconnect-object.h" + +/*XXX: no Reconnect cleanup/destroy sig. Maybe value copy the two members? */ + +static void PyReconnect_dealloc(PyReconnect *self) +{ + Py_XDECREF(self->connect); + self->ob_type->tp_free((PyObject*)self); +} + +static PyObject *PyReconnect_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyReconnect *self; + + self = (PyReconnect *)type->tp_alloc(type, 0); + if (!self) + return NULL; + + return (PyObject *)self; +} + +/* Getters */ +PyDoc_STRVAR(PyReconnect_tag_doc, + "Unique numeric tag" +); +static PyObject *PyReconnect_tag_get(PyReconnect *self, void *closure) +{ + RECONNECT_REC *data = self->data; + RET_NULL_IF_INVALID(self->data); + + return PyInt_FromLong(data->tag); +} + +PyDoc_STRVAR(PyReconnect_next_connect_doc, + "Unix time stamp when the next connection occurs" +); +static PyObject *PyReconnect_next_connect_get(PyReconnect *self, void *closure) +{ + RECONNECT_REC *data = self->data; + RET_NULL_IF_INVALID(self->data); + + return PyLong_FromUnsignedLong(data->next_connect); +} + +PyDoc_STRVAR(PyReconnect_connect_doc, + "Connection object" +); +static PyObject *PyReconnect_connect_get(PyReconnect *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_OBJ_OR_NONE(self->connect); +} + +/* specialized getters/setters */ +static PyGetSetDef PyReconnect_getseters[] = { + {"tag", (getter)PyReconnect_tag_get, NULL, + PyReconnect_tag_doc, NULL}, + {"next_connect", (getter)PyReconnect_next_connect_get, NULL, + PyReconnect_next_connect_doc, NULL}, + {"connect", (getter)PyReconnect_connect_get, NULL, + PyReconnect_connect_doc, NULL}, + {NULL} +}; + +/* Methods for object */ +static PyMethodDef PyReconnect_methods[] = { + {NULL} /* Sentinel */ +}; + +PyTypeObject PyReconnectType = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "Reconnect", /*tp_name*/ + sizeof(PyReconnect), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)PyReconnect_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + "PyReconnect objects", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + PyReconnect_methods, /* tp_methods */ + 0, /* tp_members */ + PyReconnect_getseters, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + PyReconnect_new, /* tp_new */ +}; + + +/* window item wrapper factory function */ +PyObject *pyreconnect_new(void *recon) +{ + RECONNECT_REC *rec = recon; + PyObject *connect; + PyReconnect *pyrecon; + + /* XXX: get a managed connect because there's no signals to manage reconnect */ + connect = py_irssi_chat_new(rec->conn, 1); + if (!connect) + return NULL; + + pyrecon = py_inst(PyReconnect, PyReconnectType); + if (!pyrecon) + return NULL; + + pyrecon->data = recon; + pyrecon->connect = connect; + + return (PyObject *)pyrecon; +} + +int reconnect_object_init(void) +{ + g_return_val_if_fail(py_module != NULL, 0); + + if (PyType_Ready(&PyReconnectType) < 0) + return 0; + + Py_INCREF(&PyReconnectType); + PyModule_AddObject(py_module, "Reconnect", (PyObject *)&PyReconnectType); + + return 1; +} diff --git a/src/objects/reconnect-object.h b/src/objects/reconnect-object.h new file mode 100644 index 0000000..ec0b094 --- /dev/null +++ b/src/objects/reconnect-object.h @@ -0,0 +1,20 @@ +#ifndef _RECONNECT_OBJECT_H_ +#define _RECONNECT_OBJECT_H_ + +#include +#include "base-objects.h" + +/*XXX: no Reconnect cleanup/destroy sig. Maybe value copy the two members? */ +typedef struct +{ + PyIrssiFinal_HEAD(void) + PyObject *connect; +} PyReconnect; + +extern PyTypeObject PyReconnectType; + +int reconnect_object_init(void); +PyObject *pyreconnect_new(void *recon); +#define pyreconnect_check(op) PyObject_TypeCheck(op, &PyReconnectType) + +#endif diff --git a/src/objects/server-object.c b/src/objects/server-object.c new file mode 100644 index 0000000..31415b8 --- /dev/null +++ b/src/objects/server-object.c @@ -0,0 +1,807 @@ +#include +#include "pymodule.h" +#include "factory.h" +#include "pyirssi.h" +#include "pycore.h" +#include "pyutils.h" + +static void server_cleanup(SERVER_REC *server) +{ + PyServer *pyserver = signal_get_user_data(); + + if (server == pyserver->data) + { + if (pyserver->connect) + ((PyConnect *)pyserver->connect)->data = NULL; + + if (pyserver->rawlog) + ((PyRawlog *)pyserver->rawlog)->data = NULL; + + pyserver->data = NULL; + pyserver->cleanup_installed = 0; + signal_remove_data("server disconnected", server_cleanup, pyserver); + } +} + +static void PyServer_dealloc(PyServer *self) +{ + if (self->cleanup_installed) + signal_remove_data("server disconnected", server_cleanup, self); + + Py_XDECREF(self->connect); + Py_XDECREF(self->rawlog); + + self->ob_type->tp_free((PyObject*)self); +} + +/* Getters */ +PyDoc_STRVAR(PyServer_connect_time_doc, + "Time when connect() to server finished" +); +static PyObject *PyServer_connect_time_get(PyServer *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyLong_FromLong(self->data->connect_time); +} + +PyDoc_STRVAR(PyServer_real_connect_time_doc, + "Time when server sent 'connected' message" +); +static PyObject *PyServer_real_connect_time_get(PyServer *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyLong_FromLong(self->data->real_connect_time); +} + +PyDoc_STRVAR(PyServer_tag_doc, + "Unique server tag" +); +static PyObject *PyServer_tag_get(PyServer *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->tag); +} + +PyDoc_STRVAR(PyServer_nick_doc, + "Current nick" +); +static PyObject *PyServer_nick_get(PyServer *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->nick); +} + +PyDoc_STRVAR(PyServer_connected_doc, + "Is connection finished? 1|0" +); +static PyObject *PyServer_connected_get(PyServer *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyBool_FromLong(self->data->connected); +} + +PyDoc_STRVAR(PyServer_connection_lost_doc, + "Did we lose the connection (1) or was the connection just /DISCONNECTed (0)" +); +static PyObject *PyServer_connection_lost_get(PyServer *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyBool_FromLong(self->data->connection_lost); +} + +PyDoc_STRVAR(PyServer_rawlog_doc, + "Rawlog object for the server" +); +static PyObject *PyServer_rawlog_get(PyServer *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_OBJ_OR_NONE(self->rawlog); +} + +PyDoc_STRVAR(PyServer_connect_doc, + "Connect object for the server" +); +static PyObject *PyServer_connect_get(PyServer *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_OBJ_OR_NONE(self->connect); +} + +PyDoc_STRVAR(PyServer_version_doc, + "Server version" +); +static PyObject *PyServer_version_get(PyServer *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->version); +} + +PyDoc_STRVAR(PyServer_last_invite_doc, + "Last channel we were invited to" +); +static PyObject *PyServer_last_invite_get(PyServer *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->last_invite); +} + +PyDoc_STRVAR(PyServer_server_operator_doc, + "Are we server operator (IRC op) 1|0" +); +static PyObject *PyServer_server_operator_get(PyServer *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyBool_FromLong(self->data->server_operator); +} + +PyDoc_STRVAR(PyServer_usermode_away_doc, + "Are we marked as away? 1|0" +); +static PyObject *PyServer_usermode_away_get(PyServer *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyBool_FromLong(self->data->usermode_away); +} + +PyDoc_STRVAR(PyServer_away_reason_doc, + "Away reason message" +); +static PyObject *PyServer_away_reason_get(PyServer *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->away_reason); +} + +PyDoc_STRVAR(PyServer_banned_doc, + "Were we banned from this server? 1|0" +); +static PyObject *PyServer_banned_get(PyServer *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyBool_FromLong(self->data->banned); +} + +PyDoc_STRVAR(PyServer_lag_doc, + "Current lag to server in milliseconds" +); +static PyObject *PyServer_lag_get(PyServer *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyInt_FromLong(self->data->lag); +} + +static PyGetSetDef PyServer_getseters[] = { + {"connect_time", (getter)PyServer_connect_time_get, NULL, + PyServer_connect_time_doc, NULL}, + {"real_connect_time", (getter)PyServer_real_connect_time_get, NULL, + PyServer_real_connect_time_doc, NULL}, + {"tag", (getter)PyServer_tag_get, NULL, + PyServer_tag_doc, NULL}, + {"nick", (getter)PyServer_nick_get, NULL, + PyServer_nick_doc, NULL}, + {"connected", (getter)PyServer_connected_get, NULL, + PyServer_connected_doc, NULL}, + {"connection_lost", (getter)PyServer_connection_lost_get, NULL, + PyServer_connection_lost_doc, NULL}, + {"rawlog", (getter)PyServer_rawlog_get, NULL, + PyServer_rawlog_doc, NULL}, + {"connect", (getter)PyServer_connect_get, NULL, + PyServer_connect_doc, NULL}, + {"version", (getter)PyServer_version_get, NULL, + PyServer_version_doc, NULL}, + {"last_invite", (getter)PyServer_last_invite_get, NULL, + PyServer_last_invite_doc, NULL}, + {"server_operator", (getter)PyServer_server_operator_get, NULL, + PyServer_server_operator_doc, NULL}, + {"usermode_away", (getter)PyServer_usermode_away_get, NULL, + PyServer_usermode_away_doc, NULL}, + {"away_reason", (getter)PyServer_away_reason_get, NULL, + PyServer_away_reason_doc, NULL}, + {"banned", (getter)PyServer_banned_get, NULL, + PyServer_banned_doc, NULL}, + {"lag", (getter)PyServer_lag_get, NULL, + PyServer_lag_doc, NULL}, + {NULL} +}; + +/* Methods */ +PyDoc_STRVAR(print_doc, + "prnt(channel, str, level) -> None\n" + "\n" + "Print to server\n" +); +static PyObject *PyServer_prnt(PyServer *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"channel", "str", "level", NULL}; + char *str, *channel; + int level = MSGLEVEL_CLIENTNOTICE; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss|i", kwlist, &channel, &str, &level)) + return NULL; + + printtext_string(self->data, channel, level, str); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(command_doc, + "command(cmd) -> None\n" + "\n" + "Send command\n" +); +static PyObject *PyServer_command(PyServer *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"cmd", NULL}; + char *cmd; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &cmd)) + return NULL; + + py_command(cmd, self->data, NULL); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(disconnect_doc, + "disconnect() -> None\n" + "\n" + "Disconnect from server\n" +); +static PyObject *PyServer_disconnect(PyServer *self, PyObject *args) +{ + RET_NULL_IF_INVALID(self->data); + + server_disconnect(self->data); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(isnickflag_doc, + "isnickflag(flag) -> bool\n" + "\n" + "Returns True if flag is a nick mode flag (@, + or % in IRC)\n" +); +static PyObject *PyServer_isnickflag(PyServer *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"flag", NULL}; + char flag; + int ret; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "c", kwlist, &flag)) + return NULL; + + ret = self->data->isnickflag(self->data, flag); + + return PyBool_FromLong(ret); +} + +PyDoc_STRVAR(ischannel_doc, + "ischannel(data) -> bool\n" + "\n" + "Returns True if start of `data' seems to mean channel.\n" +); +static PyObject *PyServer_ischannel(PyServer *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"data", NULL}; + char *data; + int ret; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &data)) + return NULL; + + ret = self->data->ischannel(self->data, data); + + return PyBool_FromLong(ret); +} + +PyDoc_STRVAR(get_nick_flags_doc, + "get_nick_flags() -> str\n" + "\n" + "Returns nick flag characters in order: op, voice, halfop (\"@+%\") in IRC\n" +); +static PyObject *PyServer_get_nick_flags(PyServer *self, PyObject *args) +{ + char *ret; + + RET_NULL_IF_INVALID(self->data); + + ret = (char *)self->data->get_nick_flags(self->data); + + return PyString_FromString(ret); +} + +PyDoc_STRVAR(send_message_doc, + "send_message(target, msg, target_type) -> None\n" + "\n" + "Sends a message to nick/channel. target_type 0 = channel, 1 = nick\n" +); +static PyObject *PyServer_send_message(PyServer *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"target", "msg", "target_type", NULL}; + char *target, *msg; + int target_type; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "ssi", kwlist, &target, &msg, &target_type)) + return NULL; + + self->data->send_message(self->data, target, msg, target_type); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(channels_join_doc, + "channels_join(channels, automatic=False) -> None\n" + "\n" + "Join to channels in server. `channels' may also contain keys for\n" + "channels just like with /JOIN command. `automatic' specifies if this\n" + "channel was joined 'automatically' or if it was joined because join\n" + "was requested by user. If channel join is 'automatic', irssi doesn't\n" + "jump to the window where the channel was joined.\n" +); +static PyObject *PyServer_channels_join(PyServer *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"channels", "automatic", NULL}; + char *channels; + int automatic = 0; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|i", kwlist, &channels, &automatic)) + return NULL; + + self->data->channels_join(self->data, channels, automatic); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyServer_window_item_find_doc, + "window_item_find(name) -> WindowItem object or None\n" + "\n" + "Find window item that matches best to given arguments\n" +); +static PyObject *PyServer_window_item_find(PyServer *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"name", NULL}; + char *name = ""; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &name)) + return NULL; + + return py_irssi_chat_new(window_item_find(self->data, name), 1); +} + +PyDoc_STRVAR(PyServer_window_find_item_doc, + "window_find_item(name) -> Window object or None\n" + "\n" + "Find window which contains window item with specified name/server\n" +); +static PyObject *PyServer_window_find_item(PyServer *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"name", NULL}; + char *name = ""; + WINDOW_REC *win; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &name)) + return NULL; + + win = window_find_item(self->data, name); + if (win) + return pywindow_new(win); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyServer_window_find_level_doc, + "window_find_level(level) -> Window object or None\n" + "\n" + "Find window with level\n" +); +static PyObject *PyServer_window_find_level(PyServer *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"level", NULL}; + int level = 0; + WINDOW_REC *win; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, + &level)) + return NULL; + + win = window_find_level(self->data, level); + if (win) + return pywindow_new(win); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyServer_window_find_closest_doc, + "window_find_closest(name, level) -> Window object or None\n" + "\n" + "Find window that matches best to given arguments. `name' can be either\n" + "window name or name of one of the window items.\n" +); +static PyObject *PyServer_window_find_closest(PyServer *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"name", "level", NULL}; + char *name = ""; + int level = 0; + WINDOW_REC *win; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "si", kwlist, + &name, &level)) + return NULL; + + win = window_find_closest(self->data, name, level); + if (win) + return pywindow_new(win); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyServer_channels_doc, + "channels() -> list of Channel objects\n" + "\n" + "Return list of channels for server\n" +); +static PyObject *PyServer_channels(PyServer *self, PyObject *args) +{ + RET_NULL_IF_INVALID(self->data); + + return py_irssi_chatlist_new(self->data->channels, 1); +} + +PyDoc_STRVAR(PyServer_channel_find_doc, + "channel_find(name) -> Channel object or None\n" + "\n" + "Find channel from this server\n" +); +static PyObject *PyServer_channel_find(PyServer *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"name", NULL}; + char *name = ""; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &name)) + return NULL; + + return py_irssi_chat_new(channel_find(self->data, name), 1); +} + +PyDoc_STRVAR(PyServer_nicks_get_same_doc, + "nicks_get_same(nick)\n" + "\n" + "Return all nick objects in all channels in server. List is in format:\n" + "[(Channel, Nick), (Channel, Nick), ...]\n" +); +static PyObject *PyServer_nicks_get_same(PyServer *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"nick", NULL}; + char *nick = ""; + GSList *list, *node; + PyObject *pylist = NULL; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &nick)) + return NULL; + + pylist = PyList_New(0); + if (!pylist) + return NULL; + + list = nicklist_get_same(self->data, nick); + for (node = list; node != NULL; node = node->next->next) + { + int ret; + PyObject *tup; + + tup = Py_BuildValue("(NN)", + py_irssi_chat_new(node->data, 1), + py_irssi_chat_new(node->next->data, 1)); + if (!tup) + { + Py_XDECREF(pylist); + return NULL; + } + + ret = PyList_Append(pylist, tup); + Py_DECREF(tup); + if (ret != 0) + { + Py_XDECREF(pylist); + return NULL; + } + } + + return pylist; +} + +PyDoc_STRVAR(PyServer_queries_doc, + "queries() -> list of Query objects\n" + "\n" + "Return a list of queries for server.\n" +); +static PyObject *PyServer_queries(PyServer *self, PyObject *args) +{ + RET_NULL_IF_INVALID(self->data); + + return py_irssi_chatlist_new(self->data->queries, 1); +} + +PyDoc_STRVAR(PyServer_query_find_doc, + "query_find(nick) -> Query object or None\n" + "\n" + "Find a query on this server.\n" +); +static PyObject *PyServer_query_find(PyServer *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"nick", NULL}; + char *nick = ""; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &nick)) + return NULL; + + return py_irssi_chat_new(query_find(self->data, nick), 1); +} + +PyDoc_STRVAR(PyServer_mask_match_doc, + "mask_match(mask, nick, user, host) -> bool\n" + "\n" + "Return true if mask matches nick!user@host\n" +); +static PyObject *PyServer_mask_match(PyServer *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"mask", "nick", "user", "host", NULL}; + char *mask = ""; + char *nick = ""; + char *user = ""; + char *host = ""; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "ssss", kwlist, + &mask, &nick, &user, &host)) + return NULL; + + return PyBool_FromLong(mask_match(self->data, mask, nick, user, host)); +} + +PyDoc_STRVAR(PyServer_mask_match_address_doc, + "mask_match_address(mask, nick, address) -> bool\n" + "\n" + "Return True if mask matches nick!address\n" +); +static PyObject *PyServer_mask_match_address(PyServer *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"mask", "nick", "address", NULL}; + char *mask = ""; + char *nick = ""; + char *address = ""; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "sss", kwlist, + &mask, &nick, &address)) + return NULL; + + return PyBool_FromLong(mask_match_address(self->data, mask, nick, address)); +} + +PyDoc_STRVAR(PyServer_masks_match_doc, + "masks_match(masks, nick, address) -> bool\n" + "\n" + "Return True if any mask in the masks (string separated by spaces)\n" + "matches nick!address\n" +); +static PyObject *PyServer_masks_match(PyServer *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"masks", "nick", "address", NULL}; + char *masks = ""; + char *nick = ""; + char *address = ""; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "sss", kwlist, + &masks, &nick, &address)) + return NULL; + + return PyBool_FromLong(masks_match(self->data, masks, nick, address)); +} + +PyDoc_STRVAR(PyServer_ignore_check_doc, + "ignore_check(nick, host, channel, text, level) -> bool\n" + "\n" + "Return True if ignore matches\n" +); +static PyObject *PyServer_ignore_check(PyServer *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"nick", "host", "channel", "text", "level", NULL}; + char *nick = ""; + char *host = ""; + char *channel = ""; + char *text = ""; + int level = 0; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "ssssi", kwlist, + &nick, &host, &channel, &text, &level)) + return NULL; + + return PyBool_FromLong(ignore_check(self->data, + nick, host, channel, text, level)); +} + +/* Methods for object */ +static PyMethodDef PyServer_methods[] = { + {"prnt", (PyCFunction)PyServer_prnt, METH_VARARGS | METH_KEYWORDS, + print_doc}, + {"command", (PyCFunction)PyServer_command, METH_VARARGS | METH_KEYWORDS, + command_doc}, + {"disconnect", (PyCFunction)PyServer_disconnect, METH_NOARGS, + disconnect_doc}, + {"isnickflag", (PyCFunction)PyServer_isnickflag, METH_VARARGS | METH_KEYWORDS, + isnickflag_doc}, + {"ischannel", (PyCFunction)PyServer_ischannel, METH_VARARGS | METH_KEYWORDS, + ischannel_doc}, + {"get_nick_flags", (PyCFunction)PyServer_get_nick_flags, METH_NOARGS, + get_nick_flags_doc}, + {"send_message", (PyCFunction)PyServer_send_message, METH_VARARGS | METH_KEYWORDS, + send_message_doc}, + {"channels_join", (PyCFunction)PyServer_channels_join, METH_VARARGS | METH_KEYWORDS, + channels_join_doc}, + {"window_item_find", (PyCFunction)PyServer_window_item_find, METH_VARARGS | METH_KEYWORDS, + PyServer_window_item_find_doc}, + {"window_find_item", (PyCFunction)PyServer_window_find_item, METH_VARARGS | METH_KEYWORDS, + PyServer_window_find_item_doc}, + {"window_find_level", (PyCFunction)PyServer_window_find_level, METH_VARARGS | METH_KEYWORDS, + PyServer_window_find_level_doc}, + {"window_find_closest", (PyCFunction)PyServer_window_find_closest, METH_VARARGS | METH_KEYWORDS, + PyServer_window_find_closest_doc}, + {"channels", (PyCFunction)PyServer_channels, METH_NOARGS, + PyServer_channels_doc}, + {"channel_find", (PyCFunction)PyServer_channel_find, METH_VARARGS | METH_KEYWORDS, + PyServer_channel_find_doc}, + {"nicks_get_same", (PyCFunction)PyServer_nicks_get_same, METH_VARARGS | METH_KEYWORDS, + PyServer_nicks_get_same_doc}, + {"queries", (PyCFunction)PyServer_queries, METH_NOARGS, + PyServer_queries_doc}, + {"query_find", (PyCFunction)PyServer_query_find, METH_VARARGS | METH_KEYWORDS, + PyServer_query_find_doc}, + {"mask_match", (PyCFunction)PyServer_mask_match, METH_VARARGS | METH_KEYWORDS, + PyServer_mask_match_doc}, + {"mask_match_address", (PyCFunction)PyServer_mask_match_address, METH_VARARGS | METH_KEYWORDS, + PyServer_mask_match_address_doc}, + {"masks_match", (PyCFunction)PyServer_masks_match, METH_VARARGS | METH_KEYWORDS, + PyServer_masks_match_doc}, + {"ignore_check", (PyCFunction)PyServer_ignore_check, METH_VARARGS | METH_KEYWORDS, + PyServer_ignore_check_doc}, + {NULL} /* Sentinel */ +}; + +PyTypeObject PyServerType = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "Server", /*tp_name*/ + sizeof(PyServer), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)PyServer_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + "PyServer objects", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + PyServer_methods, /* tp_methods */ + 0, /* tp_members */ + PyServer_getseters, /* tp_getset */ + &PyIrssiChatBaseType, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + + +/* server factory function + connect arg should point to a wrapped SERVER_CONNECT */ +PyObject *pyserver_sub_new(void *server, PyTypeObject *subclass) +{ + static const char *SERVER_TYPE = "SERVER"; + SERVER_REC *srec = server; + PyServer *pyserver = NULL; + PyObject *rawlog = NULL; + PyObject *connect = NULL; + + g_return_val_if_fail(server != NULL, NULL); + + connect = py_irssi_chat_new(srec->connrec, 0); + if (!connect) + return NULL; + + /* FIXME */ + /* + if (srec->rawlog) + { + rawlog = pyrawlog_new(srec->rawlog); + if (!rawlog) + return NULL; + } + */ + + pyserver = py_instp(PyServer, subclass); + if (!pyserver) + return NULL; + + pyserver->base_name = SERVER_TYPE; + pyserver->data = server; + signal_add_last_data("server disconnected", server_cleanup, pyserver); + pyserver->cleanup_installed = 1; + pyserver->rawlog = rawlog; + pyserver->connect = connect; + + return (PyObject *)pyserver; +} + +PyObject *pyserver_new(void *server) +{ + return pyserver_sub_new(server, &PyServerType); +} + +int server_object_init(void) +{ + g_return_val_if_fail(py_module != NULL, 0); + + if (PyType_Ready(&PyServerType) < 0) + return 0; + + Py_INCREF(&PyServerType); + PyModule_AddObject(py_module, "Server", (PyObject *)&PyServerType); + + return 1; +} diff --git a/src/objects/server-object.h b/src/objects/server-object.h new file mode 100644 index 0000000..0703f47 --- /dev/null +++ b/src/objects/server-object.h @@ -0,0 +1,28 @@ +#ifndef _SERVER_OBJECT_H_ +#define _SERVER_OBJECT_H_ + +#include +#include "base-objects.h" + +/* forward */ +struct _SERVER_REC; + +#define PyServer_HEAD(type) \ + PyIrssi_HEAD(type) \ + PyObject *connect; \ + PyObject *rawlog; + +typedef struct +{ + PyServer_HEAD(struct _SERVER_REC) +} PyServer; + +extern PyTypeObject PyServerType; + +int server_object_init(void); +PyObject *pyserver_sub_new(void *server, PyTypeObject *subclass); +PyObject *pyserver_new(void *server); + +#define pyserver_check(op) PyObject_TypeCheck(op, &PyServerType) + +#endif diff --git a/src/objects/statusbar-item-object.c b/src/objects/statusbar-item-object.c new file mode 100644 index 0000000..f6768af --- /dev/null +++ b/src/objects/statusbar-item-object.c @@ -0,0 +1,253 @@ +#include +#include "pyirssi.h" +#include "pymodule.h" +#include "factory.h" +#include "statusbar-item-object.h" + +/* monitor "statusbar item destroyed" signal */ +static void statusbar_item_cleanup(SBAR_ITEM_REC *sbar_item) +{ + PyStatusbarItem *pysbar_item = signal_get_user_data(); + + if (sbar_item == pysbar_item->data) + { + pysbar_item->data = NULL; + pysbar_item->cleanup_installed = 0; + signal_remove_data("statusbar item_destroy", statusbar_item_cleanup, pysbar_item); + } +} + +static void PyStatusbarItem_dealloc(PyStatusbarItem *self) +{ + if (self->cleanup_installed) + signal_remove_data("sbar_itemlist remove", statusbar_item_cleanup, self); + + self->ob_type->tp_free((PyObject*)self); +} + +static PyObject *PyStatusbarItem_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyStatusbarItem *self; + + self = (PyStatusbarItem *)type->tp_alloc(type, 0); + if (!self) + return NULL; + + return (PyObject *)self; +} + +/* Getter */ +PyDoc_STRVAR(PyStatusbarItem_min_size_doc, + "min size" +); +static PyObject *PyStatusbarItem_min_size_get(PyStatusbarItem *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyInt_FromLong(self->data->min_size); +} + +PyDoc_STRVAR(PyStatusbarItem_max_size_doc, + "max size" +); +static PyObject *PyStatusbarItem_max_size_get(PyStatusbarItem *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyInt_FromLong(self->data->max_size); +} + +PyDoc_STRVAR(PyStatusbarItem_xpos_doc, + "x position" +); +static PyObject *PyStatusbarItem_xpos_get(PyStatusbarItem *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyInt_FromLong(self->data->xpos); +} + +PyDoc_STRVAR(PyStatusbarItem_size_doc, + "size" +); +static PyObject *PyStatusbarItem_size_get(PyStatusbarItem *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyInt_FromLong(self->data->size); +} + +PyDoc_STRVAR(PyStatusbarItem_window_doc, + "parent window for statusbar item" +); +static PyObject *PyStatusbarItem_window_get(PyStatusbarItem *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_OBJ_OR_NONE(self->window); +} + +/* setters */ +static int py_setint(int *iv, PyObject *value) +{ + int tmp; + + if (value == NULL) + { + PyErr_SetString(PyExc_AttributeError, "can't delete member"); + return -1; + } + + if (!PyInt_Check(value)) + { + PyErr_SetString(PyExc_TypeError, "value must be int"); + return -1; + } + + tmp = PyInt_AsLong(value); + if (PyErr_Occurred()) + return -1; + + *iv = tmp; + + return 0; +} + +static int PyStatusbarItem_min_size_set(PyStatusbarItem *self, PyObject *value, void *closure) +{ + return py_setint(&self->data->min_size, value); +} + +static int PyStatusbarItem_max_size_set(PyStatusbarItem *self, PyObject *value, void *closure) +{ + return py_setint(&self->data->max_size, value); +} + +/* specialized getters/setters */ +static PyGetSetDef PyStatusbarItem_getseters[] = { + {"min_size", (getter)PyStatusbarItem_min_size_get, (setter)PyStatusbarItem_min_size_set, + PyStatusbarItem_min_size_doc, NULL}, + {"max_size", (getter)PyStatusbarItem_max_size_get, (setter)PyStatusbarItem_max_size_set, + PyStatusbarItem_max_size_doc, NULL}, + {"xpos", (getter)PyStatusbarItem_xpos_get, NULL, + PyStatusbarItem_xpos_doc, NULL}, + {"size", (getter)PyStatusbarItem_size_get, NULL, + PyStatusbarItem_size_doc, NULL}, + {"window", (getter)PyStatusbarItem_window_get, NULL, + PyStatusbarItem_window_doc, NULL}, + {NULL} +}; + +/* Methods */ +PyDoc_STRVAR(PyStatusbarItem_default_handler_doc, + "default_handler(get_size_only, str=None, data="", escape_vars=True) -> None\n" + "\n" + "Run default handler of item to print to statusbar\n" +); +static PyObject *PyStatusbarItem_default_handler(PyStatusbarItem *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"get_size_only", "str", "data", "escape_vars", NULL}; + int get_size_only = 0; + char *str = NULL; + char *data = ""; + int escape_vars = TRUE; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "i|zsi", kwlist, + &get_size_only, &str, &data, &escape_vars)) + return NULL; + + if (str && !*str) + str = NULL; + + statusbar_item_default_handler(self->data, get_size_only, str, data, escape_vars); + + Py_RETURN_NONE; +} + +/* Methods for object */ +static PyMethodDef PyStatusbarItem_methods[] = { + {"default_handler", (PyCFunction)PyStatusbarItem_default_handler, METH_VARARGS | METH_KEYWORDS, + PyStatusbarItem_default_handler_doc}, + {NULL} /* Sentinel */ +}; + +PyTypeObject PyStatusbarItemType = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "StatusbarItem", /*tp_name*/ + sizeof(PyStatusbarItem), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)PyStatusbarItem_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + "PyStatusbarItem objects", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + PyStatusbarItem_methods, /* tp_methods */ + 0, /* tp_members */ + PyStatusbarItem_getseters, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + PyStatusbarItem_new, /* tp_new */ +}; + + +/* sbar_item factory function */ +PyObject *pystatusbar_item_new(void *sbar_item) +{ + SBAR_ITEM_REC *si; + PyStatusbarItem *pysbar_item; + PyObject *window = NULL; + + si = sbar_item; + if (si->bar->parent_window) + { + window = pywindow_new(si->bar->parent_window); + if (!window) + return NULL; + } + + pysbar_item = py_inst(PyStatusbarItem, PyStatusbarItemType); + if (!pysbar_item) + return NULL; + + pysbar_item->window = window; + + pysbar_item->data = sbar_item; + pysbar_item->cleanup_installed = 1; + signal_add_last_data("statusbar item destroyed", statusbar_item_cleanup, pysbar_item); + + return (PyObject *)pysbar_item; +} + +int statusbar_item_object_init(void) +{ + g_return_val_if_fail(py_module != NULL, 0); + + if (PyType_Ready(&PyStatusbarItemType) < 0) + return 0; + + Py_INCREF(&PyStatusbarItemType); + PyModule_AddObject(py_module, "StatusbarItem", (PyObject *)&PyStatusbarItemType); + + return 1; +} diff --git a/src/objects/statusbar-item-object.h b/src/objects/statusbar-item-object.h new file mode 100644 index 0000000..19243f4 --- /dev/null +++ b/src/objects/statusbar-item-object.h @@ -0,0 +1,22 @@ +#ifndef _SBAR_ITEM_OBJECT_H_ +#define _SBAR_ITEM_OBJECT_H_ + +#include +#include "base-objects.h" + +/* forward */ +struct SBAR_ITEM_REC; + +typedef struct +{ + PyIrssiFinal_HEAD(struct SBAR_ITEM_REC) + PyObject *window; +} PyStatusbarItem; + +extern PyTypeObject PyStatusbarItemType; + +int statusbar_item_object_init(void); +PyObject *pystatusbar_item_new(void *sbar_item); +#define pystatusbar_item_check(op) PyObject_TypeCheck(op, &PyStatusbarItemType) + +#endif diff --git a/src/objects/textdest-object.c b/src/objects/textdest-object.c new file mode 100644 index 0000000..2ad6523 --- /dev/null +++ b/src/objects/textdest-object.c @@ -0,0 +1,285 @@ +#include +#include "pyirssi_irc.h" +#include "pymodule.h" +#include "textdest-object.h" +#include "factory.h" +#include "pycore.h" + +static int pytextdest_setup(PyTextDest *pytdest, void *td, int owned); + +/* XXX: no cleanup signal for textdest */ +static void PyTextDest_dealloc(PyTextDest *self) +{ + Py_XDECREF(self->window); + Py_XDECREF(self->server); + + if (self->owned) + { + g_free((char*)self->data->target); + g_free(self->data); + } + + self->ob_type->tp_free((PyObject*)self); +} + +static PyObject *PyTextDest_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyTextDest *self; + + self = (PyTextDest *)type->tp_alloc(type, 0); + if (!self) + return NULL; + + return (PyObject *)self; +} + +/* init function to create the textdest */ +PyDoc_STRVAR(PyTextDest_doc, + "__init__(target, level=MSGLEVEL_CLIENTNOTICE, server=None, window=None)\n" + "\n" + "Create a TextDest\n" +); +static int PyTextDest_init(PyTextDest *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"target", "level", "server", "window", NULL}; + char *target; + int level = MSGLEVEL_CLIENTNOTICE; + PyObject *server = NULL, *window = NULL; + TEXT_DEST_REC *dest; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|ioo", kwlist, + &target, &level, &server, &window)) + return -1; + + if (server == Py_None) + server = NULL; + if (window == Py_None) + window = NULL; + + if (server && !pyserver_check(server)) + { + PyErr_Format(PyExc_TypeError, "arg 3 isnt server"); + return -1; + } + + if (window && !pywindow_check(window)) + { + PyErr_Format(PyExc_TypeError, "arg 4 isnt window"); + return -1; + } + + if (self->data) + { + PyErr_Format(PyExc_RuntimeError, "TextDest already wrapped"); + return -1; + } + + dest = g_new0(TEXT_DEST_REC, 1); + format_create_dest(dest, DATA(server), g_strdup(target), level, DATA(window)); + + if (!pytextdest_setup(self, dest, 1)) + return -1; + + return 0; +} + +/* Getters */ +PyDoc_STRVAR(PyTextDest_window_doc, + "Window where the text will be written" +); +static PyObject *PyTextDest_window_get(PyTextDest *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_OBJ_OR_NONE(self->window); +} + +PyDoc_STRVAR(PyTextDest_server_doc, + "Target server" +); +static PyObject *PyTextDest_server_get(PyTextDest *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_OBJ_OR_NONE(self->server); +} + +PyDoc_STRVAR(PyTextDest_target_doc, + "Target channel/query/etc name" +); +static PyObject *PyTextDest_target_get(PyTextDest *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->target); +} + +PyDoc_STRVAR(PyTextDest_level_doc, + "Text level" +); +static PyObject *PyTextDest_level_get(PyTextDest *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyInt_FromLong(self->data->level); +} + +PyDoc_STRVAR(PyTextDest_hilight_priority_doc, + "Priority for the hilighted text" +); +static PyObject *PyTextDest_hilight_priority_get(PyTextDest *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyInt_FromLong(self->data->hilight_priority); +} + +PyDoc_STRVAR(PyTextDest_hilight_color_doc, + "Color for the hilighted text" +); +static PyObject *PyTextDest_hilight_color_get(PyTextDest *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->hilight_color); +} + +/* specialized getters/setters */ +static PyGetSetDef PyTextDest_getseters[] = { + {"window", (getter)PyTextDest_window_get, NULL, + PyTextDest_window_doc, NULL}, + {"server", (getter)PyTextDest_server_get, NULL, + PyTextDest_server_doc, NULL}, + {"target", (getter)PyTextDest_target_get, NULL, + PyTextDest_target_doc, NULL}, + {"level", (getter)PyTextDest_level_get, NULL, + PyTextDest_level_doc, NULL}, + {"hilight_priority", (getter)PyTextDest_hilight_priority_get, NULL, + PyTextDest_hilight_priority_doc, NULL}, + {"hilight_color", (getter)PyTextDest_hilight_color_get, NULL, + PyTextDest_hilight_color_doc, NULL}, + {NULL} +}; + +/* Methods */ +PyDoc_STRVAR(PyTextDest_prnt_doc, + "prnt(str) -> None\n" + "\n" + "Print str to TextDest\n" +); +static PyObject *PyTextDest_prnt(PyTextDest *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"str", NULL}; + char *str = ""; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &str)) + return NULL; + + printtext_dest(self->data, "%s", str); + + Py_RETURN_NONE; +} + +/* Methods for object */ +static PyMethodDef PyTextDest_methods[] = { + {"prnt", (PyCFunction)PyTextDest_prnt, METH_VARARGS | METH_KEYWORDS, + PyTextDest_prnt_doc}, + {NULL} /* Sentinel */ +}; + +PyTypeObject PyTextDestType = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "TextDest", /*tp_name*/ + sizeof(PyTextDest), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)PyTextDest_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + PyTextDest_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + PyTextDest_methods, /* tp_methods */ + 0, /* tp_members */ + PyTextDest_getseters, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)PyTextDest_init, /* tp_init */ + 0, /* tp_alloc */ + PyTextDest_new, /* tp_new */ +}; + +static int pytextdest_setup(PyTextDest *pytdest, void *td, int owned) +{ + PyObject *window, *server; + TEXT_DEST_REC *tdest = td; + + if (tdest->window) + { + window = pywindow_new(tdest->window); + if (!window) + return 0; + } + + server = py_irssi_chat_new(tdest->server, 1); + if (!server) + { + Py_DECREF(window); + return 0; + } + + pytdest->data = td; + pytdest->window = window; + pytdest->server = server; + pytdest->owned = owned; + + return 1; +} + +/* TextDest factory function */ +PyObject *pytextdest_new(void *td) +{ + PyTextDest *pytdest; + + pytdest = py_inst(PyTextDest, PyTextDestType); + if (!pytdest) + return NULL; + + if (!pytextdest_setup(pytdest, td, 0)) + { + Py_DECREF(pytdest); + return NULL; + } + + return (PyObject *)pytdest; +} + +int textdest_object_init(void) +{ + g_return_val_if_fail(py_module != NULL, 0); + + if (PyType_Ready(&PyTextDestType) < 0) + return 0; + + Py_INCREF(&PyTextDestType); + PyModule_AddObject(py_module, "TextDest", (PyObject *)&PyTextDestType); + + return 1; +} diff --git a/src/objects/textdest-object.h b/src/objects/textdest-object.h new file mode 100644 index 0000000..3e273e6 --- /dev/null +++ b/src/objects/textdest-object.h @@ -0,0 +1,24 @@ +#ifndef _TEXTDEST_OBJECT_H_ +#define _TEXTDEST_OBJECT_H_ + +#include +#include "base-objects.h" + +/* forward */ +struct _TEXT_DEST_REC; + +typedef struct +{ + PyIrssiFinal_HEAD(struct _TEXT_DEST_REC) + PyObject *window; + PyObject *server; + int owned; +} PyTextDest; + +extern PyTypeObject PyTextDestType; + +int textdest_object_init(void); +PyObject *pytextdest_new(void *td); +#define pytextdest_check(op) PyObject_TypeCheck(op, &PyTextDestType) + +#endif diff --git a/src/objects/theme-object.c b/src/objects/theme-object.c new file mode 100644 index 0000000..0f12217 --- /dev/null +++ b/src/objects/theme-object.c @@ -0,0 +1,195 @@ +#include +#include "pyirssi.h" +#include "pymodule.h" +#include "theme-object.h" +#include "factory.h" +#include "pycore.h" + +/* monitor "theme destroyed" signal */ +static void theme_cleanup(THEME_REC *rec) +{ + PyTheme *pytheme = signal_get_user_data(); + if (pytheme->data == rec) + { + pytheme->data = NULL; + pytheme->cleanup_installed = 0; + signal_remove_data("theme destroyed", theme_cleanup, pytheme); + } +} + +static void PyTheme_dealloc(PyTheme *self) +{ + if (self->cleanup_installed) + signal_remove_data("theme destroyed", theme_cleanup, self); + + self->ob_type->tp_free((PyObject*)self); +} + +static PyObject *PyTheme_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyTheme *self; + + self = (PyTheme *)type->tp_alloc(type, 0); + if (!self) + return NULL; + + return (PyObject *)self; +} + +/* Getters */ +/* specialized getters/setters */ +static PyGetSetDef PyTheme_getseters[] = { + {NULL} +}; + +/* Methods */ +PyDoc_STRVAR(PyTheme_format_expand_doc, + "format_expand(format, flags=0) -> str or None\n" +); +static PyObject *PyTheme_format_expand(PyTheme *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"format", "flags", NULL}; + char *format = ""; + int flags = 0; + char *ret; + PyObject *pyret; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|i", kwlist, + &format, &flags)) + return NULL; + + if (flags == 0) + ret = theme_format_expand(self->data, format); + else + ret = theme_format_expand_data(self->data, (const char **)&format, 'n', 'n', + NULL, NULL, EXPAND_FLAG_ROOT | flags); + + if (ret) + { + pyret = PyString_FromString(ret); + g_free(ret); + return pyret; + } + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyTheme_get_format_doc, + "get_format(module, tag) -> str\n" +); +static PyObject *PyTheme_get_format(PyTheme *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"module", "tag", NULL}; + char *module = ""; + char *tag = ""; + THEME_REC *theme = self->data; + FORMAT_REC *formats; + MODULE_THEME_REC *modtheme; + int i; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss", kwlist, + &module, &tag)) + return NULL; + + formats = g_hash_table_lookup(default_formats, module); + if (!formats) + return PyErr_Format(PyExc_KeyError, "unknown module, %s", module); + + for (i = 0; formats[i].def; i++) + { + if (formats[i].tag && !g_strcasecmp(formats[i].tag, tag)) + { + modtheme = g_hash_table_lookup(theme->modules, module); + if (modtheme && modtheme->formats[i]) + return PyString_FromString(modtheme->formats[i]); + else + return PyString_FromString(formats[i].def); + } + } + + return PyErr_Format(PyExc_KeyError, "unknown format tag, %s", tag); +} + +/* Methods for object */ +static PyMethodDef PyTheme_methods[] = { + {"format_expand", (PyCFunction)PyTheme_format_expand, METH_VARARGS | METH_KEYWORDS, + PyTheme_format_expand_doc}, + {"get_format", (PyCFunction)PyTheme_get_format, METH_VARARGS | METH_KEYWORDS, + PyTheme_get_format_doc}, + {NULL} /* Sentinel */ +}; + +PyTypeObject PyThemeType = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "Theme", /*tp_name*/ + sizeof(PyTheme), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)PyTheme_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + PyTheme_methods, /* tp_methods */ + 0, /* tp_members */ + PyTheme_getseters, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + PyTheme_new, /* tp_new */ +}; + +/* Theme factory function */ +PyObject *pytheme_new(void *td) +{ + PyTheme *pytheme; + + pytheme = py_inst(PyTheme, PyThemeType); + if (!pytheme) + return NULL; + + pytheme->data = td; + signal_add_last_data("theme destroyed", theme_cleanup, pytheme); + pytheme->cleanup_installed = 1; + + return (PyObject *)pytheme; +} + +int theme_object_init(void) +{ + g_return_val_if_fail(py_module != NULL, 0); + + if (PyType_Ready(&PyThemeType) < 0) + return 0; + + Py_INCREF(&PyThemeType); + PyModule_AddObject(py_module, "Theme", (PyObject *)&PyThemeType); + + return 1; +} diff --git a/src/objects/theme-object.h b/src/objects/theme-object.h new file mode 100644 index 0000000..299d54d --- /dev/null +++ b/src/objects/theme-object.h @@ -0,0 +1,18 @@ +#ifndef _THEME_OBJECT_H_ +#define _THEME_OBJECT_H_ + +#include +#include "base-objects.h" + +typedef struct +{ + PyIrssiFinal_HEAD(void) +} PyTheme; + +extern PyTypeObject PyThemeType; + +int theme_object_init(void); +PyObject *pytheme_new(void *td); +#define pytheme_check(op) PyObject_TypeCheck(op, &PyThemeType) + +#endif diff --git a/src/objects/window-item-object.c b/src/objects/window-item-object.c new file mode 100644 index 0000000..2f18f7d --- /dev/null +++ b/src/objects/window-item-object.c @@ -0,0 +1,334 @@ +#include +#include "pymodule.h" +#include "base-objects.h" +#include "window-item-object.h" +#include "pyirssi.h" +#include "pycore.h" +#include "pyutils.h" +#include "factory.h" + +/* Dealloc is overridden by sub types */ + +PyDoc_STRVAR(PyWindowItem_server_doc, + "Active name for item" +); +static PyObject *PyWindowItem_server_get(PyWindowItem *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_OBJ_OR_NONE(self->server); +} + +PyDoc_STRVAR(PyWindowItem_name_doc, + "Name of the item" +); +static PyObject *PyWindowItem_name_get(PyWindowItem *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->visible_name); +} + +PyDoc_STRVAR(PyWindowItem_createtime_doc, + "Time the witem was created" +); +static PyObject *PyWindowItem_createtime_get(PyWindowItem *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyLong_FromLong(self->data->createtime); +} + +PyDoc_STRVAR(PyWindowItem_data_level_doc, + "0=no new data, 1=text, 2=msg, 3=highlighted text" +); +static PyObject *PyWindowItem_data_level_get(PyWindowItem *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyInt_FromLong(self->data->data_level); +} + +PyDoc_STRVAR(PyWindowItem_hilight_color_doc, + "Color of the last highlighted text" +); +static PyObject *PyWindowItem_hilight_color_get(PyWindowItem *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->hilight_color); +} + +/* specialized getters/setters */ +static PyGetSetDef PyWindowItem_getseters[] = { + {"server", (getter)PyWindowItem_server_get, NULL, + PyWindowItem_server_doc, NULL}, + {"name", (getter)PyWindowItem_name_get, NULL, + PyWindowItem_name_doc, NULL}, + {"createtime", (getter)PyWindowItem_createtime_get, NULL, + PyWindowItem_createtime_doc, NULL}, + {"data_level", (getter)PyWindowItem_data_level_get, NULL, + PyWindowItem_data_level_doc, NULL}, + {"hilight_color", (getter)PyWindowItem_hilight_color_get, NULL, + PyWindowItem_hilight_color_doc, NULL}, + {NULL} +}; + +/* Methods */ +PyDoc_STRVAR(PyWindowItem_prnt_doc, + "prnt(str, level) -> None\n" + "\n" + "Print to window item\n" +); +static PyObject *PyWindowItem_prnt(PyWindowItem *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"str", "level", NULL}; + char *str; + int level = MSGLEVEL_CLIENTNOTICE; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|i", kwlist, &str, &level)) + return NULL; + + printtext_string(self->data->server, self->data->visible_name, level, str); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyWindowItem_command_doc, + "command(cmd) -> None\n" + "\n" + "Send command to window item\n" +); +static PyObject *PyWindowItem_command(PyWindowItem *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"cmd", NULL}; + char *cmd; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &cmd)) + return NULL; + + py_command(cmd, self->data->server, self->data); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyWindowItem_window_doc, + "window() -> Window object or None\n" + "\n" + "Return parent window for window item\n" +); +static PyObject *PyWindowItem_window(PyWindowItem *self, PyObject *args) +{ + WINDOW_REC *win; + + RET_NULL_IF_INVALID(self->data); + + win = window_item_window(self->data); + if (win) + return pywindow_new(win); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyWindowItem_change_server_doc, + "change_server(server) -> None\n" + "\n" + "Change server for window item\n" +); +static PyObject *PyWindowItem_change_server(PyWindowItem *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"server", NULL}; + PyObject *server = NULL; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, + &server)) + return NULL; + + if (!pyserver_check(server)) + return PyErr_Format(PyExc_TypeError, "arg must be server"); + + window_item_change_server(self->data, ((PyServer*)server)->data); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyWindowItem_is_active_doc, + "is_active() -> bool\n" + "\n" + "Returns true if window item is active\n" +); +static PyObject *PyWindowItem_is_active(PyWindowItem *self, PyObject *args) +{ + RET_NULL_IF_INVALID(self->data); + + return PyBool_FromLong(window_item_is_active(self->data)); +} + +PyDoc_STRVAR(PyWindowItem_set_active_doc, + "set_active() -> None\n" + "\n" + "Set window item active\n" +); +static PyObject *PyWindowItem_set_active(PyWindowItem *self, PyObject *args) +{ + RET_NULL_IF_INVALID(self->data); + + window_item_set_active(window_item_window(self->data), self->data); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyWindowItem_activity_doc, + "activity(data_level, hilight_color) -> None\n" + "\n" +); +static PyObject *PyWindowItem_activity(PyWindowItem *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"data_level", "hilight_color", NULL}; + int data_level = 0; + char *hilight_color = NULL; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "is", kwlist, + &data_level, &hilight_color)) + return NULL; + + window_item_activity(self->data, data_level, hilight_color); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyWindowItem_destroy_doc, + "destroy() -> None\n" + "\n" + "Destroy channel or query\n" +); +static PyObject *PyWindowItem_destroy(PyWindowItem *self, PyObject *args) +{ + RET_NULL_IF_INVALID(self->data); + + window_item_destroy(self->data); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyWindowItem_get_dcc_doc, + "get_dcc() -> DccChat object or None\n" + "\n" + "If item is a query of a =nick, return DCC chat record of nick\n" +); +static PyObject *PyWindowItem_get_dcc(PyWindowItem *self, PyObject *args) +{ + RET_NULL_IF_INVALID(self->data); + return py_irssi_new(self->data, 1); +} + +/* Methods for object */ +static PyMethodDef PyWindowItem_methods[] = { + {"prnt", (PyCFunction)PyWindowItem_prnt, METH_VARARGS | METH_KEYWORDS, + PyWindowItem_prnt_doc}, + {"command", (PyCFunction)PyWindowItem_command, METH_VARARGS | METH_KEYWORDS, + PyWindowItem_command_doc}, + {"window", (PyCFunction)PyWindowItem_window, METH_NOARGS, + PyWindowItem_window_doc}, + {"change_server", (PyCFunction)PyWindowItem_change_server, METH_VARARGS | METH_KEYWORDS, + PyWindowItem_change_server_doc}, + {"is_active", (PyCFunction)PyWindowItem_is_active, METH_NOARGS, + PyWindowItem_is_active_doc}, + {"set_active", (PyCFunction)PyWindowItem_set_active, METH_NOARGS, + PyWindowItem_set_active_doc}, + {"activity", (PyCFunction)PyWindowItem_activity, METH_VARARGS | METH_KEYWORDS, + PyWindowItem_activity_doc}, + {"destroy", (PyCFunction)PyWindowItem_destroy, METH_NOARGS, + PyWindowItem_destroy_doc}, + {"get_dcc", (PyCFunction)PyWindowItem_get_dcc, METH_NOARGS, + PyWindowItem_get_dcc_doc}, + {NULL} /* Sentinel */ +}; + +PyTypeObject PyWindowItemType = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "WindowItem", /*tp_name*/ + sizeof(PyWindowItem), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + 0, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + "PyWindowItem objects", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + PyWindowItem_methods, /* tp_methods */ + 0, /* tp_members */ + PyWindowItem_getseters, /* tp_getset */ + &PyIrssiChatBaseType, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + + +/* window item wrapper factory function */ +PyObject *pywindow_item_sub_new(void *witem, const char *name, PyTypeObject *subclass) +{ + WI_ITEM_REC *rec = witem; + PyWindowItem *pywitem = NULL; + PyObject *server; + + g_return_val_if_fail(witem != NULL, NULL); + + server = py_irssi_chat_new(rec->server, 1); + if (!server) + return NULL; + + pywitem = py_instp(PyWindowItem, subclass); + if (!pywitem) + return NULL; + + pywitem->data = witem; + pywitem->base_name = name; + pywitem->server = server; + + return (PyObject *)pywitem; +} + +PyObject *pywindow_item_new(void *witem) +{ + return pywindow_item_sub_new(witem, NULL, &PyWindowItemType); +} + +int window_item_object_init(void) +{ + g_return_val_if_fail(py_module != NULL, 0); + + if (PyType_Ready(&PyWindowItemType) < 0) + return 0; + + Py_INCREF(&PyWindowItemType); + PyModule_AddObject(py_module, "WindowItem", (PyObject *)&PyWindowItemType); + + return 1; +} diff --git a/src/objects/window-item-object.h b/src/objects/window-item-object.h new file mode 100644 index 0000000..e205ebe --- /dev/null +++ b/src/objects/window-item-object.h @@ -0,0 +1,26 @@ +#ifndef _WITEM_OBJECT_H_ +#define _WITEM_OBJECT_H_ + +#include +#include "base-objects.h" + +#define PyWindowItem_HEAD(type) \ + PyIrssi_HEAD(type) \ + PyObject *server; + +/* forward */ +struct _WI_ITEM_REC; + +typedef struct +{ + PyWindowItem_HEAD(struct _WI_ITEM_REC) +} PyWindowItem; + +extern PyTypeObject PyWindowItemType; + +int window_item_object_init(void); +PyObject *pywindow_item_sub_new(void *witem, const char *name, PyTypeObject *subclass); +PyObject *pywindow_item_new(void *witem); +#define pywindow_item_check(op) PyObject_TypeCheck(op, &PyWindowItemType) + +#endif diff --git a/src/objects/window-object.c b/src/objects/window-object.c new file mode 100644 index 0000000..d5aa475 --- /dev/null +++ b/src/objects/window-object.c @@ -0,0 +1,678 @@ +#include +#include "pyirssi_irc.h" +#include "pymodule.h" +#include "window-object.h" +#include "factory.h" +#include "pycore.h" +#include "pyutils.h" + +/* monitor "window destroyed" signal */ +static void window_cleanup(WINDOW_REC *win) +{ + PyWindow *pywindow = signal_get_user_data(); + + if (win == pywindow->data) + { + pywindow->data = NULL; + pywindow->cleanup_installed = 0; + signal_remove_data("window destroyed", window_cleanup, pywindow); + } +} + +static void PyWindow_dealloc(PyWindow *self) +{ + if (self->cleanup_installed) + signal_remove_data("window destroyed", window_cleanup, self); + + self->ob_type->tp_free((PyObject*)self); +} + +static PyObject *PyWindow_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyWindow *self; + + self = (PyWindow *)type->tp_alloc(type, 0); + if (!self) + return NULL; + + return (PyObject *)self; +} + +/* Getters */ +PyDoc_STRVAR(PyWindow_refnum_doc, + "Reference number" +); +static PyObject *PyWindow_refnum_get(PyWindow *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyInt_FromLong(self->data->refnum); +} + +PyDoc_STRVAR(PyWindow_name_doc, + "Name" +); +static PyObject *PyWindow_name_get(PyWindow *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->name); +} + +PyDoc_STRVAR(PyWindow_width_doc, + "Width" +); +static PyObject *PyWindow_width_get(PyWindow *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyInt_FromLong(self->data->width); +} + +PyDoc_STRVAR(PyWindow_height_doc, + "Height" +); +static PyObject *PyWindow_height_get(PyWindow *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyInt_FromLong(self->data->height); +} + +PyDoc_STRVAR(PyWindow_history_name_doc, + "Name of named historylist for this window" +); +static PyObject *PyWindow_history_name_get(PyWindow *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->history_name); +} + +PyDoc_STRVAR(PyWindow_active_doc, + "Active window item" +); +static PyObject *PyWindow_active_get(PyWindow *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return py_irssi_chat_new(self->data->active, 1); +} + +PyDoc_STRVAR(PyWindow_active_server_doc, + "Active server" +); +static PyObject *PyWindow_active_server_get(PyWindow *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return py_irssi_chat_new(self->data->active_server, 1); +} + +PyDoc_STRVAR(PyWindow_servertag_doc, + "active_server must be either None or have this same tag" + "(unless there's items in this window). This is used by" + "/WINDOW SERVER -sticky" +); +static PyObject *PyWindow_servertag_get(PyWindow *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->servertag); +} + +PyDoc_STRVAR(PyWindow_level_doc, + "Current window level" +); +static PyObject *PyWindow_level_get(PyWindow *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyInt_FromLong(self->data->level); +} + +PyDoc_STRVAR(PyWindow_sticky_refnum_doc, + "True if reference number is sticky" +); +static PyObject *PyWindow_sticky_refnum_get(PyWindow *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyBool_FromLong(self->data->sticky_refnum); +} + +PyDoc_STRVAR(PyWindow_data_level_doc, + "Current data level" +); +static PyObject *PyWindow_data_level_get(PyWindow *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyInt_FromLong(self->data->data_level); +} + +PyDoc_STRVAR(PyWindow_hilight_color_doc, + "Current activity hilight color" +); +static PyObject *PyWindow_hilight_color_get(PyWindow *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->hilight_color); +} + +PyDoc_STRVAR(PyWindow_last_timestamp_doc, + "Last time timestamp was written in window" +); +static PyObject *PyWindow_last_timestamp_get(PyWindow *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyLong_FromUnsignedLong(self->data->last_timestamp); +} + +PyDoc_STRVAR(PyWindow_last_line_doc, + "Last time text was written in window" +); +static PyObject *PyWindow_last_line_get(PyWindow *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + return PyLong_FromUnsignedLong(self->data->last_line); +} + +PyDoc_STRVAR(PyWindow_theme_name_doc, + "Active theme in window, None = default" +); +static PyObject *PyWindow_theme_name_get(PyWindow *self, void *closure) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(self->data->theme_name); +} + +/* specialized getters/setters */ +static PyGetSetDef PyWindow_getseters[] = { + {"refnum", (getter)PyWindow_refnum_get, NULL, + PyWindow_refnum_doc, NULL}, + {"name", (getter)PyWindow_name_get, NULL, + PyWindow_name_doc, NULL}, + {"width", (getter)PyWindow_width_get, NULL, + PyWindow_width_doc, NULL}, + {"height", (getter)PyWindow_height_get, NULL, + PyWindow_height_doc, NULL}, + {"history_name", (getter)PyWindow_history_name_get, NULL, + PyWindow_history_name_doc, NULL}, + {"active", (getter)PyWindow_active_get, NULL, + PyWindow_active_doc, NULL}, + {"active_server", (getter)PyWindow_active_server_get, NULL, + PyWindow_active_server_doc, NULL}, + {"servertag", (getter)PyWindow_servertag_get, NULL, + PyWindow_servertag_doc, NULL}, + {"level", (getter)PyWindow_level_get, NULL, + PyWindow_level_doc, NULL}, + {"sticky_refnum", (getter)PyWindow_sticky_refnum_get, NULL, + PyWindow_sticky_refnum_doc, NULL}, + {"data_level", (getter)PyWindow_data_level_get, NULL, + PyWindow_data_level_doc, NULL}, + {"hilight_color", (getter)PyWindow_hilight_color_get, NULL, + PyWindow_hilight_color_doc, NULL}, + {"last_timestamp", (getter)PyWindow_last_timestamp_get, NULL, + PyWindow_last_timestamp_doc, NULL}, + {"last_line", (getter)PyWindow_last_line_get, NULL, + PyWindow_last_line_doc, NULL}, + {"theme_name", (getter)PyWindow_theme_name_get, NULL, + PyWindow_theme_name_doc, NULL}, + {NULL} +}; + +/* Methods */ +PyDoc_STRVAR(PyWindow_items_doc, + "items() -> list of WindowItem objects\n" + "\n" + "Return a list of items in window.\n" +); +static PyObject *PyWindow_items(PyWindow *self, PyObject *args) +{ + RET_NULL_IF_INVALID(self->data); + return py_irssi_chatlist_new(self->data->items, 1); +} + +PyDoc_STRVAR(PyWindow_prnt_doc, + "prnt(str, level=MSGLEVEL_CLIENTNOTICE) -> None\n" + "\n" + "Print to window\n" +); +static PyObject *PyWindow_prnt(PyWindow *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"str", "level", NULL}; + char *str = ""; + int level = MSGLEVEL_CLIENTNOTICE; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|i", kwlist, + &str, &level)) + return NULL; + + printtext_string_window(self->data, level, str); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyWindow_command_doc, + "command(cmd) -> None\n" + "\n" + "Send command to window\n" +); +static PyObject *PyWindow_command(PyWindow *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"cmd", NULL}; + char *cmd = ""; + WINDOW_REC *old; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &cmd)) + return NULL; + + old = active_win; + active_win = self->data; + py_command(cmd, active_win->active_server, active_win->active); + if (g_slist_find(windows, old) != NULL) + active_win = old; + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyWindow_item_add_doc, + "item_add(item, automatic=False) -> None\n" + "\n" + "Add window item\n" +); +static PyObject *PyWindow_item_add(PyWindow *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"item", "automatic", NULL}; + PyObject *item = NULL; + int automatic = 0; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|i", kwlist, + &item, &automatic)) + return NULL; + + if (!pywindow_item_check(item)) + return PyErr_Format(PyExc_TypeError, "item must be window item"); + + window_item_add(self->data, ((PyWindowItem*)item)->data, automatic); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyWindow_item_remove_doc, + "item_remove(item) -> None\n" + "\n" + "Remove window item\n" +); +static PyObject *PyWindow_item_remove(PyWindow *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"item", NULL}; + PyObject *item = NULL; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, + &item)) + return NULL; + + if (!pywindow_item_check(item)) + return PyErr_Format(PyExc_TypeError, "item must be window item"); + + window_item_remove(((PyWindowItem*)item)->data); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyWindow_item_destroy_doc, + "item_destroy(item) -> None\n" + "\n" + "Destroy window item\n" +); +static PyObject *PyWindow_item_destroy(PyWindow *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"item", NULL}; + PyObject *item = NULL; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, + &item)) + return NULL; + + if (!pywindow_item_check(item)) + return PyErr_Format(PyExc_TypeError, "item must be window item"); + + window_item_destroy(((PyWindowItem*)item)->data); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyWindow_item_prev_doc, + "item_prev() -> None\n" + "\n" + "Change to previous window item\n" +); +static PyObject *PyWindow_item_prev(PyWindow *self, PyObject *args) +{ + RET_NULL_IF_INVALID(self->data); + + window_item_prev(self->data); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyWindow_item_next_doc, + "item_next() -> None\n" + "\n" + "Change to next window item\n" +); +static PyObject *PyWindow_item_next(PyWindow *self, PyObject *args) +{ + RET_NULL_IF_INVALID(self->data); + + window_item_next(self->data); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyWindow_destroy_doc, + "destroy() -> None\n" + "\n" + "Destroy the window.\n" +); +static PyObject *PyWindow_destroy(PyWindow *self, PyObject *args) +{ + RET_NULL_IF_INVALID(self->data); + + window_destroy(self->data); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyWindow_set_active_doc, + "set_active() -> None\n" + "\n" + "Set window active.\n" +); +static PyObject *PyWindow_set_active(PyWindow *self, PyObject *args) +{ + RET_NULL_IF_INVALID(self->data); + + window_set_active(self->data); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyWindow_change_server_doc, + "change_server(server) -> None\n" + "\n" + "Change server in window\n" +); +static PyObject *PyWindow_change_server(PyWindow *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"server", NULL}; + PyObject *server = NULL; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, + &server)) + return NULL; + + if (!pyserver_check(server)) + return PyErr_Format(PyExc_TypeError, "arg must be server"); + + window_change_server(self->data, ((PyServer*)server)->data); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyWindow_set_refnum_doc, + "set_refnum(refnum) -> None\n" + "\n" + "Set window refnum\n" +); +static PyObject *PyWindow_set_refnum(PyWindow *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"refnum", NULL}; + int refnum = 0; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, + &refnum)) + return NULL; + + window_set_refnum(self->data, refnum); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyWindow_set_name_doc, + "set_name(name) -> None\n" + "\n" + "Set window name\n" +); +static PyObject *PyWindow_set_name(PyWindow *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"name", NULL}; + char *name = ""; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &name)) + return NULL; + + window_set_name(self->data, name); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyWindow_set_history_doc, + "set_history(history) -> None\n" + "\n" + "Set window history\n" +); +static PyObject *PyWindow_set_history(PyWindow *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"history", NULL}; + char *history = ""; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &history)) + return NULL; + + window_set_history(self->data, history); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyWindow_set_level_doc, + "set_level(level) -> None\n" + "\n" + "Set window level\n" +); +static PyObject *PyWindow_set_level(PyWindow *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"level", NULL}; + int level = 0; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, + &level)) + return NULL; + + window_set_level(self->data, level); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyWindow_activity_doc, + "activity(data_level, hilight_color) -> None\n" + "\n" +); +static PyObject *PyWindow_activity(PyWindow *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"data_level", "hilight_color", NULL}; + int data_level = 0; + char *hilight_color = NULL; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "i|s", kwlist, + &data_level, &hilight_color)) + return NULL; + + window_activity(self->data, data_level, hilight_color); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(PyWindow_get_active_name_doc, + "get_active_name() -> str or None\n" + "\n" + "Return active item's name, or if none is active, window's name.\n" +); +static PyObject *PyWindow_get_active_name(PyWindow *self, PyObject *args) +{ + RET_NULL_IF_INVALID(self->data); + RET_AS_STRING_OR_NONE(window_get_active_name(self->data)); +} + +PyDoc_STRVAR(PyWindow_item_find_doc, + "item_find(server, name) -> WindowItem or None\n" + "\n" + "Find window item that matches best to given arguments\n" +); +static PyObject *PyWindow_item_find(PyWindow *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"server", "name", NULL}; + PyObject *server = NULL; + char *name = ""; + WI_ITEM_REC *witem; + + RET_NULL_IF_INVALID(self->data); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "Os", kwlist, + &server, &name)) + return NULL; + + if (!pyserver_check(server)) + return PyErr_Format(PyExc_TypeError, "arg 1 must be server"); + + witem = window_item_find_window(self->data, ((PyServer*)server)->data, name); + return py_irssi_chat_new(witem, 1); +} + +static PyMethodDef PyWindow_methods[] = { + {"items", (PyCFunction)PyWindow_items, METH_NOARGS, + PyWindow_items_doc}, + {"prnt", (PyCFunction)PyWindow_prnt, METH_VARARGS | METH_KEYWORDS, + PyWindow_prnt_doc}, + {"command", (PyCFunction)PyWindow_command, METH_VARARGS | METH_KEYWORDS, + PyWindow_command_doc}, + {"item_add", (PyCFunction)PyWindow_item_add, METH_VARARGS | METH_KEYWORDS, + PyWindow_item_add_doc}, + {"item_remove", (PyCFunction)PyWindow_item_remove, METH_VARARGS | METH_KEYWORDS, + PyWindow_item_remove_doc}, + {"item_destroy", (PyCFunction)PyWindow_item_destroy, METH_VARARGS | METH_KEYWORDS, + PyWindow_item_destroy_doc}, + {"item_prev", (PyCFunction)PyWindow_item_prev, METH_NOARGS, + PyWindow_item_prev_doc}, + {"item_next", (PyCFunction)PyWindow_item_next, METH_NOARGS, + PyWindow_item_next_doc}, + {"destroy", (PyCFunction)PyWindow_destroy, METH_NOARGS, + PyWindow_destroy_doc}, + {"set_active", (PyCFunction)PyWindow_set_active, METH_NOARGS, + PyWindow_set_active_doc}, + {"change_server", (PyCFunction)PyWindow_change_server, METH_VARARGS | METH_KEYWORDS, + PyWindow_change_server_doc}, + {"set_refnum", (PyCFunction)PyWindow_set_refnum, METH_VARARGS | METH_KEYWORDS, + PyWindow_set_refnum_doc}, + {"set_name", (PyCFunction)PyWindow_set_name, METH_VARARGS | METH_KEYWORDS, + PyWindow_set_name_doc}, + {"set_history", (PyCFunction)PyWindow_set_history, METH_VARARGS | METH_KEYWORDS, + PyWindow_set_history_doc}, + {"set_level", (PyCFunction)PyWindow_set_level, METH_VARARGS | METH_KEYWORDS, + PyWindow_set_level_doc}, + {"activity", (PyCFunction)PyWindow_activity, METH_VARARGS | METH_KEYWORDS, + PyWindow_activity_doc}, + {"get_active_name", (PyCFunction)PyWindow_get_active_name, METH_NOARGS, + PyWindow_get_active_name_doc}, + {"item_find", (PyCFunction)PyWindow_item_find, METH_VARARGS | METH_KEYWORDS, + PyWindow_item_find_doc}, + {NULL} /* Sentinel */ +}; + +PyTypeObject PyWindowType = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "Window", /*tp_name*/ + sizeof(PyWindow), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)PyWindow_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + "PyWindow objects", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + PyWindow_methods, /* tp_methods */ + 0, /* tp_members */ + PyWindow_getseters, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + PyWindow_new, /* tp_new */ +}; + + +/* window item wrapper factory function */ +PyObject *pywindow_new(void *win) +{ + PyWindow *pywindow; + + pywindow = py_inst(PyWindow, PyWindowType); + if (!pywindow) + return NULL; + + pywindow->data = win; + pywindow->cleanup_installed = 1; + signal_add_last_data("window destroyed", window_cleanup, pywindow); + + return (PyObject *)pywindow; +} + +int window_object_init(void) +{ + g_return_val_if_fail(py_module != NULL, 0); + + if (PyType_Ready(&PyWindowType) < 0) + return 0; + + Py_INCREF(&PyWindowType); + PyModule_AddObject(py_module, "Window", (PyObject *)&PyWindowType); + + return 1; +} diff --git a/src/objects/window-object.h b/src/objects/window-object.h new file mode 100644 index 0000000..b9860af --- /dev/null +++ b/src/objects/window-object.h @@ -0,0 +1,21 @@ +#ifndef _WINDOW_OBJECT_H_ +#define _WINDOW_OBJECT_H_ + +#include +#include "base-objects.h" + +/* forward */ +struct _WINDOW_REC; + +typedef struct +{ + PyIrssiFinal_HEAD(struct _WINDOW_REC) +} PyWindow; + +extern PyTypeObject PyWindowType; + +int window_object_init(void); +PyObject *pywindow_new(void *win); +#define pywindow_check(op) PyObject_TypeCheck(op, &PyWindowType) + +#endif diff --git a/src/pyconstants.h b/src/pyconstants.h new file mode 100644 index 0000000..f898ded --- /dev/null +++ b/src/pyconstants.h @@ -0,0 +1,7 @@ +#ifndef _PYCONSTANTS_H_ +#define _PYCONSTANTS_H_ + +void pyconstants_init(void); + +#endif + diff --git a/src/pycore.c b/src/pycore.c new file mode 100644 index 0000000..f9e4c3d --- /dev/null +++ b/src/pycore.c @@ -0,0 +1,160 @@ +#include +#include +#include +#include +#include "pyirssi.h" +#include "pycore.h" +#include "pyloader.h" +#include "pymodule.h" +#include "pysignals.h" +#include "pythemes.h" +#include "pystatusbar.h" +#include "pyconstants.h" +#include "factory.h" + +/*XXX: copy parse into utils */ +static void cmd_exec(const char *data) +{ + PyObject *co; + PyObject *ret; + PyObject *d; + PyObject *m; + char *cmd; + + if (!*data) + cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS); + + cmd = g_strconcat(data, "\n", NULL); + + m = PyImport_AddModule("__main__"); + if (!m) + goto error; + + d = PyModule_GetDict(m); + if (!d) + goto error; + + co = Py_CompileString(cmd, "", Py_single_input); + if (!co) + goto error; + + ret = PyEval_EvalCode((PyCodeObject *)co, d, d); + Py_DECREF(co); + Py_XDECREF(ret); + +error: + g_free(cmd); + if (PyErr_Occurred()) + PyErr_Print(); +} + +static void cmd_load(const char *data) +{ + char **argv; + + argv = g_strsplit(data, " ", -1); + if (*argv == NULL || **argv == '\0') + { + g_strfreev(argv); + cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS); + } + + pyloader_load_script_argv(argv); + g_strfreev(argv); +} + +static void cmd_unload(const char *data) +{ + void *free_arg; + char *script; + + if (!cmd_get_params(data, &free_arg, 1, &script)) + return; + + if (*script == '\0') + cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); + + pyloader_unload_script(script); + + cmd_params_free(free_arg); +} + +static void cmd_list() +{ + char buf[128]; + GSList *list; + + list = pyloader_list(); + + g_snprintf(buf, sizeof(buf), "%-15s %s", "Name", "File"); + + if (list != NULL) + { + GSList *node; + + printtext_string(NULL, NULL, MSGLEVEL_CLIENTCRAP, buf); + for (node = list; node != NULL; node = node->next) + { + PY_LIST_REC *item = node->data; + g_snprintf(buf, sizeof(buf), "%-15s %s", item->name, item->file); + + printtext_string(NULL, NULL, MSGLEVEL_CLIENTCRAP, buf); + } + } + else + printtext_string(NULL, NULL, MSGLEVEL_CLIENTERROR, "No python scripts are loaded"); + + pyloader_list_destroy(&list); +} + +#if 0 +/* why doesn't this get called? */ +static void intr_catch(int sig) +{ + printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "got sig %d", sig); + PyErr_SetInterrupt(); +} +#endif + +void irssi_python_init(void) +{ + Py_InitializeEx(0); + + pysignals_init(); + pystatusbar_init(); + if (!pyloader_init() || !pymodule_init() || !factory_init() || !pythemes_init()) + { + printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "Failed to load Python"); + return; + } + pyconstants_init(); + + /*PyImport_ImportModule("irssi_startup");*/ + /* Install the custom output handlers, import hook and reload function */ + /* XXX: handle import error */ + PyRun_SimpleString( + "import irssi_startup\n" + ); + + //assert(signal(SIGINT, intr_catch) != SIG_ERR); + + command_bind("pyload", NULL, (SIGNAL_FUNC) cmd_load); + command_bind("pyunload", NULL, (SIGNAL_FUNC) cmd_unload); + command_bind("pylist", NULL, (SIGNAL_FUNC) cmd_list); + command_bind("pyexec", NULL, (SIGNAL_FUNC) cmd_exec); + module_register(MODULE_NAME, "core"); +} + +void irssi_python_deinit(void) +{ + command_unbind("pyload", (SIGNAL_FUNC) cmd_load); + command_unbind("pyunload", (SIGNAL_FUNC) cmd_unload); + command_unbind("pylist", (SIGNAL_FUNC) cmd_list); + command_unbind("pyexec", (SIGNAL_FUNC) cmd_exec); + + pymodule_deinit(); + pyloader_deinit(); + pystatusbar_deinit(); + pysignals_deinit(); + Py_Finalize(); +} diff --git a/src/pycore.h b/src/pycore.h new file mode 100644 index 0000000..ae51924 --- /dev/null +++ b/src/pycore.h @@ -0,0 +1,7 @@ +#ifndef _PYCORE_H +#define _PYCORE_H + +void irssi_python_init(void); +void irssi_python_deinit(void); + +#endif diff --git a/src/pyirssi.h b/src/pyirssi.h new file mode 100644 index 0000000..3fc4223 --- /dev/null +++ b/src/pyirssi.h @@ -0,0 +1,32 @@ +#ifndef _PYIRSSI_H_ +#define _PYIRSSI_H_ + +#define MODULE_NAME "irssi_python" +#include "config.h" +#include "core.h" +#include "common.h" +#include "modules.h" +#include "commands.h" +#include "settings.h" +#include "printtext.h" +#include "statusbar.h" +#include "mainwindows.h" +#include "window-items.h" +#include "window-activity.h" +#include "levels.h" +#include "servers.h" +#include "chat-protocols.h" +#include "channels.h" +#include "queries.h" +#include "nicklist.h" +#include "chatnets.h" +#include "servers-reconnect.h" +#include "masks.h" +#include "misc.h" +#include "rawlog.h" +#include "log.h" +#include "ignore.h" +#include "fe-exec.h" +#include "pidwait.h" + +#endif diff --git a/src/pyirssi_irc.h b/src/pyirssi_irc.h new file mode 100644 index 0000000..0ebd617 --- /dev/null +++ b/src/pyirssi_irc.h @@ -0,0 +1,20 @@ +#ifndef _PY_IRSSI_IRC_H_ +#define _PY_IRSSI_IRC_H_ + +#include "pyirssi.h" +#include "irc.h" +#include "irc-servers.h" +#include "servers-redirect.h" +#include "irc-channels.h" +#include "ctcp.h" +#include "mode-lists.h" +#include "bans.h" +#include "dcc.h" +#include "dcc-get.h" +#include "dcc-send.h" +#include "dcc-chat.h" +#include "netsplit.h" +#include "notifylist.h" +#include "irc-masks.h" + +#endif diff --git a/src/pyloader.c b/src/pyloader.c new file mode 100644 index 0000000..a087827 --- /dev/null +++ b/src/pyloader.c @@ -0,0 +1,358 @@ +#include +#include +#include +#include "pyirssi.h" +#include "pyloader.h" +#include "pyutils.h" +#include "pyscript-object.h" + +/* List of loaded modules */ +static PyObject *script_modules; + +/* List of load paths for scripts */ +static GSList *script_paths = NULL; + +static PyObject *py_get_script(const char *name, int *id); +static int py_load_module(PyObject *module, const char *path); +static char *py_find_script(const char *name); + +/* Add to the list of script load paths */ +void pyloader_add_script_path(const char *path) +{ + PyObject *ppath = PySys_GetObject("path"); + if (ppath) + { + PyList_Append(ppath, PyString_FromString(path)); + script_paths = g_slist_append(script_paths, g_strdup(path)); + } +} + +/* Loads a file into a module; it is not inserted into sys.modules */ +static int py_load_module(PyObject *module, const char *path) +{ + PyObject *dict, *ret, *fp; + + if (PyModule_AddStringConstant(module, "__file__", (char *)path) < 0) + return 0; + + dict = PyModule_GetDict(module); + + if (PyDict_SetItemString(dict, "__builtins__", PyEval_GetBuiltins()) < 0) + return 0; + + /* Dont use the standard library to avoid incompatabilities with + the FILE structure and Python */ + fp = PyFile_FromString((char *)path, "r"); + if (!fp) + return 0; + + ret = PyRun_File(PyFile_AsFile(fp), path, Py_file_input, dict, dict); + Py_DECREF(fp); /* XXX: I assume that the file is closed when refs drop to zero? */ + if (!ret) + return 0; + + Py_DECREF(ret); + return 1; + +} + +/* looks up name in Irssi script directories + returns full path or NULL if not found */ +static char *py_find_script(const char *name) +{ + GSList *node; + char *fname; + char *path = NULL; + + //XXX: what if there's another ext? + if (!file_has_ext(name, "py")) + fname = g_strdup_printf("%s.py", name); + else + fname = (char *)name; + + /*XXX: use case insensitive path search? */ + for (node = script_paths; node && !path; node = node->next) + { + path = g_strdup_printf("%s/%s", (char *)node->data, fname); + + if (!g_file_test(path, G_FILE_TEST_IS_REGULAR)) + { + g_free(path); + path = NULL; + } + } + + if (fname != name) + g_free(fname); + + return path; +} + +/* Load a script manually using PyRun_File. + * This expects a null terminated array of strings + * (such as from g_strsplit) of the command line. + * The array needs at least one item + */ +int pyloader_load_script_argv(char **argv) +{ + PyObject *module = NULL, *script = NULL; + char *name = NULL, *path = NULL; + + if (py_get_script(argv[0], NULL) != NULL) + { + printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "script %s already loaded", argv[0]); + return 0; + } + + path = py_find_script(argv[0]); + if (!path) + { + printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "script %s does not exist", argv[0]); + return 0; + } + + name = file_get_filename(path); + module = PyModule_New(name); + g_free(name); + if (!module) + goto error; + + script = pyscript_new(module, argv); + Py_DECREF(module); + if (!script) + goto error; + + /* insert script obj into module dict, load file */ + if (PyModule_AddObject(module, "_script", script) != 0) + goto error; + + Py_INCREF(script); + + if (!py_load_module(module, path)) + goto error; + + if (PyList_Append(script_modules, script) != 0) + goto error; + + printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "loaded script %s", argv[0]); + /* PySys_WriteStdout("load %s, script -> 0x%x\n", argv[0], script); */ + + Py_DECREF(script); + g_free(path); + + return 1; + +error: + if (PyErr_Occurred()) + PyErr_Print(); + else + printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "error loading script %s", argv[0]); + + if (script) + { + /* make sure to clean up any formats, signals, commands that may have been + attached before the exception took place */ + pyscript_cleanup(script); + Py_DECREF(script); + } + + g_free(path); + + return 0; +} + +int pyloader_load_script(char *name) +{ + char *argv[2]; + + argv[0] = name; + argv[1] = NULL; + + return pyloader_load_script_argv(argv); +} + +static PyObject *py_get_script(const char *name, int *id) +{ + int i; + + g_return_val_if_fail(script_modules != NULL, NULL); + + for (i = 0; i < PyList_Size(script_modules); i++) + { + PyObject *script; + char *sname; + + script = PyList_GET_ITEM(script_modules, i); + sname = pyscript_get_name(script); + + if (sname && !strcmp(sname, name)) + { + if (id) + *id = i; + return script; + } + } + + return NULL; +} + +int pyloader_unload_script(const char *name) +{ + int id; + PyObject *script = py_get_script(name, &id); + + if (!script) + { + printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "%s is not loaded", name); + return 0; + } + + PySys_WriteStdout("unload %s, script -> 0x%x\n", name, script); + + pyscript_cleanup(script); + + if (PySequence_DelItem(script_modules, id) < 0) + { + PyErr_Print(); + printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "error unloading script %s", name); + return 0; + } + + /* Probably a good time to call the garbage collecter to clean up reference cycles */ + PyGC_Collect(); + printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "unloaded script %s", name); + + return 1; +} + +/* Traverse stack backwards to find the nearest valid _script object in globals */ +PyObject *pyloader_find_script_obj(void) +{ + PyFrameObject *frame; + + for (frame = PyEval_GetFrame(); frame != NULL; frame = frame->f_back) + { + g_return_val_if_fail(frame->f_globals != NULL, NULL); + PyObject *script = PyDict_GetItemString(frame->f_globals, "_script"); + if (script && pyscript_check(script)) + { + /* + PySys_WriteStdout("Found script at %s in %s, script -> 0x%x\n", + PyString_AS_STRING(frame->f_code->co_name), + PyString_AS_STRING(frame->f_code->co_filename), script); + */ + return script; + } + } + + return NULL; +} + +char *pyloader_find_script_name(void) +{ + PyObject *script = pyloader_find_script_obj(); + + if (!script) + return NULL; + + return pyscript_get_name(script); +} + +GSList *pyloader_list(void) +{ + int i; + GSList *list = NULL; + + g_return_val_if_fail(script_modules != NULL, NULL); + + for (i = 0; i < PyList_Size(script_modules); i++) + { + PyObject *scr; + char *name, *file; + + scr = PyList_GET_ITEM(script_modules, i); + name = pyscript_get_name(scr); + file = pyscript_get_filename(scr); + + if (name && file) + { + PY_LIST_REC *rec; + rec = g_new0(PY_LIST_REC, 1); + + rec->name = g_strdup(name); + rec->file = g_strdup(file); + list = g_slist_append(list, rec); + } + } + + return list; +} + +void pyloader_list_destroy(GSList **list) +{ + GSList *node; + + if (*list == NULL) + return; + + for (node = *list; node != NULL; node = node->next) + { + PY_LIST_REC *rec = node->data; + + g_free(rec->name); + g_free(rec->file); + g_free(rec); + } + + g_slist_free(*list); + + *list = NULL; +} + +int pyloader_init(void) +{ + char *pyhome; + + g_return_val_if_fail(script_paths == NULL, 0); + g_return_val_if_fail(script_modules == NULL, 0); + + script_modules = PyList_New(0); + if (!script_modules) + return 0; + + /* XXX: load autorun scripts here */ + /* Add script location to the load path (add more paths later) */ + pyhome = g_strdup_printf("%s/scripts", get_irssi_dir()); + pyloader_add_script_path(pyhome); + g_free(pyhome); + + return 1; +} + +static void py_clear_scripts() +{ + int i; + + for (i = 0; i < PyList_Size(script_modules); i++) + { + PyObject *scr = PyList_GET_ITEM(script_modules, i); + pyscript_cleanup(scr); + } + + Py_DECREF(script_modules); +} + +void pyloader_deinit(void) +{ + GSList *node; + + g_return_if_fail(script_paths != NULL); + g_return_if_fail(script_modules != NULL); + + for (node = script_paths; node != NULL; node = node->next) + g_free(node->data); + g_slist_free(script_paths); + script_paths = NULL; + + py_clear_scripts(); +} diff --git a/src/pyloader.h b/src/pyloader.h new file mode 100644 index 0000000..b7befd3 --- /dev/null +++ b/src/pyloader.h @@ -0,0 +1,23 @@ +#ifndef _PYLOADER_H_ +#define _PYLOADER_H_ + +typedef struct +{ + char *name; + char *file; +} PY_LIST_REC; + +void pyloader_add_script_path(const char *path); +int pyloader_load_script_argv(char **argv); +int pyloader_load_script(char *name); +int pyloader_unload_script(const char *name); +PyObject *pyloader_find_script_obj(void); +char *pyloader_find_script_name(void); + +GSList *pyloader_list(void); +void pyloader_list_destroy(GSList **list); + +int pyloader_init(void); +void pyloader_deinit(void); + +#endif diff --git a/src/pymodule.c b/src/pymodule.c new file mode 100644 index 0000000..7795c1a --- /dev/null +++ b/src/pymodule.c @@ -0,0 +1,1909 @@ +#include +#include "pymodule.h" +#include "pyirssi_irc.h" +#include "factory.h" +#include "pyutils.h" +#include "pysignals.h" +#include "pyloader.h" +#include "pythemes.h" +#include "pystatusbar.h" + +/* + * This module is some what different than the Perl's. + * Script specific operations are handled by the Script object + * instead of by a function in this module. command_bind, + * signal_add, etc require data to be saved about the script + * for cleanup purposes, so I moved those functions to the script + * object. + */ + +/* Main embedded module */ +PyObject *py_module = NULL; + +/* Module functions */ +/*XXX: prefix PY to avoid ambiguity with py_command function */ +PyDoc_STRVAR(PY_command_doc, + "command(cmd) -> None\n" + "\n" + "Execute command\n" +); +static PyObject *PY_command(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"cmd", NULL}; + char *cmd = ""; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &cmd)) + return NULL; + + py_command(cmd, NULL, NULL); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(py_prnt_doc, + "prnt(text, msglvl=MSGLEVEL_CLIENTNOTICE) -> None\n" + "\n" + "print output\n" +); +/*XXX: print is a python keyword, so abbreviate it */ +static PyObject *py_prnt(PyObject *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = {"text", "msglvl", NULL}; + int msglvl = MSGLEVEL_CLIENTNOTICE; + char *text = NULL; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:prnt", kwlist, + &text, &msglvl)) + return NULL; + + printtext_string(NULL, NULL, msglvl, text); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(py_get_script_doc, + "get_script() -> Script object\n" + "\n" + "Find current Irssi script object\n" +); +static PyObject *py_get_script(PyObject *self, PyObject *args) +{ + PyObject *ret = pyloader_find_script_obj(); + + /* XXX: type check */ + + if (!ret) + PyErr_SetString(PyExc_RuntimeError, "unable to find script object"); + else + Py_INCREF(ret); + + return ret; +} + +PyDoc_STRVAR(py_chatnet_find_doc, + "chatnet_find(name) -> Chatnet object or None\n" + "\n" + "Find chat network with name\n" +); +static PyObject *py_chatnet_find(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"name", NULL}; + char *name = ""; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &name)) + return NULL; + + return py_irssi_chat_new(chatnet_find(name), 1); +} + +PyDoc_STRVAR(py_chatnets_doc, + "chatnets() -> list of Chatnet objects\n" + "\n" + "Return a list of all chatnets\n" +); +static PyObject *py_chatnets(PyObject *self, PyObject *args) +{ + return py_irssi_chatlist_new(chatnets, 1); +} + +PyDoc_STRVAR(py_reconnects_doc, + "reconnects() -> list of Reconnect objects\n" + "\n" + "Return a list of all reconnects\n" +); +static PyObject *py_reconnects(PyObject *self, PyObject *args) +{ + return py_irssi_objlist_new(reconnects, 1, (InitFunc)pyreconnect_new); +} + +PyDoc_STRVAR(py_servers_doc, + "servers() -> list of Server objects\n" + "\n" + "Return a list of all servers\n" +); +static PyObject *py_servers(PyObject *self, PyObject *args) +{ + return py_irssi_chatlist_new(servers, 1); +} + +PyDoc_STRVAR(py_channels_doc, + "channels() -> list of Channel objects\n" + "\n" + "Return channel list\n" +); +static PyObject *py_channels(PyObject *self, PyObject *args) +{ + return py_irssi_chatlist_new(channels, 1); +} + +PyDoc_STRVAR(py_channel_find_doc, + "channel_find(name) -> Channel object or None\n" + "\n" + "Find channel from any server\n" +); +static PyObject *py_channel_find(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"name", NULL}; + char *name = ""; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &name)) + return NULL; + + return py_irssi_chat_new(channel_find(NULL, name), 1); +} + +PyDoc_STRVAR(py_windows_doc, + "windows() -> list of Window objects\n" + "\n" + "Get a list of all windows\n" +); +static PyObject *py_windows(PyObject *self, PyObject *args) +{ + return py_irssi_objlist_new(windows, 1, (InitFunc)pywindow_new); +} + +PyDoc_STRVAR(py_active_win_doc, + "active_win() -> Window object\n" + "\n" + "Return active window\n" +); +static PyObject *py_active_win(PyObject *self, PyObject *args) +{ + if (active_win) + return pywindow_new(active_win); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(py_active_server_doc, + "active_server() -> Server object or None\n" + "\n" + "Return active server\n" +); +static PyObject *py_active_server(PyObject *self, PyObject *args) +{ + if (active_win) + return py_irssi_chat_new(active_win->active_server, 1); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(py_window_find_name_doc, + "window_find_name(name) -> Window object or None\n" + "\n" + "Find window with name\n" +); +static PyObject *py_window_find_name(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"name", NULL}; + char *name = ""; + WINDOW_REC *win; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &name)) + return NULL; + + win = window_find_name(name); + if (win) + return pywindow_new(win); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(py_window_find_refnum_doc, + "window_find_refnum(refnum) -> Window object or None\n" + "\n" + "Find window with reference number\n" +); +static PyObject *py_window_find_refnum(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"refnum", NULL}; + int refnum = 0; + WINDOW_REC *win; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, + &refnum)) + return NULL; + + win = window_find_refnum(refnum); + if (win) + return pywindow_new(win); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(py_window_refnum_prev_doc, + "window_refnum_prev(refnum, wrap) -> int\n" + "\n" + "Return refnum for window that's previous in window list\n" +); +static PyObject *py_window_refnum_prev(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"refnum", "wrap", NULL}; + int refnum = 0; + int wrap = 0; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwlist, + &refnum, &wrap)) + return NULL; + + return PyInt_FromLong(window_refnum_prev(refnum, wrap)); +} + +PyDoc_STRVAR(py_window_refnum_next_doc, + "window_refnum_next(refnum, wrap) -> int\n" + "\n" + "Return refnum for window that's next in window list\n" +); +static PyObject *py_window_refnum_next(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"refnum", "wrap", NULL}; + int refnum = 0; + int wrap = 0; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwlist, + &refnum, &wrap)) + return NULL; + + return PyInt_FromLong(window_refnum_next(refnum, wrap)); +} + +PyDoc_STRVAR(py_windows_refnum_last_doc, + "windows_refnum_last() -> int\n" + "\n" + "Return refnum for last window.\n" +); +static PyObject *py_windows_refnum_last(PyObject *self, PyObject *args) +{ + return PyInt_FromLong(windows_refnum_last()); +} + +PyDoc_STRVAR(py_window_find_level_doc, + "window_find_level(level) -> Window object or None\n" + "\n" + "Find window with level.\n" +); +static PyObject *py_window_find_level(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"level", NULL}; + int level = 0; + WINDOW_REC *win; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, + &level)) + return NULL; + + win = window_find_level(NULL, level); + if (win) + return pywindow_new(win); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(py_window_find_item_doc, + "window_find_item(name) -> Window object or None\n" + "\n" + "Find window which contains window item with specified name.\n" +); +static PyObject *py_window_find_item(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"name", NULL}; + char *name = ""; + WINDOW_REC *win; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &name)) + return NULL; + + win = window_find_item(NULL, name); + if (win) + return pywindow_new(win); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(py_window_find_closest_doc, + "window_find_closest(name, level) -> Window object or None\n" + "\n" + "Find window that matches best to given arguments. `name' can be either\n" + "window name or name of one of the window items.\n" +); +static PyObject *py_window_find_closest(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"name", "level", NULL}; + char *name = ""; + int level = 0; + WINDOW_REC *win; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "si", kwlist, + &name, &level)) + return NULL; + + win = window_find_closest(NULL, name, level); + if (win) + return pywindow_new(win); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(py_window_item_find_doc, + "window_item_find(name) -> WindowItem object or None\n" + "\n" + "Find window item that matches best to given arguments.\n" +); +static PyObject *py_window_item_find(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"name", NULL}; + char *name = ""; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &name)) + return NULL; + + return py_irssi_chat_new(window_item_find(NULL, name), 1); +} + +/*XXX: this could be __init__ for Window */ +PyDoc_STRVAR(py_window_create_doc, + "window_create(item=None, automatic=False) -> Window object\n" + "\n" + "Create a new window\n" +); +static PyObject *py_window_create(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"item", "automatic", NULL}; + PyObject *item = NULL; + int automatic = 0; + WI_ITEM_REC *witem = NULL; + WINDOW_REC *win; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oi", kwlist, + &item, &automatic)) + return NULL; + + if (item) + { + if (pywindow_item_check(item)) + { + witem = ((PyWindowItem*)item)->data; + if (!witem) + return PyErr_Format(PyExc_TypeError, "invalid window item"); + else if (witem->server != NULL) + return PyErr_Format(PyExc_TypeError, "window item already assigned to window"); + } + else if (item == Py_None) + ; + else + return PyErr_Format(PyExc_TypeError, "item must be window item or None"); + } + + win = window_create(witem, automatic); + if (win) + return pywindow_new(win); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(py_server_find_tag_doc, + "server_find_tag(tag) -> Server object or None\n" + "\n" + "Find server with tag\n" +); +static PyObject *py_server_find_tag(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"tag", NULL}; + char *tag = ""; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &tag)) + return NULL; + + return py_irssi_chat_new(server_find_tag(tag), 1); +} + +PyDoc_STRVAR(py_server_find_chatnet_doc, + "server_find_chatnet(chatnet) -> Server object or None\n" + "\n" + "Find first server that is in chatnet\n" +); +static PyObject *py_server_find_chatnet(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"chatnet", NULL}; + char *chatnet = ""; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &chatnet)) + return NULL; + + return py_irssi_chat_new(server_find_chatnet(chatnet), 1); +} + +PyDoc_STRVAR(py_queries_doc, + "queries() -> list of Query objects\n" + "\n" + "Return a list of open queries.\n" +); +static PyObject *py_queries(PyObject *self, PyObject *args) +{ + return py_irssi_chatlist_new(queries, 1); +} + +PyDoc_STRVAR(py_query_find_doc, + "query_find(nick) -> Query object or None\n" + "\n" + "Find a query from any server.\n" +); +static PyObject *py_query_find(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"nick", NULL}; + char *nick = ""; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &nick)) + return NULL; + + return py_irssi_chat_new(query_find(NULL, nick), 1); +} + +PyDoc_STRVAR(py_mask_match_doc, + "mask_match(mask, nick, user, host) -> bool\n" + "\n" + "Return true if mask matches nick!user@host\n" +); +static PyObject *py_mask_match(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"mask", "nick", "user", "host", NULL}; + char *mask = ""; + char *nick = ""; + char *user = ""; + char *host = ""; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "ssss", kwlist, + &mask, &nick, &user, &host)) + return NULL; + + return PyBool_FromLong(mask_match(NULL, mask, nick, user, host)); +} + +PyDoc_STRVAR(py_mask_match_address_doc, + "mask_match_address(mask, nick, address) -> bool\n" + "\n" + "Return True if mask matches nick!address\n" +); +static PyObject *py_mask_match_address(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"mask", "nick", "address", NULL}; + char *mask = ""; + char *nick = ""; + char *address = ""; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "sss", kwlist, + &mask, &nick, &address)) + return NULL; + + return PyBool_FromLong(mask_match_address(NULL, mask, nick, address)); +} + +PyDoc_STRVAR(py_masks_match_doc, + "masks_match(masks, nick, address) -> bool\n" + "\n" + "Return True if any mask in the masks (string separated by spaces)\n" + "matches nick!address\n" +); +static PyObject *py_masks_match(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"masks", "nick", "address", NULL}; + char *masks = ""; + char *nick = ""; + char *address = ""; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "sss", kwlist, + &masks, &nick, &address)) + return NULL; + + return PyBool_FromLong(masks_match(NULL, masks, nick, address)); +} + +PyDoc_STRVAR(py_rawlog_set_size_doc, + "rawlog_set_size(lines) -> None\n" + "\n" + "Set the default rawlog size for new rawlogs.\n" +); +static PyObject *py_rawlog_set_size(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"lines", NULL}; + int lines = 0; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, + &lines)) + return NULL; + + rawlog_set_size(lines); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(py_logs_doc, + "logs() -> list of Log objects\n" + "\n" + "Return list of logs.\n" +); +static PyObject *py_logs(PyObject *self, PyObject *args) +{ + return py_irssi_objlist_new(logs, 1, (InitFunc)pylog_new); +} + +PyDoc_STRVAR(py_log_find_doc, + "log_find(fname) -> Log object or None\n" + "\n" + "Find log by file name.\n" +); +static PyObject *py_log_find(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"fname", NULL}; + char *fname = ""; + LOG_REC *log; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &fname)) + return NULL; + + log = log_find(fname); + if (log) + return pylog_new(log); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(py_ignores_doc, + "ignores() -> list of Ignore objects\n" + "\n" + "Return a list of ignore entries\n" +); +static PyObject *py_ignores(PyObject *self, PyObject *args) +{ + return py_irssi_objlist_new(ignores, 1, (InitFunc)pyignore_new); +} + +PyDoc_STRVAR(py_ignore_check_doc, + "ignore_check(nick, host, channel, text, level) -> bool\n" + "\n" + "Return True if ignore matches\n" +); +static PyObject *py_ignore_check(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"nick", "host", "channel", "text", "level", NULL}; + char *nick = ""; + char *host = ""; + char *channel = ""; + char *text = ""; + int level = 0; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "ssssi", kwlist, + &nick, &host, &channel, &text, &level)) + return NULL; + + return PyBool_FromLong(ignore_check(NULL, nick, host, channel, text, level)); +} + +PyDoc_STRVAR(py_dccs_doc, + "dccs() -> list of Dcc objects\n" + "\n" + "Return list of active DCCs\n" +); +static PyObject *py_dccs(PyObject *self, PyObject *args) +{ + return py_irssi_list_new(dcc_conns, 1); +} + +PyDoc_STRVAR(py_dcc_register_type_doc, + "dcc_register_type(type) -> None\n" + "\n" + "???\n" +); +static PyObject *py_dcc_register_type(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"type", NULL}; + char *type = ""; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &type)) + return NULL; + + dcc_register_type(type); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(py_dcc_unregister_type_doc, + "dcc_unregister_type(type) -> None\n" + "\n" + "???\n" +); +static PyObject *py_dcc_unregister_type(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"type", NULL}; + char *type = ""; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &type)) + return NULL; + + dcc_unregister_type(type); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(py_dcc_find_request_latest_doc, + "dcc_find_request_latest(type) -> Dcc object or None\n" + "\n" + "???\n" +); +static PyObject *py_dcc_find_request_latest(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"type", NULL}; + int type = 0; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, + &type)) + return NULL; + + return py_irssi_new(dcc_find_request_latest(type), 1); +} + +PyDoc_STRVAR(py_dcc_find_request_doc, + "dcc_find_request(type, nick, arg) -> Dcc object or None\n" + "\n" + "???\n" +); +static PyObject *py_dcc_find_request(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"type", "nick", "arg", NULL}; + int type = 0; + char *nick = ""; + char *arg = ""; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "iss", kwlist, + &type, &nick, &arg)) + return NULL; + + return py_irssi_new(dcc_find_request(type, nick, arg), 1); +} + +PyDoc_STRVAR(py_dcc_chat_find_id_doc, + "dcc_chat_find_id(id) -> Dcc object or None\n" + "\n" + "???\n" +); +static PyObject *py_dcc_chat_find_id(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"id", NULL}; + char *id = ""; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &id)) + return NULL; + + return py_irssi_new(dcc_chat_find_id(id), 1); +} + +PyDoc_STRVAR(py_dcc_str2type_doc, + "dcc_str2type(type) -> int\n" + "\n" + "???\n" +); +static PyObject *py_dcc_str2type(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"type", NULL}; + char *type = ""; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &type)) + return NULL; + + return PyInt_FromLong(dcc_str2type(type)); +} + +PyDoc_STRVAR(py_dcc_type2str_doc, + "dcc_type2str(type) -> str or None\n" + "\n" + "???\n" +); +static PyObject *py_dcc_type2str(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"type", NULL}; + int type = 0; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, + &type)) + return NULL; + + RET_AS_STRING_OR_NONE(dcc_type2str(type)); +} + +PyDoc_STRVAR(py_dcc_get_download_path_doc, + "dcc_get_download(fname) -> str\n" + "\n" + "???\n" +); +static PyObject *py_dcc_get_download_path(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"fname", NULL}; + char *fname = ""; + char *path; + PyObject *pypath; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &fname)) + return NULL; + + path = dcc_get_download_path(fname); + if (!path) + Py_RETURN_NONE; /*XXX: how to handle? */ + + pypath = PyString_FromString(path); + g_free(path); + + return pypath; +} + +PyDoc_STRVAR(py_notifies_doc, + "notifies() -> list of Notifylist objects\n" + "\n" + "Return list of notifies\n" +); +static PyObject *py_notifies(PyObject *self, PyObject *args) +{ + return py_irssi_objlist_new(notifies, 1, (InitFunc)pynotifylist_new); +} + +PyDoc_STRVAR(py_notifylist_add_doc, + "notifylist_add(mask, ircnets=None, away_check=0, idle_time_check=0) -> Notifylist object\n" + "\n" + "Add new item to notify list\n" +); +static PyObject *py_notifylist_add(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"mask", "ircnets", "away_check", "idle_check_time", NULL}; + char *mask = ""; + char *ircnets = NULL; + int away_check = 0; + int idle_check_time = 0; + NOTIFYLIST_REC *rec; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|zii", kwlist, + &mask, &ircnets, &away_check, &idle_check_time)) + return NULL; + + rec = notifylist_add(mask, ircnets, away_check, idle_check_time); + if (rec) + return pynotifylist_new(rec); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(py_notifylist_remove_doc, + "notifylist_remove(mask) -> None\n" + "\n" + "Remove notify item from notify list\n" +); +static PyObject *py_notifylist_remove(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"mask", NULL}; + char *mask = ""; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &mask)) + return NULL; + + notifylist_remove(mask); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(py_notifylist_ison_doc, + "notifylist_ison(nick, serverlist=\"\") -> IrcServer object\n" + "\n" + "Check if nick is in IRC. serverlist is a space separated list of server tags.\n" + "If it's empty string, all servers will be checked\n" +); +static PyObject *py_notifylist_ison(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"nick", "serverlist", NULL}; + char *nick = ""; + char *serverlist = ""; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|s", kwlist, + &nick, &serverlist)) + return NULL; + + return py_irssi_chat_new(notifylist_ison(nick, serverlist), 1); +} + +PyDoc_STRVAR(py_notifylist_find_doc, + "notifylist_find(mask, ircnet=None) -> Notifylist object\n" + "\n" + "Find notify\n" +); +static PyObject *py_notifylist_find(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"mask", "ircnet", NULL}; + char *mask = ""; + char *ircnet = NULL; + NOTIFYLIST_REC *rec; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|z", kwlist, + &mask, &ircnet)) + return NULL; + + rec = notifylist_find(mask, ircnet); + if (rec) + return pynotifylist_new(rec); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(py_commands_doc, + "commands() -> list of Command objects\n" + "\n" + "Return a list of all commands.\n" +); +static PyObject *py_commands(PyObject *self, PyObject *args) +{ + return py_irssi_objlist_new(commands, 1, (InitFunc)pycommand_new); +} + +PyDoc_STRVAR(py_level2bits_doc, + "level2bits(level) -> long\n" + "\n" + "Level string -> number\n" +); +static PyObject *py_level2bits(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"level", NULL}; + char *level = ""; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &level)) + return NULL; + + return PyLong_FromUnsignedLong(level2bits(level)); +} + +PyDoc_STRVAR(py_bits2level_doc, + "bits2level(bits) -> str\n" + "\n" + "Level number -> string\n" +); +static PyObject *py_bits2level(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"bits", NULL}; + unsigned bits; + char *str; + PyObject *ret; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "I", kwlist, + &bits)) + return NULL; + + str = bits2level(bits); + if (str) + { + ret = PyString_FromString(str); + g_free(str); + return ret; + } + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(py_combine_level_doc, + "combine_level(level, str) -> long\n" + "\n" + "Combine level number to level string ('+level -level'). Return new level number.\n" +); +static PyObject *py_combine_level(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"level", "str", NULL}; + int level = 0; + char *str = ""; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "is", kwlist, + &level, &str)) + return NULL; + + return PyLong_FromUnsignedLong(combine_level(level, str)); +} + +PyDoc_STRVAR(py_signal_emit_doc, + "signal_emit(signal, *args) -> None\n" + "\n" + "Emit an Irssi signal with up to 6 arguments\n" +); +static PyObject *py_signal_emit(PyObject *self, PyObject *args) +{ + PyObject *pysig; + PyObject *sigargs; + char *name; + int ret; + + if (PyTuple_Size(args) < 1) + return PyErr_Format(PyExc_TypeError, "signal name required"); + + if (PyTuple_Size(args) > SIGNAL_MAX_ARGUMENTS+1) + return PyErr_Format(PyExc_TypeError, + "no more than %d arguments for signal accepted", SIGNAL_MAX_ARGUMENTS); + + pysig = PyTuple_GET_ITEM(args, 0); + if (!PyString_Check(pysig)) + return PyErr_Format(PyExc_TypeError, "signal must be string"); + + name = PyString_AsString(pysig); + if (!name) + return NULL; + + sigargs = PySequence_GetSlice(args, 1, PyTuple_Size(args)); + if (!sigargs) + return NULL; + + ret = pysignals_emit(name, sigargs); + Py_DECREF(sigargs); + if (!ret) + return NULL; + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(py_signal_continue_doc, + "signal_continue(*args) -> None\n" + "\n" + "Continue (reemit?) the current Irssi signal with up to 6 arguments\n" +); +static PyObject *py_signal_continue(PyObject *self, PyObject *args) +{ + if (PyTuple_Size(args) > SIGNAL_MAX_ARGUMENTS) + return PyErr_Format(PyExc_TypeError, + "no more than %d arguments for signal accepted", SIGNAL_MAX_ARGUMENTS); + + if (!pysignals_continue(args)) + return NULL; + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(py_signal_stop_doc, + "signal_stop() -> None\n" + "\n" + "Stop the signal that's currently being emitted.\n" +); +static PyObject *py_signal_stop(PyObject *self, PyObject *args) +{ + signal_stop(); + Py_RETURN_NONE; +} + +PyDoc_STRVAR(py_signal_stop_by_name_doc, + "signal_stop_by_name(signal) -> None\n" + "\n" + "Stop the signal, 'signal', thats currently being emitted by name\n" +); +static PyObject *py_signal_stop_by_name(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"signal", NULL}; + char *signal = ""; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &signal)) + return NULL; + + signal_stop_by_name(signal); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(py_signal_get_emitted_doc, + "signal_get_emmited() -> signal name string\n" + "\n" + "Get name of current signal\n" +); +static PyObject *py_signal_get_emitted(PyObject *self, PyObject *args) +{ + RET_AS_STRING_OR_NONE(signal_get_emitted()); +} + +PyDoc_STRVAR(py_signal_get_emitted_id_doc, + "signal_get_emmited_id() -> signal id int\n" + "\n" + "Get id of current signal\n" +); +static PyObject *py_signal_get_emitted_id(PyObject *self, PyObject *args) +{ + return PyInt_FromLong(signal_get_emitted_id()); +} + +PyDoc_STRVAR(py_settings_get_str_doc, + "settings_get_str(key) -> str\n" + "\n" + "Get value for setting.\n" +); +static PyObject *py_settings_get_str(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"key", NULL}; + char *key = ""; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &key)) + return NULL; + + RET_AS_STRING_OR_NONE(settings_get_str(key)); +} + +PyDoc_STRVAR(py_settings_get_int_doc, + "settings_get_int(key) -> int\n" + "\n" + "Get value for setting." +); +static PyObject *py_settings_get_int(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"key", NULL}; + char *key = ""; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &key)) + return NULL; + + return PyInt_FromLong(settings_get_int(key)); +} + +PyDoc_STRVAR(py_settings_get_bool_doc, + "settings_get_bool(key) -> bool\n" + "\n" + "Get value for setting.\n" +); +static PyObject *py_settings_get_bool(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"key", NULL}; + char *key = ""; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &key)) + return NULL; + + return PyBool_FromLong(settings_get_bool(key)); +} + +PyDoc_STRVAR(py_settings_get_time_doc, + "settings_get_time(key) -> long\n" + "\n" + "Get value for setting.\n" +); +static PyObject *py_settings_get_time(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"key", NULL}; + char *key = ""; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &key)) + return NULL; + + return PyLong_FromLong(settings_get_time(key)); +} + +PyDoc_STRVAR(py_settings_get_level_doc, + "settings_get_level(key) -> int\n" + "\n" + "Get value for setting.\n" +); +static PyObject *py_settings_get_level(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"key", NULL}; + char *key = ""; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &key)) + return NULL; + + return PyInt_FromLong(settings_get_level(key)); +} + +PyDoc_STRVAR(py_settings_get_size_doc, + "settings_get_size(key) -> long\n" + "\n" + "Get value for setting.\n" +); +static PyObject *py_settings_get_size(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"key", NULL}; + char *key = ""; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &key)) + return NULL; + + return PyLong_FromLong(settings_get_size(key)); +} + +PyDoc_STRVAR(py_settings_set_str_doc, + "settings_set_str(key, value) -> None\n" + "\n" + "Set string value for setting\n" +); +static PyObject *py_settings_set_str(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"key", "value", NULL}; + char *key = ""; + char *value = ""; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss", kwlist, + &key, &value)) + return NULL; + + settings_set_str(key, value); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(py_settings_set_int_doc, + "settings_set_int(key, value) -> None\n" + "\n" + "Set int value for setting" +); +static PyObject *py_settings_set_int(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"key", "value", NULL}; + char *key = ""; + int value = 0; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "si", kwlist, + &key, &value)) + return NULL; + + settings_set_int(key, value); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(py_settings_set_bool_doc, + "settings_set_bool(key, value) -> None\n" + "\n" + "Set bool value for setting\n" +); +static PyObject *py_settings_set_bool(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"key", "value", NULL}; + char *key = ""; + int value = 0; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "si", kwlist, + &key, &value)) + return NULL; + + settings_set_bool(key, value); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(py_settings_set_time_doc, + "settings_set_time(key, value) -> bool\n" + "\n" + "Set string value for setting\n" +); +static PyObject *py_settings_set_time(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"key", "value", NULL}; + char *key = ""; + char *value = ""; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss", kwlist, + &key, &value)) + return NULL; + + return PyBool_FromLong(settings_set_time(key, value)); +} + +PyDoc_STRVAR(py_settings_set_level_doc, + "settings_set_level(key, value) -> bool\n" + "\n" + "Set string value for setting\n" +); +static PyObject *py_settings_set_level(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"key", "value", NULL}; + char *key = ""; + char *value = ""; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss", kwlist, + &key, &value)) + return NULL; + + return PyBool_FromLong(settings_set_level(key, value)); +} + +PyDoc_STRVAR(py_settings_set_size_doc, + "settings_set_size(key, value) -> bool\n" + "\n" + "Set string value for setting\n" +); +static PyObject *py_settings_set_size(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"key", "value", NULL}; + char *key = ""; + char *value = ""; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss", kwlist, + &key, &value)) + return NULL; + + return PyBool_FromLong(settings_set_size(key, value)); +} + +PyDoc_STRVAR(py_pidwait_add_doc, + "pidwait_add(pid) -> None\n" + "\n" + "Add pid to wait list\n" +); +static PyObject *py_pidwait_add(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"pid", NULL}; + int pid = 0; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, + &pid)) + return NULL; + + pidwait_add(pid); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(py_pidwait_remove_doc, + "pidwait_remove(pid) -> None\n" + "\n" + "Remove pid from wait list\n" +); +static PyObject *py_pidwait_remove(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"pid", NULL}; + int pid = 0; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, + &pid)) + return NULL; + + pidwait_remove(pid); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(py_format_get_length_doc, + "format_get_length(str) -> int length\n" +); +static PyObject *py_format_get_length(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"str", NULL}; + char *str = ""; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &str)) + return NULL; + + return PyInt_FromLong(format_get_length(str)); +} + +PyDoc_STRVAR(py_format_real_length_doc, + "format_real_length(str, len) -> int length\n" +); +static PyObject *py_format_real_length(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"str", "len", NULL}; + char *str = ""; + int len; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "sl", kwlist, + &str, &len)) + return NULL; + + return PyInt_FromLong(format_real_length(str, len)); +} + +PyDoc_STRVAR(py_strip_codes_doc, + "strip_codes(input) -> str\n" +); +static PyObject *py_strip_codes(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"input", NULL}; + char *input = ""; + char *ret; + PyObject *pyret; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &input)) + return NULL; + + ret = strip_codes(input); + if (ret) + { + pyret = PyString_FromString(ret); + g_free(ret); + return pyret; + } + + Py_RETURN_NONE; +} + +#if 0 +PyDoc_STRVAR(py_format_get_text_doc, + "format_get_text(textdest, module, formatnum, ...) -> str\n" + "\n" + "Return a substituted format string from module and formatnum.\n" + "module is a string.\n" + "\n" + "Example:\n" + "TODO\n" +); +static PyObject *py_format_get_text(PyObject *self, PyObject *varargs) +{ + PyTextDest *textdest = NULL; + char *module = ""; + unsigned int formatnum = 0; + PyObject *args = NULL, *pycharargs = NULL; + THEME_REC *theme; + MODULE_THEME_REC *modtheme; + char **charargs = NULL; + char *ret; + int i; + + args = PySequence_GetSlice(varargs, 0, 3); + if (!args) + goto error; + + pycharargs = PySequence_GetSlice(varargs, 3, PyTuple_Size(varargs)); + if (!pycharargs) + goto error; + + if (!PyArg_ParseTuple(args, "OsI", + &textdest, &module, &formatnum)) + goto error; + + if (!pytextdest_check((PyObject *)textdest)) + { + PyErr_Format(PyExc_TypeError, "arg 1 must be TextDest"); + goto error; + } + + /* Bleh, check that formatnum is within range */ + theme = window_get_theme(textdest->data->window); + + /* FIXME: how to boundscheck formatnum ?? */ + + /* size + 1 for terminating NULL ptr */ + charargs = g_new0(char *, PyTuple_Size(pycharargs) + 1); + + for (i = 0; i < PyTuple_Size(pycharargs); i++) + { + PyObject *obj = PyTuple_GET_ITEM(pycharargs, i); + char *str; + + if (!PyString_Check(obj)) + { + PyErr_Format(PyExc_TypeError, + "non string in string argument list (arg %d)", + i + 4); + goto error; + } + + str = PyString_AsString(obj); + if (!str) + goto error; + + charargs[i] = str; + } + + /* return string, or if string is NULL, return None */ + ret = format_get_text_theme_charargs(theme, module, DATA(textdest), formatnum, charargs); + Py_DECREF(args); + Py_DECREF(pycharargs); + g_free(charargs); + + if (ret) + { + PyObject *pyret; + + pyret = PyString_FromString(ret); + g_free(ret); + + return pyret; + } + + Py_RETURN_NONE; + +error: + Py_XDECREF(args); + Py_XDECREF(pycharargs); + g_free(charargs); + + return NULL; +} +#endif + +PyDoc_STRVAR(py_themes_reload_doc, + "themes_reload() -> None\n" +); +static PyObject *py_themes_reload(PyObject *self, PyObject *args) +{ + themes_reload(); + Py_RETURN_NONE; +} + +PyDoc_STRVAR(py_current_theme_doc, + "current_theme() -> Theme object\n" +); +static PyObject *py_current_theme(PyObject *self, PyObject *args) +{ + if (current_theme) + return pytheme_new(current_theme); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(py_statusbar_items_redraw_doc, + "statusbar_items_redraw(name) -> None\n" +); +static PyObject *py_statusbar_items_redraw(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"name", NULL}; + char *name = ""; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &name)) + return NULL; + + statusbar_items_redraw(name); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(py_statusbars_recreate_items_doc, + "statusbars_recreate_items() -> None" +); +static PyObject *py_statusbars_recreate_items(PyObject *self, PyObject *args) +{ + statusbars_recreate_items(); + + Py_RETURN_NONE; +} + +/* XXX: we can unregister any statusbar items, not just the ones from this script */ +PyDoc_STRVAR(py_statusbar_item_unregister_doc, + "statusbar_item_unregister(name) -> None" +); +static PyObject *py_statusbar_item_unregister(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"name", NULL}; + char *name = ""; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, + &name)) + return NULL; + + pystatusbar_item_unregister(name); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(py_active_mainwin_doc, + "active_mainwin() -> MainWindow object\n" + "\n" + "return active main window\n" +); +static PyObject *py_active_mainwin(PyObject *self, PyObject *args) +{ + if (!active_mainwin) + Py_RETURN_NONE; + + return pymain_window_new(active_mainwin); +} + +PyDoc_STRVAR(py_mainwindows_doc, + "mainwindows() -> list of MainWindow objects\n" + "\n" + "return a list of mainwindows\n" +); +static PyObject *py_mainwindows(PyObject *self, PyObject *args) +{ + return py_irssi_objlist_new(mainwindows, 1, (InitFunc)pymain_window_new); +} + +/* expect a list of tuples [('str', 0), ...] */ +static GSList *py_register_conv(PyObject *list) +{ + int i; + GSList *ret = NULL; + + if (list == Py_None) + return NULL; + + if (!PyList_Check(list)) + { + PyErr_Format(PyExc_TypeError, "expect a list of tuples of string and int"); + return NULL; + } + + for (i = 0; i < PyList_Size(list); i++) + { + char *key; + int val; + PyObject *tup = PyList_GET_ITEM(list, i); + + if (!PyTuple_Check(tup) || !PyArg_ParseTuple(tup, "si", &key, &val)) + { + if (!PyErr_Occurred() || PyErr_ExceptionMatches(PyExc_TypeError)) + { + PyErr_Clear(); + PyErr_SetString(PyExc_TypeError, "expect a list of tuples of string and int"); + } + + /* return the list so far; caller will clear it on error */ + break; + } + + ret = g_slist_append(ret, g_strdup(key)); + ret = g_slist_append(ret, GINT_TO_POINTER(val)); + } + + return ret; +} + +PyDoc_STRVAR(py_server_redirect_register_doc, + "server_redirect_register(command, stop, start=None, opt=None, remote=False, timeout=0) -> None\n" + "\n" + "Register new redirection command. By default irssi has already\n" + "registered at least: whois, whowas, who, list, ison, userhost, ping,\n" + "\"mode channel\" (/MODE #channel), \"mode b\" (/MODE #channel b), \"mode e\"\n" + "and \"mode I\".\n" + "\n" + "`command' specifies the name of the command to register, it doesn't\n" + "have to be a real command name, but something you just specify to\n" + "Server.redirect_event() when using this redirection.\n" + "\n" + "`start', `stop', `opt' - lists of ('event', argpos) tuples.\n" + "List of events that start and stop this redirection.\n" + "Start event list may be empty, but there must be at least one\n" + "stop event. Optional events are checked only if they are received\n" + "immediately after one of the stop-events. `argpos' specifies the\n" + "word number in event string which is compared to wanted argument,\n" + "-1 = don't compare, TRUE always.\n" + "\n" + "`remote' specifies if the command is by default a remote command\n" + "(eg. sent to another server). Server.redirect_event() may override this.\n" + "\n" + "`timeout' - If remote is TRUE, specifies how many seconds to wait for\n" + "reply before aborting.\n" + "\n" + "Example (already done by irssi):\n" + "\n" + "server_redirect_register('mode channel',\n" + " start = None,\n" + " stop = [ \n" + " ('event 324', 1), # MODE-reply\n" + " ('event 403', 1), # no such channel\n" + " ('event 442', 1), # \"you're not on that channel\"\n" + " ('event 479', 1) # \"Cannot join channel (illegal name)\"\n" + " ], \n" + " opt = [ \n" + " ('event 329', 1) # Channel create time\n" + " ] \n" + ")\n" +); +static PyObject *py_server_redirect_register(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"command", "stop", "start", "opt", "remote", "timeout", NULL}; + char *command = ""; + int remote = 0; + int timeout = 0; + PyObject *start = NULL; + PyObject *stop = NULL; + PyObject *opt = NULL; + GSList *node; + GSList *gstart = NULL; + GSList *gstop = NULL; + GSList *gopt = NULL; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "sO|OOii", kwlist, + &command, &stop, &start, &opt, &remote, &timeout)) + return NULL; + + gstart = py_register_conv(start); + if (PyErr_Occurred()) + goto error; + + gstop = py_register_conv(stop); + if (!gstop || PyErr_Occurred()) + { + if (!PyErr_Occurred()) + PyErr_SetString(PyExc_TypeError, "stop list must be provided"); + + goto error; + } + + gopt = py_register_conv(opt); + if (PyErr_Occurred()) + goto error; + + server_redirect_register_list(command, remote, timeout, gstart, gstop, gopt); + + Py_RETURN_NONE; + +error: + /* clean up all lists */ + for (node = gstart; node; node = node->next->next) + g_free(node->data); + for (node = gstop; node; node = node->next->next) + g_free(node->data); + for (node = gopt; node; node = node->next->next) + g_free(node->data); + + g_slist_free(gstart); + g_slist_free(gstop); + g_slist_free(gopt); + + return NULL; + +} + +PyDoc_STRVAR(py_command_runsub_doc, + "command_runsub(cmd, data, server=None, item=None) -> None\n" + "\n" + "Run subcommands for `cmd'. First word in `data' is parsed as\n" + "subcommand. `server' is Server object for current\n" + "WindowItem `item'.\n" + "\n" + "Call command_runsub in handler function for `cmd' and bind\n" + "with command_bind(\"`cmd' `subcmd'\", subcmdfunc[, category]);\n" +); +static PyObject *py_command_runsub(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"cmd", "data", "server", "item", NULL}; + char *cmd = ""; + char *data = ""; + PyObject *pserver = Py_None; + PyObject *pitem = Py_None; + SERVER_REC *server = NULL; + WI_ITEM_REC *item = NULL; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss|OO", kwlist, + &cmd, &data, &pserver, &pitem)) + return NULL; + + if (pserver != Py_None && !pyserver_check(pserver)) + return PyErr_Format(PyExc_TypeError, "server must be a server"); + + if (pitem != Py_None && !pywindow_item_check(pitem)) + return PyErr_Format(PyExc_TypeError, "item must be a window item"); + + if (pserver != Py_None) + server = DATA(pserver); + + if (pitem != Py_None) + item = DATA(pitem); + + command_runsub(cmd, data, server, item); + + Py_RETURN_NONE; +} + +static PyMethodDef ModuleMethods[] = { + {"prnt", (PyCFunction)py_prnt, METH_VARARGS | METH_KEYWORDS, + py_prnt_doc}, + {"get_script", (PyCFunction)py_get_script, METH_NOARGS, + py_get_script_doc}, + {"chatnet_find", (PyCFunction)py_chatnet_find, METH_VARARGS | METH_KEYWORDS, + py_chatnet_find_doc}, + {"chatnets", (PyCFunction)py_chatnets, METH_NOARGS, + py_chatnets_doc}, + {"reconnects", (PyCFunction)py_reconnects, METH_NOARGS, + py_reconnects_doc}, + {"servers", (PyCFunction)py_servers, METH_NOARGS, + py_servers_doc}, + {"windows", (PyCFunction)py_windows, METH_NOARGS, + py_windows_doc}, + {"active_win", (PyCFunction)py_active_win, METH_NOARGS, + py_active_win_doc}, + {"active_server", (PyCFunction)py_active_server, METH_NOARGS, + py_active_server_doc}, + {"window_find_name", (PyCFunction)py_window_find_name, METH_VARARGS | METH_KEYWORDS, + py_window_find_name_doc}, + {"window_find_refnum", (PyCFunction)py_window_find_refnum, METH_VARARGS | METH_KEYWORDS, + py_window_find_refnum_doc}, + {"window_refnum_prev", (PyCFunction)py_window_refnum_prev, METH_VARARGS | METH_KEYWORDS, + py_window_refnum_prev_doc}, + {"window_refnum_next", (PyCFunction)py_window_refnum_next, METH_VARARGS | METH_KEYWORDS, + py_window_refnum_next_doc}, + {"windows_refnum_last", (PyCFunction)py_windows_refnum_last, METH_NOARGS, + py_windows_refnum_last_doc}, + {"window_find_level", (PyCFunction)py_window_find_level, METH_VARARGS | METH_KEYWORDS, + py_window_find_level_doc}, + {"window_find_item", (PyCFunction)py_window_find_item, METH_VARARGS | METH_KEYWORDS, + py_window_find_item_doc}, + {"window_find_closest", (PyCFunction)py_window_find_closest, METH_VARARGS | METH_KEYWORDS, + py_window_find_closest_doc}, + {"window_item_find", (PyCFunction)py_window_item_find, METH_VARARGS | METH_KEYWORDS, + py_window_item_find_doc}, + {"window_create", (PyCFunction)py_window_create, METH_VARARGS | METH_KEYWORDS, + py_window_create_doc}, + {"server_find_tag", (PyCFunction)py_server_find_tag, METH_VARARGS | METH_KEYWORDS, + py_server_find_tag_doc}, + {"server_find_chatnet", (PyCFunction)py_server_find_chatnet, METH_VARARGS | METH_KEYWORDS, + py_server_find_chatnet_doc}, + {"command", (PyCFunction)PY_command, METH_VARARGS | METH_KEYWORDS, + PY_command_doc}, + {"channels", (PyCFunction)py_channels, METH_NOARGS, + py_channels_doc}, + {"channel_find", (PyCFunction)py_channel_find, METH_VARARGS | METH_KEYWORDS, + py_channel_find_doc}, + {"query_find", (PyCFunction)py_query_find, METH_VARARGS | METH_KEYWORDS, + py_query_find_doc}, + {"queries", (PyCFunction)py_queries, METH_NOARGS, + py_queries_doc}, + {"mask_match", (PyCFunction)py_mask_match, METH_VARARGS | METH_KEYWORDS, + py_mask_match_doc}, + {"mask_match_address", (PyCFunction)py_mask_match_address, METH_VARARGS | METH_KEYWORDS, + py_mask_match_address_doc}, + {"masks_match", (PyCFunction)py_masks_match, METH_VARARGS | METH_KEYWORDS, + py_masks_match_doc}, + {"rawlog_set_size", (PyCFunction)py_rawlog_set_size, METH_VARARGS | METH_KEYWORDS, + py_rawlog_set_size_doc}, + {"logs", (PyCFunction)py_logs, METH_NOARGS, + py_logs_doc}, + {"log_find", (PyCFunction)py_log_find, METH_VARARGS | METH_KEYWORDS, + py_log_find_doc}, + {"ignores", (PyCFunction)py_ignores, METH_NOARGS, + py_ignores_doc}, + {"ignore_check", (PyCFunction)py_ignore_check, METH_VARARGS | METH_KEYWORDS, + py_ignore_check_doc}, + {"dccs", (PyCFunction)py_dccs, METH_NOARGS, + py_dccs_doc}, + {"dcc_register_type", (PyCFunction)py_dcc_register_type, METH_VARARGS | METH_KEYWORDS, + py_dcc_register_type_doc}, + {"dcc_unregister_type", (PyCFunction)py_dcc_unregister_type, METH_VARARGS | METH_KEYWORDS, + py_dcc_unregister_type_doc}, + {"dcc_find_request_latest", (PyCFunction)py_dcc_find_request_latest, METH_VARARGS | METH_KEYWORDS, + py_dcc_find_request_latest_doc}, + {"dcc_find_request", (PyCFunction)py_dcc_find_request, METH_VARARGS | METH_KEYWORDS, + py_dcc_find_request_doc}, + {"dcc_chat_find_id", (PyCFunction)py_dcc_chat_find_id, METH_VARARGS | METH_KEYWORDS, + py_dcc_chat_find_id_doc}, + {"dcc_str2type", (PyCFunction)py_dcc_str2type, METH_VARARGS | METH_KEYWORDS, + py_dcc_str2type_doc}, + {"dcc_type2str", (PyCFunction)py_dcc_type2str, METH_VARARGS | METH_KEYWORDS, + py_dcc_type2str_doc}, + {"dcc_get_download_path", (PyCFunction)py_dcc_get_download_path, METH_VARARGS | METH_KEYWORDS, + py_dcc_get_download_path_doc}, + {"notifies", (PyCFunction)py_notifies, METH_NOARGS, + py_notifies_doc}, + {"notifylist_add", (PyCFunction)py_notifylist_add, METH_VARARGS | METH_KEYWORDS, + py_notifylist_add_doc}, + {"notifylist_remove", (PyCFunction)py_notifylist_remove, METH_VARARGS | METH_KEYWORDS, + py_notifylist_remove_doc}, + {"notifylist_ison", (PyCFunction)py_notifylist_ison, METH_VARARGS | METH_KEYWORDS, + py_notifylist_ison_doc}, + {"notifylist_find", (PyCFunction)py_notifylist_find, METH_VARARGS | METH_KEYWORDS, + py_notifylist_find_doc}, + {"commands", (PyCFunction)py_commands, METH_NOARGS, + py_commands_doc}, + {"level2bits", (PyCFunction)py_level2bits, METH_VARARGS | METH_KEYWORDS, + py_level2bits_doc}, + {"bits2level", (PyCFunction)py_bits2level, METH_VARARGS | METH_KEYWORDS, + py_bits2level_doc}, + {"combine_level", (PyCFunction)py_combine_level, METH_VARARGS | METH_KEYWORDS, + py_combine_level_doc}, + {"signal_emit", (PyCFunction)py_signal_emit, METH_VARARGS, + py_signal_emit_doc}, + {"signal_stop", (PyCFunction)py_signal_stop, METH_NOARGS, + py_signal_stop_doc}, + {"signal_stop_by_name", (PyCFunction)py_signal_stop_by_name, METH_VARARGS | METH_KEYWORDS, + py_signal_stop_by_name_doc}, + {"signal_get_emitted", (PyCFunction)py_signal_get_emitted, METH_NOARGS, + py_signal_get_emitted_doc}, + {"signal_get_emitted_id", (PyCFunction)py_signal_get_emitted_id, METH_NOARGS, + py_signal_get_emitted_id_doc}, + {"signal_continue", (PyCFunction)py_signal_continue, METH_VARARGS, + py_signal_continue_doc}, + {"settings_get_str", (PyCFunction)py_settings_get_str, METH_VARARGS | METH_KEYWORDS, + py_settings_get_str_doc}, + {"settings_get_int", (PyCFunction)py_settings_get_int, METH_VARARGS | METH_KEYWORDS, + py_settings_get_int_doc}, + {"settings_get_bool", (PyCFunction)py_settings_get_bool, METH_VARARGS | METH_KEYWORDS, + py_settings_get_bool_doc}, + {"settings_get_time", (PyCFunction)py_settings_get_time, METH_VARARGS | METH_KEYWORDS, + py_settings_get_time_doc}, + {"settings_get_level", (PyCFunction)py_settings_get_level, METH_VARARGS | METH_KEYWORDS, + py_settings_get_level_doc}, + {"settings_get_size", (PyCFunction)py_settings_get_size, METH_VARARGS | METH_KEYWORDS, + py_settings_get_size_doc}, + {"settings_set_str", (PyCFunction)py_settings_set_str, METH_VARARGS | METH_KEYWORDS, + py_settings_set_str_doc}, + {"settings_set_int", (PyCFunction)py_settings_set_int, METH_VARARGS | METH_KEYWORDS, + py_settings_set_int_doc}, + {"settings_set_bool", (PyCFunction)py_settings_set_bool, METH_VARARGS | METH_KEYWORDS, + py_settings_set_bool_doc}, + {"settings_set_time", (PyCFunction)py_settings_set_time, METH_VARARGS | METH_KEYWORDS, + py_settings_set_time_doc}, + {"settings_set_level", (PyCFunction)py_settings_set_level, METH_VARARGS | METH_KEYWORDS, + py_settings_set_level_doc}, + {"settings_set_size", (PyCFunction)py_settings_set_size, METH_VARARGS | METH_KEYWORDS, + py_settings_set_size_doc}, + {"pidwait_add", (PyCFunction)py_pidwait_add, METH_VARARGS | METH_KEYWORDS, + py_pidwait_add_doc}, + {"pidwait_remove", (PyCFunction)py_pidwait_remove, METH_VARARGS | METH_KEYWORDS, + py_pidwait_remove_doc}, + {"format_get_length", (PyCFunction)py_format_get_length, METH_VARARGS | METH_KEYWORDS, + py_format_get_length_doc}, + {"format_real_length", (PyCFunction)py_format_real_length, METH_VARARGS | METH_KEYWORDS, + py_format_real_length_doc}, + {"strip_codes", (PyCFunction)py_strip_codes, METH_VARARGS | METH_KEYWORDS, + py_strip_codes_doc}, + /*{"format_get_text", (PyCFunction)py_format_get_text, METH_VARARGS, + py_format_get_text_doc},*/ + {"themes_reload", (PyCFunction)py_themes_reload, METH_NOARGS, + py_themes_reload_doc}, + {"current_theme", (PyCFunction)py_current_theme, METH_NOARGS, + py_current_theme_doc}, + {"statusbar_items_redraw", (PyCFunction)py_statusbar_items_redraw, METH_VARARGS | METH_KEYWORDS, + py_statusbar_items_redraw_doc}, + {"statusbars_recreate_items", (PyCFunction)py_statusbars_recreate_items, METH_NOARGS, + py_statusbars_recreate_items_doc}, + {"statusbar_item_unregister", (PyCFunction)py_statusbar_item_unregister, METH_VARARGS | METH_KEYWORDS, + py_statusbar_item_unregister_doc}, + {"active_mainwin", (PyCFunction)py_active_mainwin, METH_NOARGS, + py_active_mainwin_doc}, + {"mainwindows", (PyCFunction)py_mainwindows, METH_NOARGS, + py_mainwindows_doc}, + {"server_redirect_register", (PyCFunction)py_server_redirect_register, METH_VARARGS | METH_KEYWORDS, + py_server_redirect_register_doc}, + {"command_runsub", (PyCFunction)py_command_runsub, METH_VARARGS | METH_KEYWORDS, + py_command_runsub_doc}, + {NULL, NULL, 0, NULL} /* Sentinel */ +}; + +int pymodule_init(void) +{ + g_return_val_if_fail(py_module == NULL, 0); + + py_module = Py_InitModule("_irssi", ModuleMethods); + if (!py_module) + return 0; + + return 1; +} + +void pymodule_deinit(void) +{ + g_return_if_fail(py_module != NULL); + + Py_DECREF(py_module); + py_module = NULL; +} diff --git a/src/pymodule.h b/src/pymodule.h new file mode 100644 index 0000000..242eecf --- /dev/null +++ b/src/pymodule.h @@ -0,0 +1,11 @@ +#ifndef _PY_MODULE_H_ +#define _PY_MODULE_H_ + +#include + +/* This is global so that type objects and such can be easily attached */ +extern PyObject *py_module; +int pymodule_init(void); +void pymodule_deinit(void); + +#endif diff --git a/src/pysigmap.h b/src/pysigmap.h new file mode 100644 index 0000000..c34fbf7 --- /dev/null +++ b/src/pysigmap.h @@ -0,0 +1,188 @@ +/* Include in your C module */ +static PY_SIGNAL_SPEC_REC py_sigmap[] = { + {"gui exit", "", 0, 0, 0}, + {"gui dialog", "ss", 0, 0, 0}, + {"send command", "sSW", 0, 0, 0}, + {"chat protocol created", "?", 0, 0, 0}, + {"chat protocol updated", "?", 0, 0, 0}, + {"chat protocol destroyed", "?", 0, 0, 0}, + {"channel created", "Ci", 0, 0, 0}, + {"channel destroyed", "C", 0, 0, 0}, + {"chatnet created", "c", 0, 0, 0}, + {"chatnet destroyed", "c", 0, 0, 0}, + {"commandlist new", "o", 0, 0, 0}, + {"commandlist remove", "o", 0, 0, 0}, + {"error command", "is", 0, 0, 0}, + {"send command", "sSW", 0, 0, 0}, + {"send text", "sSW", 0, 0, 0}, + {"command ", "sSW", 0, 0, 1}, + {"default command", "sSW", 0, 0, 0}, + {"ignore created", "g", 0, 0, 0}, + {"ignore destroyed", "g", 0, 0, 0}, + {"ignore changed", "g", 0, 0, 0}, + {"log new", "l", 0, 0, 0}, + {"log remove", "l", 0, 0, 0}, + {"log create failed", "l", 0, 0, 0}, + {"log locked", "l", 0, 0, 0}, + {"log started", "l", 0, 0, 0}, + {"log stopped", "l", 0, 0, 0}, + {"log rotated", "l", 0, 0, 0}, + {"log written", "ls", 0, 0, 0}, + {"module loaded", "??", 0, 0, 0}, + {"module unloaded", "??", 0, 0, 0}, + {"module error", "isss", 0, 0, 0}, + {"nicklist new", "Cn", 0, 0, 0}, + {"nicklist remove", "Cn", 0, 0, 0}, + {"nicklist changed", "Cns", 0, 0, 0}, + {"nicklist host changed", "Cn", 0, 0, 0}, + {"nicklist gone changed", "Cn", 0, 0, 0}, + {"nicklist serverop changed", "Cn", 0, 0, 0}, + {"pidwait", "ii", 0, 0, 0}, + {"query created", "qi", 0, 0, 0}, + {"query destroyed", "q", 0, 0, 0}, + {"query nick changed", "qs", 0, 0, 0}, + {"window item name changed", "W", 0, 0, 0}, + {"query address changed", "q", 0, 0, 0}, + {"query server changed", "qS", 0, 0, 0}, + {"rawlog", "ls", 0, 0, 0}, + {"server looking", "S", 0, 0, 0}, + {"server connected", "S", 0, 0, 0}, + {"server connecting", "Su", 0, 0, 0}, + {"server connect failed", "S", 0, 0, 0}, + {"server disconnected", "S", 0, 0, 0}, + {"server quit", "Ss", 0, 0, 0}, + {"server sendmsg", "Sssi", 0, 0, 0}, + {"setup changed", "", 0, 0, 0}, + {"setup reread", "s", 0, 0, 0}, + {"setup saved", "si", 0, 0, 0}, + {"ban type changed", "s", 0, 0, 0}, + {"channel joined", "C", 0, 0, 0}, + {"channel wholist", "C", 0, 0, 0}, + {"channel sync", "C", 0, 0, 0}, + {"channel topic changed", "C", 0, 0, 0}, + {"ctcp msg", "Sssss", 0, 0, 0}, + {"ctcp msg ", "Sssss", 0, 0, 1}, + {"default ctcp msg", "Sssss", 0, 0, 0}, + {"ctcp reply", "Sssss", 0, 0, 0}, + {"ctcp reply ", "Sssss", 0, 0, 1}, + {"default ctcp reply", "Sssss", 0, 0, 0}, + {"ctcp action", "Sssss", 0, 0, 0}, + {"awaylog show", "lii", 0, 0, 0}, + {"server nick changed", "S", 0, 0, 0}, + {"event connected", "S", 0, 0, 0}, + {"server event", "Ssss", 0, 0, 0}, + {"event ", "Ssss", 0, 0, 1}, + {"default event", "Ssss", 0, 0, 0}, + {"whois default event", "Ssss", 0, 0, 0}, + {"server incoming", "Ss", 0, 0, 0}, + {"redir ", "Ssss", 0, 0, 1}, + {"server lag", "S", 0, 0, 0}, + {"server lag disconnect", "S", 0, 0, 0}, + {"massjoin", "CL", 0, 0, 0}, + {"ban new", "Cb", 0, 0, 0}, + {"ban remove", "Cbs", 0, 0, 0}, + {"channel mode changed", "Cs", 0, 0, 0}, + {"nick mode changed", "Cnsss", 0, 0, 0}, + {"user mode changed", "Ss", 0, 0, 0}, + {"away mode changed", "S", 0, 0, 0}, + {"netsplit server new", "SS", 0, 0, 0}, + {"netsplit server remove", "SS", 0, 0, 0}, + {"netsplit new", "N", 0, 0, 0}, + {"netsplit remove", "N", 0, 0, 0}, + {"dcc ctcp ", "sd", 0, 0, 1}, + {"default dcc ctcp", "sd", 0, 0, 0}, + {"dcc unknown ctcp", "sss", 0, 0, 0}, + {"dcc reply ", "sd", 0, 0, 1}, + {"default dcc reply", "sd", 0, 0, 0}, + {"dcc unknown reply", "sss", 0, 0, 0}, + {"dcc chat message", "ds", 0, 0, 0}, + {"dcc created", "d", 0, 0, 0}, + {"dcc destroyed", "d", 0, 0, 0}, + {"dcc connected", "d", 0, 0, 0}, + {"dcc rejecting", "d", 0, 0, 0}, + {"dcc closed", "d", 0, 0, 0}, + {"dcc request", "ds", 0, 0, 0}, + {"dcc request send", "d", 0, 0, 0}, + {"dcc chat message", "ds", 0, 0, 0}, + {"dcc transfer update", "d", 0, 0, 0}, + {"dcc get receive", "d", 0, 0, 0}, + {"dcc error connect", "d", 0, 0, 0}, + {"dcc error file create", "ds", 0, 0, 0}, + {"dcc error file open", "ssi", 0, 0, 0}, + {"dcc error get not found", "s", 0, 0, 0}, + {"dcc error send exists", "ss", 0, 0, 0}, + {"dcc error unknown type", "s", 0, 0, 0}, + {"dcc error close not found", "sss", 0, 0, 0}, + {"autoignore new", "S?", 0, 0, 0}, + {"autoignore remove", "S?", 0, 0, 0}, + {"flood", "Sssis", 0, 0, 0}, + {"notifylist new", "O", 0, 0, 0}, + {"notifylist remove", "O", 0, 0, 0}, + {"notifylist joined", "Ssssss", 0, 0, 0}, + {"notifylist away changed", "Ssssss", 0, 0, 0}, + {"notifylist unidle", "Ssssss", 0, 0, 0}, + {"notifylist left", "Ssssss", 0, 0, 0}, + {"proxy client connected", "?", 0, 0, 0}, + {"proxy client disconnected", "?", 0, 0, 0}, + {"gui print text", "wiiist", 0, 0, 0}, + {"gui print text finished", "w", 0, 0, 0}, + {"complete word", "?wssi", 0, 0, 0}, + {"irssi init read settings", "", 0, 0, 0}, + {"exec new", "p", 0, 0, 0}, + {"exec remove", "pi", 0, 0, 0}, + {"exec input", "ps", 0, 0, 0}, + {"message public", "Sssss", 0, 0, 0}, + {"message private", "Ssss", 0, 0, 0}, + {"message own_public", "Sss", 0, 0, 0}, + {"message own_private", "Ssss", 0, 0, 0}, + {"message join", "Ssss", 0, 0, 0}, + {"message part", "Sssss", 0, 0, 0}, + {"message quit", "Ssss", 0, 0, 0}, + {"message kick", "Ssssss", 0, 0, 0}, + {"message nick", "Ssss", 0, 0, 0}, + {"message own_nick", "Ssss", 0, 0, 0}, + {"message invite", "Ssss", 0, 0, 0}, + {"message topic", "Sssss", 0, 0, 0}, + {"keyinfo created", "?", 0, 0, 0}, + {"keyinfo destroyed", "?", 0, 0, 0}, + {"print text", "tss", 0, 0, 0}, + {"theme created", "?", 0, 0, 0}, + {"theme destroyed", "?", 0, 0, 0}, + {"window hilight", "w", 0, 0, 0}, + {"window activity", "wi", 0, 0, 0}, + {"window item hilight", "W", 0, 0, 0}, + {"window item activity", "Wi", 0, 0, 0}, + {"window item new", "wW", 0, 0, 0}, + {"window item remove", "wW", 0, 0, 0}, + {"window item changed", "wW", 0, 0, 0}, + {"window item server changed", "wW", 0, 0, 0}, + {"window created", "w", 0, 0, 0}, + {"window destroyed", "w", 0, 0, 0}, + {"window changed", "ww", 0, 0, 0}, + {"window changed automatic", "w", 0, 0, 0}, + {"window server changed", "wS", 0, 0, 0}, + {"window refnum changed", "wi", 0, 0, 0}, + {"window name changed", "w", 0, 0, 0}, + {"window history changed", "ws", 0, 0, 0}, + {"window level changed", "w", 0, 0, 0}, + {"message irc op_public", "Sssss", 0, 0, 0}, + {"message irc own_wall", "Sss", 0, 0, 0}, + {"message irc own_action", "Sss", 0, 0, 0}, + {"message irc action", "Sssss", 0, 0, 0}, + {"message irc own_notice", "Sss", 0, 0, 0}, + {"message irc notice", "Sssss", 0, 0, 0}, + {"message irc own_ctcp", "Ssss", 0, 0, 0}, + {"message irc ctcp", "Ssssss", 0, 0, 0}, + {"message irc mode", "Sssss", 0, 0, 0}, + {"message dcc own", "ds", 0, 0, 0}, + {"message dcc own_action", "ds", 0, 0, 0}, + {"message dcc own_ctcp", "dss", 0, 0, 0}, + {"message dcc", "ds", 0, 0, 0}, + {"message dcc action", "ds", 0, 0, 0}, + {"message dcc ctcp", "dss", 0, 0, 0}, + {"gui key pressed", "i", 0, 0, 0}, + {"beep", "", 0, 0, 0}, + {NULL} +}; + +#define py_sigmap_len() (sizeof(py_sigmap) / sizeof(py_sigmap[0]) - 1) diff --git a/src/pysignals.c b/src/pysignals.c new file mode 100644 index 0000000..95718aa --- /dev/null +++ b/src/pysignals.c @@ -0,0 +1,805 @@ +#include +#include "pyirssi.h" +#include "pysignals.h" +#include "factory.h" + +/* NOTE: + * There are two different records used to store signal related data: + * PY_SIGNAL_SPEC_REC and PY_SIGNAL_REC. Each SPEC_REC declares a "plain" + * signal, or a type of "variable" signal. Each PY_SIGNAL_REC stores data + * about a handler for a signal. + * + * Plain signals are emitted using the same text every time. They are never + * extended or altered in any way. Plain signals make up the vast majority + * of Irssi signals. These include (some random examples): "beep", + * "printtext", "log new", "ban new", etc. + * + * Variable signals are emitted by joining a common prefix with text that + * varies from emit to emit. These are signals that have a "" suffix + * in Irssi's signal listing. irssi-python uses the trailing space to + * distinguish between plain signals and variable signals. Example prefixes: + * "redir ", "command ", "event ". "command nick" would be emitted when the + * user types /nick yournick at the prompt. + * + * While PY_SIGNAL_SPEC_REC stores data about each individual signal, + * PY_SIGNAL_REC stores data about each handler of a signal (or command). + * A listing of SPEC_REC entries is stored globally in this module for each + * signal known to irssi-python. Each Script holds a list of PY_SIGNAL_REC + * entries to remember signals and commands bound by the script. The + * PY_SIGNAL_REC data includes references to a callable PyObject and a + * PY_SIGNAL_SPEC_REC entry for the argument type list of the signal. + * + * Signals must be registered to be accessible to Python scripts. + * Registering a dynamic signal adds a new SPEC_REC with a refcount of 1. + * If another script registers the same signal, the original entry's refcount + * is incremented. Binding to the signal also increments its reference count. + * Likewise, unregistering or unbinding a dynamic signal will decrement its + * refcount. When refcount hits 0, the dynamic signal is removed from the list, + * and scripts can no longer bind to or emit the signal untill it is + * re-registered. Built-in signals in the sigmap are not from the heap and are + * never removed; it is an error for the refcount of any such signal entry to + * drop to 0. + */ + +typedef struct _PY_SIGNAL_SPEC_REC +{ + char *name; + char *arglist; + int refcount; + int dynamic; + int is_var; /* is this entry a prefix for a variable signal? */ +} PY_SIGNAL_SPEC_REC; + +#include "pysigmap.h" + +#define SIGNAME(sig) (sig->command? sig->command : sig->signal->name) +/* This macro is useful for PY_SIGNAL_REC entries bound to "variable" signals, + * whose names extend the name prefix stored in the SPEC_REC entry. + * + * Example: + * sig->command == "command nick" + * sig->signal->name == "command " + * + * The exact signal text differs from the prefix, so the text must be stored + * separately in each PY_SIGNAL_REC entry. + * + * However, entries for "plain" signals do not require any extra data stored, + * so sig->command is NULL. + * + * Example: + * sig->command == NULL; + * sig->signal->name == "massjoin"; + * + * "massjoin" is not a prefix for any signal, so any PY_SIGNAL_REC + * referencing the "massjoin" SPEC_REC entry will have a NULL command. + */ + +/* hashtable for normal signals, tree for variable signal prefixes. */ +static GHashTable *py_sighash = NULL; +static GTree *py_sigtree = NULL; + +static void py_run_handler(PY_SIGNAL_REC *rec, void **args); +static void py_sig_proxy(void *p1, void *p2, void *p3, void *p4, void *p5, void *p6); +static void py_signal_ref(PY_SIGNAL_SPEC_REC *sig); +static int py_signal_unref(PY_SIGNAL_SPEC_REC *sig); +static void py_signal_add(PY_SIGNAL_SPEC_REC *sig); +static PY_SIGNAL_REC *py_signal_rec_new(const char *signal, PyObject *func, const char *command); +static void py_signal_rec_destroy(PY_SIGNAL_REC *sig); +static PyObject *py_mkstrlist(void *iobj); +static PyObject *py_i2py(char code, void *iobj); +static void *py_py2i(char code, PyObject *pobj, int arg, const char *signal); +static void py_getstrlist(GList **list, PyObject *pylist); +static int precmp(const char *spec, const char *test); +static PY_SIGNAL_SPEC_REC *py_signal_lookup(const char *name); +static void py_signal_remove(PY_SIGNAL_SPEC_REC *sig); +static int py_convert_args(void **args, PyObject *argtup, const char *signal); + +PY_SIGNAL_REC *pysignals_command_bind(const char *cmd, PyObject *func, + const char *category, int priority) +{ + PY_SIGNAL_REC *rec = py_signal_rec_new("send command", func, cmd); + g_return_val_if_fail(rec != NULL, NULL); + + command_bind_full(MODULE_NAME, priority, cmd, + -1, category, (SIGNAL_FUNC)py_sig_proxy, rec); + + return rec; +} + +int pysignals_command_bind_list(GSList **list, const char *command, + PyObject *func, const char *category, int priority) +{ + PY_SIGNAL_REC *rec = pysignals_command_bind(command, func, category, priority); + if (!rec) + return 0; + + *list = g_slist_append(*list, rec); + return 1; +} + +/* return NULL if signal is invalid */ +PY_SIGNAL_REC *pysignals_signal_add(const char *signal, PyObject *func, int priority) +{ + PY_SIGNAL_REC *rec = py_signal_rec_new(signal, func, NULL); + + if (rec == NULL) + return NULL; + + signal_add_full(MODULE_NAME, priority, SIGNAME(rec), + (SIGNAL_FUNC)py_sig_proxy, rec); + + return rec; +} + +int pysignals_signal_add_list(GSList **list, const char *signal, + PyObject *func, int priority) +{ + PY_SIGNAL_REC *rec = pysignals_signal_add(signal, func, priority); + if (!rec) + return 0; + + *list = g_slist_append(*list, rec); + return 1; +} + +void pysignals_command_unbind(PY_SIGNAL_REC *rec) +{ + g_return_if_fail(rec->is_signal == FALSE); + g_return_if_fail(rec->command != NULL); + + command_unbind_full(rec->command, (SIGNAL_FUNC)py_sig_proxy, rec); + py_signal_rec_destroy(rec); +} + +void pysignals_signal_remove(PY_SIGNAL_REC *rec) +{ + g_return_if_fail(rec->is_signal == TRUE); + + signal_remove_full(SIGNAME(rec), (SIGNAL_FUNC)py_sig_proxy, rec); + py_signal_rec_destroy(rec); +} + +void pysignals_remove_generic(PY_SIGNAL_REC *rec) +{ + if (rec->is_signal) + pysignals_signal_remove(rec); + else + pysignals_command_unbind(rec); +} + +/* returns 1 when found and removed successfully */ +int pysignals_remove_search(GSList **siglist, const char *name, + PyObject *func, PSG_TYPE type) +{ + GSList *node; + + for (node = *siglist; node != NULL; node = node->next) + { + PY_SIGNAL_REC *sig = node->data; + + if ((sig->is_signal && type == PSG_COMMAND) || + (!sig->is_signal && type == PSG_SIGNAL)) + continue; + + if ((strcmp(SIGNAME(sig), name) == 0) && + (func == NULL || func == sig->handler)) + { + pysignals_remove_generic(sig); + *siglist = g_slist_delete_link(*siglist, node); + + /* deleting node won't harm iteration because it quits here */ + return 1; + } + } + + return 0; +} + +void pysignals_remove_list(GSList *siglist) +{ + GSList *node = siglist; + + for (node = siglist; node != NULL; node = node->next) + pysignals_remove_generic(node->data); +} + +static PyObject *py_mkstrlist(void *iobj) +{ + PyObject *list; + GList *node, **ptr; + ptr = iobj; + + list = PyList_New(0); + if (!list) + return NULL; + + for (node = *ptr; node != NULL; node = node->next) + { + int ret; + PyObject *str; + + str = PyString_FromString(node->data); + if (!str) + { + Py_DECREF(list); + return NULL; + } + + ret = PyList_Append(list, str); + Py_DECREF(str); + if (ret != 0) + { + Py_DECREF(list); + return NULL; + } + } + + return list; +} + +/* irssi obj -> PyObject */ +static PyObject *py_i2py(char code, void *iobj) +{ + if (iobj == NULL) + Py_RETURN_NONE; + + switch (code) + { + case '?': + Py_RETURN_NONE; + + case 's': + return PyString_FromString((char *)iobj); + case 'u': + return PyLong_FromUnsignedLong(*(unsigned long*)iobj); + case 'I': + return PyInt_FromLong(*(int *)iobj); + case 'i': + return PyInt_FromLong((int)iobj); + + case 'G': + return py_mkstrlist(iobj); + case 'L': /* list of nicks */ + return py_irssi_chatlist_new((GSList *)iobj, 1); + + case 'c': + case 'S': + case 'C': + case 'q': + case 'n': + case 'W': + return py_irssi_chat_new(iobj, 1); + + case 'd': + return py_irssi_new(iobj, 1); + + case 'r': + return pyreconnect_new(iobj); + case 'o': + return pycommand_new(iobj); + case 'l': + return pylog_new(iobj); + case 'a': + return pyrawlog_new(iobj); + case 'g': + return pyignore_new(iobj); + case 'b': + return pyban_new(iobj); + case 'N': + return pynetsplit_new(iobj); + case 'e': + return pynetsplit_server_new(iobj); + case 'O': + return pynotifylist_new(iobj); + case 'p': + return pyprocess_new(iobj); + case 't': + return pytextdest_new(iobj); + case 'w': + return pywindow_new(iobj); + } + + return PyErr_Format(PyExc_TypeError, "unknown code %c", code); +} + +/* PyObject -> irssi obj*/ +static void *py_py2i(char code, PyObject *pobj, int arg, const char *signal) +{ + char *type; + + if (pobj == Py_None) + return NULL; + + switch (code) + { + /* XXX: string doesn't persist */ + case 's': + type = "str"; + if (PyString_Check(pobj)) return PyString_AsString(pobj); + break; + case 'i': + type = "int"; + if (PyInt_Check(pobj)) return (void*)PyInt_AsLong(pobj); + break; + + case 'L': /* list of nicks */ + /*FIXME*/ + return NULL; + + case 'c': + type = "Chatnet"; + if (pychatnet_check(pobj)) return DATA(pobj); + break; + case 'S': + type = "Server"; + if (pyserver_check(pobj)) return DATA(pobj); + break; + case 'C': + type = "Channel"; + if (pychannel_check(pobj)) return DATA(pobj); + break; + case 'q': + type = "Query"; + if (pyquery_check(pobj)) return DATA(pobj); + break; + case 'n': + type = "Nick"; + if (pynick_check(pobj)) return DATA(pobj); + break; + case 'W': + type = "WindowItem"; + if (pywindow_item_check(pobj)) return DATA(pobj); + break; + + case 'd': + type = "DCC"; + if (pydcc_check(pobj)) return DATA(pobj); + break; + + case 'r': + type = "Reconnect"; + if (pyreconnect_check(pobj)) return DATA(pobj); + break; + case 'o': + type = "Command"; + if (pycommand_check(pobj)) return DATA(pobj); + break; + case 'l': + type = "Log"; + if (pylog_check(pobj)) return DATA(pobj); + break; + case 'a': + type = "Rawlog"; + if (pyrawlog_check(pobj)) return DATA(pobj); + break; + case 'g': + type = "Ignore"; + if (pyignore_check(pobj)) return DATA(pobj); + break; + case 'b': + type = "Ban"; + if (pyban_check(pobj)) return DATA(pobj); + break; + case 'N': + type = "Netsplit"; + if (pynetsplit_check(pobj)) return DATA(pobj); + break; + case 'e': + type = "NetsplitServer"; + if (pynetsplit_server_check(pobj)) return DATA(pobj); + break; + case 'O': + type = "Notifylist"; + if (pynotifylist_check(pobj)) return DATA(pobj); + break; + case 'p': + type = "Process"; + if (pyprocess_check(pobj)) return DATA(pobj); + break; + case 't': + type = "TextDest"; + if (pytextdest_check(pobj)) return DATA(pobj); + break; + case 'w': + type = "Window"; + if (pywindow_check(pobj)) return DATA(pobj); + break; + default: + PyErr_Format(PyExc_TypeError, "don't know type code %c", code); + return NULL; + } + + PyErr_Format(PyExc_TypeError, "signal `%s': expected type %s for arg %d, but got %s", + signal, type, arg, pobj->ob_type->tp_name); + return NULL; +} + +static void py_getstrlist(GList **list, PyObject *pylist) +{ + GList *out = NULL; + int i; + PyObject *str; + char *cstr; + + for (i = 0; i < PyList_Size(pylist); i++) + { + str = PyList_GET_ITEM(pylist, i); + if (!PyString_Check(str)) + { + PyErr_SetString(PyExc_TypeError, "string list contains invalid elements"); + PyErr_Print(); + return; + } + + cstr = g_strdup(PyString_AS_STRING(str)); + out = g_list_append(out, cstr); + } + + g_list_foreach(*list, (GFunc)g_free, NULL); + g_list_free(*list); + *list = out; +} + +static void py_run_handler(PY_SIGNAL_REC *rec, void **args) +{ + PyObject *argtup, *ret; + char *arglist = rec->signal->arglist; + int arglen, i, j; + + arglen = strlen(arglist); + g_return_if_fail(arglen <= SIGNAL_MAX_ARGUMENTS); + + argtup = PyTuple_New(arglen); + if (!argtup) + goto error; + + for (i = 0; i < arglen; i++) + { + PyObject *arg = py_i2py(arglist[i], args[i]); + if (!arg) + goto error; + + PyTuple_SET_ITEM(argtup, i, arg); + } + + ret = PyObject_CallObject(rec->handler, argtup); + if (!ret) + goto error; + + /*XXX: IN/OUT arg handling not well tested */ + for (i = 0, j = 0; i < arglen; i++) + { + GList **list; + PyObject *pyarg = PyTuple_GET_ITEM(argtup, i); + + switch (arglist[i]) + { + case 'G': + list = args[i]; + py_getstrlist(list, pyarg); + break; + + case 'I': + if (ret != Py_None) + { + PyObject *value; + int *intarg = args[i]; + + /* expect a proper return value to set reference arg. + * if return is a tuple, find the next item + */ + if (PyTuple_Check(ret)) + value = PyTuple_GET_ITEM(ret, j++); + else + value = ret; + + if (!PyInt_Check(value)) + continue; + + *intarg = PyInt_AS_LONG(value); + } + break; + } + } + + Py_XDECREF(ret); + +error: + Py_XDECREF(argtup); + if (PyErr_Occurred()) + PyErr_Print(); +} + +static void py_sig_proxy(void *p1, void *p2, void *p3, void *p4, void *p5, void *p6) +{ + PY_SIGNAL_REC *rec = signal_get_user_data(); + void *args[6]; + + args[0] = p1; args[1] = p2; args[2] = p3; + args[3] = p4; args[4] = p5; args[5] = p6; + py_run_handler(rec, args); +} + +static int py_convert_args(void **args, PyObject *argtup, const char *signal) +{ + char *arglist; + PY_SIGNAL_SPEC_REC *spec; + int i; + int maxargs; + + spec = py_signal_lookup(signal); + if (!spec) + { + PyErr_Format(PyExc_KeyError, "signal not found"); + return 0; + } + + /*XXX: specifying fewer signal args than in the format implicitly + sets overlooked args to NULL or 0 */ + + arglist = spec->arglist; + maxargs = strlen(arglist); + for (i = 0; i < maxargs && i < PyTuple_Size(argtup); i++) + { + args[i] = py_py2i(arglist[i], + PyTuple_GET_ITEM(argtup, i), + i+1, signal); + + if (PyErr_Occurred()) /* XXX: any cleanup needed? */ + return -1; + } + + return maxargs; +} + +int pysignals_emit(const char *signal, PyObject *argtup) +{ + int arglen; + void *args[6]; + + memset(args, 0, sizeof args); + + arglen = py_convert_args(args, argtup, signal); + if (arglen < 0) + return 0; + + signal_emit(signal, arglen, + args[0], args[1], args[2], + args[3], args[4], args[5]); + + return 1; +} + +int pysignals_continue(PyObject *argtup) +{ + const char *signal; + int arglen; + void *args[6]; + + memset(args, 0, sizeof args); + + signal = signal_get_emitted(); + if (!signal) + { + PyErr_Format(PyExc_LookupError, "cannot determine current signal"); + return 0; + } + + arglen = py_convert_args(args, argtup, signal); + if (arglen < 0) + return 0; + + signal_continue(arglen, + args[0], args[1], args[2], + args[3], args[4], args[5]); + + return 1; +} + +/* returns NULL if signal is invalid, incr reference to func */ +static PY_SIGNAL_REC *py_signal_rec_new(const char *signal, PyObject *func, const char *command) +{ + PY_SIGNAL_REC *rec; + PY_SIGNAL_SPEC_REC *spec; + + g_return_val_if_fail(func != NULL, NULL); + + spec = py_signal_lookup(signal); + if (!spec) + return NULL; + + rec = g_new0(PY_SIGNAL_REC, 1); + rec->signal = spec; + rec->handler = func; + Py_INCREF(func); + + if (command) + { + rec->is_signal = FALSE; + rec->command = g_strdup(command); + } + else + { + rec->is_signal = TRUE; + /* handle variable signal. requested signal will be longer than spec->name, ie + * signal = "var signal POOOM", spec->name = "var signal " + */ + if (strcmp(signal, spec->name) != 0) + rec->command = g_strdup(signal); + } + + py_signal_ref(spec); + + return rec; +} + +static void py_signal_rec_destroy(PY_SIGNAL_REC *sig) +{ + py_signal_unref(sig->signal); + Py_DECREF(sig->handler); + g_free(sig->command); + g_free(sig); +} + +static void py_signal_add(PY_SIGNAL_SPEC_REC *sig) +{ + if (sig->is_var) + g_tree_insert(py_sigtree, sig->name, sig); + else + g_hash_table_insert(py_sighash, sig->name, sig); +} + +static void py_signal_remove(PY_SIGNAL_SPEC_REC *sig) +{ + int ret; + + if (sig->is_var) + g_tree_remove(py_sigtree, sig->name); + else + { + ret = g_hash_table_remove(py_sighash, sig->name); + g_return_if_fail(ret != FALSE); + } +} + +static int precmp(const char *spec, const char *test) +{ + while (*spec == *test++) + if (*spec++ == '\0') + return 0; + + /* Variable event prefix matches (spec must never be empty string)*/ + /* precmp("var event ", "var event POOOM") -> 0 */ + if (*spec == '\0' && *(spec-1) == ' ') + return 0; + + return *(const unsigned char *)(test - 1) - *(const unsigned char *)spec; +} + +static PY_SIGNAL_SPEC_REC *py_signal_lookup(const char *name) +{ + PY_SIGNAL_SPEC_REC *ret; + + /* First check the normal signals hash, then check the variable signal prefixes in the tree */ + ret = g_hash_table_lookup(py_sighash, name); + if (!ret) + ret = g_tree_search(py_sigtree, (GCompareFunc)precmp, name); + + return ret; +} + +static void py_signal_ref(PY_SIGNAL_SPEC_REC *sig) +{ + g_return_if_fail(sig->refcount >= 0); + + sig->refcount++; +} + +static int py_signal_unref(PY_SIGNAL_SPEC_REC *sig) +{ + g_return_val_if_fail(sig->refcount >= 1, 0); + g_return_val_if_fail(sig->refcount > 1 || sig->dynamic, 0); + + sig->refcount--; + + if (sig->refcount == 0) + { + py_signal_remove(sig); + + /* freeing name also takes care of the key */ + g_free(sig->name); + g_free(sig->arglist); + g_free(sig); + + return 1; + } + + return 0; +} + +/* returns 0 when signal already exists, but with different args, or when + similar signal prefix is already present. */ +int pysignals_register(const char *name, const char *arglist) +{ + int len; + PY_SIGNAL_SPEC_REC *spec; + + len = strlen(name); + g_return_val_if_fail(len > 0, 0); + + spec = py_signal_lookup(name); + if (!spec) + { + spec = g_new0(PY_SIGNAL_SPEC_REC, 1); + spec->is_var = name[len-1] == ' '; /* trailing space means signal prefix */ + spec->dynamic = 1; + spec->refcount = 0; + spec->name = g_strdup(name); + spec->arglist = g_strdup(arglist); + + py_signal_add(spec); + } + else if (strcmp(spec->arglist, arglist) || strcmp(spec->name, name)) + return 0; + + spec->refcount++; + + return 1; +} + +/* returns 0 when name doesn't exist */ +int pysignals_unregister(const char *name) +{ + PY_SIGNAL_SPEC_REC *spec; + + spec = py_signal_lookup(name); + if (!spec) + return 0; + + py_signal_unref(spec); + return 1; +} + +void pysignals_init(void) +{ + int i; + + g_return_if_fail(py_sighash == NULL); + g_return_if_fail(py_sigtree == NULL); + + py_sigtree = g_tree_new((GCompareFunc)strcmp); + py_sighash = g_hash_table_new(g_str_hash, g_str_equal); + + for (i = 0; i < py_sigmap_len(); i++) + { + py_sigmap[i].refcount = 1; + py_sigmap[i].dynamic = 0; + py_signal_add(&py_sigmap[i]); + } +} + +static int py_check_sig(char *key, PY_SIGNAL_SPEC_REC *value, void *data) +{ + /* shouldn't need to deallocate any script recs -- all remaining at + this point should not be dynamic. non dynamic signals should have + no outstanding references */ + g_return_val_if_fail(value->dynamic == 0, FALSE); + g_return_val_if_fail(value->refcount == 1, FALSE); + + return FALSE; +} + +/* XXX: remember to remove all scripts before calling this deinit */ +void pysignals_deinit(void) +{ + g_return_if_fail(py_sighash != NULL); + g_return_if_fail(py_sigtree != NULL); + + g_tree_foreach(py_sigtree, (GTraverseFunc)py_check_sig, NULL); + g_hash_table_foreach_remove(py_sighash, (GHRFunc)py_check_sig, NULL); + + g_tree_destroy(py_sigtree); + g_hash_table_destroy(py_sighash); + py_sigtree = NULL; + py_sighash = NULL; +} diff --git a/src/pysignals.h b/src/pysignals.h new file mode 100644 index 0000000..bec72c9 --- /dev/null +++ b/src/pysignals.h @@ -0,0 +1,44 @@ +#ifndef _PYSIGNALS_H_ +#define _PYSIGNALS_H_ +#include + +/* forward */ +struct _PY_SIGNAL_SPEC_REC; + +typedef struct _PY_SIGNAL_REC +{ + struct _PY_SIGNAL_SPEC_REC *signal; + char *command; /* used for command and variable signal */ + PyObject *handler; + int is_signal; +} PY_SIGNAL_REC; + +typedef enum +{ + PSG_COMMAND, + PSG_SIGNAL, + PSG_ALL, +} PSG_TYPE; + +PY_SIGNAL_REC *pysignals_command_bind(const char *cmd, PyObject *func, + const char *category, int priority); +PY_SIGNAL_REC *pysignals_signal_add(const char *signal, PyObject *func, + int priority); +int pysignals_command_bind_list(GSList **list, const char *command, + PyObject *func, const char *category, int priority); +int pysignals_signal_add_list(GSList **list, const char *signal, + PyObject *func, int priority); +void pysignals_command_unbind(PY_SIGNAL_REC *rec); +void pysignals_signal_remove(PY_SIGNAL_REC *rec); +void pysignals_remove_generic(PY_SIGNAL_REC *rec); +int pysignals_remove_search(GSList **siglist, const char *name, + PyObject *func, PSG_TYPE type); +void pysignals_remove_list(GSList *siglist); +int pysignals_emit(const char *signal, PyObject *argtup); +int pysignals_continue(PyObject *argtup); +int pysignals_register(const char *name, const char *arglist); +int pysignals_unregister(const char *name); +void pysignals_init(void); +void pysignals_deinit(void); + +#endif diff --git a/src/pysource.c b/src/pysource.c new file mode 100644 index 0000000..413ab2c --- /dev/null +++ b/src/pysource.c @@ -0,0 +1,130 @@ +#include +#include "pyirssi.h" +#include "pysource.h" + +typedef struct _PY_SOURCE_REC +{ + int tag; + GSList **tag_list; + int fd; + PyObject *func; + PyObject *data; +} PY_SOURCE_REC; + +static PY_SOURCE_REC *py_source_rec_new(GSList **tag_list, int fd, PyObject *func, PyObject *data) +{ + PY_SOURCE_REC *rec; + + rec = g_new0(PY_SOURCE_REC, 1); + rec->tag_list = tag_list; + rec->fd = fd; + rec->func = func; + rec->data = data; + + Py_INCREF(func); + Py_XINCREF(data); + + return rec; +} + +static int py_remove_tag(GSList **list, int handle) +{ + GSList *node; + + node = g_slist_find(*list, GINT_TO_POINTER(handle)); + if (!node) + return 0; + + *list = g_slist_delete_link(*list, node); + + return 1; +} + +static void py_source_destroy(PY_SOURCE_REC *rec) +{ + g_return_if_fail(py_remove_tag(rec->tag_list, rec->tag) == 1); + Py_DECREF(rec->func); + Py_XDECREF(rec->data); + g_free(rec); +} + +static int py_handle_ret(PyObject *ret) +{ + int res; + + if (!ret) + { + PyErr_Print(); + res = FALSE; + } + else + { + res = PyObject_IsTrue(ret); + Py_DECREF(ret); + } + + return res; +} + +static int py_timeout_proxy(PY_SOURCE_REC *rec) +{ + PyObject *ret; + + g_return_val_if_fail(rec != NULL, FALSE); + + if (rec->data) + ret = PyObject_CallFunction(rec->func, "O", rec->data); + else + ret = PyObject_CallFunction(rec->func, ""); + + return py_handle_ret(ret); +} + +static int py_io_proxy(GIOChannel *src, GIOCondition condition, PY_SOURCE_REC *rec) +{ + PyObject *ret; + + g_return_val_if_fail(rec != NULL, FALSE); + + if (rec->data) + ret = PyObject_CallFunction(rec->func, "iiO", rec->fd, condition, rec->data); + else + ret = PyObject_CallFunction(rec->func, "ii", rec->fd, condition); + + return py_handle_ret(ret); +} + +int pysource_timeout_add_list(GSList **list, int msecs, PyObject *func, PyObject *data) +{ + PY_SOURCE_REC *rec; + + g_return_val_if_fail(func != NULL, -1); + + rec = py_source_rec_new(list, -1, func, data); + rec->tag = g_timeout_add_full(G_PRIORITY_DEFAULT, msecs, + (GSourceFunc)py_timeout_proxy, rec, + (GDestroyNotify)py_source_destroy); + + *list = g_slist_append(*list, GINT_TO_POINTER(rec->tag)); + + return rec->tag; +} + +int pysource_io_add_watch_list(GSList **list, int fd, int cond, PyObject *func, PyObject *data) +{ + PY_SOURCE_REC *rec; + GIOChannel *channel; + + g_return_val_if_fail(func != NULL, 1); + + rec = py_source_rec_new(list, fd, func, data); + channel = g_io_channel_unix_new(fd); + rec->tag = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, cond, + (GIOFunc)py_io_proxy, rec, + (GDestroyNotify)py_source_destroy); + g_io_channel_unref(channel); + + *list = g_slist_append(*list, GINT_TO_POINTER(rec->tag)); + + return rec->tag; +} diff --git a/src/pysource.h b/src/pysource.h new file mode 100644 index 0000000..78b55ec --- /dev/null +++ b/src/pysource.h @@ -0,0 +1,10 @@ +#ifndef _PYSOURCE_H_ +#define _PYSOURCE_H_ + +#include + +/* condition is G_INPUT_READ or G_INPUT_WRITE */ +int pysource_io_add_watch_list(GSList **list, int fd, int cond, PyObject *func, PyObject *data); +int pysource_timeout_add_list(GSList **list, int msecs, PyObject *func, PyObject *data); + +#endif diff --git a/src/pystatusbar.c b/src/pystatusbar.c new file mode 100644 index 0000000..8537718 --- /dev/null +++ b/src/pystatusbar.c @@ -0,0 +1,132 @@ +#include "pystatusbar.h" +#include "pyirssi.h" +#include "factory.h" + +typedef struct +{ + char *name; + PyObject *script; + PyObject *handler; +} PY_BAR_ITEM_REC; + +/* Map: item name -> bar item obj */ +static GHashTable *py_bar_items = NULL; + +static void py_add_bar_handler(const char *iname, PyObject *script, PyObject *handler) +{ + PY_BAR_ITEM_REC *sitem; + + sitem = g_new0(PY_BAR_ITEM_REC, 1); + sitem->name = g_strdup(iname); + sitem->script = script; + sitem->handler = handler; + Py_INCREF(script); + Py_INCREF(handler); + + g_hash_table_insert(py_bar_items, sitem->name, sitem); +} + +static void py_destroy_handler(PY_BAR_ITEM_REC *sitem) +{ + statusbar_item_unregister(sitem->name); + + g_free(sitem->name); /* destroy key */ + Py_DECREF(sitem->script); + Py_DECREF(sitem->handler); + g_free(sitem); +} + +static void py_statusbar_proxy_call(SBAR_ITEM_REC *item, int sizeonly, PY_BAR_ITEM_REC *sitem) +{ + PyObject *pybaritem; + PyObject *ret; + + g_return_if_fail(PyCallable_Check(sitem->handler)); + + pybaritem = pystatusbar_item_new(item); + if (!pybaritem) + { + PyErr_Print(); + pystatusbar_item_unregister(sitem->name); + } + + ret = PyObject_CallFunction(sitem->handler, "Oi", pybaritem, sizeonly); + if (!ret) + { + PyErr_Print(); + pystatusbar_item_unregister(sitem->name); + } + else + Py_DECREF(ret); +} + +static void py_statusbar_proxy(SBAR_ITEM_REC *item, int sizeonly) +{ + PY_BAR_ITEM_REC *sitem; + + sitem = g_hash_table_lookup(py_bar_items, item->config->name); + if (sitem) + py_statusbar_proxy_call(item, sizeonly, sitem); + else + { + statusbar_item_default_handler(item, sizeonly, NULL, "", TRUE); + g_critical("unknown handler for Python statusbar proxy: %s", item->config->name); + } +} + +void pystatusbar_item_register(PyObject *script, const char *sitem, + const char *value, PyObject *func) +{ + if (func) + { + g_return_if_fail(PyCallable_Check(func)); + py_add_bar_handler(sitem, script, func); + } + + statusbar_item_register(sitem, value, func? py_statusbar_proxy : NULL); +} + +/* remove selected status bar item handler */ +void pystatusbar_item_unregister(const char *iname) +{ + if (!g_hash_table_remove(py_bar_items, iname)) + statusbar_item_unregister(iname); +} + +/* remove all statusbar item handlers for script */ +/* XXX: Only status bar items registered with a handler are stored in the hash table. + * Items registered with only a value are not stored, so there is no way to unregister + * them when the script is unloaded. + */ +static int py_check_clean(char *key, PY_BAR_ITEM_REC *value, PyObject *script) +{ + if (value->script == script) + return 1; + + return 0; +} + +void pystatusbar_cleanup_script(PyObject *script) +{ + g_hash_table_foreach_remove(py_bar_items, (GHRFunc)py_check_clean, script); +} + +void pystatusbar_init(void) +{ + g_return_if_fail(py_bar_items == NULL); + + /* key is freed by destroy_handler */ + py_bar_items = g_hash_table_new_full(g_str_hash, g_str_equal, + NULL, (GDestroyNotify)py_destroy_handler); +} + +/* XXX: this must be called after cleaning up all the loaded scripts */ +void pystatusbar_deinit(void) +{ + g_return_if_fail(py_bar_items != NULL); + g_return_if_fail(g_hash_table_size(py_bar_items) == 0); + + g_hash_table_destroy(py_bar_items); + py_bar_items = NULL; +} + diff --git a/src/pystatusbar.h b/src/pystatusbar.h new file mode 100644 index 0000000..9749c9f --- /dev/null +++ b/src/pystatusbar.h @@ -0,0 +1,13 @@ +#ifndef _PYSTATUSBAR_H_ +#define _PYSTATUSBAR_H_ + +#include + +void pystatusbar_item_register(PyObject *script, const char *sitem, + const char *value, PyObject *func); +void pystatusbar_item_unregister(const char *iname); +void pystatusbar_cleanup_script(PyObject *script); +void pystatusbar_init(void); +void pystatusbar_deinit(void); + +#endif diff --git a/src/pythemes.c b/src/pythemes.c new file mode 100644 index 0000000..a3e8927 --- /dev/null +++ b/src/pythemes.c @@ -0,0 +1,287 @@ +#include +#include "pythemes.h" +#include "pyirssi.h" +#include "factory.h" +#include "pymodule.h" +#include "pyloader.h" + +static void py_get_mod(char *full, int fullsz, const char *script) +{ + g_snprintf(full, fullsz, "irssi_python/%s.py", script); +} + +/* Edited from Perl Themes.xs */ +int pythemes_printformat(TEXT_DEST_REC *dest, const char *name, const char *format, PyObject *argtup) +{ + char *arglist[MAX_FORMAT_PARAMS + 1]; + THEME_REC *theme; + char *str; + char script[256]; + int formatnum; + int i; + + py_get_mod(script, sizeof script, name); + + formatnum = format_find_tag(script, format); + if (formatnum < 0) { + PyErr_Format(PyExc_KeyError, "unregistered format '%s'", format); + return 0; + } + + memset(arglist, 0, sizeof arglist); + for (i = 0; i < MAX_FORMAT_PARAMS && i < PyTuple_Size(argtup); i++) { + PyObject *obj = PyTuple_GET_ITEM(argtup, i); + char *str; + + if (!PyString_Check(obj)) { + PyErr_Format(PyExc_TypeError, "format argument list contains non-string data"); + return 0; + } + + str = PyString_AsString(obj); + if (!str) + return 0; + + arglist[i] = str; + } + + theme = window_get_theme(dest->window); + signal_emit("print format", 5, theme, script, + dest, GINT_TO_POINTER(formatnum), arglist); + + str = format_get_text_theme_charargs(theme, script, dest, formatnum, arglist); + if (*str != '\0') printtext_dest(dest, "%s", str); + g_free(str); + + return 1; +} + +static void py_destroy_format_list(FORMAT_REC *recs) +{ + int i; + + for (i = 0; recs[i].def; i++) + { + g_free(recs[i].def); + g_free(recs[i].tag); + } + + g_free(recs); +} + +/* register a list of formats in this format: + * [ (name, format), ... ] + */ +int pythemes_register(const char *name, PyObject *list) +{ + char script[256]; + FORMAT_REC *formatrecs; + int i; + + py_get_mod(script, sizeof script, name); + + if (!PyList_Check(list)) + { + PyErr_Format(PyExc_TypeError, "arg must be list"); + return 0; + } + + if (PyList_Size(list) == 0) + { + PyErr_Format(PyExc_TypeError, "cannot register empty list"); + return 0; + } + + if (g_hash_table_lookup(default_formats, script)) + { + PyErr_Format(PyExc_KeyError, "format list already registered by script"); + return 0; + } + + formatrecs = g_new0(FORMAT_REC, PyList_Size(list) + 2); + formatrecs[0].tag = g_strdup(script); + formatrecs[0].def = g_strdup("Python script"); + + for (i = 0; i < PyList_Size(list); i++) + { + FORMAT_REC *rec; + PyObject *item; + char *key, *value; + + rec = &formatrecs[i + 1]; + item = PyList_GET_ITEM(list, i); + if (!PyTuple_Check(item) || !PyArg_ParseTuple(item, "ss", &key, &value)) + { + if (!PyErr_Occurred() || PyErr_ExceptionMatches(PyExc_TypeError)) + { + PyErr_Clear(); + PyErr_Format(PyExc_TypeError, "format list must contain tuples of two strings"); + } + py_destroy_format_list(formatrecs); + return 0; + } + + rec->tag = g_strdup(key); + rec->def = g_strdup(value); + rec->params = MAX_FORMAT_PARAMS; + } + + theme_register_module(script, formatrecs); + + return 1; +} + +void pythemes_unregister(const char *name) +{ + char script[256]; + FORMAT_REC *formats; + + py_get_mod(script, sizeof script, name); + + formats = g_hash_table_lookup(default_formats, script); + if (!formats) + return; + + py_destroy_format_list(formats); + theme_unregister_module(script); +} + +/* XXX: test binding a PyCFunction to different sources. Not sure + if this is a good thing or not, but it seems to work */ +PyDoc_STRVAR(py_printformat_doc, + "for Server objects:\n" + "printformat(target, level, format, ...) -> None\n" + "\n" + "For all else:\n" + "printformat(level, format, ...) -> None\n" +); +static PyObject *py_printformat(PyObject *self, PyObject *all) +{ + int level; + char *format; + char *target; + PyObject *args = NULL, *varargs = NULL; + TEXT_DEST_REC dest; + char *script; + int formatstart; + + if (self && pyserver_check(self)) + formatstart = 3; + else + formatstart = 2; + + args = PySequence_GetSlice(all, 0, formatstart); + if (!args) + goto error; + + varargs = PySequence_GetSlice(all, formatstart, PyTuple_Size(all)); + if (!varargs) + goto error; + + if (self && pyserver_check(self)) + { + if (!PyArg_ParseTuple(args, "sis", &target, &level, &format)) + goto error; + } + else + { + if (!PyArg_ParseTuple(args, "is", &level, &format)) + goto error; + } + + script = pyloader_find_script_name(); + if (!script) + { + PyErr_Format(PyExc_RuntimeError, "No script found"); + goto error; + } + + /* create the text dest depending on whether this function is called from + module level or as a method of one of the objects */ + if (self == NULL) /* module */ + format_create_dest(&dest, NULL, NULL, level, NULL); + else if (pyserver_check(self)) + format_create_dest(&dest, DATA(self), target, level, NULL); + else if (pywindow_check(self)) + format_create_dest(&dest, NULL, NULL, level, DATA(self)); + else if (pywindow_item_check(self)) + { + PyWindowItem *pywi = (PyWindowItem *)self; + format_create_dest(&dest, pywi->data->server, pywi->data->visible_name, level, NULL); + } + + if (!pythemes_printformat(&dest, script, format, varargs)) + goto error; + + Py_DECREF(args); + Py_DECREF(varargs); + + Py_RETURN_NONE; + +error: + Py_XDECREF(args); + Py_XDECREF(varargs); + + return NULL; +} + +/* XXX: these funcs could be moved to pyutils.c */ +static int py_add_module_func(PyMethodDef *mdef) +{ + PyObject *func; + + g_return_val_if_fail(py_module != NULL, 0); + + func = PyCFunction_New(mdef, NULL); + if (!func) + return 0; + + if (PyModule_AddObject(py_module, mdef->ml_name, func) != 0) + { + Py_DECREF(func); + return 0; + } + + return 1; +} + +static int py_add_method(PyTypeObject *type, PyMethodDef *mdef) +{ + int ret; + PyObject *func; + + g_return_val_if_fail(type->tp_dict != NULL, 0); + + func = PyDescr_NewMethod(type, mdef); + if (!func) + return 0; + + ret = PyDict_SetItemString(type->tp_dict, mdef->ml_name, func); + Py_DECREF(func); + if (ret != 0) + return 0; + + return 1; +} + +int pythemes_init(void) +{ + static PyMethodDef pfdef = {"printformat", (PyCFunction)py_printformat, + METH_VARARGS, py_printformat_doc}; + + /* add function to main module and as member some types */ + + if (!py_add_module_func(&pfdef)) + return 0; + + if (!py_add_method(&PyServerType, &pfdef)) + return 0; + + if (!py_add_method(&PyWindowType, &pfdef)) + return 0; + + if (!py_add_method(&PyWindowItemType, &pfdef)) + return 0; + + return 1; +} diff --git a/src/pythemes.h b/src/pythemes.h new file mode 100644 index 0000000..92af965 --- /dev/null +++ b/src/pythemes.h @@ -0,0 +1,13 @@ +#ifndef _PYTHEMES_H_ +#define _PYTHEMES_H_ + +#include + +struct _TEXT_DEST_REC; + +int pythemes_printformat(struct _TEXT_DEST_REC *dest, const char *script, const char *format, PyObject *argtup); +int pythemes_register(const char *script, PyObject *list); +void pythemes_unregister(const char *script); +int pythemes_init(void); + +#endif diff --git a/src/pyutils.c b/src/pyutils.c new file mode 100644 index 0000000..05e1f31 --- /dev/null +++ b/src/pyutils.c @@ -0,0 +1,81 @@ +#include +#include "pyirssi.h" +#include "pyutils.h" +#include "settings.h" +#include "servers.h" + +/* copy paste from perl bindings */ +void py_command(const char *cmd, SERVER_REC *server, WI_ITEM_REC *item) +{ + const char *cmdchars; + char *sendcmd = (char *) cmd; + + if (*cmd == '\0') + return; + + cmdchars = settings_get_str("cmdchars"); + if (strchr(cmdchars, *cmd) == NULL) { + /* no command char - let's put it there.. */ + sendcmd = g_strdup_printf("%c%s", *cmdchars, cmd); + } + + signal_emit("send command", 3, sendcmd, server, item); + if (sendcmd != cmd) g_free(sendcmd); +} + +/* return the file extension for a file, or empty string + don't free result */ +char *file_get_ext(const char *file) +{ + const char *dot = NULL; + + while (*file) + { + if (*file == '.') + dot = file; + + file++; + } + + if (dot) + return (char *) dot + 1; + + return (char *) file; +} + +int file_has_ext(const char *file, const char *ext) +{ + const char *fext = file_get_ext(file); + + return !strcmp(fext, ext); +} + + +/* return whats in the braces -> /path/to/{filename}.py + result must be freed */ +char *file_get_filename(const char *path) +{ + const char *begin; + const char *end; + char *name; + size_t len; + + begin = strrchr(path, '/'); + if (!begin) + begin = path; + else + begin++; + + end = strrchr(begin, '.'); + if (end != NULL && end > begin) + len = end - begin; + else + len = strlen(begin); + + name = g_strnfill(len, 0); + + strncpy(name, begin, len); + + return name; +} + diff --git a/src/pyutils.h b/src/pyutils.h new file mode 100644 index 0000000..7b2ca7b --- /dev/null +++ b/src/pyutils.h @@ -0,0 +1,12 @@ +#ifndef _PYUTILS_H_ +#define _PYUTILS_H_ + +#include "servers.h" + +void py_command(const char *cmd, SERVER_REC *server, WI_ITEM_REC *item); +char *file_get_ext(const char *file); +int file_has_ext(const char *file, const char *ext); +char *file_get_filename(const char *path); + + +#endif diff --git a/src/sig2code.awk b/src/sig2code.awk new file mode 100644 index 0000000..d6bdb0d --- /dev/null +++ b/src/sig2code.awk @@ -0,0 +1,61 @@ +BEGIN { + FS = "[ \t]*->[ \t]*"; + + #read in codes + while (getline < "sig2code.txt") + { + sub(/^[ \t]*/, ""); + if (NF < 2) + continue; + + #print $1, $2 + sigmap[$2] = $1 + } + + close("sig2code.txt"); + + FS = "[ \t]*,[ \t]*"; + + print "/* Include in your C module */"; + print "static PY_SIGNAL_SPEC_REC py_sigmap[] = {"; +} + +function match_type(t) +{ + for (type in sigmap) + { + if (index(t, type) != 0) + return sigmap[type]; + } + + return "?"; +} + +$1 ~ /^[ \t]*"/ && $1 !~ /"script error"/ { + sub(/^[ \t]*/, ""); + + signal = $1 + if (signal ~ /.*$/) + { + varsig = 1; + sub(//, "", signal); + } + else + varsig = 0; + + args = ""; + for (i = 2; i <= NF; i++) + { + args = args""match_type($i); + } + + printf(" {%s, \"%s\", 0, 0, %d},\n", signal, args, varsig); +} + +END { + print " {NULL}" ; + print "};"; + print ""; + print "#define py_sigmap_len() (sizeof(py_sigmap) / sizeof(py_sigmap[0]) - 1)"; +} + diff --git a/src/sig2code.txt b/src/sig2code.txt new file mode 100644 index 0000000..379e88e --- /dev/null +++ b/src/sig2code.txt @@ -0,0 +1,44 @@ + Conversion codes notes + I = int *arg IN/OUT + G = string GList **arg IN/OUT (list must be reconstructed) + L = list of nicks + + Scalars + s -> char * + u -> ulong * + I -> int * + i -> int + + Lists of things (completion.c and massjoin.c) + G -> GList * of char* + L -> GSList of NICK_RECs + + Chat objects + c -> CHATNET_REC + S -> SERVER_REC + C -> CHANNEL_REC + q -> QUERY_REC + n -> NICK_REC + W -> WI_ITEM_REC + + Irssi objects + d -> DCC_REC + + Other objects + r -> RECONNECT_REC + o -> COMMAND_REC + l -> LOG_REC + a -> RAWLOG_REC + g -> IGNORE_REC + ? -> MODULE_REC + b -> BAN_REC + N -> NETSPLIT_REC + e -> NETSPLIT_SERVER_REC + ? -> AUTOIGNORE_REC + O -> NOTIFYLIST_REC + ? -> THEME_REC + ? -> KEYINFO_REC + p -> PROCESS_REC + t -> TEXT_DEST_REC + w -> WINDOW_REC + -- cgit