From d29ca0b107a5b6abb4eadd036f37acd33bb72ed0 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Wed, 26 Apr 2000 08:10:09 +0000 Subject: [PATCH] rest of the ~rewrite? git-svn-id: http://svn.irssi.org/repos/irssi/trunk@172 dbcabf3a-b0e7-0310-adc4-f8d773084564 --- Makefile.am | 10 +- NEWS | 123 ++++- README | 1 + TODO | 96 ++-- autogen.sh | 9 + config | 58 +-- configure.in | 54 ++- docs/COMMANDS | 387 --------------- docs/FAQ | 33 -- docs/FORMATS | 19 - docs/PERL | 621 ------------------------ docs/SIGNALS | 224 --------- docs/SPECIAL_VARS | 104 ----- src/Makefile.am | 8 +- src/common-setup.h | 3 - src/common.h | 2 +- src/lib-config/get.c | 36 +- src/lib-config/iconfig.h | 14 +- src/lib-config/parse.c | 21 +- src/lib-config/set.c | 25 + src/lib-config/write.c | 7 +- src/perl/Makefile.am | 30 ++ src/perl/get-signals.pl | 38 ++ src/perl/irssi-perl.c | 529 +++++++++++++++++++++ src/perl/irssi-perl.h | 7 + src/perl/module.h | 3 + src/perl/perl-signals.h | 108 +++++ src/perl/xs/Irssi.pm | 21 + src/perl/xs/Irssi.xs | 933 +++++++++++++++++++++++++++++++++++++ src/perl/xs/Makefile.PL.in | 6 + src/perl/xs/typemap | 14 + src/perl/xsinit.c | 41 ++ 32 files changed, 2049 insertions(+), 1536 deletions(-) delete mode 100644 docs/COMMANDS delete mode 100644 docs/FAQ delete mode 100644 docs/FORMATS delete mode 100644 docs/PERL delete mode 100644 docs/SIGNALS delete mode 100644 docs/SPECIAL_VARS create mode 100644 src/perl/Makefile.am create mode 100755 src/perl/get-signals.pl create mode 100644 src/perl/irssi-perl.c create mode 100644 src/perl/irssi-perl.h create mode 100644 src/perl/module.h create mode 100644 src/perl/perl-signals.h create mode 100644 src/perl/xs/Irssi.pm create mode 100644 src/perl/xs/Irssi.xs create mode 100644 src/perl/xs/Makefile.PL.in create mode 100644 src/perl/xs/typemap create mode 100644 src/perl/xsinit.c diff --git a/Makefile.am b/Makefile.am index 263c34f8..3b9e61f3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -23,9 +23,6 @@ if HAVE_GNOME desktopdir = $(datadir)/gnome/apps/Internet desktop_DATA = irssi.desktop -pixmapsdir=$(datadir)/pixmaps -pixmaps_DATA=irssi-icon.png - corbadir = $(sysconfdir)/CORBA/servers corba_DATA = irssi.gnorba endif @@ -33,6 +30,8 @@ endif confdir = $(sysconfdir)/irssi conf_DATA = config colorless.theme split.theme +noinst_HEADERS = irssi-version.h + EXTRA_DIST = \ autogen.sh \ README \ @@ -40,9 +39,8 @@ EXTRA_DIST = \ file2header.sh \ irssi.spec \ $(conf_DATA) \ - $(pixmaps_DATA) \ - $(corba_DATA) \ - $(desktop_DATA) + irssi.gnorba \ + irssi.desktop ## make rpms rpm: Makefile diff --git a/NEWS b/NEWS index ac57843a..c8f4a8ba 100644 --- a/NEWS +++ b/NEWS @@ -1,8 +1,14 @@ v0.7.90 2000-04-xx Timo Sirainen * On the way to 0.8.0 .. Major rewriting/rearranging code. There's - some changes in behaviour because I'm trying to make Irssi a bit - more compatible with EPIC. + some changes in behaviour because I'm trying to make Irssi + compatible with EPIC as much as possible (except the scripting, + perl should be enough?) + + * Irssi isn't anymore IRC specific client, you could easily take the + whole IRC part away and use some other chat protocol instead, or + use both at the same time. Currently however, only IRC protocol + is supported. See docs/design.txt for more information. * libPropList isn't needed anymore - I'm using my own configuration library. This is mostly because different proplists worked a bit @@ -32,16 +38,125 @@ v0.7.90 2000-04-xx Timo Sirainen And finally I'm also using `const' all over the place. + * Signal handlers changed - you don't anymore return value 0 if you + wish to stop signal. Instead use signal_stop() or + signal_stop_by_name(). + + + Flood protection when sending commands to server works now better. + It allows sending first 5 messages immediately, but after that + only one message is sent every 2.2 seconds. + + This is the same flood protection that most IRC servers use, so + the only affect this protection has is that when sending a lot of + commands to server you won't get kicked out from server because of + "excessive flood". + + This can be changed from settings `cmd_max_at_once' and + `cmd_queue_speed'. If you want to disable this for some reason, use + /SET cmd_queue_speed 0 + /EVAL - Expand all the special variables from string and run it. Commands can be split with ; character. See - docs/SPECIAL_VARS for more info. + docs/special_vars.txt for more info. + Aliases are parsed just like /EVAL - arguments are in $0..$9. + Text formats are also parsed like /EVAL, arguments used to be in $1..$9, now they're in $0..$8 so it messes up existing themes.. + /SET [key [value]] - no more the '=' character. Boolean values also need to be changed with ON/OFF/TOGGLE values (not yes/no). - Settings aren't saved to disk until you use /SAVE. + + /SAVE [] - saves the settings to disk. + /REHASH [] - re-read the configuration file on the fly + /TOGGLE [ON/OFF] - same as /SET TOGGLE + + /ALIAS [-] [], /UNALIAS + Show, add or remove aliases. /ALIAS -alias = /UNALIAS alias + + /NOTIFY [-list] [-away] [-idle [minutes]] [ircnet [ircnet...]] + -away notifies about away-status changes + -idle notifies if idle time is first larger than `minutes' + (default is hour) and then it drops down. + -list lists the notify list entries with all their settings + /UNNOTIFY + + /NOTIFY without any arguments displays if the people in notify + list are online or offline. + + /HILIGHT [-nick | -regexp | -word] [-color ] + [-level ] [-channels ] + -nick: match only for nick + -regexp: `text' is a regular expression + -word: `text' must match to full words + -color: print the reply with `color' - color can be a bold (^B), + underline (^_) etc. too + -level: match only for `level' messages, default is + publics,msgs,notices,actions + -channels: match only in `channels' + /DEHILIGHT | + + /LASTLOG [-] [-new] [-regexp | -word] [- [...]] + [] [ []] + -: don't print the "Lastlog:" and "End of Lastlog" messages. + -new: show only lines since last /LASTLOG + -regexp: `text' is a regular expression + -word: `text' must match to full words + -level: what levels to check, like -public -msgs (default is all) + : text to search for, or all if empty + : maximum number of lines to show + : skip the last `start' lines + + /IGNORE [-regexp | -word] [-pattern ] [-except] + [-channels ] <^levels> + -regexp: `pattern' is a regular expression + -word: `pattern' must match to full words + -pattern: must match to the message's text + -except: *DON'T* ignore + -channels: ignore only in channels + : either a nick mask or list of channels + : list of levels to ignore + <^levels>: list of levels to NOT ignore + (/ignore -except nick notices = /ignore nick ^notices) + /UNIGNORE | + + The best match always wins, so you can have: + /IGNORE * CTCPS + /IGNORE -except *!*@host.org CTCPS + + /LOG OPEN [-noopen] [-autoopen] [-channels ] [-window] + [-rotate hour|day|month] [] + -noopen: create the entry to log list, but don't start logging + -autoopen: automatically open this log file at startup + -channels: log only in specified channels/nicks + -window: Log this window + -rotate: Reopen the log file every hour, day or month. This + makes only sense if you specify date/time formats + to file name. + : File name where to log, it is parsed with strftime(), + so %d=day, etc. see "man strftime" for more info. + : Defaults to ALL + /LOG CLOSE | - close log and remove from log list + /LOG START | - start logging to file + /LOG STOP | - stop logging to file + /LOG - display the log list + NOTE: Log files are locked after opened, so two irssi's can't + accidentally try to write to same log file. + + /WINDOW LOG ON|OFF|TOGGLE [] + Start/stop logging window, same as /LOG OPEN -window. If file name + isn't given, it defaults to ~/irc.log. or + ~/irc.log.Window if window doesn't have name. + /WINDOW LOGFILE + Creates the entry to log list, same as /LOG OPEN -window -noopen. + Also, if /WINDOW LOG ON is used it starts logging to this file. + + /SET AUTOLOG ON|OFF|TOGGLE + /SET AUTOLOG_LEVEL + /SET AUTOLOG_PATH - expandos can be used, $0 is the target. + Enables automatic logging, files are automatically created as + needed and after some time of inactivity, they are closed. If you + are using multiple servers, it makes sense to use the server tag + as part of the file name, for example ~/irclogs/$tag/$0.log (this + is the default). + + /SET window_auto_change - if enabled, irssi will automatically + change to automatically created windows (like queries). It will + also clear your command line and put it to command history so that + you don't accidentally write anything to wrong window. You'll get + the command back by pressing up arrow. + + /SET show_quit_once - show quit message only once instead of in + all channel windows the nick was joined. + + Server reconnections work better. It will now automatically set + your previous user mode and away message (and rejoin the channels, + which it already did before) after reconnected. If you use /SERVER + to connect to different IRC network, none of this will be done. v0.7.28 2000-03-11 Timo Sirainen diff --git a/README b/README index e38b428f..1da069f1 100644 --- a/README +++ b/README @@ -94,6 +94,7 @@ There's also some others, you can get a full list with ./configure --help --port -p - specify port --noconnect -! Don't autoconnect to any servers at startup --nick -n Specify what nick to use + --hostname -h Specify what host name to use * BUGS / SUGGESTIONS diff --git a/TODO b/TODO index 5036694c..5745b584 100644 --- a/TODO +++ b/TODO @@ -1,40 +1,34 @@ - - notifylist ei toimi, /ALIAS, /IGNORE -- g_strndup() !!!!! auttaa varmaan vaikka missä -- server-specific source_host +- rikki: + - dcc + - gnome versio.. + - pluginit, perlskriptit + +- teemat (toimiiko ne edes?) + - teeman vaihto tekstiversiolla, tekstien muuttaminen tekstiversiolla + - teemoihin tee jotain pientä selitystä edes! + - irssi can't find new themes in ~/.irssi/ while running - scan for new + themes when opening themes dialog? irssi-text also needs to be restarted + to use new themes.. + - use different themes in different channels/queries? + - logi voisi käyttää omaa teemaa + +- mites se awaylogi? +- /WALL, ja sen replyt +- /ON +- /CAT +- servereiden ja ircnettien asetusten käpistelyyn jotkut käskyt - curses sijainti jotain rikkoo -Day changed to 30-26 2000 -[00:10] .. [00:20] - - "away mode changed" - - dcc on särki - - /server +blah tekis uuden ikkunan. + - /msg =dcc_chatti,#kanava .. ei pelaa tollanen. voisi laittaa coreen tuon + ja jotain hookkeja et eri chattiprotoille voisi vaikka mennä se teksti.. + ctcp:lle sama? + - who ja listiin ne eri vipuset -[17:37] -!- Magi [^magi@magi.yok.utu.fi] has quit IRC [Killed (Uni-Stuttgart.DE ((^magi@magi.yok.utu.fi)GMD.DE <- (.@vipek-IV.vip.net.pl)*.pl[ircd@hub.irc.pl]))] -:Magi!^magi@magi.yok.utu.fi QUIT : - -Kalled (gart.DE ((^magi@magi.yok.utu.fi)GMD.DE <- (.@vipek-IV.vip.net.pl)*.pl[ircd@hub.irc.pl])) - ~cras@0:0:0:0:0:ffff: - -teemoihin tee jotain pientä selitystä edes! - - alt+left/right vaihtaa kanavaa.. - - - checkkaa miten ne autojoin_channelsit nyt meni.. että vapautetaan ym. - raiseta ikkuna jossa on tekstiä mut ei over aktiivisen päälle - line-split.c: varmista että se 64k limitti toimii eikä esim. kaada! - vaihda /set nimet järkevimmiksi -- optio että vaihtaa automaagisesti sinne autocreatettuun ikkunaan. tyhjennä -entry (laita historyyn) ettei uusi rivi mene query ikkunaan suoraan vahingossa. -- "älä näytä n. sekunttia pienempää lagia" -- cmd line switchi source hostille -- autojoinikaan ei tunnu oikein pelaavan..? vain kun vaihtuu serveri -- quit näytettäisiin vaan yhdessä ikkunassa. - /exec - - optionaalisesti voisi niitä logeja ajella siinä toisessa irssisessiossa - - msg:issä kun tulee sitä away viestiä näyttäisi vaan kerran.. - - logrotate - - ignoroida tietyt ctcpt. regexpit. ignorettaa tekstiä .. - egopallo/#tv.fi CANAL|MAFIA|... - autorun.ircnet - - flood protectionia paremmaksi - bottipluginiin tms. .. channel not available tms. rejoini *** Bugs @@ -44,11 +38,9 @@ entry (laita historyyn) ettei uusi rivi mene query ikkunaan suoraan vahingossa. channels that were joined in previous server. If IRC network is different than in previous server it shouldn't join the channels.. - some problems when using multiple windows with focus being all the time in - one of the windows and it can't be changed to different window?! + one of the windows and it can't be changed to different window?! Probably + has something to do with click to focus. - split windows are buggy, destroying them doesn't really work well.. - - irssi can't find new themes in ~/.irssi/ while running - scan for new - themes when opening themes dialog? irssi-text also needs to be restarted - to use new themes.. - mirc ctcp togglemenuitem isn't updated right - multiple dcc connections from different irc networks from same nick doesn't work. Maybe create "server nick" and "refer nick" variables to @@ -62,18 +54,9 @@ entry (laita historyyn) ettei uusi rivi mene query ikkunaan suoraan vahingossa. activity for example .. make some generic flag for items to use. - "you have new mail" - active server tag somewhere in window - - word wrapping doesn't work perfectly, if colors/bolds/etc are used, they're - treated as spaces. So things like (blah blah) can happen (/who) *** Big things - - Complete modularisation of everything, split irc-extra, ui-common and - gui-* (gui especially) into separate logical components. The modules would - have init(), deinit(), save_state() and restore_state() - save/restore - should save as much as possible so that it would be possible to restart the - whole base system. Like when upgrading to newer version you wouldn't need - to quit irc at all :) - - session saving thing.. specify what channels/queries/dcc chats to open in which window (real/tabbed/in same window with some other), what irc net channels goes to where, what channels/queries to open at startup, etc. @@ -107,30 +90,13 @@ entry (laita historyyn) ettei uusi rivi mene query ikkunaan suoraan vahingossa. *** Needs rethinking .. - * Logging, check how ircii logging works and try to do everything that it - can do ;) currently logging is done by directly writing to disk things - that are displayed in screen, it could instead (optionally) print things - simply as "JOIN #blah nick (a@b.c)". - ... just make a different theme for logging to use? .. - - log option: add the open/close time to log - - log directory, automatically log all channels and queries there - - overwrite/append - - all windows, just queries, only the channels in channel list - - you can be joined to same channels in different irc networks (or even - the same ircnet!) - create the logs to different directiories/names - - logging: longer format dd.mm.yy hh:mm:ss (configurable?) - - * Notify list, join the two different dialogs, ability to track changes in - gone flag + * Notify list, join the two different dialogs - _one_ popup dialog could open which lists all nicks in notifylist, maybe sorted by arrival time, display the dates, latest joined could be with different color? etc. - - nick-specific options: - - check for gone-flag changes (use userhosts instead of isons) + - nick-specific options: - pop up the dialog - run some command (like /exec as soon as I get that done :) - - dialog: keep track of hosts/realnames so after closing and opening the - dialog again they would show up.. * common api for statusbar handling - it should work just as well in text mode and gui, colors could be done @@ -144,11 +110,9 @@ entry (laita historyyn) ettei uusi rivi mene query ikkunaan suoraan vahingossa. *** Little things - - reload configuration file on the fly - /savewindows - save the current channel/query positions to file and load them at startup. - multi-DCC - open multiple sockets to transfer the file - - re-set away message when reconnecting to server - autoaway when idling - nickserv support (automatic /msg nickserv identify password) - /exec @@ -168,25 +132,19 @@ entry (laita historyyn) ettei uusi rivi mene query ikkunaan suoraan vahingossa. who are away and who are not.. optionally it could instead just watch if someone hasn't written anything to channel in n minutes and mark it "away" to nicklist. - - use different themes in different channels/queries? - /connect ircnet could connect to ircnet - change some GLists to GHashTables, aliases at least - check new irssi versions with http rather than with irssibot.. - implement requesting files with DCC GET from remote client for dcc file servers. good for people behind firewalls. - - use different nicks/realnames in different irc networks - gnome statubar: - clock? - dcc transfer meter (gtk progressbar) - you could configure which events (whois, notify, etc.) to show in what windows (all, current, status, msgs) - - gui for configuring plugin specific theme format texts - dcc send: allow selection of multiple files to send (also for dnd from gmc!) Allow dropping files to anywhere in irssi. - /timer, /clones - display net splits? - - regexp for hilighting words? - - subcommands (dcc, window, ..) could use common function instead of copy and - pasting the same function all the time and modifying just two words... - {}|~ are same as []\^ (not in all irc networks) - does this really affect irssi at all..? diff --git a/autogen.sh b/autogen.sh index 9a198abb..bf36cc97 100755 --- a/autogen.sh +++ b/autogen.sh @@ -14,4 +14,13 @@ PKG_NAME="Irssi" exit 1 } +# get versions + +version=`cat configure.in|grep AM_INIT_AUTOMAKE|sed 's/[^,]*, \([^\)]*\).*/\1/'` +version_date=`date +%Y%m%d` + +echo "/* automatically created by autogen.sh */" > irssi-version.h +echo "#define IRSSI_VERSION \"$version\"" >> irssi-version.h +echo "#define IRSSI_VERSION_DATE \"$version_date\"" >> irssi-version.h + . $srcdir/macros/autogen.sh diff --git a/config b/config index 49c68c37..6ca31901 100644 --- a/config +++ b/config @@ -9,13 +9,12 @@ setupservers = ( ); ircnets = ( - {name = IRCNet; max_kicks = 4; max_modes = 3; max_msgs = 5;}, + {name = IRCNet; max_kicks = 4; max_modes = 3; max_msgs = 5; max_whois = 4;}, {name = EFNet; max_kicks = 4; max_modes = 4; max_msgs = 3;}, {name = Undernet; max_kicks = 4; max_modes = 3; max_msgs = 3;}, {name = DALNet; max_kicks = 4; max_modes = 6; max_msgs = 3;}, {name = OPN; max_kicks = 1; max_modes = 6; max_msgs = 100;}, - {name = PTlink; max_kicks = 1; max_modes = 6; max_msgs = 100;}, - {name = Multichat; max_kicks = 1; max_modes = 6; max_msgs = 100;} + {name = PTlink; max_kicks = 1; max_modes = 6; max_msgs = 100;} ); channels = ( @@ -25,29 +24,36 @@ channels = ( autojoin = No; } ); -aliases = ( - {alias = J; command = "join";}, - {alias = LEAVE; command = "part";}, - {alias = BYE; command = "quit";}, - {alias = WI; command = "whois";}, - {alias = WII; command = "whois $0 $0";}, - {alias = WW; command = "whowas";}, - {alias = W; command = "who $C";}, - {alias = N; command = "names $C";}, - {alias = M; command = "msg";}, - {alias = T; command = "topic";}, - {alias = C; command = "clear";}, - {alias = CL; command = "clear";}, - {alias = K; command = "kick";}, - {alias = KB; command = "kickban";}, - {alias = KN; command = "knockout";}, - {alias = B; command = "ban";}, - {alias = UB; command = "unban";}, - {alias = IG; command = "ignore";}, - {alias = UNIG; command = "unignore";}, - {alias = SB; command = "scrollback";}, - {alias = UMODE; command = "mode $N";} -); +aliases = { + J = "join"; + LEAVE = "part"; + BYE = "quit"; + EXIT = "quit"; + SIGNOFF = "quit"; + DESCRIBE = "action"; + DATE = "time"; + HOST = "userhost"; + LAST = "lastlog"; + SAY = "msg *"; + WI = "whois"; + WII = "whois $0 $0"; + WW = "whowas"; + W = "who $C"; + N = "names $C"; + M = "msg"; + T = "topic"; + C = "clear"; + CL = "clear"; + K = "kick"; + KB = "kickban"; + KN = "knockout"; + B = "ban"; + UB = "unban"; + IG = "ignore"; + UNIG = "unignore"; + SB = "scrollback"; + UMODE = "mode $N"; +}; popups = ( {label = "Whois"; command = "/whois %s";}, {label = "DCC Send File"; command = "/dcc send %s";}, diff --git a/configure.in b/configure.in index 198a91a6..b25655e0 100644 --- a/configure.in +++ b/configure.in @@ -1,7 +1,7 @@ AC_INIT(src) AM_CONFIG_HEADER(config.h) -AM_INIT_AUTOMAKE(irssi, 0.7.28) +AM_INIT_AUTOMAKE(irssi, 0.7.90) AM_MAINTAINER_MODE @@ -194,7 +194,7 @@ dnl ** dnl ** just some generic stuff... dnl ** -AC_CHECK_FUNCS(mkfifo) +AC_CHECK_FUNCS(mkfifo fcntl) AC_CHECK_LIB(socket, socket, [ PROG_LIBS="$PROG_LIBS -lsocket" @@ -312,7 +312,7 @@ AC_SUBST(GUI_CFLAGS) dnl ** -dnl ** gui-text checks +dnl ** fe-text checks dnl ** AM_PATH_GLIB(1.2.0,,, gmodule) @@ -397,6 +397,22 @@ AM_CONDITIONAL(HAVE_PERL, test "$want_perl" = "yes") AC_SUBST(MYSQL_LIBS) +dnl ** +dnl ** Keep all the libraries here so each frontend doesn't need to +dnl ** keep track of them all +dnl ** +CORE_LIBS="../core/libcore.la ../lib-config/libirssi_config.la" +IRC_LIBS="../irc/libirc.la ../irc/core/libirc_core.la ../irc/dcc/libirc_dcc.la ../irc/flood/libirc_flood.la ../irc/notifylist/libirc_notifylist.la" +FE_COMMON_LIBS="../fe-common/core/libfe_common_core.la ../fe-common/irc/libfe_common_irc.la ../fe-common/irc/notifylist/libfe_common_irc_notifylist.la ../fe-common/irc/dcc/libfe_common_irc_dcc.la ../fe-common/irc/flood/libfe_common_irc_flood.la" + +AC_SUBST(CORE_LIBS) +AC_SUBST(IRC_LIBS) +AC_SUBST(FE_COMMON_LIBS) + +dnl ** common libraries needed by frontends +COMMON_LIBS="$FE_COMMON_LIBS $IRC_LIBS $CORE_LIBS" +AC_SUBST(COMMON_LIBS) + dnl ** dnl ** memory debugging dnl ** @@ -427,18 +443,28 @@ po/Makefile.in intl/Makefile macros/Makefile src/Makefile -src/irc-base/Makefile -src/irc-extra/Makefile -src/ui-common/Makefile -src/gui-none/Makefile -src/gui-text/Makefile -src/gui-gnome/Makefile -src/gui-gnome/help/Makefile -src/gui-gnome/help/C/Makefile -src/gui-gnome/pixmaps/Makefile +src/core/Makefile +src/irc/Makefile +src/irc/core/Makefile +src/irc/dcc/Makefile +src/irc/notifylist/Makefile +src/irc/flood/Makefile +src/fe-common/Makefile +src/fe-common/core/Makefile +src/fe-common/irc/Makefile +src/fe-common/irc/dcc/Makefile +src/fe-common/irc/flood/Makefile +src/fe-common/irc/notifylist/Makefile +src/fe-none/Makefile +src/fe-text/Makefile +src/fe-gnome/Makefile +src/fe-gnome/help/Makefile +src/fe-gnome/help/C/Makefile +src/fe-gnome/pixmaps/Makefile src/lib-config/Makefile src/lib-popt/Makefile -src/settings/Makefile +src/perl/Makefile +src/perl/xs/Makefile.PL servertest/Makefile scripts/Makefile docs/Makefile @@ -451,8 +477,6 @@ plugins/proxy/Makefile plugins/external/Makefile plugins/bot/Makefile plugins/sql/Makefile -plugins/perl/xs/Makefile.PL -plugins/perl/Makefile stamp.h irssi.spec) diff --git a/docs/COMMANDS b/docs/COMMANDS deleted file mode 100644 index 2a01a3bb..00000000 --- a/docs/COMMANDS +++ /dev/null @@ -1,387 +0,0 @@ - - ** Some definitions - - -"Level" usually means that you can use these words there: - - CRAP - Can be almost anything - PUB - Public messages in channel - MSGS - Private messages - CHAN - Channel messages: joins, parts, quits, etc. - NOTICES - Notices - SNOTES - Notices from server - WALLOPS - Wallops - ACTIONS - Actions (/me) - DCC - DCC messages - CTCP - CTCP messages - HILIGHT - Hilighted text - CLIENTNOTICES - Irssi's notices - CLIENTERRORS - Irssi's error messages - - - ** Server handling - - -CONNECT
[port [password [nick]]] - - Connect to specified server, if there's no password set it to - - -DISCONNECT <* / tag> [message] - - Disconnect from server - -SERVER
[port [password [nick]]] - - Disconnect from current server and connect to new one - -SERVERS - - Display a list of servers - -RMRECONNS - - Remove all servers from reconnection list - - - ** Basic IRC commands - - -QUIT [message] - - Quit irssi - -JOIN [key] [, channel...] - - Join to channel(s) - -PART [channel] [message] - - Leave from channel - -QUERY - - Create query window - -UNQUERY - - Close query window - -MSG - - Send message to nick/channel - -ME - - Send action to channel (/me thinks..) - -NOTICE - - Send notice to nick/channel - -WHOIS [server/nick] - - Send WHOIS query, you can also specify from what server to ask the - information. If you type the nick twice it will ask from the same - server what nick is using. - -AWAY [message] - - Sets yourself away/unaway - -AWAYALL [message] - - Sets yourself away/unaway to all connected servers - -WHO - - Show WHO list - -NAMES [channel] - - List nicks (in channel) - - - ** Bit more advanced commands - - -MODE - - Get/set channel/nick mode. - - Get channel modes: - b - Get ban list - e - Get ban exception list - I - Get invite list - - Set channel modes (use +/- before these): - b *!ban@mask - Set/remove ban - e *!ban@mask - Set/remove ban exception - I *!ban@mask - Set/remove channel invite - o nick - Set/remove op status - v nick - Set/remove voice status - l limit - Set remove max. people limit in channel - k key - Set/remove channel key - s - Secret - p - Private - m - Moderated - i - Invite only - n - No external messages - t - Only ops can change topic - - User modes: - i - Invisible - w - Show wallops - s - Show server notices - -TOPIC [channel] [topic] - - Get/set channel topic - -INVITE [channel] - - Invite nick to channel - -CTCP - - Send CTCP request to nick/channel (PING, VERSION, ..) - -NCTCP - - Send CTCP reply to nick/channel - -PING - - Send CTCP PING to nick and tell how long it took to receive the reply - -ISON [nick [nick...]] - - Ask if nicks are in IRC. - -WALL [channel] - - Send notice message to all operators in channel. - -OP, DEOP, VOICE, DEVOICE [channel] [nick [nick...] - - Op/deop/voice/devoice nick(s) in channel - -KICK [channel] - - Kick nick from channel - -KICKBAN [channel] - - Kick+ban nick from channel - -KNOCKOUT [secs] - - Kick+ban+delay (default to 5min)+unban - -BAN [channel] [nick [nick...]] - - Ban nick(s) in channel - -UNBAN [channel] [mask [mask...]] - - Remove ban(s) from channel - -BANSTAT [channel] - - List bans and ban exceptions in channel - -BANTYPE - - Set ban type: - - Normal - *!user@*.domain.net - Host - *!*@host.domain.net - Domain - *!*@*.domain.net - Custom [nick] [user] [host] [domain] - eg. /bantype custom nick domain - nick!*@*.domain.net - eg. /bantype custom user host - *!user@host.domain.net - -INVITELIST [channel] - - List invites (+I) in channel - -VERSION [server] - - Displays irssi version and asks IRC server's version - -VER [nick/channel] - - Sends CTCP VERSION request to nick/channel - -SV [nick/channel] - - Sends irssi version text to nick/channel - -KILL - - Kill nick from irc network. [irc ops only] - -WALLOPS - - Write wallops message. [irc ops only] - -QUOTE - - Send raw data to irc server - DON'T USE THIS unless you really know - what you're doing! - - - ** DCC handling - - -DCC - - List DCC connections (same as DCC LIST) - -DCC CHAT - - Open DCC chat - -DCC SEND - - Send file to nick - -DCC GET [filename] - - Get file offered by nick - -DCC RESUME [filename] - - (MIRC) Resume getting file offered by nick - -DCC CLOSE [filename] - - Close DCC connection - -DCC LIST - - List DCC connections - -MIRCDCC [n] - - Set MIRC style CTCPs on/off - - - ** User interface handling - - -WINDOW - - NEW [HIDDEN/TAB] - - Create new window (in tab) - - CLOSE - - Close the current window - - SERVER - - Change which server to use in current window - - PREV/NEXT/GOTO - - Go to previous/next/Nth window - - LEVEL <[+/-]pub/msgs/...> - - Change window level, eg. - /window level msgs - creates messages window - /window level all -msgs - creates status window - -CLEAR - - Clear screen - -ECHO - - Print text to screen - -MODES - - Open channel modes dialog (GTK/GNOME version) - -GWHOIS - - Display WHOIS information in dialog (GTK/GNOME version) - -LAST [-pub -msgs...] - - Display (only public/msgs/..) lines where appears - (Text version only) - - - ** Configuration - - -SET [key [value]] - - Get/set configuration. Boolean values also need to be changed - with ON/OFF/TOGGLE values (not yes/no). Settings aren't saved - to disk until you use /SAVE. - -TOGGLE key [ON|OFF] - - Same as /SET TOGGLE, or if ON or OFF parameter is given - it will work just like /SET. - -SAVE - - Save configuration to disk. - -ALIAS, UNALIAS [command] - - Set/remove alias, /unalias is the same as /alias without command - Typing extra / before /command (//command) ignores any aliases - -IGNORE, UNIGNORE [level [level..]] - - Ignore/unignore specified level(s) or everything from nick - -NOTIFY [ircnet [ircnet..]] - - Add mask (nick) to notify list for specified ircnets.. - -UNNOTIFY - - Remove mask from notify list. - -LOG - - CREATE [<+/->level ...] [#channel/nick [ - [<+/->level ...] ...] - - Create and start logging to file - - Example: /log create mylog -all +msgs #linux +chan +public - (or simply #linux +all logs everything that appears in #linux - window). - - CLOSE - - Close log and remove from configuration - - START - - Start logging to file - - STOP - - Stop logging to file - - LIST - - List logs. - -LOAD [arguments] - - Load plugin - -UNLOAD - - Unload plugin - diff --git a/docs/FAQ b/docs/FAQ deleted file mode 100644 index c7b0da6e..00000000 --- a/docs/FAQ +++ /dev/null @@ -1,33 +0,0 @@ -Getting bored at work.. so I decided to start writing this FAQ :) - -Q: Why can't I change channel topic from the topic entry widget? -A: You need to doubleclick it first, this is because the focus gets there - too easily and I got tired of accidentally changing topic all the time :) - -Q: What are the grey nicks in nicklist? -A: People who are away, this list is updated every now and then with sending - USERHOST commands to server, no nick is updated more frequently than once - per 5 minutes (except when doing WHO, WHOIS, etc. commands irssi - automatically updates the list) - -Q: Can I switch the channels with keyboard? -A: Yes, with Alt-1..0 for channels 1-10 and Alt-Q..P for channels 11-20 or - Ctrl-N to next window and Ctrl-P to previous window - -Q: Can I use bolds/underlines/reverses/bells/colors? -A: Sure, even while they don't get displayed in the entry line: - Ctrl-B = bold, Ctrl-G = bell, Ctrl-- = underline, Ctrl-V = reverse, - Ctrl-C = color - -Q: What does the "Join to #channel was synced in xx secs" mean? -A: After joined to channel, irssi asks the server for channel's mode, - who list, bans, ban exceptions and invite list (the later two only with - servers that support it (ircnet)). After all this is got, it displays the - sync message. - -Q: Is there any way to get WHOIS (etc.) replies to be displayed in the - current window instead of status window? -A: Just stop using the status window (take it off from preferences). But if - you still prefer to use the status window.. nope, not possible yet, but - it's been in TODO for a while to let the user decide what events to - display in what windows (status, msgs, current, all). diff --git a/docs/FORMATS b/docs/FORMATS deleted file mode 100644 index 633b0e42..00000000 --- a/docs/FORMATS +++ /dev/null @@ -1,19 +0,0 @@ - text text background - --------------------------------------------------------------------- - %k %K %0 black bold black black - %r %R %1 red bold red red - %g %G %2 green bold green green - %y %Y %3 yellow bold yellow yellow - %b %B %4 blue bold blue blue - %m %M %5 magenta bold magenta magenta - %p %P magenta (think: purple) - %c %C %6 cyan bold cyan cyan - %w %W %7 white bold white white - %n All colors turned off - %U Underline on/off - %8 Reverse on/off - %9 %_ Bold on/off - %: Insert newline - %| Marks the indentation position - %% A single % - diff --git a/docs/PERL b/docs/PERL deleted file mode 100644 index 94b83e11..00000000 --- a/docs/PERL +++ /dev/null @@ -1,621 +0,0 @@ - Running Perl scripts - -------------------- - -Place new scripts to ~/.irssi/scripts/, or /usr/lib/irssi/scripts/ -directory and run then with /RUN script. Or you could also run the -script from another place by specifying the whole path to it. Scripts -in ~/.irssi/scripts/autorun/ directory are automatically run at -startup. - -Using /PERLFLUSH closes and reopens the perl interpreter removing all -Perl scripts from memory. There's currently no way to unload a single Perl -script. Also, Irssi doesn't check if you run the same script twice or -different scripts use signal_add() for the same named function - it will -probably crash or do some weird things then. - - - Irssi's signals - --------------- - -Irssi is pretty much based on sending and handling different signals. -Like when you receive a message from server, say, -":nick!user@there.org PRIVMSG you :blahblah". Irssi will first send a -"server incoming" signal with the raw line as it's first parameter. You -probably don't want to use this signal. Next thing Irssi does is to -interpret the header and send a "server event" signal with arguments -"PRIVMSG you...", server, "nick", "user@there.org". You probably don't -want to use this either, since next irssi will send an "event privmsg" -signal with the "you :blahblah" as it's argument. You can at any point -grab the signal, do whatever you want to do with it and optionally stop -it from going any further by returning from the function with value 1. - -For example: - --------------------------------------------------------- -sub event_privmsg { - # $data = "nick/#channel :text" - my ($data, $server, $nick, $address) = @_; - my ($target, $text) = $data =~ /^(\S*)\s:(.*)/; - - return 1 if ($text =~ /free.*porn/); - return 1 if ($nick =~ /idiot/); -} - -Irssi::signal_add("event privmsg", "event_privmsg") --------------------------------------------------------- - -This will hide all public or private messages that match the regexp -"free.*porn" or the sender's nick contain the word "idiot". - -You can also use signal_add_last() if you wish to let the Irssi's internal -functions be run before yours. - -A list of signals that irssi send can be found from SIGNALS file. - - - Message levels - -------------- - -Several functions expect message levels. Sometimes numeric and sometimes -alphabetic. Yes, it's stupid, will fix it :) For now you can use -Irssi::level2bits() function to convert the level string to numeric. Here's -all the levels that irssi supports currently: - -CRAP, MSGS, PUBLIC, NOTICES, SNOTES, CTCPS, ACTIONS, JOINS, PARTS -QUITS, KICKS, MODES, SMODES, TOPICS, WALLOPS, INVITES, NICKS, PONGS -DCC, CLIENTNOTICE, CLIENTCRAP, CLIENTERROR, HILIGHT -(and NOHILIGHT if you don't want the message to be hilighted ever..) - -For example: - -$server->printtext("#channel", Irssi::level2bits('clientcrap'), 'Hello, world'); - -Writes text to #channel window with clientcrap level. - - - Functions that you can use in Irssi's Perl scripts - -------------------------------------------------- - -This is just my very first implementation and things will probably change. - -Commands marked with (!!) mean that you shouldn't use it unless you -know what you're doing.. - -If there's a "Xxxx::" text before the command, it means that it belongs to -that package. Like "Server::command" means that you should either call it as - Irssi::Server::command($server, $cmd); -or more easily: - $server->command($cmd); - -Commands that don't have the Xxxx prefix are called as Irssi::command(); - - - *** General - -Channel cur_channel() - return current channel -Server cur_server() - return current server - -channels() - return list of all channels -servers() - return list of all servers -commands() - return list of all commands -dccs() - return list of all dcc connections -logs() - return list of all log files -plugins() - return list of all plugins - -print(str) - Print `str' to current window as "Irssi notice". - -command(cmd, [Server server, [Channel channel]]) - Send a command `cmd' (in current channel). This will work just as if you - had typed `cmd' in command line, so you'll need to use /COMMANDS or the - text will be sent to the channel. - -Server::command(cmd, [Channel channel]) - Just like above, except different calling method. - -Channel::command(cmd) - Just like above, except different calling method. - -Server::printtext(channel, level, str) - Print `str'. - -setup_get(option) - Get value of `option' from setup and return it. - - - *** Message levels - -level2bits(level) - Level string -> number - -bits2level(bits) - Level number -> string - -combine_level(level, str) - Combine level number to level string ("+level -level"). - Return new level number. - - - *** Signals / timeouts - -signal_emit(signal, ...) - Send signal `signal' - -signal_add(signal, func) - Bind `signal' to function `func' - -signal_add_last(signal, func) - Bind `signal' to function `func'. Call `func' as late as possible. - -signal_remove(signal, func) - Unbind `signal' from function `func' - -tag timeout_add(msecs, func, data) - Call `func' every `msecs' milliseconds (1000 = 1 second) with - parameter `data'. Returns tag which can be used to stop the timeout. - -timeout_remove(tag) - Remove timeout with tag. - - - *** Commands - -Command::values() - Get some information about command. This function returns a reference to - hash table. Hash table has keys: - "cmd" - Command - "category" - Category - -command_bind(cmd, category, func) - Bind command `cmd' to call function `func'. `category' is the - category where the command is displayed in /HELP. - -command_unbind(cmd, func) - Unbind command `cmd' from function 'func. - -Server::irc_send_cmd_split(cmd, arg, max_nicks) - Split the `cmd' into several commands so `arg' argument has only - `max_nicks' number of nicks. - - Example: $server->irc_send_cmd_split("KICK #channel nick1,nick2,nick3 :byebye", 2, 2); - Irssi will send commands "KICK #channel nick1,nick2 :byebye" and - "KICK #channel nick3 :byebye" to server. - - - *** Server Connects - -This is a record where we keep connection information. All Servers and -Reconnects records have pointer to one of these. - -Connect::values() - Get some information about connect. This function returns a reference to - hash table. Hash table has keys: - "address" - Address where we connected (irc.blah.org) - "port" - Port where we connected - "password" - Password we used in connection. - - "ircnet" - IRC network - "wanted_nick" - Nick which we would prefer to use - "alternate_nick" - Alternate nick which we would prefer to use - "username" - User name - "realname" - Real name - -Connect server_create_conn(address, [port=6667, [password='', [nick='', [channels='']]]]) - Create new server connection. - - *** Server functions - -Server::values() - Get some information about server. This function returns a reference to - hash table. Hash table has keys: - "address" - Address where we connected (irc.blah.org) - "port" - Port where we connected - "password" - Password we used in connection. - - "ircnet" - IRC network - "wanted_nick" - Nick which we would prefer to use - "alternate_nick" - Alternate nick which we would prefer to use - "username" - User name - "realname" - Real name - - "tag" - Unique server tag. - "real_address" - Who the server thinks it is (irc1.blah.org) - "nick" - Current nick - "usermode" - Current user mode - "usermode_away" - Are we marked as away? 1|0 - "away_reason" - Away reason - "connected" - Is connection finished? 1|0 - "connection_lost" - Did we lose the connection (1) or was - the connection meant to be disconnected (0) - Example: - %server_info = %{Irssi::cur_server->values()}; - Irssi::print("Current server = ".$server_info{'address'}); - -Server Connect::connect() - Connect to server. - -Server::disconnect() - Disconnect from server. - -Server server_find_tag(tag) - Find server with tag - -Server server_find_ircnet(ircnet) - Find first server that is in `ircnet' - -Channel channel_find(channel) - Find `channel' from any server - -Channel Server::channel_find_level(level) - Find channel with level `level' preferably from specified server, but - fallbacks to any channel the matching level. - -Server::send_raw(cmd) - Send raw message to server, it will be flood protected so you - don't need to worry about it. - -Server::ctcp_send_reply(data) - Send CTCP reply. This will be "CTCP flood protected" so if there's too - many CTCP requests in buffer, this reply might not get sent. - - - *** Server redirections - -WARNING: It's easy to mess up the Irssi's internal server expectations with -these commands! - -This is a powerful feature of Irssi that I can't seen in other IRC clients. -You can EASILY grab the server's reply for a command you send to server -without any horrible kludges. - -Server::redirect_init(command, last, ...) - Initialize redirection for specified command. This needs to be done only - once. Irssi already initializes commands "WHOIS", "WHO", "LIST" and "ISON". - `command' is the whole name of the signal, like "command whois". - `last' specifies how many of the items in `...' is considered as the - "last event" from the command. - - Example: $server->redirection_init('command who', - 2, # 2 first events will finish the command - 'event 401', # unknown nick (finished) - 'event 315', # end of who (finished) - 'event 352'); # who line (wait..) - -Server::redirect_event(arg, last, ...) - Add redirection. `arg' is a space separated list of arguments that should - match before Irssi will redirect the event (think of /WHOIS nick nick and - doing another to different nick immediately after it, there's no way of - knowing which will return first. so, arg would be in this case 'nick'). - - `last' specifies how many of the following events are considered as - "last event" from command - just like in redirect_init(). - - `...' is `event, signal, argpos, ...`, where - `event' is the event we're waiting from server. - `signal' is the signal we will send after receiving the event. It should - always start with 'redir ' so that Irssi's perl handler knows to - send correct arguments to signal handler. - `argpos' is the argument position in event's data or -1 if it - should be ignored. - - Example: - $server->send_raw('WHOIS :cras'); - $server->redirect_event('cras', 2, - "event 318", "redir end_of_whois", -1, - "event 402", "redir no_such_server", -1, - "event 401", "redir no_such_nick", 1, - "event 311", "redir whois", 1, - "event 301", "redir whois_away", 1, - "event 312", "redir whois_server", 1, - "event 313", "redir whois_oper", 1, - "event 317", "redir whois_idle", 1, - "event 319", "redir whois_channels", 1); - In the 402-case we tried "/WHOIS nick nick" but nick didn't exist.. - -group Server::redirect_single_event(arg, last, group, event, signal, argpos) - Same as redirect_event() except you can set it up in pieces. - If `group' is 0, it will create new group and return it's id. - - - *** IRC masks - -irc_mask_match(mask, nick, user, host) - Return 1 if `mask' matches nick!user@host. - -irc_mask_match_address(mask, nick, address) - Return 1 if `mask' matches nick!address. - -irc_masks_match(masks, nick, address) - Return 1 if any mask in the `masks' (string separated with spaces) - matches nick!address. - -irc_get_mask(nick, host, flags) - Create IRC mask from nick!host. - flags = you need to combine these: - (FIXME: export the IRC_xxx defines to perl (or something)) - IRC_MASK_NICK 0x01 - IRC_MASK_USER 0x02 - IRC_MASK_HOST 0x04 - IRC_MASK_DOMAIN 0x08 - - - *** Channels - -Channel::values() - Get some information about channel. This function returns a reference to - hash table. Hash table has keys: - "server" - Server of the channel - "name" - Channel name - "type" - Channel type ("channel", "query", "dcc chat", "empty") - "topic" - Channel topic - "key" - Channel key (password) - "limit" - Max. users in channel (+l mode) - "level" - Channel's level number. - "new_data" - 0=no new data, 1=text, 2=msg, 3=msg for you - "synced" - Channel is synchronized - "wholist" - Channel has received /WHO list - "names_got" - Channel has received /NAMES list - "chanop" - You are channel operator - "left" - You just left the channel (for "channel destroyed" event) - "kicked" - You was just kicked out of the channel (for - "channel destroyed" event) - -Channel Server::channel_create(channel, type, automatic) - Create new channel with name `channel'. `type' is one of: - (FIXME: export these to perl somehow) - CHANNEL_TYPE_CHANNEL 0 - CHANNEL_TYPE_QUERY 1 - CHANNEL_TYPE_DCC_CHAT 2 - CHANNEL_TYPE_EMPTY 3 - `automatic' means that channel is created "automatically" and - Irssi will NOT change the active window to it. - -Channel::destroy() - Destroy channel. - -Channel::change_name(name) - Change channel's name - -Channel::get_mode() - Return channel's mode - -Channel Server::channel_find(channel) - Find `channel' in server. - -Channel Server::channel_find_closest(channel, level) - Find `channel' or if not found, some other channel that has - level `level' (number). - -Channel channel_find_level(level) - Find channel with level `level'. - - - *** Channel modes - -Ban::values() - Get some information about ban. This function returns a reference to - hash table. Hash table has keys: - "ban" - The ban - "setby" - Nick of who set the ban - "time" - Timestamp when ban was set - -Ban Channel::ban_add(ban, nick, time) - Add new ban. (!!) - -Channel::ban_remove(ban) - Remove ban. (!!) - -Ban Channel::ban_exception_add(ban, nick, time) - Add ban exception (!!) - -Channel::ban_exception_remove(ban) - Remove ban exception (!!) - -Channel::invitelist_add(mask) - Add invite (!!) - -Channel::invitelist_remove(mask) - Remove invite (!!) - -Channel::modes_parse_channel(setby, modestr) - Parse mode string (!!) - -Channel::ban_get_mask(nick) - Get ban mask for `nick'. - -Channel::modes_set(data, mode) - Set mode `mode' ("+o", "-o", etc.) to all nicks in `data' - separated with spaces. - - - *** Nick list - -Nick::values() - Get some information about nick. This function returns a reference to - hash table. Hash table has keys: - "nick" - Plain nick - "host" - Host (blah@there.org) - "name" - Real name - "hops" - Hop count to the server nick is using - "op", "voice", "gone", "ircop" - 1 or 0 - "last_check" - timestamp when last checked gone/ircop status. - "send_massjoin" - Waiting to be sent in a "massjoin" signal - 1 or 0 - -Nick Channel::nicklist_insert(nick, op, voice, send_massjoin) - Add nick to nicklist. (!!) - -Channel::nicklist_remove(nick) - Remove nick from nicklist. (!!) - -Nick Channel::nicklist_find(mask) - Find nick from nicklist. - -Channel::nicklist_getnicks(channel) - Return a list of all nicks (Nick packages) in channel. - - - *** DCC - -Dcc:destroy() - Destroy DCC connection. (!!) - -dcc_type2str(type) - DCC type number to string - -dcc_str2type(type) - DCC type string to number - -Dcc dcc_find_item(type, nick, arg) - Find DCC connection. - -Dcc dcc_find_by_port(nick, port) - Find DCC connection by port. - - - *** Reconnects - -Reconnect::values() - Get some information about reconnect. This function returns a reference to - hash table. Hash table has keys: - "tag" - Unique numeric tag - "next_connect" - Unix time stamp when the next connection occurs - - "address" - Address where we connected (irc.blah.org) - "port" - Port where we connected - "password" - Password we used in connection. - - "ircnet" - IRC network - "wanted_nick" - Nick which we would prefer to use - "alternate_nick" - Alternate nick which we would prefer to use - "username" - User name - "realname" - Real name - - - *** Netsplits - -Netsplit::values() - Get some information about netsplit. This function returns a reference to - hash table. Hash table has keys: - "nick" - Nick - "address" - Nick's host - "server" - The server nick was in - "destserver" - The other server where split occured. - "destroy" - Timestamp when this record should be destroyed - /*FIXME: add list of channels the nick was in;*/ - -Netsplit Server::netsplit_find(nick, address) - Check if nick!address is on the other side of netsplit. Netsplit records - are automatically removed after 30 minutes (current default).. - -Nick Server::netsplit_find_channel(nick, address, channel) - Find nick record for nick!address in channel `channel'. - - - *** Notify list - -notifylist_add(nick, ircnet) - Add `nick' to notify list in irc network `ircnet' - -Server notifylist_ison(nick, ircnets) - Check if `nick' is in IRC. `ircnets' is a space separated - list of irc networks. If it's empty string, all servers will be checked. - -Server::notifylist_ison_server(nick) - Check if `nick' is on IRC server. - - - *** Rawlog - -Server::rawlog_input(str) - Send `str' to raw log as input text. (!!) - -Server::rawlog_output(str) - Send `str' to raw log as output text. (!!) - -Server::rawlog_redirect(str) - Send `str' to raw log as redirection text. (!!) - - - *** Ignores - -Autoignore::values() - Get some information about autoignore. This function returns a reference to - hash table. Hash table has keys: - "nick" - Ignored nick - "timeleft" - Seconds left to ignore - "level" - Ignoring level number - -ignore_add(mask, level) - Ignore `mask' with level string - -ignore_remove(mask, level) - Unignore level string from `mask' - -Server::ignore_check(nick, host, type) - Return 1 if nick!host is ignored with level number `type'. - -Server::autoignore_add(type, nick) - Autoignore `nick' in server with level number `type'. - -Server::autoignore_remove(mask, level) - Remove autoignoring `nick' from server. `level' is a string. - - - *** Logging - -Log::values() - Get some information about log. This function returns a reference to - hash table. Hash table has keys: - "fname" - Log file name - "autoopen_log" - Automatically open log at startup - "last" - Timestamp when last write occured. - "level" - Global logging level. - /*FIXME: add list of Logitems;*/ - -Logitem::values() - Get some information about logitem. This function returns a reference to - hash table. Hash table has keys: - "name" - Log item name. - "level" - Logging level number. - -Log log_create(fname, data) - Create log file. `data' = logging level ("-all #channel +public") - -Log log_create_with_level(fname, level) - Create log file with level number. - -Log log_file_find(fname) - Find log file. - -Log::destroy() - Destroy log file - -Log::open() - Start logging - -Log::close() - Stop logging - -Log::append_item(name, level) - Append log item with level number `level' to log file. (!!) - -Log::remove_item(log, name) - Remove log item. (!!) - - - *** Plugins - -Plugin::values() - Get some information about plugin. This function returns a reference to - hash table. Hash table has keys: - "name" - Plugin name - "description" - Plugin description - -plugin_load(name, args) - Load plugin. - -plugin_get_description(name) - Get plugin description string. - -Plugin plugin_find(name) - Find plugin. diff --git a/docs/SIGNALS b/docs/SIGNALS deleted file mode 100644 index 7939275c..00000000 --- a/docs/SIGNALS +++ /dev/null @@ -1,224 +0,0 @@ -IRC base --------- - -* Requires to work properly: - - "gui exit" - "gui channel open", CHANNEL_REC - "send command", char *command, SERVER_REC, CHANNEL_REC - -* Provides signals: - -irc.c: - - "send command", char *args, SERVER_REC - "command ", char *args, SERVER_REC, CHANNEL_REC - "default command", char *args, SERVER_REC, CHANNEL_REC - - "server event", char *data, SERVER_REC, char *sender_nick, char *sender_address - "event ", char *args, SERVER_REC, char *sender_nick, char *sender_address - "default event", char *data, SERVER_REC, char *sender_nick, char *sender_address - - "server incoming", SERVER_REC, char *data - -(for perl parser..) - "redir ", char *args, SERVER_REC, char *sender_nick, char *sender_address - -bans.c: - - "ban new", BAN_REC - "ban remove", BAN_REC - "ban exception new", BAN_REC - "ban exception remove", BAN_REC - "ban type changed", char *bantype - -commands.c: - "commandlist new", COMMAND_REC - "commandlist remove", COMMAND_REC - -channels.c: - - "channel created", CHANNEL_REC - "channel destroyed", CHANNEL_REC - "channel name changed", CHANNEL_REC - "channel topic changed", CHANNEL_REC - "channel server changed", CHANNEL_REC, SERVER_REC *oldserver - - "channel query", CHANNEL_REC - "channel wholist", CHANNEL_REC - "channel sync", CHANNEL_REC - -ctcp.c: - - "ctcp msg ", char *args, SERVER_REC, char *nick, char *addr, char *target - "default ctcp msg", char *args, SERVER_REC, char *nick, char *addr, char *target - "ctcp reply ", char *args, SERVER_REC, char *nick, char *addr, char *target - "default ctcp reply", char *args, SERVER_REC, char *nick, char *addr, char *target - -lag.c: - - "server lag", SERVER_REC - "server lag disconnect", SERVER_REC - "lag", char *server, int lag - -modes.c: - - "invitelist new", CHANNEL_REC, char *mask - "invitelist remove", CHANNEL_REC, char *mask - - "channel mode changed", CHANNEL_REC - "user mode changed", SERVER_REC - "nick mode changed", CHANNEL_REC, NICK_REC - -netsplit.c: - - "netsplit add", NETSPLIT_REC - "netsplit remove", NETSPLIT_REC - -nicklist.c: - - "nicklist new", CHANNEL_REC, NICK_REC - "nicklist remove", CHANNEL_REC, NICK_REC - "nicklist changed", CHANNEL_REC, NICK_REC, char *oldnick - "nick gone changed", CHANNEL_REC, NICK_REC - "nick ircop changed", CHANNEL_REC, NICK_REC - "server nick changed", SERVER_REC - "massjoin", CHANNEL_REC, GSList of NICK_RECs - -rawlog.c: - - "rawlog", SERVER_REC, char *data - -server.c: - - "server connect failed", SERVER_REC - "server connected", SERVER_REC - "server connecting", SERVER_REC, ulong *ip - "server looking", SERVER_REC - "server disconnected", SERVER_REC - "event connected", SERVER_REC - -server-reconnect.c: - - "server reconnect new", RECONNECT_REC - "server reconnect remove", RECONNECT_REC - "server reconnect not found", char *tag - -signal.c: - - "signal", char *name, ... - "last signal", char *name, ... - -IRC extra ---------- - -* Requires to work properly: - - "print text stripped", SERVER_REC, char *channel, int level, char *text - "plugin add menu", char *menuitem, void (*func) (gpointer, PLUGIN_REC), PLUGIN_REC - -* Provides signals: - -dcc.c: - - "dcc ctcp ", char *args, DCC_REC - "default dcc ctcp", char *args, DCC_REC - "dcc unknown ctcp", char *args, char *sender, char *sendaddr - - "dcc reply ", char *args, DCC_REC - "default dcc reply", char *args, DCC_REC - "dcc unknown reply", char *args, char *sender, char *sendaddr - - "dcc chat message", DCC_REC, char *msg - - "dcc created", DCC_REC - "dcc destroyed", DCC_REC - "dcc connected", DCC_REC - "dcc rejecting", DCC_REC - "dcc closed", DCC_REC - "dcc chat message", DCC_REC, char *msg - "dcc transfer update", DCC_REC - "dcc request", DCC_REC - "dcc get receive", DCC_REC - "dcc error connect", DCC_REC - "dcc error file create", DCC_REC, char *filename - "dcc error file not found", char *nick, char *filename - "dcc error get not found", char *nick - "dcc error send exists", char *nick, char *filename - "dcc error unknown type", char *type - "dcc error close not found", char *type, char *nick, char *filename - -flood.c: - - "flood", SERVER_REC, char *nick, char *host, char *level, char *target - -ignore.c: - - "autoignore new", SERVER_REC, AUTOIGNORE_REC - "autoignore remove", SERVER_REC, AUTOIGNORE_REC - "ignore new", LIST_REC - "ignore change", LIST_REC - "ignore remove", LIST_REC - -log.c: - - "log created", LOG_REC - "log destroyed", LOG_REC - "log opened", LOG_REC - "log closed", LOG_REC - "log written", LOG_REC, char *line - "log item created", LOG_REC, LOG_ITEM_REC - "log item destroyed", LOG_REC, LOG_ITEM_REC - -notifylist.c: - - "notifylist new", LIST_REC - "notifylist remove", LIST_REC - "notifylist joined", SERVER_REC, char *nick, char *username, char *host, char *realname - "notifylist left", SERVER_REC, char *nick - -plugins.c: - - "plugin created", PLUGIN_REC - "plugin loaded", PLUGIN_REC - "plugin destroyed", PLUGIN_REC - - "plugin error already loaded", char *plugin - "plugin error invalid", char *plugin - "plugin error load", char *plugin, char *error - "plugin error not loaded", char *plugin - "plugin error version", char *plugin - -UI common ---------- - -* Requires to work properly: - - "gui print text", CHANNEL_REC, int fg, int bg, int flags, char *text - "gui window goto", int number - -* Can be used to determine when all "gui print text"s are sent (not required) - - "print text finished", CHANNEL_REC - -* Provides signals: - -ui-keyboard.c: - - "keyinfo created", KEYINFO_REC - "keyinfo destroyed", KEYINFO_REC - -ui-printtext.c: - - "print text", SERVER_REC, char *channel, int level, char *text - "print text stripped", SERVER_REC, char *channel, int level, char *text - -ui-themes.c: - - "theme created", THEME_REC - "theme destroyed", THEME_REC - -ui-windows.c: - - "window created", WINDOW_REC - "window destroyed", WINDOW_REC diff --git a/docs/SPECIAL_VARS b/docs/SPECIAL_VARS deleted file mode 100644 index e8020558..00000000 --- a/docs/SPECIAL_VARS +++ /dev/null @@ -1,104 +0,0 @@ -NOTE: This is just a slightly modified file taken from EPIC's help. -'!' at start of the line means that the feature doesn't work yet.. - -Special Variables and Expandos - -Irssi supports a number of reserved, dynamic variables, sometimes -referred to as expandos. They are special in that the client is -constantly updating their values automatically. There are also -numerous variable modifiers available. - - Modifier Description - $variable A normal variable, expanding to the first match of: - | 1) an internal SET variable - | 2) an environment variable - $[num]variable Expands to the variables value, with 'num' width. If - | the number is negative, the value is right-aligned. - | The value is padded to meet the width with the - | character given after number (default is space). - | The value is truncated to specified width unless - | '!' character precedes the number. - $#variable Expands to the number of words in $variable. If $variable - | is omitted, it assumes $* - $@variable Expands to the number of characters in $variable. if - | $variable is omitted, it assumes $* - $($subvariable) This is somewhat similar to a pointer, in that the - | value of $subvar is taken as the name of the - | variable to expand to. Nesting is allowed. - ${expression} Permits the value to be embedded in another string - | unambiguously. -! $!history! Expands to a matching entry in the client's command - | history, wildcards allowed. -! $"some text" Uses 'text' as an input prompt, and returns whatever - | is typed next. This usage is deprecated, use the - | INPUT command instead. -! $'some text' Same as $"text" except that it only returns the first - | next typed character. - -Whenever an alias is called, these expandos are set to the arguments passed -to it. If none of these expandos are used in the alias, or the $() form -shown above, any arguments passed will automatically be appended to the last -command in the alias. - - Expando Description - $* expands to all arguments passed to an alias - $n expands to argument 'n' passed to an alias (counting from zero) - $n-m expands to arguments 'n' through 'm' passed to an alias - $n- expands to all arguments from 'n' on passed to an alias - $-m expands to all arguments up to 'm' passed to an alias - $~ expands to the last argument passed to an alias - -These variables are set and updated dynamically by the client. The case of -$A .. $Z is important. - - Variable Description -! $, last person who sent you a MSG -! $. last person to whom you sent a MSG -! $: last person to join a channel you are on -! $; last person to send a public message to a channel you are on - $A text of your AWAY message, if any -! $B body of last MSG you sent - $C current channel -! $D last person that NOTIFY detected a signon for -! $E idle time -! $F time client was started, $time() format -! $H current server numeric being processed -! $I channel you were last INVITEd to - $J client version text string - $K current value of CMDCHARS -! $L current contents of the input line - $M modes of current channel, if any - $N current nickname -! $O value of STATUS_OPER if you are an irc operator - $P if you are a channel operator in $C, expands to a '@' - $Q nickname of whomever you are QUERYing -! $R version of current server - $S current server name - $T target of current input (channel or QUERY nickname) -! $U value of cutbuffer -! $V client release date (numeric version string) - $W current working directory -! $X your /userhost $N address (user@host) - $Y value of REALNAME - $Z time of day (hh:mm) - $$ a literal '$' - -For example, assume you have the following alias: - - alias blah msg $D Hi there! - -If /blah is passed any arguments, they will automatically be appended to the -MSG text. For example: - - /blah oops /* command as entered */ - "Hi there! oops" /* text sent to $D */ - -Another useful form is ${}. In general, variables can be embedded inside -strings without problems, assuming the surrounding text could not be -misinterpreted as part of the variable name. This form guarantees that -surrounding text will not affect the expression's return value. - - /eval echo foo$Nfoo /* breaks, looks for $nfoo */ - /eval echo foo${N}foo /* ${N} returns current nickname */ - fooYourNickfoo /* returned by above command */ - diff --git a/src/Makefile.am b/src/Makefile.am index 7f8b82f1..a548c4f4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,13 +1,13 @@ if BUILD_TEXTUI -TEXTUI=gui-text +TEXTUI=fe-text endif if BUILD_GNOMEUI -GNOMEUI=gui-gnome +GNOMEUI=fe-gnome endif if BUILD_IRSSIBOT -BOTUI=gui-none +BOTUI=fe-none endif noinst_HEADERS = \ @@ -17,4 +17,4 @@ noinst_HEADERS = \ irssi-plugin.h \ irssi-plugin-gui.h -SUBDIRS = lib-popt lib-config irc-base irc-extra ui-common $(GNOMEUI) $(TEXTUI) $(BOTUI) +SUBDIRS = lib-popt lib-config core irc fe-common perl $(GNOMEUI) $(TEXTUI) $(BOTUI) diff --git a/src/common-setup.h b/src/common-setup.h index e04ca4f0..a658e836 100644 --- a/src/common-setup.h +++ b/src/common-setup.h @@ -13,9 +13,6 @@ /* How often to check if there's anyone to be unbanned in knockout list */ #define KNOCKOUT_TIMECHECK 10000 -/* How often to check users in notify list */ -#define NOTIFY_TIMECHECK 30000 - /* How often to check for gone status of nick */ #define MAX_GONE_REFRESH_TIME 300 diff --git a/src/common.h b/src/common.h index e3dde2c6..4714c82f 100644 --- a/src/common.h +++ b/src/common.h @@ -35,7 +35,7 @@ #include #include -#include "irc-base/memdebug.h" +#include "core/memdebug.h" #include "nls.h" #define g_free_not_null(a) \ diff --git a/src/lib-config/get.c b/src/lib-config/get.c index b5c3f42e..8ac3e667 100644 --- a/src/lib-config/get.c +++ b/src/lib-config/get.c @@ -40,11 +40,10 @@ CONFIG_NODE *config_node_find(CONFIG_NODE *node, const char *key) /* find the section from node - if not found create it unless new_type is -1. you can also specify in new_type if it's NODE_TYPE_LIST or NODE_TYPE_BLOCK */ -CONFIG_NODE *config_node_section(CONFIG_REC *rec, CONFIG_NODE *parent, const char *key, int new_type) +CONFIG_NODE *config_node_section(CONFIG_NODE *parent, const char *key, int new_type) { CONFIG_NODE *node; - g_return_val_if_fail(rec != NULL, NULL); g_return_val_if_fail(parent != NULL, NULL); g_return_val_if_fail(is_node_list(parent), NULL); @@ -91,7 +90,7 @@ CONFIG_NODE *config_node_traverse(CONFIG_REC *rec, const char *section, int crea is_list = **tmp == '('; if (create) new_type = is_list ? NODE_TYPE_LIST : NODE_TYPE_BLOCK; - node = config_node_section(rec, node, *tmp + is_list, new_type); + node = config_node_section(node, *tmp + is_list, new_type); if (node == NULL) return NULL; } g_strfreev(list); @@ -252,3 +251,34 @@ int config_node_get_keyvalue(CONFIG_NODE *node, const char *key, const char *val return -1; } + +/* Return all values from from the list `node' in a g_strsplit() array */ +char **config_node_get_list(CONFIG_NODE *node) +{ + GString *values; + GSList *tmp; + char **ret; + + g_return_val_if_fail(node != NULL, NULL); + g_return_val_if_fail(is_node_list(node), NULL); + + /* put values to string */ + values = g_string_new(NULL); + for (tmp = node->value; tmp != NULL; tmp = tmp->next) { + node = tmp->data; + + if (node->type == NODE_TYPE_VALUE) + g_string_sprintfa(values, "%s ", (char *) node->value); + } + + /* split the values to **str array */ + if (values->len == 0) + ret = NULL; + else { + g_string_truncate(values, values->len-1); + ret = g_strsplit(values->str, " ", -1); + } + + g_string_free(values, TRUE); + return ret; +} diff --git a/src/lib-config/iconfig.h b/src/lib-config/iconfig.h index bbee0f6e..320b0629 100644 --- a/src/lib-config/iconfig.h +++ b/src/lib-config/iconfig.h @@ -108,13 +108,17 @@ int config_set_bool(CONFIG_REC *rec, const char *section, const char *key, int v CONFIG_NODE *config_node_find(CONFIG_NODE *node, const char *key); /* Find the section from node - if not found create it unless new_type is -1. You can also specify in new_type if it's NODE_TYPE_LIST or NODE_TYPE_BLOCK */ -CONFIG_NODE *config_node_section(CONFIG_REC *rec, CONFIG_NODE *parent, const char *key, int new_type); +CONFIG_NODE *config_node_section(CONFIG_NODE *parent, const char *key, int new_type); /* Find the section with the whole path. Create the path if necessary `create' is TRUE. */ CONFIG_NODE *config_node_traverse(CONFIG_REC *rec, const char *section, int create); /* Get the value of keys `key' and `key_value' and put them to `ret_key' and `ret_value'. Returns -1 if not found. */ int config_node_get_keyvalue(CONFIG_NODE *node, const char *key, const char *value_key, char **ret_key, char **ret_value); +/* Return all values from from the list `node' in a g_strsplit() array */ +char **config_node_get_list(CONFIG_NODE *node); +/* Add all values in `array' to `node' */ +void config_node_add_list(CONFIG_NODE *node, char **array); char *config_node_get_str(CONFIG_NODE *parent, const char *key, const char *def); int config_node_get_int(CONFIG_NODE *parent, const char *key, int def); @@ -124,13 +128,15 @@ void config_node_set_str(CONFIG_NODE *parent, const char *key, const char *value void config_node_set_int(CONFIG_NODE *parent, const char *key, int value); void config_node_set_bool(CONFIG_NODE *parent, const char *key, int value); -/* add/change the value of the `key' */ +/* Add/change the value of the `key' */ void config_node_set_str(CONFIG_NODE *parent, const char *key, const char *value); -/* remove one node from block/list. +/* Remove one node from block/list. ..set_str() with value = NULL does the same. */ void config_node_remove(CONFIG_NODE *parent, CONFIG_NODE *node); +/* Remove n'th node from a list */ +void config_node_list_remove(CONFIG_NODE *node, int index); -/* clear the entire configuration */ +/* Clear the entire configuration */ void config_nodes_remove_all(CONFIG_REC *rec); #endif diff --git a/src/lib-config/parse.c b/src/lib-config/parse.c index 5171161c..25f9ccec 100644 --- a/src/lib-config/parse.c +++ b/src/lib-config/parse.c @@ -62,7 +62,7 @@ static void config_parse_get_token(GScanner *scanner, CONFIG_NODE *node) #undef g_strdup_printf /* This is free'd by GLib itself */ scanner->value.v_string = g_strdup_printf("%lu", scanner->value.v_int); #ifdef MEM_DEBUG -#define g_strdup_printf ig_strdup_printf +#define g_strdup_printf(a, b...) ig_strdup_printf(__FILE__, __LINE__, a, ##b) #endif } break; @@ -127,8 +127,10 @@ static int config_parse_symbol(CONFIG_REC *rec, CONFIG_NODE *node) key = g_strdup(rec->scanner->value.v_string); config_parse_get_token(rec->scanner, node); - if (rec->scanner->token != '=') + if (rec->scanner->token != '=') { + g_free(key); return '='; + } config_parse_get_token(rec->scanner, node); } @@ -155,7 +157,7 @@ static int config_parse_symbol(CONFIG_REC *rec, CONFIG_NODE *node) if (key == NULL && node->type != NODE_TYPE_LIST) return G_TOKEN_ERROR; - newnode = config_node_section(rec, node, key, NODE_TYPE_BLOCK); + newnode = config_node_section(node, key, NODE_TYPE_BLOCK); config_parse_loop(rec, newnode, '}'); g_free_not_null(key); @@ -170,7 +172,7 @@ static int config_parse_symbol(CONFIG_REC *rec, CONFIG_NODE *node) /* list */ if (key == NULL) return G_TOKEN_ERROR; - newnode = config_node_section(rec, node, key, NODE_TYPE_LIST); + newnode = config_node_section(node, key, NODE_TYPE_LIST); config_parse_loop(rec, newnode, ')'); g_free_not_null(key); @@ -197,17 +199,18 @@ static void config_parse_loop(CONFIG_REC *rec, CONFIG_NODE *node, int expect) g_return_if_fail(rec != NULL); g_return_if_fail(node != NULL); - do { + for (;;) { + config_parse_peek_token(rec->scanner, node); + if (rec->scanner->next_token == expect || + rec->scanner->next_token == G_TOKEN_EOF) break; + expected_token = config_parse_symbol(rec, node); if (expected_token != G_TOKEN_NONE) { if (expected_token == G_TOKEN_ERROR) expected_token = G_TOKEN_NONE; g_scanner_unexp_token(rec->scanner, expected_token, NULL, "symbol", NULL, NULL, TRUE); } - - config_parse_peek_token(rec->scanner, node); - } while (rec->scanner->next_token != expect && - rec->scanner->next_token != G_TOKEN_EOF); + } } static void config_parse_error_func(GScanner *scanner, char *message, int is_error) diff --git a/src/lib-config/set.c b/src/lib-config/set.c index 49457576..6748fce9 100644 --- a/src/lib-config/set.c +++ b/src/lib-config/set.c @@ -43,6 +43,22 @@ void config_node_remove(CONFIG_NODE *parent, CONFIG_NODE *node) g_free(node); } +/* Remove n'th node from a list */ +void config_node_list_remove(CONFIG_NODE *node, int index) +{ + GSList *tmp; + + g_return_if_fail(node != NULL); + g_return_if_fail(is_node_list(node)); + + for (tmp = node->value; tmp != NULL; tmp = tmp->next, index--) { + if (index == 0) { + config_node_remove(node, tmp->data); + break; + } + } +} + void config_nodes_remove_all(CONFIG_REC *rec) { g_return_if_fail(rec != NULL); @@ -120,3 +136,12 @@ int config_set_bool(CONFIG_REC *rec, const char *section, const char *key, int v { return config_set_str(rec, section, key, value ? "yes" : "no"); } + +/* Add all values in `array' to `node' */ +void config_node_add_list(CONFIG_NODE *node, char **array) +{ + char **tmp; + + for (tmp = array; *tmp != NULL; tmp++) + config_node_set_str(node, NULL, *tmp); +} diff --git a/src/lib-config/write.c b/src/lib-config/write.c index 30a41fd4..552600a7 100644 --- a/src/lib-config/write.c +++ b/src/lib-config/write.c @@ -76,7 +76,7 @@ static int config_has_specials(const char *text) g_return_val_if_fail(text != NULL, FALSE); while (*text != '\0') { - if ((unsigned char) *text <= 32 || *text == '"' || *text == '\\') + if (!isalnum((int) *text)) return TRUE; text++; } @@ -162,7 +162,7 @@ static int config_write_node(CONFIG_REC *rec, CONFIG_NODE *node, int line_feeds) case NODE_TYPE_BLOCK: /* key = { */ if (node->key != NULL) { - if (config_write_str(rec, node->key) == -1 || + if (config_write_word(rec, node->key, FALSE) == -1 || config_write_str(rec, " = ") == -1) return -1; } @@ -182,7 +182,7 @@ static int config_write_node(CONFIG_REC *rec, CONFIG_NODE *node, int line_feeds) case NODE_TYPE_LIST: /* key = ( */ if (node->key != NULL) { - if (config_write_str(rec, node->key) == -1 || + if (config_write_word(rec, node->key, FALSE) == -1 || config_write_str(rec, " = ") == -1) return -1; } @@ -327,7 +327,6 @@ int config_write(CONFIG_REC *rec, const char *fname, int create_mode) config_error(rec, errno == 0 ? "bug" : g_strerror(errno)); return -1; } - write(rec->handle, "\n", 1); close(rec->handle); rec->handle = -1; diff --git a/src/perl/Makefile.am b/src/perl/Makefile.am new file mode 100644 index 00000000..4093d2ad --- /dev/null +++ b/src/perl/Makefile.am @@ -0,0 +1,30 @@ +noinst_LTLIBRARIES = libperl.la + +libperl_la_DEPENDENCIES = perl-signals.h + +INCLUDES = $(GLIB_CFLAGS) \ + -DPLUGINSDIR=\""$(libdir)/irssi/plugins"\" \ + -DSCRIPTDIR=\""$(libdir)/irssi/scripts"\" \ + $(PERL_CFLAGS) \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/src/core + +libperl_la_SOURCES = \ + irssi-perl.c \ + xsinit.c + +perl-signals.h: $(top_srcdir)/docs/signals.txt $(srcdir)/get-signals.pl + cat $(top_srcdir)/docs/signals.txt | $(perlpath) $(srcdir)/get-signals.pl > perl-signals.h + +EXTRA_DIST = \ + get-signals.pl \ + xs/Irssi.xs \ + xs/Irssi.pm \ + xs/Makefile.PL.in \ + xs/typemap + +all-local: + cd xs && if [ ! -f Makefile ]; then $(perlpath) Makefile.PL; fi && $(MAKE) && cd .. + +install-exec-local: + cd xs && make install && cd .. diff --git a/src/perl/get-signals.pl b/src/perl/get-signals.pl new file mode 100755 index 00000000..73b6401f --- /dev/null +++ b/src/perl/get-signals.pl @@ -0,0 +1,38 @@ +#!/usr/bin/perl + +print "static PERL_SIGNAL_ARGS_REC perl_signal_args[] =\n{\n"; + +while () { + chomp; + + last if (/UI common/); + next if (!/^ "([^"]*)"(<.*>)?,\s*(.*)/); + next if (/\.\.\./); + next if (/\(/); + + $signal = $1; + $_ = $3; + + s/char \*[^,]*/string/g; + s/ulong \*[^,]*/ulongptr/g; + s/int[^,]*/int/g; + s/GSList of (\w+)s/gslist_\1/g; + + s/SERVER_REC \*[^,]*/Irssi::Server/g; + s/RECONNECT_REC \*[^,]*/Irssi::Reconnect/g; + s/CHANNEL_REC \*[^,]*/Irssi::Channel/g; + s/COMMAND_REC \*[^,]*/Irssi::Command/g; + s/NICK_REC \*[^,]*/Irssi::Nick/g; + s/BAN_REC \*[^,]*/Irssi::Ban/g; + s/NETSPLIT_REC \*[^,]*/Irssi::Netsplit/g; + s/DCC_REC \*[^,]*/Irssi::Dcc/g; + s/LOG_REC \*[^,]*/Irssi::Log/g; + s/LOG_ITEM_REC \*[^,]*/Irssi::Logitem/g; + s/PLUGIN_REC \*[^,]*/Irssi::Plugin/g; + s/AUTOIGNORE_REC \*[^,]*/Irssi::Autoignore/g; + + s/([\w:]+)(,|$)/"\1"\2/g; + print " { -1, \"$signal\", { $_, NULL } },\n"; +} + +print "\n { -1, NULL }\n};\n"; diff --git a/src/perl/irssi-perl.c b/src/perl/irssi-perl.c new file mode 100644 index 00000000..494e0da5 --- /dev/null +++ b/src/perl/irssi-perl.c @@ -0,0 +1,529 @@ +/* + perl.c : irssi + + Copyright (C) 1999 Timo Sirainen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#ifndef _SEM_SEMUN_UNDEFINED +#define HAS_UNION_SEMUN +#endif +#include + +#undef _ +#undef PACKAGE + +#include "module.h" +#include "modules.h" +#include "signals.h" +#include "commands.h" + +extern void xs_init(void); + +typedef struct { + int signal_id; + char *signal; + char *args[7]; +} PERL_SIGNAL_ARGS_REC; + +typedef struct { + char *signal; + int signal_id; + + char *func; + int last; +} PERL_SIGNAL_REC; + +typedef struct { + int tag; + char *func; + char *data; +} PERL_TIMEOUT_REC; + +#include "perl-signals.h" + +static GHashTable *first_signals, *last_signals; +static GSList *perl_timeouts; +static PerlInterpreter *irssi_perl_interp; +static int signal_grabbed, siglast_grabbed; + +static void sig_signal(void *signal, ...); +static void sig_lastsignal(void *signal, ...); + +static void perl_signal_destroy(PERL_SIGNAL_REC *rec) +{ + GHashTable *table; + GSList *siglist; + void *signal_idp; + + table = rec->last ? last_signals : first_signals; + signal_idp = GINT_TO_POINTER(rec->signal_id); + + siglist = g_hash_table_lookup(table, signal_idp); + if (siglist == NULL) return; + + siglist = g_slist_remove(siglist, rec); + g_hash_table_remove(table, signal_idp); + if (siglist != NULL) g_hash_table_insert(table, signal_idp, siglist); + + if (!rec->last && signal_grabbed && g_hash_table_size(first_signals) == 0) { + signal_grabbed = FALSE; + signal_remove("signal", (SIGNAL_FUNC) sig_signal); + } + + if (rec->last && siglast_grabbed && g_hash_table_size(last_signals) == 0) { + siglast_grabbed = FALSE; + signal_remove("last signal", (SIGNAL_FUNC) sig_lastsignal); + } + + if (strncmp(rec->signal, "command ", 8) == 0) + command_unbind(rec->signal+8, NULL); + + g_free(rec->signal); + g_free(rec->func); + g_free(rec); +} + +static void perl_timeout_destroy(PERL_TIMEOUT_REC *rec) +{ + perl_timeouts = g_slist_remove(perl_timeouts, rec); + + g_source_remove(rec->tag); + g_free(rec->func); + g_free(rec->data); + g_free(rec); +} + +static void irssi_perl_start(void) +{ + /* stolen from xchat, thanks :) */ + char *args[] = {"", "-e", "0"}; + char load_file[] = + "sub load_file()\n" + "{\n" + " (my $file_name) = @_;\n" + " open FH, $file_name or return 2;\n" + " local($/) = undef;\n" + " $file = ;\n" + " close FH;\n" + " eval $file;\n" + " eval $file if $@;\n" + " return 1 if $@;\n" + " return 0;\n" + "}"; + + first_signals = g_hash_table_new((GHashFunc) g_direct_hash, (GCompareFunc) g_direct_equal); + last_signals = g_hash_table_new((GHashFunc) g_direct_hash, (GCompareFunc) g_direct_equal); + perl_timeouts = NULL; + + irssi_perl_interp = perl_alloc(); + perl_construct(irssi_perl_interp); + + perl_parse(irssi_perl_interp, xs_init, 3, args, NULL); + perl_eval_pv(load_file, TRUE); +} + +static void signal_destroy_hash(void *key, PERL_SIGNAL_REC *rec) +{ + perl_signal_destroy(rec); +} + +static void irssi_perl_stop(void) +{ + g_hash_table_foreach(first_signals, (GHFunc) signal_destroy_hash, NULL); + g_hash_table_destroy(first_signals); + g_hash_table_foreach(last_signals, (GHFunc) signal_destroy_hash, NULL); + g_hash_table_destroy(last_signals); + + while (perl_timeouts != NULL) + perl_timeout_destroy(perl_timeouts->data); + + perl_destruct(irssi_perl_interp); + perl_free(irssi_perl_interp); + irssi_perl_interp = NULL; +} + +static void cmd_run(char *data) +{ + dSP; + struct stat statbuf; + char *fname; + int retcount; + + /* add .pl suffix if it's missing */ + data = (strlen(data) <= 3 || strcmp(data+strlen(data)-3, ".pl") == 0) ? + g_strdup(data) : g_strdup_printf("%s.pl", data); + + if (g_path_is_absolute(data)) { + /* whole path specified */ + fname = g_strdup(data); + } else { + /* check from ~/.irssi/scripts/ */ + fname = g_strdup_printf("%s/.irssi/scripts/%s", g_get_home_dir(), data); + if (stat(fname, &statbuf) != 0) { + /* check from SCRIPTDIR */ + g_free(fname), + fname = g_strdup_printf(SCRIPTDIR"/%s", data); + } + } + g_free(data); + + ENTER; + SAVETMPS; + + PUSHMARK(SP); + XPUSHs(sv_2mortal(newSVpv(fname, strlen(fname)))); g_free(fname); + PUTBACK; + + retcount = perl_call_pv("load_file", G_EVAL|G_SCALAR); + SPAGAIN; + + if (SvTRUE(ERRSV)) { + STRLEN n_a; + + signal_emit("perl error", 1, SvPV(ERRSV, n_a)); + (void) POPs; + } + else while (retcount--) (void) POPi; + + PUTBACK; + FREETMPS; + LEAVE; +} + +static void cmd_flush(const char *data) +{ + irssi_perl_stop(); + irssi_perl_start(); +} + +static void perl_signal_to(const char *signal, const char *func, int last) +{ + PERL_SIGNAL_REC *rec; + GHashTable *table; + GSList *siglist; + void *signal_idp; + + rec = g_new(PERL_SIGNAL_REC, 1); + rec->signal_id = module_get_uniq_id_str("signals", signal); + rec->signal = g_strdup(signal); + rec->func = g_strdup(func); + rec->last = last; + + table = last ? last_signals : first_signals; + signal_idp = GINT_TO_POINTER(rec->signal_id); + + siglist = g_hash_table_lookup(table, signal_idp); + if (siglist != NULL) g_hash_table_remove(table, signal_idp); + + siglist = g_slist_append(siglist, rec); + g_hash_table_insert(table, signal_idp, siglist); + + if (!last && !signal_grabbed) { + signal_grabbed = TRUE; + signal_add("signal", (SIGNAL_FUNC) sig_signal); + } else if (last && !siglast_grabbed) { + siglast_grabbed = TRUE; + signal_add("last signal", (SIGNAL_FUNC) sig_lastsignal); + } +} + +void perl_signal_add(const char *signal, const char *func) +{ + perl_signal_to(signal, func, FALSE); +} + +void perl_signal_add_last(const char *signal, const char *func) +{ + perl_signal_to(signal, func, TRUE); +} + +static void perl_signal_remove_list(GSList *list, const char *func) +{ + while (list != NULL) { + PERL_SIGNAL_REC *rec = list->data; + + if (strcmp(func, rec->func) == 0) { + perl_signal_destroy(rec); + break; + } + + list = list->next; + } +} + +void perl_signal_remove(const char *signal, const char *func) +{ + GSList *list; + int signal_id; + + signal_id = module_get_uniq_id_str("signals", signal); + + list = g_hash_table_lookup(first_signals, GINT_TO_POINTER(signal_id)); + if (list != NULL) + perl_signal_remove_list(list, func); + else { + list = g_hash_table_lookup(last_signals, GINT_TO_POINTER(signal_id)); + if (list != NULL) perl_signal_remove_list(list, func); + } +} + +static int perl_timeout(PERL_TIMEOUT_REC *rec) +{ + dSP; + int retcount; + + ENTER; + SAVETMPS; + + PUSHMARK(SP); + XPUSHs(sv_2mortal(newSVpv(rec->data, strlen(rec->data)))); + PUTBACK; + + retcount = perl_call_pv(rec->func, G_EVAL|G_SCALAR); + SPAGAIN; + + if (SvTRUE(ERRSV)) { + STRLEN n_a; + + signal_emit("perl error", 1, SvPV(ERRSV, n_a)); + (void) POPs; + } + else while (retcount--) (void) POPi; + + PUTBACK; + FREETMPS; + LEAVE; + + return 1; +} + +int perl_timeout_add(int msecs, const char *func, const char *data) +{ + PERL_TIMEOUT_REC *rec; + + rec = g_new(PERL_TIMEOUT_REC, 1); + rec->func = g_strdup(func); + rec->data = g_strdup(data); + rec->tag = g_timeout_add(msecs, (GSourceFunc) perl_timeout, rec); + + perl_timeouts = g_slist_append(perl_timeouts, rec); + return rec->tag; +} + +void perl_timeout_remove(int tag) +{ + GSList *tmp; + + for (tmp = perl_timeouts; tmp != NULL; tmp = tmp->next) { + PERL_TIMEOUT_REC *rec = tmp->data; + + if (rec->tag == tag) { + perl_timeout_destroy(rec); + break; + } + } +} + +static int call_perl(const char *func, int signal, va_list va) +{ + dSP; + PERL_SIGNAL_ARGS_REC *rec; + int retcount, n, ret; + void *arg; + HV *stash; + + /* first check if we find exact match */ + rec = NULL; + for (n = 0; perl_signal_args[n].signal != NULL; n++) + { + if (signal == perl_signal_args[n].signal_id) + { + rec = &perl_signal_args[n]; + break; + } + } + + if (rec == NULL) + { + /* try to find by name */ + const char *signame; + + signame = module_find_id_str("signals", signal); + for (n = 0; perl_signal_args[n].signal != NULL; n++) + { + if (strncmp(signame, perl_signal_args[n].signal, + strlen(perl_signal_args[n].signal)) == 0) + { + rec = &perl_signal_args[n]; + break; + } + } + } + + ENTER; + SAVETMPS; + + PUSHMARK(sp); + + if (rec != NULL) + { + /* put the arguments to perl stack */ + for (n = 0; n < 7; n++) + { + arg = va_arg(va, gpointer); + + if (rec->args[n] == NULL) + break; + + if (strcmp(rec->args[n], "string") == 0) + XPUSHs(sv_2mortal(newSVpv(arg == NULL ? "" : arg, arg == NULL ? 0 : strlen(arg)))); + else if (strcmp(rec->args[n], "int") == 0) + XPUSHs(sv_2mortal(newSViv(GPOINTER_TO_INT(arg)))); + else if (strcmp(rec->args[n], "ulongptr") == 0) + XPUSHs(sv_2mortal(newSViv(*(gulong *) arg))); + else if (strncmp(rec->args[n], "glist_", 6) == 0) + { + GSList *tmp; + + stash = gv_stashpv(rec->args[n]+6, 0); + for (tmp = arg; tmp != NULL; tmp = tmp->next) + XPUSHs(sv_2mortal(sv_bless(newRV_noinc(newSViv(GPOINTER_TO_INT(tmp->data))), stash))); + } + else + { + stash = gv_stashpv(rec->args[n], 0); + XPUSHs(sv_2mortal(sv_bless(newRV_noinc(newSViv(GPOINTER_TO_INT(arg))), stash))); + } + } + } + + PUTBACK; + retcount = perl_call_pv((char *) func, G_EVAL|G_SCALAR); + SPAGAIN; + + ret = 0; + if (SvTRUE(ERRSV)) + { + STRLEN n_a; + + signal_emit("perl error", 1, SvPV(ERRSV, n_a)); + (void)POPs; + } + else + { + SV *sv; + + if (retcount > 0) + { + sv = POPs; + if (SvIOK(sv) && SvIV(sv) == 1) ret = 1; + } + for (n = 2; n <= retcount; n++) + (void)POPi; + } + + PUTBACK; + FREETMPS; + LEAVE; + + return ret; +} + +static void sig_signal(void *signal, ...) +{ + GSList *list; + va_list va; + + va_start(va, signal); + + list = g_hash_table_lookup(first_signals, signal); + while (list != NULL) { + PERL_SIGNAL_REC *rec = list->data; + + if (call_perl(rec->func, GPOINTER_TO_INT(signal), va)) { + signal_stop(); + return; + } + list = list->next; + } + + va_end(va); +} + +static void sig_lastsignal(void *signal, ...) +{ + GSList *list; + va_list va; + + va_start(va, signal); + + list = g_hash_table_lookup(last_signals, signal); + while (list != NULL) { + PERL_SIGNAL_REC *rec = list->data; + + if (call_perl(rec->func, GPOINTER_TO_INT(signal), va)) { + signal_stop(); + return; + } + list = list->next; + } + + va_end(va); +} + +static void irssi_perl_autorun(void) +{ + DIR *dirp; + struct dirent *dp; + char *path, *fname; + + path = g_strdup_printf("%s/.irssi/scripts/autorun", g_get_home_dir()); + dirp = opendir(path); + if (dirp == NULL) { + g_free(path); + return; + } + + while ((dp = readdir(dirp)) != NULL) { + fname = g_strdup_printf("%s/%s", path, dp->d_name); + cmd_run(fname); + g_free(fname); + } + closedir(dirp); + g_free(path); +} + +void irssi_perl_init(void) +{ + command_bind("run", NULL, (SIGNAL_FUNC) cmd_run); + command_bind("perlflush", NULL, (SIGNAL_FUNC) cmd_flush); + signal_grabbed = siglast_grabbed = FALSE; + + irssi_perl_start(); + irssi_perl_autorun(); +} + +void irssi_perl_deinit(void) +{ + irssi_perl_stop(); + + command_unbind("run", (SIGNAL_FUNC) cmd_run); + command_unbind("perlflush", (SIGNAL_FUNC) cmd_flush); + if (signal_grabbed) signal_remove("signal", (SIGNAL_FUNC) sig_signal); + if (siglast_grabbed) signal_remove("last signal", (SIGNAL_FUNC) sig_lastsignal); +} diff --git a/src/perl/irssi-perl.h b/src/perl/irssi-perl.h new file mode 100644 index 00000000..b26ac3b0 --- /dev/null +++ b/src/perl/irssi-perl.h @@ -0,0 +1,7 @@ +#ifndef __IRSSI_PERL_H +#define __IRSSI_PERL_H + +void irssi_perl_init(void); +void irssi_perl_deinit(void); + +#endif diff --git a/src/perl/module.h b/src/perl/module.h new file mode 100644 index 00000000..986e32e1 --- /dev/null +++ b/src/perl/module.h @@ -0,0 +1,3 @@ +#include "common.h" + +#define MODULE_NAME "irssi-perl" diff --git a/src/perl/perl-signals.h b/src/perl/perl-signals.h new file mode 100644 index 00000000..654c1a51 --- /dev/null +++ b/src/perl/perl-signals.h @@ -0,0 +1,108 @@ +static PERL_SIGNAL_ARGS_REC perl_signal_args[] = +{ + { -1, "gui channel open", { "CHANNEL_REC", NULL } }, + { -1, "send command", { "string", "SERVER_REC", "CHANNEL_REC", NULL } }, + { -1, "send command", { "string", "SERVER_REC", NULL } }, + { -1, "command ", { "string", "SERVER_REC", "CHANNEL_REC", NULL } }, + { -1, "default command", { "string", "SERVER_REC", "CHANNEL_REC", NULL } }, + { -1, "server event", { "string", "SERVER_REC", "string", "string", NULL } }, + { -1, "event ", { "string", "SERVER_REC", "string", "string", NULL } }, + { -1, "default event", { "string", "SERVER_REC", "string", "string", NULL } }, + { -1, "server incoming", { "SERVER_REC", "string", NULL } }, + { -1, "redir ", { "string", "SERVER_REC", "string", "string", NULL } }, + { -1, "ban new", { "BAN_REC", NULL } }, + { -1, "ban remove", { "BAN_REC", NULL } }, + { -1, "ban exception new", { "BAN_REC", NULL } }, + { -1, "ban exception remove", { "BAN_REC", NULL } }, + { -1, "ban type changed", { "string", NULL } }, + { -1, "commandlist new", { "COMMAND_REC", NULL } }, + { -1, "commandlist remove", { "COMMAND_REC", NULL } }, + { -1, "channel created", { "CHANNEL_REC", NULL } }, + { -1, "channel destroyed", { "CHANNEL_REC", NULL } }, + { -1, "channel name changed", { "CHANNEL_REC", NULL } }, + { -1, "channel topic changed", { "CHANNEL_REC", NULL } }, + { -1, "channel server changed", { "CHANNEL_REC", "Irssi::Server", NULL } }, + { -1, "channel query", { "CHANNEL_REC", NULL } }, + { -1, "channel wholist", { "CHANNEL_REC", NULL } }, + { -1, "channel sync", { "CHANNEL_REC", NULL } }, + { -1, "ctcp msg ", { "string", "SERVER_REC", "string", "string", "string", NULL } }, + { -1, "default ctcp msg", { "string", "SERVER_REC", "string", "string", "string", NULL } }, + { -1, "ctcp reply ", { "string", "SERVER_REC", "string", "string", "string", NULL } }, + { -1, "default ctcp reply", { "string", "SERVER_REC", "string", "string", "string", NULL } }, + { -1, "server lag", { "SERVER_REC", NULL } }, + { -1, "server lag disconnect", { "SERVER_REC", NULL } }, + { -1, "lag", { "string", "int", NULL } }, + { -1, "invitelist new", { "CHANNEL_REC", "string", NULL } }, + { -1, "invitelist remove", { "CHANNEL_REC", "string", NULL } }, + { -1, "channel mode changed", { "CHANNEL_REC", NULL } }, + { -1, "user mode changed", { "SERVER_REC", NULL } }, + { -1, "nick mode changed", { "CHANNEL_REC", "NICK_REC", NULL } }, + { -1, "netsplit add", { "NETSPLIT_REC", NULL } }, + { -1, "netsplit remove", { "NETSPLIT_REC", NULL } }, + { -1, "nicklist new", { "CHANNEL_REC", "NICK_REC", NULL } }, + { -1, "nicklist remove", { "CHANNEL_REC", "NICK_REC", NULL } }, + { -1, "nicklist changed", { "CHANNEL_REC", "NICK_REC", "string", NULL } }, + { -1, "nick gone changed", { "CHANNEL_REC", "NICK_REC", NULL } }, + { -1, "nick ircop changed", { "CHANNEL_REC", "NICK_REC", NULL } }, + { -1, "server nick changed", { "SERVER_REC", NULL } }, + { -1, "massjoin", { "CHANNEL_REC", "gslist_NICK_REC", NULL } }, + { -1, "rawlog", { "SERVER_REC", "string", NULL } }, + { -1, "server connect failed", { "SERVER_REC", NULL } }, + { -1, "server connected", { "SERVER_REC", NULL } }, + { -1, "server connecting", { "SERVER_REC", "ulongptr", NULL } }, + { -1, "server looking", { "SERVER_REC", NULL } }, + { -1, "server disconnected", { "SERVER_REC", NULL } }, + { -1, "event connected", { "SERVER_REC", NULL } }, + { -1, "server reconnect new", { "RECONNECT_REC", NULL } }, + { -1, "server reconnect remove", { "RECONNECT_REC", NULL } }, + { -1, "server reconnect not found", { "string", NULL } }, + { -1, "print text stripped", { "SERVER_REC", "string", "int", "string", NULL } }, + { -1, "dcc ctcp ", { "string", "DCC_REC", NULL } }, + { -1, "default dcc ctcp", { "string", "DCC_REC", NULL } }, + { -1, "dcc unknown ctcp", { "string", "string", "string", NULL } }, + { -1, "dcc reply ", { "string", "DCC_REC", NULL } }, + { -1, "default dcc reply", { "string", "DCC_REC", NULL } }, + { -1, "dcc unknown reply", { "string", "string", "string", NULL } }, + { -1, "dcc chat message", { "DCC_REC", "string", NULL } }, + { -1, "dcc created", { "DCC_REC", NULL } }, + { -1, "dcc destroyed", { "DCC_REC", NULL } }, + { -1, "dcc connected", { "DCC_REC", NULL } }, + { -1, "dcc rejecting", { "DCC_REC", NULL } }, + { -1, "dcc closed", { "DCC_REC", NULL } }, + { -1, "dcc chat message", { "DCC_REC", "string", NULL } }, + { -1, "dcc transfer update", { "DCC_REC", NULL } }, + { -1, "dcc request", { "DCC_REC", NULL } }, + { -1, "dcc get receive", { "DCC_REC", NULL } }, + { -1, "dcc error connect", { "DCC_REC", NULL } }, + { -1, "dcc error file create", { "DCC_REC", "string", NULL } }, + { -1, "dcc error file not found", { "string", "string", NULL } }, + { -1, "dcc error get not found", { "string", NULL } }, + { -1, "dcc error send exists", { "string", "string", NULL } }, + { -1, "dcc error unknown type", { "string", NULL } }, + { -1, "dcc error close not found", { "string", "string", "string", NULL } }, + { -1, "flood", { "SERVER_REC", "string", "string", "string", "string", NULL } }, + { -1, "autoignore new", { "SERVER_REC", "AUTOIGNORE_REC", NULL } }, + { -1, "autoignore remove", { "SERVER_REC", "AUTOIGNORE_REC", NULL } }, + { -1, "log new", { "LOG_REC", NULL } }, + { -1, "log remove", { "LOG_REC", NULL } }, + { -1, "log locked", { "LOG_REC", NULL } }, + { -1, "log started", { "LOG_REC", NULL } }, + { -1, "log stopped", { "LOG_REC", NULL } }, + { -1, "log written", { "LOG_REC", "string", NULL } }, + { -1, "notifylist new", { "NOTIFYLIST_REC", NULL } }, + { -1, "notifylist remove", { "NOTIFYLIST_REC", NULL } }, + { -1, "notifylist joined", { "SERVER_REC", "string", "string", "string", "string", "string", NULL } }, + { -1, "notifylist away changed", { "SERVER_REC", "string", "string", "string", "string", "string", NULL } }, + { -1, "notifylist unidle", { "SERVER_REC", "string", "string", "string", "string", "string", NULL } }, + { -1, "notifylist left", { "SERVER_REC", "string", "string", "string", "string", "string", NULL } }, + { -1, "plugin created", { "PLUGIN_REC", NULL } }, + { -1, "plugin loaded", { "PLUGIN_REC", NULL } }, + { -1, "plugin destroyed", { "PLUGIN_REC", NULL } }, + { -1, "plugin error already loaded", { "string", NULL } }, + { -1, "plugin error invalid", { "string", NULL } }, + { -1, "plugin error load", { "string", "string", NULL } }, + { -1, "plugin error not loaded", { "string", NULL } }, + { -1, "plugin error version", { "string", NULL } }, + + { -1, NULL } +}; diff --git a/src/perl/xs/Irssi.pm b/src/perl/xs/Irssi.pm new file mode 100644 index 00000000..bd6af5fb --- /dev/null +++ b/src/perl/xs/Irssi.pm @@ -0,0 +1,21 @@ +# +# Perl interface to irssi functions. +# + +package Irssi; + +use strict; +use vars qw($VERSION @ISA @EXPORT @EXPORT_OK); + +$VERSION = "0.10"; + +require Exporter; +require DynaLoader; + +@ISA = qw(Exporter DynaLoader); +@EXPORT = qw(channel_find_any); +@EXPORT_OK = qw(); +bootstrap Irssi $VERSION; + +1; + diff --git a/src/perl/xs/Irssi.xs b/src/perl/xs/Irssi.xs new file mode 100644 index 00000000..95c75163 --- /dev/null +++ b/src/perl/xs/Irssi.xs @@ -0,0 +1,933 @@ +/* This could be split to different files / modules ..? */ +#include "EXTERN.h" +#include "perl.h" +#include "XSUB.h" + +#undef _ +#include +#include +#include +#include + +typedef SERVER_REC *Irssi__Server; +typedef SERVER_CONNECT_REC *Irssi__Connect; +typedef RECONNECT_REC *Irssi__Reconnect; +typedef CHANNEL_REC *Irssi__Channel; +typedef COMMAND_REC *Irssi__Command; +typedef NICK_REC *Irssi__Nick; +typedef BAN_REC *Irssi__Ban; +typedef DCC_REC *Irssi__Dcc; +typedef NETSPLIT_REC *Irssi__Netsplit; +typedef AUTOIGNORE_REC *Irssi__Autoignore; +typedef LOG_REC *Irssi__Log; +typedef LOG_ITEM_REC *Irssi__Logitem; +typedef PLUGIN_REC *Irssi__Plugin; + +#define new_pv(a) (newSVpv((a) == NULL ? "" : (a), (a) == NULL ? 0 : strlen(a))) + +void add_connect_hash(HV *hv, SERVER_CONNECT_REC *conn) +{ + hv_store(hv, "address", 7, new_pv(conn->address), 0); + hv_store(hv, "port", 4, newSViv(conn->port), 0); + hv_store(hv, "password", 8, new_pv(conn->password), 0); + + hv_store(hv, "ircnet", 6, new_pv(conn->ircnet), 0); + hv_store(hv, "wanted_nick", 11, new_pv(conn->nick), 0); + hv_store(hv, "alternate_nick", 14, new_pv(conn->alternate_nick), 0); + hv_store(hv, "username", 8, new_pv(conn->username), 0); + hv_store(hv, "realname", 8, new_pv(conn->realname), 0); + hv_store(hv, "autojoin_channels", 17, new_pv(conn->autojoin_channels), 0); +} + +MODULE = Irssi PACKAGE = Irssi + +PROTOTYPES: ENABLE + +Irssi::Channel +cur_channel() +CODE: + RETVAL = cur_channel; +OUTPUT: + RETVAL + +Irssi::Server +cur_server() +CODE: + RETVAL = cur_channel->server; +OUTPUT: + RETVAL + +void +channels() +PREINIT: + GSList *tmp; + HV *stash; +PPCODE: + stash = gv_stashpv("Irssi::Channel", 0); + for (tmp = channels; tmp != NULL; tmp = tmp->next) { + XPUSHs(sv_2mortal(sv_bless(newRV_noinc(newSViv(GPOINTER_TO_INT(tmp->data))), stash))); + } + +void +servers() +PREINIT: + GSList *tmp; + HV *stash; +PPCODE: + stash = gv_stashpv("Irssi::Server", 0); + for (tmp = servers; tmp != NULL; tmp = tmp->next) { + XPUSHs(sv_2mortal(sv_bless(newRV_noinc(newSViv(GPOINTER_TO_INT(tmp->data))), stash))); + } + +void +commands() +PREINIT: + GSList *tmp; + HV *stash; +PPCODE: + stash = gv_stashpv("Irssi::Command", 0); + for (tmp = commands; tmp != NULL; tmp = tmp->next) { + XPUSHs(sv_2mortal(sv_bless(newRV_noinc(newSViv(GPOINTER_TO_INT(tmp->data))), stash))); + } + +void +dccs() +PREINIT: + GSList *tmp; + HV *stash; +PPCODE: + stash = gv_stashpv("Irssi::Dcc", 0); + for (tmp = dcc_conns; tmp != NULL; tmp = tmp->next) { + XPUSHs(sv_2mortal(sv_bless(newRV_noinc(newSViv(GPOINTER_TO_INT(tmp->data))), stash))); + } + +void +logs() +PREINIT: + GSList *tmp; + HV *stash; +PPCODE: + stash = gv_stashpv("Irssi::Log", 0); + for (tmp = logs; tmp != NULL; tmp = tmp->next) { + XPUSHs(sv_2mortal(sv_bless(newRV_noinc(newSViv(GPOINTER_TO_INT(tmp->data))), stash))); + } + +void +plugins() +PREINIT: + GSList *tmp; + HV *stash; +PPCODE: + stash = gv_stashpv("Irssi::Plugin", 0); + for (tmp = plugins; tmp != NULL; tmp = tmp->next) { + XPUSHs(sv_2mortal(sv_bless(newRV_noinc(newSViv(GPOINTER_TO_INT(tmp->data))), stash))); + } + +Irssi::Connect +server_create_conn(dest, port=6667, password=NULL, nick=NULL, channels=NULL) + char *dest + int port + char *password + char *nick + char *channels + +Irssi::Server +server_find_tag(tag) + char *tag + +Irssi::Server +server_find_ircnet(ircnet) + char *ircnet + +Irssi::Channel +channel_find(channel) + char *channel +CODE: + RETVAL = channel_find(NULL, channel); +OUTPUT: + RETVAL + +void +print(str) + char *str +CODE: + printtext(NULL, NULL, MSGLEVEL_CLIENTNOTICE, str); + +void +signal_emit(signal, ...) + char *signal +CODE: + void *p[6]; + int n; + + memset(p, 0, sizeof(p)); + for (n = 1; n < items && n < 6; n++) { + p[n-1] = SvPOKp(ST(n)) ? SvPV(ST(n), PL_na) : (void *) SvIV((SV*)SvRV(ST(n))); + } + signal_emit(signal, items-1, p[0], p[1], p[2], p[3], p[4], p[5]); + +void +signal_add(signal, func) + char *signal + char *func +CODE: + perl_signal_add(signal, func); + +void +signal_add_last(signal, func) + char *signal + char *func +CODE: + perl_signal_add_last(signal, func); + +void +signal_remove(signal, func) + char *signal + char *func +CODE: + perl_signal_remove(signal, func); + +int +timeout_add(msecs, func, data) + int msecs + char *func + char *data +CODE: + RETVAL = perl_timeout_add(msecs, func, data); +OUTPUT: + RETVAL + +void +timeout_remove(tag) + int tag +CODE: + perl_timeout_remove(tag); + +void +command_bind(cmd, category, func) + char *cmd + char *category + char *func +CODE: + char *signal; + + command_bind(cmd, *category ? category : "Perl scripts' commands", NULL); + signal = g_strconcat("command ", cmd, NULL); + perl_signal_add(signal, func); + g_free(signal); + +void +command_unbind(cmd, func) + char *cmd + char *func +CODE: + char *signal; + + command_unbind(cmd, NULL); + signal = g_strconcat("command ", cmd, NULL); + perl_signal_remove(signal, func); + g_free(signal); + +void +command(cmd, server=cur_channel->server, channel=cur_channel) + char *cmd + Irssi::Server server + Irssi::Channel channel +CODE: + signal_emit("send command", 3, cmd, server, channel); + +int +is_channel(text) + char *text +CODE: + RETVAL = ischannel(*text); +OUTPUT: + RETVAL + +int +irc_mask_match(mask, nick, user, host) + char *mask + char *nick + char *user + char *host + +int +irc_mask_match_address(mask, nick, address) + char *mask + char *nick + char *address + +int +irc_masks_match(masks, nick, address) + char *masks + char *nick + char *address + +char * +irc_get_mask(nick, host, flags) + char *nick + char *host + int flags + +int +level2bits(str) + char *str + +char * +bits2level(bits) + int bits + +int +combine_level(level, str) + int level + char *str + +Irssi::Dcc +dcc_find_item(type, nick, arg) + int type + char *nick + char *arg + +Irssi::Dcc +dcc_find_by_port(nick, port) + char *nick + int port + +char * +dcc_type2str(type) + int type + +int +dcc_str2type(type) + char *type + +void +ignore_add(mask, level) + char *mask + char *level + +void +ignore_remove(mask, level) + char *mask + char *level + +Irssi::Log +log_create(fname, data) + char *fname + char *data + +Irssi::Log +log_create_with_level(fname, level) + char *fname + int level + +Irssi::Log +log_file_find(fname) + char *fname + +void +notifylist_add(nick, ircnet) + char *nick + char *ircnet + +Irssi::Server +notifylist_ison(nick, serverlist) + char *nick + char *serverlist + +int +plugin_load(name, args) + char *name + char *args + +char * +plugin_get_description(name) + char *name + +Irssi::Plugin +plugin_find(name) + char *name + +void +setup_get(option) + char *option +PREINIT: + char *ret; +PPCODE: + switch(setup_option_type(option)) { + case SETUP_TYPE_TOGGLEBUTTON: + XPUSHs(sv_2mortal(newSViv(setup_get_bool(option)))); + break; + case SETUP_TYPE_SPIN: + case SETUP_TYPE_INT_OBJECT: + XPUSHs(sv_2mortal(newSViv(setup_get_int(option)))); + break; + case SETUP_TYPE_ENTRY: + ret = setup_get_str(option); + XPUSHs(sv_2mortal(newSVpv(ret, strlen(ret)))); + break; + } + + +#******************************************************* +MODULE = Irssi PACKAGE = Irssi::Server PREFIX = server_ +#******************************************************* + +void +send_raw(server, cmd) + Irssi::Server server + char *cmd +CODE: + irc_send_cmd(server, cmd); + +void +command(server, cmd, channel=cur_channel) + char *cmd + Irssi::Server server + Irssi::Channel channel +CODE: + if (channel->server != server) { + GSList *tmp; + + for (tmp = channels; tmp != NULL; tmp = tmp->next) { + CHANNEL_REC *rec = tmp->data; + + if (rec->server == server) { + channel = rec; + break; + } + } + } + signal_emit("send command", 3, cmd, server, channel); + +void +server_disconnect(server) + Irssi::Server server + +Irssi::Channel +channel_create(server, channel, type, automatic) + Irssi::Server server + char *channel + int type + int automatic + +Irssi::Channel +channel_find(server, channel) + Irssi::Server server + char *channel + +Irssi::Channel +channel_find_closest(server, channel, level) + Irssi::Server server + char *channel + int level + +Irssi::Channel +channel_find_level(server, level) + Irssi::Server server + int level + +void +printtext(server, channel, level, str) + Irssi::Server server + char *channel + int level + char *str +CODE: + printtext(server, channel, level, str); + +void +irc_send_cmd_split(server, cmd, arg, max_nicks) + Irssi::Server server + char *cmd + int arg + int max_nicks + +void +ctcp_send_reply(server, data) + Irssi::Server server + char *data + +Irssi::Netsplit +netsplit_find(server, nick, address) + Irssi::Server server + char *nick + char *address + +Irssi::Nick +netsplit_find_channel(server, nick, address, channel) + Irssi::Server server + char *nick + char *address + char *channel + +void +rawlog_input(server, str) + Irssi::Server server + char *str + +void +rawlog_output(server, str) + Irssi::Server server + char *str + +void +rawlog_redirect(server, str) + Irssi::Server server + char *str + +void +server_redirect_init(server, command, last, ...) + Irssi::Server server + char *command + int last +PREINIT: + GSList *list; + int n; +CODE: + list = NULL; + for (n = 3; n < items; n++) { + list = g_slist_append(list, SvPV(ST(n), PL_na)); + } + server_redirect_initv(server, command, last, list); + +int +server_redirect_single_event(server, arg, last, group, event, signal, argpos) + Irssi::Server server + char *arg + int last + int group + char *event + char *signal + int argpos + +void +server_redirect_event(server, arg, last, ...) + Irssi::Server server + char *arg + int last +PREINIT: + int n, group; +CODE: + group = 0; + for (n = 3; n+3 <= items; n += 3, last--) { + group = server_redirect_single_event(server, arg, last > 0, group, + (char *) SvPV(ST(n), PL_na), (char *) SvPV(ST(n+1), PL_na), (int) SvIV(ST(n+2))); + } + +void +autoignore_add(server, type, nick) + Irssi::Server server + int type + char *nick + +int +autoignore_remove(server, mask, level) + Irssi::Server server + char *mask + char *level + +int +ignore_check(server, nick, host, type) + Irssi::Server server + char *nick + char *host + int type + +int +notifylist_ison_server(server, nick) + Irssi::Server server + char *nick + +void +values(server) + Irssi::Server server +PREINIT: + HV *hv; +PPCODE: + hv = newHV(); + add_connect_hash(hv, server->connrec); + hv_store(hv, "real_address", 12, new_pv(server->real_address), 0); + hv_store(hv, "tag", 3, new_pv(server->tag), 0); + hv_store(hv, "nick", 4, new_pv(server->nick), 0); + hv_store(hv, "usermode", 8, new_pv(server->usermode), 0); + hv_store(hv, "usermode_away", 13, newSViv(server->usermode_away), 0); + hv_store(hv, "away_reason", 11, new_pv(server->away_reason), 0); + hv_store(hv, "connected", 9, newSViv(server->connected), 0); + hv_store(hv, "connection_lost", 15, newSViv(server->connection_lost), 0); + XPUSHs(sv_2mortal(newRV_noinc((SV*)hv))); + +#******************************************************* +MODULE = Irssi PACKAGE = Irssi::Connect PREFIX = server_ +#******************************************************* + +void +values(conn) + Irssi::Connect conn +PREINIT: + HV *hv; +PPCODE: + hv = newHV(); + add_connect_hash(hv, conn); + XPUSHs(sv_2mortal(newRV_noinc((SV*)hv))); + +Irssi::Server +server_connect(conn) + Irssi::Connect conn + +#******************************************************* +MODULE = Irssi PACKAGE = Irssi::Reconnect +#******************************************************* + +void +values(reconnect) + Irssi::Reconnect reconnect +PREINIT: + HV *hv; +PPCODE: + hv = newHV(); + add_connect_hash(hv, reconnect->conn); + hv_store(hv, "tag", 3, newSViv(reconnect->tag), 0); + hv_store(hv, "next_connect", 12, newSViv(reconnect->next_connect), 0); + XPUSHs(sv_2mortal(newRV_noinc((SV*)hv))); + +#******************************************************* +MODULE = Irssi PACKAGE = Irssi::Channel PREFIX = channel_ +#******************************************************* + +void +command(channel, cmd) + Irssi::Channel channel + char *cmd +CODE: + signal_emit("send command", 3, cmd, channel->server, channel); + +void +channel_destroy(channel) + Irssi::Channel channel + +void +channel_change_name(channel, name) + Irssi::Channel channel + char *name + +char * +channel_get_mode(channel) + Irssi::Channel channel + +Irssi::Nick +nicklist_insert(channel, nick, op, voice, send_massjoin) + Irssi::Channel channel + char *nick + int op + int voice + int send_massjoin + +void +nicklist_remove(channel, nick) + Irssi::Channel channel + Irssi::Nick nick + +Irssi::Nick +nicklist_find(channel, mask) + Irssi::Channel channel + char *mask + +void +nicklist_getnicks(channel) + Irssi::Channel channel +PREINIT: + GSList *list, *tmp; + HV *stash; +PPCODE: + list = nicklist_getnicks(channel); + + stash = gv_stashpv("Irssi::Nick", 0); + for (tmp = list; tmp != NULL; tmp = tmp->next) { + XPUSHs(sv_2mortal(sv_bless(newRV_noinc(newSViv(GPOINTER_TO_INT(tmp->data))), stash))); + } + g_slist_free(list); + +Irssi::Ban +ban_add(channel, ban, nick, time) + Irssi::Channel channel + char *ban + char *nick + time_t time + +void +ban_remove(channel, ban) + Irssi::Channel channel + char *ban + +Irssi::Ban +ban_exception_add(channel, ban, nick, time) + Irssi::Channel channel + char *ban + char *nick + time_t time + +void +ban_exception_remove(channel, ban) + Irssi::Channel channel + char *ban + +char * +ban_get_mask(channel, nick) + Irssi::Channel channel + char *nick + +void +modes_set(channel, data, mode) + Irssi::Channel channel + char *data + char *mode +CODE: + modes_set(data, mode, channel->server, channel); + +void +modes_parse_channel(channel, setby, modestr) + Irssi::Channel channel + char *setby + char *modestr + +void +invitelist_add(channel, mask) + Irssi::Channel channel + char *mask + +void +invitelist_remove(channel, mask) + Irssi::Channel channel + char *mask + +void +values(channel) + Irssi::Channel channel +PREINIT: + HV *hv, *stash; + char *type; +PPCODE: + switch (channel->type) + { + case CHANNEL_TYPE_CHANNEL: + type = "channel"; + break; + case CHANNEL_TYPE_QUERY: + type = "query"; + break; + case CHANNEL_TYPE_DCC_CHAT: + type = "dcc chat"; + break; + default: + type = "empty"; + break; + } + hv = newHV(); + stash = gv_stashpv("Irssi::Server", 0); + hv_store(hv, "server", 6, sv_bless(newRV_noinc(newSViv(GPOINTER_TO_INT(channel->server))), stash), 0); + + hv_store(hv, "name", 4, new_pv(channel->name), 0); + hv_store(hv, "type", 4, new_pv(type), 0); + + hv_store(hv, "topic", 5, new_pv(channel->topic), 0); + hv_store(hv, "key", 3, new_pv(channel->key), 0); + hv_store(hv, "limit", 5, newSViv(channel->limit), 0); + + hv_store(hv, "level", 5, newSViv(channel->level), 0); + hv_store(hv, "new_data", 8, newSViv(channel->new_data), 0); + + hv_store(hv, "synced", 6, newSViv(channel->synced), 0); + hv_store(hv, "wholist", 7, newSViv(channel->wholist), 0); + hv_store(hv, "names_got", 9, newSViv(channel->names_got), 0); + hv_store(hv, "chanop", 6, newSViv(channel->chanop), 0); + hv_store(hv, "left", 4, newSViv(channel->left), 0); + hv_store(hv, "kicked", 6, newSViv(channel->kicked), 0); + + XPUSHs(sv_2mortal(newRV_noinc((SV*)hv))); + +#******************************************************* +MODULE = Irssi PACKAGE = Irssi::Command +#******************************************************* + +void +values(cmd) + Irssi::Command cmd +PREINIT: + HV *hv; +PPCODE: + hv = newHV(); + hv_store(hv, "cmd", 3, new_pv(cmd->cmd), 0); + hv_store(hv, "category", 8, new_pv(cmd->category), 0); + XPUSHs(sv_2mortal(newRV_noinc((SV*)hv))); + +#******************************************************* +MODULE = Irssi PACKAGE = Irssi::Nick +#******************************************************* + +void +values(nick) + Irssi::Nick nick +PREINIT: + HV *hv; +PPCODE: + hv = newHV(); + hv_store(hv, "nick", 4, new_pv(nick->nick), 0); + hv_store(hv, "host", 4, new_pv(nick->host), 0); + hv_store(hv, "name", 4, new_pv(nick->realname), 0); + hv_store(hv, "hops", 4, newSViv(nick->hops), 0); + hv_store(hv, "op", 2, newSViv(nick->op), 0); + hv_store(hv, "voice", 5, newSViv(nick->voice), 0); + hv_store(hv, "gone", 4, newSViv(nick->gone), 0); + hv_store(hv, "ircop", 5, newSViv(nick->ircop), 0); + hv_store(hv, "last_check", 10, newSViv(nick->last_check), 0); + hv_store(hv, "send_massjoin", 13, newSViv(nick->send_massjoin), 0); + XPUSHs(sv_2mortal(newRV_noinc((SV*)hv))); + +#******************************************************* +MODULE = Irssi PACKAGE = Irssi::Ban +#******************************************************* + +void +values(ban) + Irssi::Ban ban +PREINIT: + HV *hv; +PPCODE: + hv = newHV(); + hv_store(hv, "ban", 3, new_pv(ban->ban), 0); + hv_store(hv, "setby", 5, new_pv(ban->setby), 0); + hv_store(hv, "time", 4, newSViv(ban->time), 0); + XPUSHs(sv_2mortal(newRV_noinc((SV*)hv))); + +#******************************************************* +MODULE = Irssi PACKAGE = Irssi::Dcc PREFIX = dcc_ +#******************************************************* + +void +dcc_destroy(dcc) + Irssi::Dcc dcc + +void +values(ban) + Irssi::Ban ban +PREINIT: + HV *hv; +PPCODE: + hv = newHV(); + hv_store(hv, "ban", 3, new_pv(ban->ban), 0); + hv_store(hv, "setby", 5, new_pv(ban->setby), 0); + hv_store(hv, "time", 4, newSViv(ban->time), 0); + XPUSHs(sv_2mortal(newRV_noinc((SV*)hv))); + +#******************************************************* +MODULE = Irssi PACKAGE = Irssi::Netsplit +#******************************************************* + +void +values(netsplit) + Irssi::Netsplit netsplit +PREINIT: + HV *hv; +PPCODE: + hv = newHV(); + hv_store(hv, "nick", 4, new_pv(netsplit->nick), 0); + hv_store(hv, "address", 7, new_pv(netsplit->address), 0); + hv_store(hv, "server", 6, new_pv(netsplit->server), 0); + hv_store(hv, "destserver", 10, new_pv(netsplit->destserver), 0); + hv_store(hv, "destroy", 7, newSViv(netsplit->destroy), 0); + /*FIXME: add GSList *channels;*/ + XPUSHs(sv_2mortal(newRV_noinc((SV*)hv))); + +#******************************************************* +MODULE = Irssi PACKAGE = Irssi::Autoignore +#******************************************************* + +void +values(ai) + Irssi::Autoignore ai +PREINIT: + HV *hv; +PPCODE: + hv = newHV(); + hv_store(hv, "nick", 4, new_pv(ai->nick), 0); + hv_store(hv, "timeleft", 8, newSViv(ai->timeleft), 0); + hv_store(hv, "level", 5, newSViv(ai->level), 0); + XPUSHs(sv_2mortal(newRV_noinc((SV*)hv))); + +#******************************************************* +MODULE = Irssi PACKAGE = Irssi::Log PREFIX = log_ +#******************************************************* + +void +values(log) + Irssi::Log log +PREINIT: + HV *hv; +PPCODE: + hv = newHV(); + hv_store(hv, "fname", 5, new_pv(log->fname), 0); + hv_store(hv, "autoopen_log", 12, newSViv(log->autoopen_log), 0); + hv_store(hv, "last", 4, newSViv(log->last), 0); + hv_store(hv, "level", 5, newSViv(log->level), 0); + /*FIXME: add GSList *items;*/ + XPUSHs(sv_2mortal(newRV_noinc((SV*)hv))); + +void +destroy(log) + Irssi::Log log +CODE: + log_file_destroy(log); + +int +open(log) + Irssi::Log log +CODE: + log_file_open(log); + +void +close(log) + Irssi::Log log +CODE: + log_file_close(log); + +void +log_append_item(log, name, level) + Irssi::Log log + char *name + int level + +void +log_remove_item(log, name) + Irssi::Log log + char *name + +#******************************************************* +MODULE = Irssi PACKAGE = Irssi::Logitem +#******************************************************* + +void +values(item) + Irssi::Logitem item +PREINIT: + HV *hv; +PPCODE: + hv = newHV(); + hv_store(hv, "name", 4, new_pv(item->name), 0); + hv_store(hv, "level", 5, newSViv(item->level), 0); + XPUSHs(sv_2mortal(newRV_noinc((SV*)hv))); + +#******************************************************* +MODULE = Irssi PACKAGE = Irssi::Plugin PREFIX = plugin_ +#******************************************************* + +void +values(plugin) + Irssi::Plugin plugin +PREINIT: + HV *hv; +PPCODE: + hv = newHV(); + hv_store(hv, "name", 4, new_pv(plugin->name), 0); + hv_store(hv, "description", 11, new_pv(plugin->description), 0); + XPUSHs(sv_2mortal(newRV_noinc((SV*)hv))); diff --git a/src/perl/xs/Makefile.PL.in b/src/perl/xs/Makefile.PL.in new file mode 100644 index 00000000..430d59db --- /dev/null +++ b/src/perl/xs/Makefile.PL.in @@ -0,0 +1,6 @@ +use ExtUtils::MakeMaker; + +WriteMakefile('NAME' => 'Irssi', + 'LIBS' => '', + 'INC' => '-I@top_srcdir@/src @GLIB_CFLAGS@', + 'VERSION_FROM' => '@srcdir@/Irssi.pm'); diff --git a/src/perl/xs/typemap b/src/perl/xs/typemap new file mode 100644 index 00000000..ba1bc85c --- /dev/null +++ b/src/perl/xs/typemap @@ -0,0 +1,14 @@ +TYPEMAP +Irssi::Server T_PTROBJ +Irssi::Connect T_PTROBJ +Irssi::Reconnect T_PTROBJ +Irssi::Channel T_PTROBJ +Irssi::Command T_PTROBJ +Irssi::Nick T_PTROBJ +Irssi::Ban T_PTROBJ +Irssi::Dcc T_PTROBJ +Irssi::Netsplit T_PTROBJ +Irssi::Autoignore T_PTROBJ +Irssi::Log T_PTROBJ +Irssi::Logitem T_PTROBJ +Irssi::Plugin T_PTROBJ diff --git a/src/perl/xsinit.c b/src/perl/xsinit.c new file mode 100644 index 00000000..590eddb7 --- /dev/null +++ b/src/perl/xsinit.c @@ -0,0 +1,41 @@ +#if defined(__cplusplus) && !defined(PERL_OBJECT) +#define is_cplusplus +#endif + +#ifdef is_cplusplus +extern "C" { +#endif + +#include +#include +#ifdef PERL_OBJECT +#define NO_XSLOCKS +#include +#include "win32iop.h" +#include +#include +#endif +#ifdef is_cplusplus +} +# ifndef EXTERN_C +# define EXTERN_C extern "C" +# endif +#else +# ifndef EXTERN_C +# define EXTERN_C extern +# endif +#endif + +EXTERN_C void xs_init _((void)); + +EXTERN_C void boot_DynaLoader _((CV* cv)); + +EXTERN_C void +xs_init(void) +{ + char *file = __FILE__; + dXSUB_SYS; + + /* DynaLoader is a special case */ + newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file); +}