1
0
mirror of https://github.com/irssi/irssi.git synced 2024-06-09 06:20:45 +00:00

rest of the ~rewrite?

git-svn-id: http://svn.irssi.org/repos/irssi/trunk@172 dbcabf3a-b0e7-0310-adc4-f8d773084564
This commit is contained in:
Timo Sirainen 2000-04-26 08:10:09 +00:00 committed by cras
parent c95034c6de
commit d29ca0b107
32 changed files with 2049 additions and 1536 deletions

View File

@ -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

123
NEWS
View File

@ -1,8 +1,14 @@
v0.7.90 2000-04-xx Timo Sirainen <tss@iki.fi>
* 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 <tss@iki.fi>
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 <commands> - 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 [<filename>] - saves the settings to disk.
/REHASH [<filename>] - re-read the configuration file on the fly
+ /TOGGLE <key> [ON/OFF] - same as /SET <key> TOGGLE
+ /ALIAS [-]<alias> [<command>], /UNALIAS <alias>
Show, add or remove aliases. /ALIAS -alias = /UNALIAS alias
+ /NOTIFY [-list] [-away] [-idle [minutes]] <mask> [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 <mask>
/NOTIFY without any arguments displays if the people in notify
list are online or offline.
+ /HILIGHT [-nick | -regexp | -word] [-color <color>]
[-level <level>] [-channels <channels>] <text>
-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 <ref#> | <text>
+ /LASTLOG [-] [-new] [-regexp | -word] [-<level> [...]]
[<pattern>] [<count> [<start>]]
-: 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)
<pattern>: text to search for, or all if empty
<count>: maximum number of lines to show
<start>: skip the last `start' lines
+ /IGNORE [-regexp | -word] [-pattern <pattern>] [-except]
[-channels <channel>] <mask> <levels> <^levels>
-regexp: `pattern' is a regular expression
-word: `pattern' must match to full words
-pattern: <pattern> must match to the message's text
-except: *DON'T* ignore
-channels: ignore only in channels
<mask>: either a nick mask or list of channels
<levels>: list of levels to ignore
<^levels>: list of levels to NOT ignore
(/ignore -except nick notices = /ignore nick ^notices)
/UNIGNORE <ref#> | <mask>
The best match always wins, so you can have:
/IGNORE * CTCPS
/IGNORE -except *!*@host.org CTCPS
+ /LOG OPEN [-noopen] [-autoopen] [-channels <channels>] [-window]
[-rotate hour|day|month] <filename> [<levels>]
-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.
<filename>: File name where to log, it is parsed with strftime(),
so %d=day, etc. see "man strftime" for more info.
<levels>: Defaults to ALL
/LOG CLOSE <ref#> | <fname> - close log and remove from log list
/LOG START <ref#> | <fname> - start logging to file
/LOG STOP <ref#> | <fname> - 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 [<filename>]
Start/stop logging window, same as /LOG OPEN -window. If file name
isn't given, it defaults to ~/irc.log.<windowname> or
~/irc.log.Window<ref#> if window doesn't have name.
/WINDOW LOGFILE <filename>
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 <level>
/SET AUTOLOG_PATH <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 <tss@iki.fi>

1
README
View File

@ -94,6 +94,7 @@ There's also some others, you can get a full list with ./configure --help
--port -p <port> - 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

96
TODO
View File

@ -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 (<newline>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..?

View File

@ -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

58
config
View File

@ -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 = "<MULTICOMMA>Whois"; command = "/whois %s";},
{label = "DCC Send File"; command = "/dcc send %s";},

View File

@ -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)

View File

@ -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 <address> [port [password [nick]]]
Connect to specified server, if there's no password set it to -
DISCONNECT <* / tag> [message]
Disconnect from server
SERVER <address> [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 <channel> [key] [, channel...]
Join to channel(s)
PART [channel] [message]
Leave from channel
QUERY <nick>
Create query window
UNQUERY <nick>
Close query window
MSG <nick/channel> <message>
Send message to nick/channel
ME <message>
Send action to channel (/me thinks..)
NOTICE <nick/channel> <message>
Send notice to nick/channel
WHOIS [server/nick] <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 <nick/channel>
Show WHO list
NAMES [channel]
List nicks (in channel)
** Bit more advanced commands
MODE <channel/nick> <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 <nick> [channel]
Invite nick to channel
CTCP <nick/channel> <command>
Send CTCP request to nick/channel (PING, VERSION, ..)
NCTCP <nick/channel> <reply>
Send CTCP reply to nick/channel
PING <nick>
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] <message>
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] <nick> <reason>
Kick nick from channel
KICKBAN [channel] <nick> <reason>
Kick+ban nick from channel
KNOCKOUT [secs] <nick> <reason>
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 <normal/host/domain/custom>
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 <nick> <message>
Kill nick from irc network. [irc ops only]
WALLOPS <message>
Write wallops message. [irc ops only]
QUOTE <message>
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 <nick>
Open DCC chat
DCC SEND <nick> <filename>
Send file to nick
DCC GET <nick> [filename]
Get file offered by nick
DCC RESUME <nick> [filename]
(MIRC) Resume getting file offered by nick
DCC CLOSE <type> <nick> [filename]
Close DCC connection
DCC LIST
List DCC connections
MIRCDCC [n]
Set MIRC style CTCPs on/off
** User interface handling
WINDOW <NEW/CLOSE/SERVER/PREV/NEXT/GOTO/LEVEL>
NEW [HIDDEN/TAB]
Create new window (in tab)
CLOSE
Close the current window
SERVER <tag>
Change which server to use in current window
PREV/NEXT/GOTO <N>
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 <text>
Print text to screen
MODES
Open channel modes dialog (GTK/GNOME version)
GWHOIS <nick>
Display WHOIS information in dialog (GTK/GNOME version)
LAST [-pub -msgs...] <text>
Display (only public/msgs/..) lines where <text> 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 <key> TOGGLE, or if ON or OFF parameter is given
it will work just like /SET.
SAVE
Save configuration to disk.
ALIAS, UNALIAS <alias> [command]
Set/remove alias, /unalias is the same as /alias without command
Typing extra / before /command (//command) ignores any aliases
IGNORE, UNIGNORE <mask> [level [level..]]
Ignore/unignore specified level(s) or everything from nick
NOTIFY <mask> [ircnet [ircnet..]]
Add mask (nick) to notify list for specified ircnets..
UNNOTIFY <mask>
Remove mask from notify list.
LOG <CREATE/CLOSE/START/STOP/LIST>
CREATE <filename> [<+/->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 <filename>
Close log and remove from configuration
START <filename>
Start logging to file
STOP <filename>
Stop logging to file
LIST
List logs.
LOAD <plugin> [arguments]
Load plugin
UNLOAD <plugin>
Unload plugin

View File

@ -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).

View File

@ -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 %

621
docs/PERL
View File

@ -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.

View File

@ -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 "<cmd>, 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 "<cmd>, 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 "<cmd>, 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 "<cmd>, 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 "<cmd>, 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 "<cmd>, char *args, DCC_REC
"default dcc ctcp", char *args, DCC_REC
"dcc unknown ctcp", char *args, char *sender, char *sendaddr
"dcc reply "<cmd>, 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

View File

@ -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 */

View File

@ -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)

View File

@ -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

View File

@ -35,7 +35,7 @@
#include <glib.h>
#include <gmodule.h>
#include "irc-base/memdebug.h"
#include "core/memdebug.h"
#include "nls.h"
#define g_free_not_null(a) \

View File

@ -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;
}

View File

@ -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

View File

@ -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)

View File

@ -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);
}

View File

@ -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;

30
src/perl/Makefile.am Normal file
View File

@ -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 ..

38
src/perl/get-signals.pl Executable file
View File

@ -0,0 +1,38 @@
#!/usr/bin/perl
print "static PERL_SIGNAL_ARGS_REC perl_signal_args[] =\n{\n";
while (<STDIN>) {
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";

529
src/perl/irssi-perl.c Normal file
View File

@ -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 <EXTERN.h>
#ifndef _SEM_SEMUN_UNDEFINED
#define HAS_UNION_SEMUN
#endif
#include <perl.h>
#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 = <FH>;\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);
}

7
src/perl/irssi-perl.h Normal file
View File

@ -0,0 +1,7 @@
#ifndef __IRSSI_PERL_H
#define __IRSSI_PERL_H
void irssi_perl_init(void);
void irssi_perl_deinit(void);
#endif

3
src/perl/module.h Normal file
View File

@ -0,0 +1,3 @@
#include "common.h"
#define MODULE_NAME "irssi-perl"

108
src/perl/perl-signals.h Normal file
View File

@ -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 }
};

21
src/perl/xs/Irssi.pm Normal file
View File

@ -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;

933
src/perl/xs/Irssi.xs Normal file
View File

@ -0,0 +1,933 @@
/* This could be split to different files / modules ..? */
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#undef _
#include <irssi-plugin.h>
#include <irc-base/server-setup.h>
#include <irc-base/server-reconnect.h>
#include <irc-base/server-redirect.h>
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)));

View File

@ -0,0 +1,6 @@
use ExtUtils::MakeMaker;
WriteMakefile('NAME' => 'Irssi',
'LIBS' => '',
'INC' => '-I@top_srcdir@/src @GLIB_CFLAGS@',
'VERSION_FROM' => '@srcdir@/Irssi.pm');

14
src/perl/xs/typemap Normal file
View File

@ -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

41
src/perl/xsinit.c Normal file
View File

@ -0,0 +1,41 @@
#if defined(__cplusplus) && !defined(PERL_OBJECT)
#define is_cplusplus
#endif
#ifdef is_cplusplus
extern "C" {
#endif
#include <EXTERN.h>
#include <perl.h>
#ifdef PERL_OBJECT
#define NO_XSLOCKS
#include <XSUB.h>
#include "win32iop.h"
#include <fcntl.h>
#include <perlhost.h>
#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);
}