From 770ae4596d3e826c63e8c9fa441d65bd0889f03c Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Fri, 3 Sep 1999 14:27:29 +0000 Subject: [PATCH] Initial revision git-svn-id: http://svn.irssi.org/repos/irssi/trunk@3 dbcabf3a-b0e7-0310-adc4-f8d773084564 --- .cvsignore | 31 + AUTHORS | 1 + COMMANDS | 383 ++++++ Makefile.am | 46 + NEWS | 0 README | 82 ++ README-HEBREW | 43 + TODO | 140 ++ acconfig.h | 25 + autogen.sh | 21 + colorless.theme | 101 ++ config | 36 + configure.in | 363 ++++++ file2header.sh | 5 + irssi.desktop | 6 + irssi.gnorba | 5 + irssi.spec.in | 87 ++ servertest/.cvsignore | 8 + servertest/Makefile.am | 13 + servertest/server.c | 463 +++++++ src/.cvsignore | 2 + src/Makefile.am | 17 + src/common-setup.h | 125 ++ src/common.h | 114 ++ src/irssi-plugin-gui.h | 11 + src/irssi-plugin.h | 9 + src/signal.doc | 178 +++ stamp.h.in | 0 window-views-patch.diff | 2672 +++++++++++++++++++++++++++++++++++++++ 29 files changed, 4987 insertions(+) create mode 100644 .cvsignore create mode 100644 AUTHORS create mode 100644 COMMANDS create mode 100644 Makefile.am create mode 100644 NEWS create mode 100644 README create mode 100644 README-HEBREW create mode 100644 TODO create mode 100644 acconfig.h create mode 100755 autogen.sh create mode 100644 colorless.theme create mode 100644 config create mode 100644 configure.in create mode 100755 file2header.sh create mode 100644 irssi.desktop create mode 100644 irssi.gnorba create mode 100644 irssi.spec.in create mode 100644 servertest/.cvsignore create mode 100644 servertest/Makefile.am create mode 100644 servertest/server.c create mode 100644 src/.cvsignore create mode 100644 src/Makefile.am create mode 100644 src/common-setup.h create mode 100644 src/common.h create mode 100644 src/irssi-plugin-gui.h create mode 100644 src/irssi-plugin.h create mode 100644 src/signal.doc create mode 100644 stamp.h.in create mode 100644 window-views-patch.diff diff --git a/.cvsignore b/.cvsignore new file mode 100644 index 00000000..5296986d --- /dev/null +++ b/.cvsignore @@ -0,0 +1,31 @@ +Makefile +Makefile.in +aclocal.m4 +config.cache +config.guess +config.h +config.log +config.status +config.sub +configure +configure.scan +libtool +ltconfig +ltmain.sh +stamp-h +stamp-h.in +stamp.h +version.h +config.h.in +.exrc +gnome-bug +gnome-config +install-sh +missing +mkinstalldirs +INSTALL +intl +ABOUT-NLS +COPYING +irssi.spec +default-config.h diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 00000000..d0235c5b --- /dev/null +++ b/AUTHORS @@ -0,0 +1 @@ +Timo Sirainen, cras@irccrew.org diff --git a/COMMANDS b/COMMANDS new file mode 100644 index 00000000..71bf1f87 --- /dev/null +++ b/COMMANDS @@ -0,0 +1,383 @@ + + ** Some definations + + +"Level" usually means that you can use these words there: + + CRAP - Can be almost anything + PUB - Public messages in channel + MSGS - Private messages + CHAN - Channel messages: joins, parts, quits, etc. + NOTICES - Notices + SNOTES - Notices from server + WALLOPS - Wallops + ACTIONS - Actions (/me) + DCC - DCC messages + CTCP - CTCP messages + HILIGHT - Hilighted text + CLIENTNOTICES - Irssi's notices + CLIENTERRORS - Irssi's error messages + + + ** Server handling + + +CONNECT
[:port[:password]] + + Connect to specified server + +DISCONNECT <* / tag> [message] + + Disconnect from server + +SERVER
[:port[:password]] + + Disconnect from current server and connect to new one + +SERVERS + + Display a list of servers + +RMRECONNS + + Remove all servers from reconnection list + + + ** Basic IRC commands + + +QUIT [message] + + Quit irssi + +JOIN [key] [, channel...] + + Join to channel(s) + +PART [channel] [message] + + Leave from channel + +QUERY + + Create query window + +UNQUERY + + Close query window + +MSG + + Send message to nick/channel + +ME + + Send action to channel (/me thinks..) + +NOTICE + + Send notice to nick/channel + +WHOIS [server/nick] + + Send WHOIS query, you can also specify from what server to ask the + information. If you type the nick twice it will ask from the same + server what nick is using. + +AWAY [message] + + Sets yourself away/unaway + +AWAYALL [message] + + Sets yourself away/unaway to all connected servers + +WHO + + Show WHO list + +NAMES [channel] + + List nicks (in channel) + + + ** Bit more advanced commands + + +MODE + + Get/set channel/nick mode. + + Get channel modes: + b - Get ban list + e - Get ban exception list + I - Get invite list + + Set channel modes (use +/- before these): + b *!ban@mask - Set/remove ban + e *!ban@mask - Set/remove ban exception + I *!ban@mask - Set/remove channel invite + o nick - Set/remove op status + v nick - Set/remove voice status + l limit - Set remove max. people limit in channel + k key - Set/remove channel key + s - Secret + p - Private + m - Moderated + i - Invite only + n - No external messages + t - Only ops can change topic + + User modes: + i - Invisible + w - Show wallops + s - Show server notices + +TOPIC [channel] [topic] + + Get/set channel topic + +INVITE [channel] + + Invite nick to channel + +CTCP + + Send CTCP request to nick/channel (PING, VERSION, ..) + +NCTCP + + Send CTCP reply to nick/channel + +PING + + Send CTCP PING to nick and tell how long it took to receive the reply + +ISON [nick [nick...]] + + Ask if nicks are in IRC. + +WALL [channel] + + Send notice message to all operators in channel. + +OP, DEOP, VOICE, DEVOICE [channel] [nick [nick...] + + Op/deop/voice/devoice nick(s) in channel + +KICK [channel] + + Kick nick from channel + +KICKBAN [channel] + + Kick+ban nick from channel + +KNOCKOUT [secs] + + Kick+ban+delay (default to 5min)+unban + +BAN [channel] [nick [nick...]] + + Ban nick(s) in channel + +UNBAN [channel] [mask [mask...]] + + Remove ban(s) from channel + +BANSTAT [channel] + + List bans and ban exceptions in channel + +BANTYPE + + Set ban type: + + Normal - *!user@*.domain.net + Host - *!*@host.domain.net + Domain - *!*@*.domain.net + Custom [nick] [user] [host] [domain] + eg. /bantype custom nick domain - nick!*@*.domain.net + eg. /bantype custom user host - *!user@host.domain.net + +INVITELIST [channel] + + List invites (+I) in channel + +VERSION [server] + + Displays irssi version and asks IRC server's version + +VER [nick/channel] + + Sends CTCP VERSION request to nick/channel + +SV [nick/channel] + + Sends irssi version text to nick/channel + +KILL + + Kill nick from irc network. [irc ops only] + +WALLOPS + + Write wallops message. [irc ops only] + +QUOTE + + Send raw data to irc server - DON'T USE THIS unless you really know + what you're doing! + + + ** DCC handling + + +DCC + + List DCC connections (same as DCC LIST) + +DCC CHAT + + Open DCC chat + +DCC SEND + + Send file to nick + +DCC GET [filename] + + Get file offered by nick + +DCC RESUME [filename] + + (MIRC) Resume getting file offered by nick + +DCC CLOSE [filename] + + Close DCC connection + +DCC LIST + + List DCC connections + +MIRCDCC [n] + + Set MIRC style CTCPs on/off + + + ** User interface handling + + +WINDOW + + NEW [HIDDEN/TAB] + + Create new window (in tab) + + CLOSE + + Close the current window + + SERVER + + Change which server to use in current window + + PREV/NEXT/GOTO + + Go to previous/next/Nth window + + LEVEL <[+/-]pub/msgs/...> + + Change window level, eg. + /window level msgs - creates messages window + /window level all -msgs - creates status window + +CLEAR + + Clear screen + +ECHO + + Print text to screen + +MODES + + Open channel modes dialog (GTK/GNOME version) + +GWHOIS + + Display WHOIS information in dialog (GTK/GNOME version) + +LAST [-pub -msgs...] + + Display (only public/msgs/..) lines where appears + (Text version only) + + + ** Configuration + + +SET [key [=value / [key [key..]] + + Get/set configuration + +ALIAS, UNALIAS [command] + + Set/remove alias, /unalias is the same as /alias without command + + These codes are extracted in commands: + %0 : name of alias + %1, %2, %3 .. : %th word + &1, &2, &3 .. : &th word + the rest of the text after it + %c : channel name + + Typing extra / before /command (//command) ignores any aliases + +IGNORE, UNIGNORE [level [level..]] + + Ignore/unignore specified level(s) or everything from nick + +NOTIFY [ircnet [ircnet..]] + + Add mask (nick) to notify list for specified ircnets.. + +UNNOTIFY + + Remove mask from notify list. + +LOG + + CREATE [<+/->level ...] [#channel/nick [ + [<+/->level ...] ...] + + Create and start logging to file + + Example: /log create mylog -all +msgs #linux +chan +public + (or simply #linux +all logs everything that appears in #linux + window). + + CLOSE + + Close log and remove from configuration + + START + + Start logging to file + + STOP + + Stop logging to file + + LIST + + List logs. + +LOAD [arguments] + + Load plugin + +UNLOAD + + Unload plugin + diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 00000000..176258b8 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,46 @@ +# create default-config.h +config.h: default-config.h + +default-config.h: config + ./file2header.sh config > default-config.h + +## if +#SUBDIRS = po intl macros support # +## else +if BUILD_PLUGINS +PLUGINS=plugins +endif +if BUILD_SERVERTEST +SERVERTEST=servertest +endif + +SUBDIRS = macros src $(PLUGINS) $(SERVERTEST) +## endif + +## to automatically rebuild aclocal.m4 if any of the macros in +## `macros/' change +@MAINT@include macros/macros.dep +@MAINT@macros/macros.dep: macros/Makefile.am +@MAINT@ cd macros && $(MAKE) macros.dep + +if HAVE_GNOME +appletdir = $(datadir)/applets/Network +applet_DATA = irssi.desktop + +corbadir = $(sysconfdir)/CORBA/servers +corba_DATA = irssi.gnorba +endif + +confdir = $(sysconfdir)/irssi +conf_DATA = config colorless.theme + +EXTRA_DIST = window-views-patch.diff \ + autogen.sh \ + README-HEBREW \ + COMMANDS \ + file2header.sh \ + irssi.spec.in \ + irssi.spec \ + $(conf_DATA) \ + irssi.gnorba \ + irssi.desktop diff --git a/NEWS b/NEWS new file mode 100644 index 00000000..e69de29b diff --git a/README b/README new file mode 100644 index 00000000..39514fdc --- /dev/null +++ b/README @@ -0,0 +1,82 @@ + + +irssi + + + * ABOUT + +Irssi is an IRC client made with GTK+ toolkit and (optional) GNOME libraries. +A small text mode version is also somewhat working, there's also a really +simple daemon version which just loads "bot" plugin (which doesn't exist). +I'd also like to see KDE version but someone else will have to do it. + + + * FEATURES + +See COMMANDS file for list of all commands irssi knows. + +I've been asked quite a lot about why should one use irssi, what does it do +that other IRC clients don't? Well, to tell you the truth, I have no idea :) +Still I've got a lot of mails saying it's the best GUI IRC client they've +ever used :) Let's see.. It should be easy to use, it has most of the +features IRC client needs and it's pretty stable. Here's a small list of what +it does: + + - Nice configuration :) Especially the color settings. + - You can connect to multiple servers. Irssi is also IRC network aware so + you can specify some settings to work only in specified IRC networks. + - Automatically connect to IRC server(s) at startup, automatically join to + channels when connected + - All code is nonblocking, it won't hang while connecting to server or + opening DCC connection. Host lookups are done in separate processes. + - DCC send, receive and chat with GUI + - GNOME panel support, channels and queries are displayed in GNOME panel + where you can easily see which channels have been updated (label turns to + red) and click in them to open the channel. + - Doubleclicking URL in text widget launches specified web/ftp/email client, + also doubleclicking channel/nick join to channel or creates query. + - Aliases, ignores, autoignoring when flooding, notify lists, completing + specified words with tab (like home<tab> -> http://my.home.page), + hilighting lines with specified texts + - Smart nick completion + - Configurable logging support + - You can use ZVT widget to print texts, it's really fast so you can be + joined to many high traffic channels and irssi won't slow up + - Plugins support, creating plugins is really easy. + - Lots of nice GUI stuff :) + + + * INSTALLATION + +./configure +make +make install + +Configure can use these parameters (all of these defaults to yes): + + --with-proplist=dir Specify libPropList directory + --with-servertest Build test irc server which you can use to try crash + irc clients + --without-gnome Build without GNOME libraries + --without-gnome-panel Build without GNOME panel + --without-imlib Build without Imlib library + --without-socks Build without socks library + --without-textui Build without text mode version + --enable-memdebug Enable memory debugging, great for finding memory + leaks + --enable-gtk-hebrew Enable Hebrew support - see README-HEBREW + +There's also some others, you can get a full list with ./configure --help + +If you don't want to run irssi in panel, add --no-applet to command line +parameters. + + + * BUGS / SUGGESTIONS + +See TODO file if it is already listed in there - if not send me email.. + + + * AUTHOR + +Timo Sirainen, cras@irccrew.org, cras/ircnet/#irssi, http://xlife.dhs.org/irssi/ diff --git a/README-HEBREW b/README-HEBREW new file mode 100644 index 00000000..2f740ae2 --- /dev/null +++ b/README-HEBREW @@ -0,0 +1,43 @@ +Hebrew support in irssi +----------------------- + +Before you can enjoy IRCing in Hebrew, you need to get two other things. + +1. FriBidi, a free implementation of the Unicode BiDi algorithm). + See http://imagic.weizmann.ac.il/~dov/freesw/FriBidi/ + +2. hebxfonts, a collection of Unicode-encoded Hebrew fonts along + with the keyboard mappings to use them (the right Alt key will be + configured to generate Hebrew characters). + See http://metalab.unc.edu/pub/Linux/X11/fonts/ + +After you get these two, you should be ok to go. To enable the Hebrew +support, specify --enable-gtk-hebrew=. If the path starts with a +tilde (~), it is taken relative to your home directory. Here's a good +idea: + + configure --enable-gtk-hebrew=~/.gnome/irssi-hebrew.gtkrc + +After compiling and installing, you should copy the supplied gtkrc +file to where you told the program it would find it. Say you're at the +root of the irssi source tree, typing: + + cp src/gui-gnome/irssi-hebrew.gtkrc ~/.gnome/irssi-hebrew.gtkrc + +would do the trick. + +One last configuration task is done from within irssi. Fire it up, +then go to the preferences dialog box and select a Hebrew font. +(e.g., -misc-fixed-medium-r-normal-*-*-120-*-*-c-*-iso8859-8) + +The Hebrew support is not complete; it works as expected (ie, reversing +stuff with the FriBidi thingy) for the text entry field and for the +output text. In other places, you may see Hebrew characters, only +going left-to-right; in yet other places, you may not see Hebrew at all. + +I have no intention of making this any better; comprehensive support +for Hebrew should come from within the GTK+ widget set, and not by +patching applications. + + +Ronen Tzur diff --git a/TODO b/TODO new file mode 100644 index 00000000..a3e5d477 --- /dev/null +++ b/TODO @@ -0,0 +1,140 @@ + - window goto active, name + +*** Bugs + + - If there's any empty lists in configuration file (like ircnets = ();), + libPropList crashes irssi at startup.. Irssi doesn't save any empty lists + now, but still this needs to be fixed in libPropList.. + - after changing irssi-text's screen size to smaller it leaves some empty + lines to windows before printing text, redrawing screen moves the lines + back up.. hm.. + - 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 + DCC_REC? + - gfloat doesn't work in formats .. why? In DCC messages kb and kb/s values + could be shown as floats.. + +*** text GUI + + - statusbar: + - when starting to run out of space some items could be made smaller, + activity for example .. make some generic flag for items to use. + - activity: hilight number if window has message for you or hilighted + text + - "you have new mail" + - active server tag somewhere in window + - word wrapping doesn't work perfectly, if colors/bolds/etc are used, they're + treated as spaces. So things like (blah blah) can happen (/who) + - autojoining to channels, make the code common in gui-gnome and gui-text + +*** Big things + + - keyboard configuration + - 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. + use dialog with gtktree widget to change it. + - split windows with gtkpaned (check window-views-patch.diff) + - really transparently working irc proxy, saves scrollback buffers, etc. + Or maybe the existing ones already work? + - some sort of address book? our own irssi ctcp to ask for other irssi users + for their information (of course not without asking (except optionally)).. + could be nice also to automatically update it, keep track of all seen + users gathered when joining channels, whois, who, etc. commands. + automatically updating information could be host masks, nicks, ips, seen in + channels, operator in channels, .. user specified checks like last topic or + mode changes or even msgs to you/some channel/with some keyword. great for + spying people ;) maybe even useful sometimes.. + + .. but what database would be best for this? + + - GTK version: icons to toolbars, accelerators to menus + - Windows style MDI windows are possible with GtkFixed .. Some people would + like this.. too much job for me, it would need building the MDI windows + ourself (title bar, borders, resizing, etc.) + + - online help, documentation, ... + - plugins: + - perl plugin .. implementation problems, C's structures need to be + handled some way .. like for server structure get_address(), + get_port(), set_address(), set_port() etc.. + - other scripting plugins would be easier? scheme, tcl, pythong? + sula premirex uses scheme, it would probably be pretty easy to learn + from it how to do it to irssi :) + - IRC bot, eggdrop is too old, needs a replacement ;) + - DCC file server, I'm not too excited about this, maybe someone else + wants to do it.. + - Multiplayer games! :) Chess, tic-tac-toe, othello, battleship, tetris, + etc. Existing games should probably be used .. though there doesn't + seem to be any of these (except tetris) for gnome right now.. + - audio / video chat :) + +*** Little things + + - command line parameter handling, specify what server/ircnet to autoconnect + or none. + - /list: + - gui optional + - sort it by clicking the headers + - change the size of columns + - total number of channels + - copy/paste things in list? + - search the list + - 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 + - use different themes in different channels/queries? + - improve msgslevels and ignoring .. Like ignoring "chan" doesn't work now. + It could be changed to joins, parts, quits, topics, nicks, .. just rip all + the msglevels from bitchx and use them :) + - use server-idle instead of channel.query thing.. + - lag meter + - possibility to display different colors in nicks from different people.. + and different colors for word hilighting too + - /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. + - support for ircii translation tables (/usr/lib/irc/translation/*) + - use different nicks/realnames in different irc networks + - zvt problems/todo: + - need some way to disable all the extra features, like sending 0x8e + messes up your fonts. + - the ugly cursor just keeps blinking + - when clicking an empty spot on screen it sometimes tells that there's + some weird crap in there.. + - word wrapping + - notify list: + - dialog: keep track of hosts/realnames so after closing and opening the + dialog again they would show up.. + - summary list (for irssi-text) + - nick-specific options: + - check for gone-flag changes (use userhosts instead of isons) + - create popup dialog + - run some command (like /exec as soon as I get that done :) + - gnome statubar: + - clock? + - dcc transfer meter (gtk progressbar) + - you could configure which events (whois, notify, etc.) to show in what + windows (all, current, status) + - gui for configuring plugin specific theme format texts + - awaylog (/log create ~/away.log -all +msgs or something), autoaway + - make window/save buffer and find work with zvt + - dcc send: allow selection of multiple files to send (also for dnd from + gmc!) Allow dropping files to anywhere in irssi. + - logging: longer format dd.mm.yy hh:mm:ss (configurable?) + - net split/join detection ? is this even needed? more harmful than useful? + - /timer, /clones + - run multiple commands with one alias (what was this needed for? can't + remember..) + - 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... diff --git a/acconfig.h b/acconfig.h new file mode 100644 index 00000000..e90d0d05 --- /dev/null +++ b/acconfig.h @@ -0,0 +1,25 @@ +#undef HAVE_GTK +#undef HAVE_GNOME +#undef HAVE_GNOME_PANEL +#undef SYSCONFDIR +#undef PLUGINSDIR +#undef PERLSCRIPTDIR +#undef GTK_10 +#undef HAVE_SOCKS_H +#undef HAVE_IMLIB +#undef MEM_DEBUG +#undef HAVE_IPV6 +#undef GTK_HEBREW +#undef GTK_HEBREW_RC + +#undef HAVE_NCURSES_USE_DEFAULT_COLORS +#undef HAVE_CURSES_IDCOK + +#undef HAS_CURSES +#undef USE_SUNOS_CURSES +#undef USE_BSD_CURSES +#undef USE_SYSV_CURSES +#undef USE_NCURSES +#undef NO_COLOR_CURSES +#undef SCO_FLAVOR +#undef NCURSES_970530 diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 00000000..5afe8b70 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,21 @@ +#!/bin/sh +# Run this to generate all the initial makefiles, etc. + +srcdir=`dirname $0` +test -z "$srcdir" && srcdir=. + +# I'm too lazy to update version number into several places.. :) +version=`cat configure.in|grep AM_INIT_AUTOMAKE|perl -pe 's/^[^,]*,[ ]*([^\)]*).*/$1/'` +cat irssi.spec.in |sed s/^Version:/Version:\ $version/ > irssi.spec + +PKG_NAME="Irssi" + +(test -f $srcdir/configure.in \ +## put other tests here +) || { + echo -n "**Error**: Directory "\`$srcdir\'" does not look like the" + echo " top-level $PKG_NAME directory" + exit 1 +} + +. $srcdir/macros/autogen.sh diff --git a/colorless.theme b/colorless.theme new file mode 100644 index 00000000..2d8b2c1c --- /dev/null +++ b/colorless.theme @@ -0,0 +1,101 @@ +{ + default_color = 7; + colors = {}; + formats = { + line_start = "-!- "; + line_start_irssi = "-!- Irssi: "; + connecting = "Connecting to %_$1%_ [$2] port %_$3%_"; + disconnected = "Disconnected from %_$1%_ [$2]"; + join = "%_$1%_ [$2] has joined %_$3"; + cannot_join = "Cannot join to channel %_$1%_ [$2]"; + part = "%_$1%_ [$2] has left %_$3%_ [$4]"; + kick = "%_$1%_ was kicked from $2 by %_$3%_ [$4]"; + quit = "%_$1%_ [$2] has quit IRC [$3]"; + names = "[%_Users%_($1)] $2"; + endofnames = "%_$1%_: Total of %_$2%_ nicks [%_$3%_ ops, %_$4%_ voices, %_$5%_ normal]"; + topic = "Topic for $1: $2"; + no_topic = "No topic set for $1"; + new_topic = "%_$1%_ changed the topic of $2 to: $3"; + topic_unset = "Topic unset by %_$1%_ on $2"; + topic_info = "Topic set by %_$1%_ [$2]"; + chanmode_change = "mode/$1 [$2] by %_$3"; + channel_mode = "mode/$1 [$2]"; + banlist = "%_$1%_: ban $2"; + banlist_long = "%_$1%_: ban $2 [by %_$3%_, $4 secs ago]"; + ebanlist = "%_$1%_: ban exception $2"; + ebanlist_long = "%_$1%_: ban exception $2 [by %_$3%_, $4 secs ago]"; + invitelist = "%_$1%_: invite $2"; + usermode_change = "Mode change [%_$1%_] for user $2"; + your_nick_changed = "You're now known as $1"; + nick_changed = "%_$1%_ is now known as $2"; + your_nick_owned = "Your nick is owned by %_$4%_ [$2@$3]"; + whois = "%_$1%_ [$2@$3]%N ircname : $4"; + whois_idle_signon = " idle : $2 hours $3 mins $4 secs [signon: $5]"; + own_msg = "<$1> $2"; + own_msg_channel = "<$1:$2> $3"; + own_msg_private = "[msg($1)] $2"; + own_notice = "[notice($1)] $2"; + own_me = " * $1 $2"; + own_ctcp = "[ctcp($1)] $2 $3"; + own_dcc = "[dcc($1)] $2"; + pubmsg_me = "<$1> $2"; + pubmsg_me_channel = "<$1:$2> $3"; + pubmsg = "<$1> $2"; + pubmsg_channel = "<$1:$2> $3"; + msg_private = "[$1($2)] $3"; + dcc_msg = "[$1(dcc)] $2"; + notice_server = "!$1 $2"; + notice_public = "-$1:$2- $3"; + notice_private = "-$1($2)- $3"; + action_dcc = " (*dcc*) $1 $2"; + action_private = " (*) $1 $2"; + action_public = " * $1 $2"; + action_public_channel = " * $1:$2 $3"; + ctcp_reply = "CTCP %_$1%_ reply from %_$2%_: $3"; + ctcp_requested = ">>> %_$1%_ [$2] requested %_$3%_ from %_$4"; + dcc_ctcp = ">>> DCC CTCP received from %_$1%_: $2"; + dcc_chat = "DCC CHAT from %_$1%_ [$2 port $3]"; + dcc_chat_not_found = "No DCC CHAT connection open to %_$1"; + dcc_chat_connected = "DCC %_CHAT%_ connection with %_$1%_ [$2 port $3] established"; + dcc_chat_disconnected = "DCC lost chat to %_$1"; + dcc_send = "DCC SEND from %_$1%_ [$2 port $3]: $4 [$5 bytes]"; + dcc_send_exists = "DCC already sending file $1 for %_$2%_"; + dcc_send_not_found = "DCC not sending file $2 to %_$1"; + dcc_send_file_not_found = "DCC file not found: $1"; + dcc_send_connected = "DCC sending file $1 for %_$2%_ [$3 port $4]"; + dcc_send_complete = "DCC sent file $1 [%_$2%_kb] for %_$3%_ in %_$4%_ secs [%_$5kb/s%_]"; + dcc_send_aborted = "DCC aborted sending file $1 for %_$2%_"; + dcc_get_not_found = "DCC no file offered by %_$1"; + dcc_get_connected = "DCC receiving file $1 from %_$2%_ [$3 port $4]"; + dcc_get_complete = "DCC received file $1 [$2kb] from %_$3%_ in %_$4%_ secs [$5kb/s]"; + dcc_get_aborted = "DCC aborted receiving file $1 from %_$2%_"; + dcc_unknown_ctcp = "DCC unknown ctcp $1 from %_$2%_ [$3]"; + dcc_unknown_reply = "DCC unknown reply $1 from %_$2%_ [$3]"; + dcc_unknown_command = "DCC unknown command: $1"; + dcc_unknown_type = "DCC unknown type %_$1"; + dcc_connect_error = "DCC can't connect to %_$1%_ port %_$2"; + dcc_cant_create = "DCC can't create file $1"; + dcc_rejected = "DCC $1 was rejected by %_$2%_ [$3]"; + dcc_close = "DCC $1 close for %_$2%_ [$3]"; + log_opened = "Log file $1 opened"; + log_open_failed = "Couldn't open log file $1"; + log_not_open = "Log file $1 not open"; + log_closed = "Closed log file $1"; + log_listentry = "$1: $2"; + log_sublistentry = " + $1: $2"; + ircjoin = "%_$1%_ [$2@$3] [%_$4%_] has joined to IRC"; + plugin_cant_load = "Can't load plugin %_$1%_"; + plugin_not_loaded = "Plugin %_$1%_ not loaded"; + }; + + plugins = { + sample = "start stop"; + }; + + pluginformats = { + sample = { + start = "Sample plugin loaded"; + stop = "Sample plugin unloaded"; + }; + }; +} diff --git a/config b/config new file mode 100644 index 00000000..a1c67685 --- /dev/null +++ b/config @@ -0,0 +1,36 @@ +{ + setupservers = ( + {server = irc.funet.fi;ircnet = ircnet;port = 6667;autoconnect = No;} + ); + + ircnets = ({name = ircnet;}); + + channels = ( + { + name = "#irssi"; + ircnet = ircnet; + autojoin = No; + } + ); + aliases = ( + {alias = J;command = "/join &1";}, + {alias = LEAVE;command = "/part &1";}, + {alias = BYE;command = "/quit &1";}, + {alias = WI;command = "/whois &1";}, + {alias = WII;command = "/whois %1 %1";}, + {alias = WW;command = "/whowas &1";}, + {alias = W;command = "/who *";}, + {alias = N;command = "/names *";}, + {alias = M;command = "/msg &1";}, + {alias = T;command = "/topic &1";}, + {alias = C;command = "/clear";}, + {alias = CL;command = "/clear";}, + {alias = K;command = "/kick &1";}, + {alias = KB;command = "/kickban &1";}, + {alias = KN;command = "/knockout &1";}, + {alias = B;command = "/ban &1";}, + {alias = UB;command = "/unban &1";}, + {alias = IG;command = "/ignore &1";}, + {alias = UNIG;command = "/unignore &1";} + ); +} diff --git a/configure.in b/configure.in new file mode 100644 index 00000000..a0af0232 --- /dev/null +++ b/configure.in @@ -0,0 +1,363 @@ +AC_INIT(src) + +AM_CONFIG_HEADER(config.h) +AM_INIT_AUTOMAKE(irssi, 0.7.16) + +AM_MAINTAINER_MODE + +AM_ACLOCAL_INCLUDE(macros) + +AC_ISC_POSIX +AC_PROG_CC +AC_PROG_CPP +AC_STDC_HEADERS +AC_ARG_PROGRAM +AM_PROG_LIBTOOL + +AC_CHECK_HEADERS(string.h stdlib.h unistd.h dirent.h sys/ioctl.h) + +GNOME_INIT + +AC_ARG_WITH(proplist, +[ --with-proplist Specify libPropList location], + proplist_dir=$withval) + +AC_ARG_WITH(socks, +[ --with-socks Build with socks support], + if test x$withval = xyes; then + want_socks=yes + else + if test "x$withval" = xno; then + want_socks=no + else + want_socks=yes + fi + fi, + want_socks=no) + +AC_ARG_WITH(imlib, +[ --with-imlib Build with imlib support], + if test x$withval = xyes; then + want_imlib=yes + else + if test "x$withval" = xno; then + want_imlib=no + else + want_imlib=yes + fi + fi, + want_imlib=yes) + +AC_ARG_WITH(gnome-panel, +[ --with-gnome-panel Build with gnome panel applet support], + if test x$withval = xyes; then + want_gnome_panel=yes + else + if test "x$withval" = xno; then + want_gnome_panel=no + else + want_gnome_panel=yes + fi + fi, + want_gnome_panel=yes) + +AC_ARG_WITH(textui, +[ --with-textui Build irssi-text], + if test x$withval = xyes; then + want_textui=yes + else + if test "x$withval" = xno; then + want_textui=no + else + want_textui=yes + fi + fi, + want_textui=yes) + +AC_ARG_WITH(plugins, +[ --with-plugins Build plugins], + if test x$withval = xyes; then + want_plugins=yes + else + if test "x$withval" = xno; then + want_plugins=no + else + want_plugins=yes + fi + fi, + want_plugins=yes) + +AC_ARG_WITH(servertest, +[ --with-servertest Build servertest], + if test x$withval = xyes; then + want_servertest=yes + else + if test "x$withval" = xno; then + want_servertest=no + else + want_servertest=yes + fi + fi, + want_servertest=no) + +AC_ARG_ENABLE(memdebug, +[ --enable-memdebug Enable memory debugging], + if test x$enableval = xyes; then + want_memdebug=yes + else + if test "x$enableval" = xno; then + want_memdebug=no + else + want_memdebug=yes + fi + fi, + want_memdebug=no) + +AC_ARG_ENABLE(ipv6, +[ --enable-ipv6 Enable IPv6 support], + if test x$enableval = xyes; then + want_ipv6=yes + else + if test "x$enableval" = xno; then + want_ipv6=no + else + want_ipv6=yes + fi + fi, + want_ip6=no) + +AC_ARG_ENABLE(gtk-hebrew, +[ --enable-gtk-hebrew Enable Hebrew support], + if test "x$enableval" = xno; then + want_gtk_hebrew=no + HEBREW_LIBS="" + else + AC_DEFINE(GTK_HEBREW) + AC_DEFINE_UNQUOTED(GTK_HEBREW_RC, "$enableval") + HEBREW_LIBS="-lfribidi" + want_gtk_hebrew=yes + fi, + want_gtk_hebrew=no) + +dnl ** +dnl ** just some generic stuff... +dnl ** + +AC_CHECK_FUNCS(mkfifo) + +AC_CHECK_LIB(socket, socket, [ + LIBS="$LIBS -lsocket" +]) + +AC_CHECK_LIB(nsl, inet_addr, [ + LIBS="$LIBS -lnsl" +], -lsocket) + +# gcc specific options +if test "x$ac_cv_prog_gcc" = "xyes"; then + CFLAGS="$CFLAGS -Wall" +fi + +if test "x$prefix" = "xNONE"; then + prefix="/usr/local" +else + prefix=$prefix +fi + +AM_CONDITIONAL(BUILD_PLUGINS, test "x$want_plugins" = "xyes") +AM_CONDITIONAL(BUILD_SERVERTEST, test "x$want_servertest" = "xyes") +AC_DEFINE_UNQUOTED(SYSCONFDIR, "$prefix/etc") +AC_DEFINE_UNQUOTED(PLUGINSDIR, "$prefix/lib/irssi/plugins") + +dnl ** +dnl ** check for libPropList +dnl ** + +if test "x$proplist_dir" = "x"; then + proplib= +else + proplib=-L$proplist_dir/lib +fi + +AC_CHECK_LIB(PropList, PLSave, [ + LIBS="$LIBS $proplib -lPropList" + if test "x$proplist_dir" != "x"; then + CFLAGS="$CFLAGS -I$proplist_dir/include" + fi +], [ + echo "ERROR: Irssi needs libPropList for configuration file handling." + echo "Go get it from http://xlife.dhs.org/irssi/download.php" + AC_ERROR(["libPropList not found"]) +], $LIBS $proplib -lPropList) + + +dnl ** +dnl ** check for socks +dnl ** + +if test "x$want_socks" = "xyes"; then + AC_CHECK_LIB(socks, connect, [ + LIBS="$LIBS -lsocks" + AC_CHECK_HEADER(socks.h, [ + AC_DEFINE(HAVE_SOCKS_H) + CFLAGS="$CFLAGS -DSOCKS" + AC_MSG_RESULT(["socks5 library found, building with it"]) + ], [ + AC_MSG_RESULT(["socks4 library found, building with it"]) + CFLAGS="$CFLAGS -Dconnect=Rconnect -Dgetsockname=Rgetsockname -Dgetpeername=Rgetpeername -Dbind=Rbind -Daccept=Raccept -Dlisten=Rlisten -Dselect=Rselect" + ]) + ]) +fi + +dnl ** +dnl ** check for gnome +dnl ** + +if test "x$want_gnome" = "xyes"; then + if test "x$GNOME_LIBS" = "x"; then + want_gnome="no"; + fi +fi + +AM_CONDITIONAL(HAVE_GNOME, test "x$want_gnome" = "xyes") +if test "x$want_gnome" = "xyes"; then + AC_DEFINE(HAVE_GTK) + AC_DEFINE(HAVE_GNOME) + GNOME_SUPPORT_CHECKS + GUI_CFLAGS="$GNOME_INCLUDEDIR" + + dnl ** + dnl ** check for gnome panel applet library + dnl ** + + if test "x$want_gnome_panel" = "xyes"; then + AC_CHECK_LIB(panel_applet, applet_widget_init, [ + GUI_LIBS="$GNOME_LIBDIR $GNOMEGNORBA_LIBS $ZVT_LIBS -lpanel_applet" + AC_DEFINE(HAVE_GNOME_PANEL) + ], [ + GUI_LIBS="$GNOME_LIBDIR $GNOMEUI_LIBS $ZVT_LIBS" + want_gnome_panel="no" + ], $GNOME_LIBDIR $GNOMEGNORBA_LIBS -lpanel_applet) + else + GUI_LIBS="$GNOME_LIBDIR $GNOMEUI_LIBS $ZVT_LIBS" + fi + +else + want_gnome_panel="no" + AC_DEFINE(HAVE_GTK) + AM_PATH_GTK(1.2.0) + GUI_CFLAGS="$GTK_CFLAGS" + GUI_LIBS="$GTK_LIBS" + + if test "x$gtk_config_minor_version" = "x0"; then + AC_DEFINE(GTK_10) + fi + + if test "x$want_imlib" = "xyes"; then + AM_PATH_GDK_IMLIB(, [define_imlib=true]) + if test x$define_imlib = xtrue; then + AC_DEFINE(HAVE_IMLIB) + GUI_CFLAGS="$GUI_CFLAGS $GDK_IMLIB_CFLAGS" + GUI_LIBS="$GDK_IMLIB_LIBS" + fi + fi +fi + +if test "x$GUI_LIBS" != "x"; then + GUI_LIBS="$GUI_LIBS $HEBREW_LIBS" +fi + +AC_SUBST(GUI_LIBS) +AC_SUBST(GUI_CFLAGS) +AM_CONDITIONAL(BUILD_GNOMEUI, test "x$GUI_LIBS" != "x") +AM_CONDITIONAL(HAVE_GNOME_PANEL, test "x$want_gnome_panel" = "xyes") + +dnl ** +dnl ** gui-text checks +dnl ** + +AM_PATH_GLIB(1.2.0,,, gmodule) + +dnl ** +dnl ** curses checks +dnl ** + +if test "x$want_textui" = "xyes"; then + AC_CHECK_CURSES + + if test "x$ncurses_version" != "x"; then + AC_CHECK_LIB(ncurses, use_default_colors, [ + AC_DEFINE(HAVE_NCURSES_USE_DEFAULT_COLORS) + ],, $CURSES_LIBS) + AC_CHECK_LIB(ncurses, idcok, [ + AC_DEFINE(HAVE_CURSES_IDCOK) + ],, $CURSES_LIBS) + else + AC_CHECK_LIB(curses, idcok, [ + AC_DEFINE(HAVE_CURSES_IDCOK) + ],, $CURSES_LIBS) + fi +else + has_curses=false +fi +AM_CONDITIONAL(HAS_CURSES, test "$has_curses" = true) + +dnl ** +dnl ** memory debugging +dnl ** + +if test "x$want_memdebug" = "xyes"; then + AC_DEFINE(MEM_DEBUG) +fi +AM_CONDITIONAL(BUILD_MEMDEBUG, test "x$want_memdebug" = "xyes") + +dnl ** +dnl ** IPv6 support +dnl ** + +if test "x$want_ipv6" = "xyes"; then + AC_DEFINE(HAVE_IPV6) +fi + +dnl ** +dnl ** internationalization support +dnl ** + +dnl ALL_LINGUAS="" +dnl AM_GNU_GETTEXT +dnl AC_LINK_FILES($nls_cv_header_libgt, $nls_cv_header_intl) + +AC_OUTPUT( +Makefile +dnl ## internationalization support +dnl po/Makefile.in +dnl 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/lib-config/Makefile +src/lib-nongui/Makefile +src/settings/Makefile +servertest/Makefile +plugins/Makefile +plugins/sample/Makefile +plugins/speech/Makefile +plugins/sound/Makefile +plugins/proxy/Makefile +plugins/external/Makefile +plugins/bot/Makefile +stamp.h) + +dnl ** +dnl ** internationalization support +dnl ** + +dnl stamp.h],[sed -e "/POTFILES =/r po/POTFILES" po/Makefile.in > po/Makefile]) diff --git a/file2header.sh b/file2header.sh new file mode 100755 index 00000000..c3729d37 --- /dev/null +++ b/file2header.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +echo "gchar *default_config =" +cat $1|sed 's/\\/\\\\/g'|sed 's/"/\\"/g'|sed 's/^/\"/'|sed 's/$/\\n\"/' +echo ";" diff --git a/irssi.desktop b/irssi.desktop new file mode 100644 index 00000000..b90c5a9e --- /dev/null +++ b/irssi.desktop @@ -0,0 +1,6 @@ +[Desktop Entry] +Name=irssi +Comment=irssi IRC client +Exec=irssi +Terminal=0 +Type=Application diff --git a/irssi.gnorba b/irssi.gnorba new file mode 100644 index 00000000..6296e4ff --- /dev/null +++ b/irssi.gnorba @@ -0,0 +1,5 @@ +[irssi] +type=exe +repo_id=IDL:GNOME/Applet:1.0 +description=irssi IRC client +location_info=irssi diff --git a/irssi.spec.in b/irssi.spec.in new file mode 100644 index 00000000..9f561d96 --- /dev/null +++ b/irssi.spec.in @@ -0,0 +1,87 @@ +Name: irssi +Version: +Release: 1 +Packager: Red Hat Contrib|Net +Vendor: Timo Sirainen +Distribution: Red Hat Contrib|Net +Summary: Irssi is a GTK based IRC client +Copyright: GPL +Group: X11/Applications/Networking +URL: http://xlife.dhs.org/irssi/ +Source: http://xlife.dhs.org/irssi/files/%{name}-%{version}.tar.bz2 +Requires: gtk+ +Prefix: /usr +BuildRoot: /tmp/%{name}-%{version} + +%changelog +* Sun Aug 29 1999 JT Traub +- Updated to 0.7.15 sources +- Fixed config stuff that changed since last version. + +* Thu Mar 25 1999 JT Traub +- Updated sources + +* Sat Mar 13 1999 JT Traub +- Updated to 0.7.4 sources +- Added the irssi-text bin to the package. + +* Mon Feb 22 1999 JT Traub +- Made spec file compliant with RHCN guidelines. + +* Sun Feb 13 1999 JT Traub +- Updated to 0.6.0 sources. +- Cleaned up spec file to make it relocatable on install + +* Sun Feb 7 1999 JT Traub +- Updated sources to 0.5.0 +- removed obsolete patch lines + +* Sat Feb 3 1999 JT Traub +- Updated sources to 0.4.0 +- Deleted old patch line + +* Sat Jan 30 1999 JT Traub +- Updated sources to 0.3.6 +- Updated spec to install the .desktop file. +- Removed the now obsolete patch lines + +* Wed Jan 27 1999 JT Traub +- Upgraded to 0.3.5 + +* Sun Jan 24 1999 JT Traub +- First attempt at building this + +%description +Irssi is a GTK based GUI IRC client by Timo Sirainen . +More information can be found at http://xlife.dhs.org/irssi/. + + +%prep +%setup + +%build +./configure --prefix=%{prefix} +make + +%install +rm -rf $RPM_BUILD_ROOT +make prefix=$RPM_BUILD_ROOT%{prefix} install +strip $RPM_BUILD_ROOT%{prefix}/bin/irssi +strip $RPM_BUILD_ROOT%{prefix}/bin/irssi-text +strip $RPM_BUILD_ROOT%{prefix}/bin/irssi-bot + + +%clean +rm -rf $RPM_BUILD_ROOT + +%files +%defattr (-,root,root) +%doc AUTHORS COPYING INSTALL ChangeLog README TODO NEWS +%attr(755,root,root) %{prefix}/bin/irssi +%attr(755,root,root) %{prefix}/bin/irssi-text +%attr(755,root,root) %{prefix}/bin/irssi-bot +%attr(644,root,root) %config %{prefix}/etc/irssi/* +%attr(644,root,root) %{prefix}/etc/CORBA/servers/irssi.gnorba +%attr(644,root,root) %{prefix}/share/applets/Network/irssi.desktop +%attr(644,root,root) %{prefix}/share/gnome/help/irssi/C/* +%attr(644,root,root) %{prefix}/lib/irssi/plugins/* diff --git a/servertest/.cvsignore b/servertest/.cvsignore new file mode 100644 index 00000000..ca8c752b --- /dev/null +++ b/servertest/.cvsignore @@ -0,0 +1,8 @@ +*.la +*.lo +.deps +.libs +Makefile +Makefile.in +so_locations +ircserver diff --git a/servertest/Makefile.am b/servertest/Makefile.am new file mode 100644 index 00000000..4eb03cdf --- /dev/null +++ b/servertest/Makefile.am @@ -0,0 +1,13 @@ +bin_PROGRAMS = ircserver + +INCLUDES = $(GLIB_CFLAGS) -I$(top_srcdir)/src + +if BUILD_MEMDEBUG +memdebug_src=../src/irc-base/memdebug.o +else +memdebug_src= +endif + +ircserver_LDADD = -lglib ../src/irc-base/network.o $(memdebug_src) + +ircserver_SOURCES = server.c diff --git a/servertest/server.c b/servertest/server.c new file mode 100644 index 00000000..90ce2bd5 --- /dev/null +++ b/servertest/server.c @@ -0,0 +1,463 @@ +#include + +#include + +#define FLOOD_TIMEOUT 100000 + +typedef struct +{ + gchar *name; + GList *nicks; +} +CHANNEL_REC; + +GList *channels; +gchar *clientnick, *clienthost; + +int clienth; + +/* Read a line */ +gint read_line(gboolean socket, gint handle, GString *output, GString *buffer) +{ + gchar tmpbuf[512]; + gint recvlen, pos; + + g_return_val_if_fail(handle != -1, -1); + g_return_val_if_fail(output != NULL, -1); + g_return_val_if_fail(buffer != NULL, -1); + + g_string_truncate(output, 0); + + recvlen = socket ? + net_receive(handle, tmpbuf, sizeof(tmpbuf)-1) : + read(handle, tmpbuf, sizeof(tmpbuf)-1); + + if (recvlen <= 0) + { + if (buffer->len > 0) + { + /* no new data got but still something in buffer.. */ + for (pos = 0; pos < buffer->len; pos++) + { + if (buffer->str[pos] == 13 || buffer->str[pos] == 10) + { + recvlen = 0; + break; + } + } + if (recvlen < 0 && buffer->len > 0) + { + /* connection closed and last line is missing \n .. + just add it so we can see if it had anything useful.. */ + recvlen = 0; + g_string_append_c(buffer, '\n'); + } + } + + if (recvlen < 0) return -1; + } + else + { + /* append received data to buffer */ + tmpbuf[recvlen] = '\0'; + g_string_append(buffer, tmpbuf); + } + + for (pos = 0; pos < buffer->len; pos++) + { + if (buffer->str[pos] == 13 || buffer->str[pos] == 10) + { + /* end of line */ + buffer->str[pos] = '\0'; + g_string_assign(output, buffer->str); + + if (buffer->str[pos] == 13 && buffer->str[pos+1] == 10) + { + /* skip \n too */ + pos++; + } + + g_string_erase(buffer, 0, pos+1); + return 1; + } + } + + /* EOL wasn't found, wait for more data.. */ + return 0; +} +void client_send(char *text) +{ + write(clienth, text, strlen(text)); + write(clienth, "\r\n", 2); +} + +void makerand(char *str, int len) +{ + for (; len > 0; len--) + *str++ = (rand() % 20)+'A'; +} + +void makerand2(char *str, int len) +{ +#if 0 + gchar c; + + while (len > 0) + { + c = rand() & 255; + if (c != 0 && c != 13 && c != 10) + { + *str++ = c; + len--; + } + } +#else + makerand(str, len); +#endif +} + +void send_cmd(void) +{ + static gint nicks = 0; + GList *tmp; + char str[512]; + int pos; + + /* send msg to every channel */ + str[511] = '\0'; + + for (tmp = g_list_first(channels); tmp != NULL; tmp = tmp->next) + { + CHANNEL_REC *rec = tmp->data; + + makerand(str, 511); + str[0] = ':'; + str[10] = '!'; + str[20] = '@'; + + switch (rand() % 10) + { + case 0: + /* join */ + pos = 2+sprintf(str+2, "%d", nicks++); /* don't use same nick twice */ + str[pos] = '-'; + str[10] = '\0'; + g_list_append(rec->nicks, g_strdup(str+1)); + str[10] = '!'; + sprintf(str+30, " JOIN :%s", rec->name); + break; + case 1: + /* part */ + if (g_list_length(rec->nicks) > 1 && rand() % 3 == 0) + { + gchar *nick; + + nick = g_list_nth(rec->nicks, rand()%(g_list_length(rec->nicks)-1)+1)->data; + if (rand() % 3 == 0) + sprintf(str, ":kicker!some@where KICK %s %s :go away", rec->name, nick); + else if (rand() % 3 == 0) + sprintf(str, ":%s!dunno@where QUIT %s :i'm outta here", nick, rec->name); + else + sprintf(str, ":%s!dunno@where PART %s", nick, rec->name); + rec->nicks = g_list_remove(rec->nicks, nick); + g_free(nick); + } + else + str[0] = '\0'; + break; + case 2: + /* nick change */ + if (g_list_length(rec->nicks) > 1) + { + gchar *nick; + + nick = g_list_nth(rec->nicks, rand()%(g_list_length(rec->nicks)-1)+1)->data; + pos = sprintf(str, ":%s!dunno@where NICK ", nick); + str[pos] = '_'; + str[50] = '\0'; + rec->nicks = g_list_remove(rec->nicks, nick); + rec->nicks = g_list_append(rec->nicks, g_strdup(str+pos)); + g_free(nick); + } + else + str[0] = '\0'; + break; + case 3: + /* topic */ + pos = 30+sprintf(str+30, " TOPIC %s :", rec->name); + str[pos] = 'x'; + break; + case 4: + /* mode */ + sprintf(str+30, " MODE %s :%cnt", rec->name, (rand() & 1) ? '+' : '-'); + break; + case 5: + /* notice */ + pos = 30+sprintf(str+30, " NOTICE %s :", rec->name); + str[pos] = 'X'; + break; + case 6: + /* nick mode change */ + if (g_list_length(rec->nicks) > 1) + { + gchar *nick; + + nick = g_list_nth(rec->nicks, rand()%(g_list_length(rec->nicks)-1)+1)->data; + pos = sprintf(str, ":server MODE %s +%c %s", rec->name, rand()&1 ? 'o' : 'v', nick); + str[pos] = '_'; + str[50] = '\0'; + rec->nicks = g_list_remove(rec->nicks, nick); + rec->nicks = g_list_append(rec->nicks, g_strdup(str+pos)); + g_free(nick); + } + else + str[0] = '\0'; + break; + default: + pos = 30+sprintf(str+30, " PRIVMSG %s :", rec->name); + makerand2(str+pos, 511-pos); + if (rand() % 4 == 0) + { + pos += sprintf(str+pos, "\001ACTION "); + str[510] = 1; + } + else if (rand() % 10 == 0) + { + pos += sprintf(str+pos, "\001VERSION\001"); + pos++; + } + else if (rand() % 2 == 0) + { + pos += sprintf(str+pos, "%s: ", clientnick); + } + str[pos] = 'X'; + break; + } + + client_send(str); + } + + makerand(str, 511); + str[0] = ':'; + str[10] = '!'; + str[20] = '@'; + + switch (rand() % 11) + { + case 0: + /* join */ + if (g_list_length(channels) < 20) + { + CHANNEL_REC *rec; + int n, pos; + + n = (rand()%20)+25; + pos = sprintf(str, ":%s!%s JOIN :", clientnick, clienthost); + str[pos] = '#'; + str[n] = '\0'; + + rec = g_new(CHANNEL_REC, 1); + rec->name = g_strdup(str+pos); + rec->nicks = g_list_append(NULL, g_strdup(clientnick)); + + channels = g_list_append(channels, rec); + client_send(str); + + sprintf(str, ":server 353 %s = %s :@%s", clientnick, rec->name, clientnick); + client_send(str); + sprintf(str, ":server 366 %s %s :End of /NAMES list.", clientnick, rec->name); + } + else + str[0] = '\0'; + break; + case 1: + /* leave channel (by kick) */ + if (g_list_length(channels) > 3) + { + CHANNEL_REC *chan; + + chan = g_list_nth(channels, rand()%g_list_length(channels))->data; + if (rand() % 3 != 0) + { + pos = sprintf(str, ":%s!%s PART %s :", clientnick, clienthost, chan->name); + str[pos] = 'x'; + } + else + { + str[0] = ':'; + sprintf(str+30, " KICK %s %s :byebye", chan->name, clientnick); + } + + g_free(chan->name); + g_list_foreach(chan->nicks, (GFunc) g_free, NULL); g_list_free(chan->nicks); + g_free(chan); + channels = g_list_remove(channels, chan); + } + else + str[0] = '\0'; + break; + case 2: + /* ctcp version */ + sprintf(str+30, " PRIVMSG %s :\001VERSION\001", clientnick); + break; + case 3: + /* ctcp ping */ + sprintf(str+30, " PRIVMSG %s :\001PING\001", clientnick); + break; + case 4: + /* user mode */ + sprintf(str+30, " MODE %s :%ciw", clientnick, (rand() & 1) ? '+' : '-'); + break; + case 5: + /* msg */ + pos = 30+sprintf(str+30, " PRIVMSG %s :", clientnick); + str[pos] = 'X'; + break; + case 6: + /* notice */ + pos = 30+sprintf(str+30, " NOTICE %s :", clientnick); + str[pos] = 'X'; + break; + case 7: + /* invite */ + pos = 30+sprintf(str+30, " INVITE %s", clientnick); + str[pos] = 'X'; + break; + case 8: + /* error */ + pos = sprintf(str, ":server ERROR :"); + str[pos] = 'X'; + break; + case 9: + /* wallops */ + pos = sprintf(str, ":server WALLOPS :"); + str[pos] = 'X'; + break; + case 10: + /* ping */ + pos = sprintf(str, ":server PING :"); + str[pos] = 'X'; + break; + } + client_send(str); +} + +void handle_command(char *str) +{ + if (strncmp(str, "NICK ", 5) == 0) + { + clientnick = g_strdup(str+5); /* got the nick */ + } +} + +guint gui_timeout_add(guint32 interval, GUITimeoutFunction function, gpointer data) +{ + return -1; +} + +int main(void) +{ + static fd_set fdset; + struct timeval tv; + int serverh, port; + IPADDR ip; + +#ifdef HAVE_IPV6 + if (net_gethostname("::1", &ip) != 0) + { + printf("net_gethostname()\n"); + return 1; + } +#else + if (net_gethostname("127.0.0.1", &ip) != 0) + { + printf("net_gethostname()\n"); + return 1; + } +#endif + + srand(0); + port = 6660; + serverh = net_listen(&ip, &port); + if (serverh == -1) + { + printf("listen()\n"); + return 1; + } + + clienth = -1; channels = NULL; + for (;;) + { + FD_ZERO(&fdset); + if (clienth != -1) FD_SET(clienth, &fdset); + FD_SET(serverh, &fdset); + + tv.tv_sec = 0; + tv.tv_usec = FLOOD_TIMEOUT; + if (select((serverh > clienth ? serverh : clienth)+1, &fdset, NULL, NULL, &tv) <= 0) + { + /* nothing happened, bug the client with some commands.. */ + if (clienth != -1 && clientnick != NULL) send_cmd(); + } + else + { + if (FD_ISSET(serverh, &fdset)) + { + /* client connecting! */ + if (clienth != -1) + { + /* only one client allowed.. */ + int handle; + + handle = net_accept(serverh, NULL, &port); + if (handle != -1) + { + client_send("Only one client allowed"); + close(handle); + continue; + } + } + else + { + IPADDR clientip; + + clienth = net_accept(serverh, &clientip, &port); + if (clienth != -1) + { + clienthost = g_strdup(net_ip2host(&clientip)); + client_send(":server 001 pla"); + client_send(":server 002 plapla"); + client_send(":server 003 plaplapla"); + client_send(":server 004 connected!"); + } + } + } + else + { + /* clients sending something.. */ + GString *str, *buf; + int ret; + + str = g_string_new(NULL); + buf = g_string_new(NULL); + do + { + ret = read_line(TRUE, clienth, str, buf); + if (ret == -1) + { + /* client disconnected */ + close(clienth); + clienth = -1; + break; + } + if (ret == 1) handle_command(str->str); + } + while (ret == 1); + g_string_free(str, TRUE); + g_string_free(buf, TRUE); + } + } + } + + return 0; +} diff --git a/src/.cvsignore b/src/.cvsignore new file mode 100644 index 00000000..282522db --- /dev/null +++ b/src/.cvsignore @@ -0,0 +1,2 @@ +Makefile +Makefile.in diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 00000000..d4e162f9 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,17 @@ +if HAS_CURSES +TEXTUI=gui-text +endif + +if BUILD_GNOMEUI +GNOMEUI=gui-gnome +endif + +noinst_HEADERS = \ + common.h \ + common-setup.h \ + irssi-plugin.h \ + irssi-plugin-gui.h + +SUBDIRS = irc-base irc-extra ui-common lib-config lib-nongui settings $(GNOMEUI) $(TEXTUI) gui-none + +EXTRA_DIST = signal.doc diff --git a/src/common-setup.h b/src/common-setup.h new file mode 100644 index 00000000..96549351 --- /dev/null +++ b/src/common-setup.h @@ -0,0 +1,125 @@ +#ifndef __COMMON_SETUP_H +#define __COMMON_SETUP_H + +#define DCC_FILE_CREATE_MODE 0644 +#define LOG_FILE_CREATE_MODE 0644 +#define CMD_CHAR '/' + +/* How often to check if there's anyone to be unignored in autoignore list */ +#define AUTOIGNORE_TIMECHECK 10000 + +/* 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 + +/* Maximum time to wait for more JOINs before sending massjoin signal */ +#define MAX_MASSJOIN_WAIT 5000 + +/* lists */ +extern GList *aliases, *ignores, *completions, *notifies, *hilights; + +/* look and feel */ +extern gboolean toggle_show_menubar; +extern gboolean toggle_show_toolbar; +extern gboolean toggle_show_statusbar; +extern gboolean toggle_show_nicklist; +extern gboolean toggle_show_timestamps; +extern gboolean toggle_hide_text_style; +extern gboolean toggle_bell_beeps; +extern gboolean toggle_actlist_moves; +extern gboolean toggle_privmsg_beeps; + +extern gboolean toggle_use_status_window; +extern gboolean toggle_use_msgs_window; +extern gboolean toggle_autoraise_msgs_window; +extern gboolean toggle_autocreate_query; +extern gboolean toggle_notifylist_popups; +extern gboolean toggle_use_tabbed_windows; +extern gint tab_orientation; + +/* misc */ +extern gchar *url_www_client; +extern gchar *url_ftp_client; +extern gchar *url_mail_client; + +extern gchar *ctcp_version_reply; +extern gchar *default_quit_message; +extern gchar *default_user_mode; + +extern gint max_command_history; +extern gint max_textwidget_lines; +extern gint rawlog_lines; +extern gint block_remove_lines; + +extern gint knockout_time; /* How many seconds to keep /knockouted ban */ +extern gboolean check_irssi_versions; /* Check if there's new irssi version available */ + +/* nick completion */ +extern gchar *completion_char; +extern gboolean completion_disable_auto; +extern gint completion_keep_publics; +extern gint completion_keep_ownpublics; +extern gint completion_keep_privates; + +/* flood protection */ +extern gint flood_timecheck; /* Flood check timeout */ +extern gint flood_max_msgs; /* Max msgs in FLOOD_TIMECHECK msecs before considered as flooding */ +extern gint autoignore_time; /* How many seconds to keep someone autoignored */ +extern gint ctcp_timecheck; /* CTCP reply send timeout */ +extern gint max_ctcp_queue; /* Max CTCP reply queue length */ +extern gint cmd_queue_speed; /* Minimum timeout before sending the next command to server */ + +/* dcc */ +extern gboolean toggle_dcc_autodisplay_dialog; +extern gboolean toggle_dcc_autoget; +extern gboolean toggle_dcc_autorename; +extern gint dcc_max_autoget_size; +extern gchar *dcc_download_path; + +extern gboolean toggle_dcc_fast_send; +extern gchar *dcc_upload_path; + +extern gboolean toggle_dcc_mirc_ctcp; +extern gint dcc_block_size; +extern gint dcc_timeout; + +/* servers */ +typedef struct +{ + gchar *server; + gchar *ircnet; + gchar *password; + gint port; + gboolean autoconnect; + time_t last_connect; /* to avoid reconnecting too fast.. */ +} +SETUP_SERVER_REC; + +/* servers */ +extern GList *setupservers; /* list of local servers */ +extern GList *ircnets; /* list of available ircnets */ +extern gint server_reconnect_time; /* reconnect to server no sooner than n seconds */ +extern gchar *source_host; /* Our own IP to use */ +extern gboolean source_host_ok; /* Use source_host_ip .. */ +extern IPADDR source_host_ip; /* Resolved address */ +extern gchar *default_nick, *alternate_nick, *user_name, *real_name; +extern gboolean toggle_skip_motd; + +/* IRC proxy */ +extern gboolean toggle_use_ircproxy; +extern gchar *proxy_address; +extern gint proxy_port; +extern gchar *proxy_string; + +/* appearance */ +extern gboolean toggle_use_zvt; +extern gboolean toggle_use_transparency; +extern gboolean toggle_shaded_transparency; +extern gint panel_max_channels; + +#endif diff --git a/src/common.h b/src/common.h new file mode 100644 index 00000000..d78a5562 --- /dev/null +++ b/src/common.h @@ -0,0 +1,114 @@ +#ifndef __COMMON_H +#define __COMMON_H + +#define IRSSI_AUTHOR "Timo Sirainen " +#define IRSSI_WEBSITE "http://xlife.dhs.org/irssi/" + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +# ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_STDLIB_H +# include +#endif +#include +#include + +#include +#include +#include +#include +#include + +#ifdef HAVE_UNISTD_H +# include +#endif +#ifdef HAVE_DIRENT_H +# include +#endif +#include + +#ifdef HAVE_SOCKS_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +typedef struct +{ + gushort family; +#ifdef HAVE_IPV6 + struct in6_addr addr; +#else + struct in_addr addr; +#endif +} +IPADDR; + +#include "lib-config/irssi-config.h" +#include "common-setup.h" + +/* GUI library must provide these functions: */ + +typedef enum +{ + GUI_INPUT_READ = 1 << 0, + GUI_INPUT_WRITE = 1 << 1, + GUI_INPUT_EXCEPTION = 1 << 2 +} GUIInputCondition; + +typedef void (*GUIInputFunction) (gpointer data, gint handle, GUIInputCondition condition); +typedef gint (*GUITimeoutFunction) (gpointer data); + +gint gui_input_add(gint handle, GUIInputCondition condition, + GUIInputFunction function, gpointer data); +void gui_input_remove(gint tag); + +guint gui_timeout_add(guint32 interval, GUITimeoutFunction function, gpointer data); +void gui_timeout_remove(gint tag); + +#ifdef MEM_DEBUG + +void ig_mem_profile(void); + +void ig_set_data(gchar *data); + +gpointer ig_malloc(gint size, gchar *file, gint line); +gpointer ig_malloc0(gint size, gchar *file, gint line); +gpointer ig_realloc(gpointer mem, gulong size, gchar *file, gint line); +gchar *ig_strdup(const char *str, gchar *file, gint line); +gchar *ig_strconcat(const char *str, ...); +gchar *ig_strdup_printf(const gchar *format, ...) G_GNUC_PRINTF (1, 2); +void ig_free(gpointer p); +GString *ig_string_new(gchar *str); +void ig_string_free(GString *str, gboolean freeit); + +#define g_malloc(a) ig_malloc(a, __FILE__, __LINE__) +#define g_malloc0(a) ig_malloc0(a, __FILE__, __LINE__) +#define g_realloc(a,b) ig_realloc(a, b, __FILE__, __LINE__) +#define g_strdup(a) ig_strdup(a, __FILE__, __LINE__) +#define g_strconcat ig_strconcat +#define g_strdup_printf ig_strdup_printf +#define g_strdup_vprintf ig_strdup_vprintf +#define g_free ig_free +#define g_string_new ig_string_new +#define g_string_free ig_string_free + +#endif + +#endif diff --git a/src/irssi-plugin-gui.h b/src/irssi-plugin-gui.h new file mode 100644 index 00000000..94698308 --- /dev/null +++ b/src/irssi-plugin-gui.h @@ -0,0 +1,11 @@ +/* This contains all the necessary includes for creating GUI widgets to + plugins */ + +#ifdef HAVE_GTK +#include "gui-gnome/irssi.h" +#include "gui-gnome/setup-int.h" +#endif + +#if defined (HAVE_CURSES) || defined (HAVE_SLANG) +#include "gui-text/irssi.h" +#endif diff --git a/src/irssi-plugin.h b/src/irssi-plugin.h new file mode 100644 index 00000000..684b56fd --- /dev/null +++ b/src/irssi-plugin.h @@ -0,0 +1,9 @@ +/* This contains all the necessary includes for irssi plugins. + irc-extra/plugins.h and irc-extra/plugins-commands.h has all the plugin + management functions */ + +#include "common.h" +#include "irc-base/irc-base.h" +#include "irc-extra/irc-extra.h" +#include "ui-common/ui-common.h" +#include "settings/settings.h" diff --git a/src/signal.doc b/src/signal.doc new file mode 100644 index 00000000..b7e238ef --- /dev/null +++ b/src/signal.doc @@ -0,0 +1,178 @@ +IRC base +-------- + +* Requires to work properly: + + "gui exit", CHANNEL_REC + "gui channel open", CHANNEL_REC + "send command", gchar *command, SERVER_REC, CHANNEL_REC + +* Provides signals: + +bans.c: + + "ban new", BAN_REC + "ban remove", BAN_REC + "ban exception new", BAN_REC + "ban exception remove", BAN_REC + "ban type changed", gchar *bantype + +channels.c: + + "channel created", CHANNEL_REC + "channel destroyed", CHANNEL_REC + "channel name changed", CHANNEL_REC + "channel topic changed", CHANNEL_REC + + "channel query", CHANNEL_REC + "channel sync", CHANNEL_REC + +ctcp.c: + + "ctcp msg ", gchar *args, SERVER_REC, gchar *nick, gchar *addr, gchar *target + "default ctcp msg", gchar *args, SERVER_REC, gchar *nick, gchar *addr, gchar *target + "ctcp reply ", gchar *args, SERVER_REC, gchar *nick, gchar *addr, gchar *target + "default ctcp reply", gchar *args, SERVER_REC, gchar *nick, gchar *addr, gchar *target + +irc.c: + + "send command", gchar *args, SERVER_REC + "command ", gchar *args, SERVER_REC, CHANNEL_REC + "default command", gchar *args, SERVER_REC, CHANNEL_REC + + "server event", gchar *args, SERVER_REC, gchar *sender_nick, gchar *sender_address + "event ", gchar *args, SERVER_REC, gchar *sender_nick, gchar *sender_address + "default event", gchar *args, SERVER_REC, gchar *sender_nick, gchar *sender_address + +modes.c: + + "invitelist new", CHANNEL_REC, gchar *mask + "invitelist remove", CHANNEL_REC, gchar *mask + + "channel mode changed", CHANNEL_REC + "user mode changed", SERVER_REC + "nick mode changed", CHANNEL_REC, NICK_REC + +nicklist.c: + + "nicklist new" CHANNEL_REC, NICK_REC + "nicklist remove" CHANNEL_REC, NICK_REC + "nicklist changed" CHANNEL_REC, NICK_REC, gchar *oldnick + "server nick changed" SERVER_REC + "massjoin" CHANNEL_REC, GList of NICK_RECs + +server.c: + + "server connect failed", SERVER_REC + "server connected", SERVER_REC + "server connecting", SERVER_REC, gulong *ip + "server looking", SERVER_REC + "server disconnected", SERVER_REC + "event connected", SERVER_REC + +signal.c: + "signal", gchar *name, ... + +IRC extra +--------- + +* Requires to work properly: + + "print text stripped", SERVER_REC, gchar *channel, GINT_TO_POINTER(level), gchar *text + "plugin add menu", gchar *menuitem, void (*unload_func) (gpointer, PLUGIN_REC), PLUGIN_REC + +* Provides signals: + +dcc.c: + + "dcc ctcp", gchar *args, DCC_REC + "default dcc ctcp", gchar *args, DCC_REC + "dcc unknown ctcp", gchar *args, gchar *sender, gchar *sendaddr + + "dcc reply", gchar *args, DCC_REC + "default dcc reply", gchar *args, DCC_REC + "dcc unknown reply", gchar *args, gchar *sender, gchar *sendaddr + + "dcc chat message", DCC_REC, gchar *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, gchar *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, gchar *filename + "dcc error file not found", gchar *nick, gchar *filename + "dcc error get not found", gchar *nick + "dcc error send exists", gchar *nick, gchar *filename + "dcc error unknown type", gchar *type + "dcc error close not found", gchar *type, gchar *nick, gchar *filename + +flood.c: + + "flood", SERVER_REC, gchar *nick, gchar *host, gchar *level, gchar *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, gchar *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, gchar *nick, gchar *username, gchar *host, gchar *realname + "notifylist left", SERVER_REC, gchar *nick + +plugins.c: + + "plugin created", PLUGIN_REC + "plugin destroyed", PLUGIN_REC + "plugin cant load", gchar *name + "plugin already loaded", gchar *name + "plugin not loaded", gchar *name + +UI common +--------- + +* Requires to work properly: + + "gui print text", CHANNEL_REC, GINT_TO_POINTER fg, bg, flags, gchar *text + "gui window goto", GINT_TO_POINTER(number) + +( "print text finished", CHANNEL_REC ) - can be used to determine when + all "gui print text"s are sent + +* Provides signals: + +ui-printtext.c: + + "print text", SERVER_REC, gchar *channel, GINT_TO_POINTER(level), gchar *text + "print text stripped", SERVER_REC, gchar *channel, GINT_TO_POINTER(level), gchar *text + +ui-themes.c: + + "theme created", THEME_REC + "theme destroyed", THEME_REC + +ui-windows.c: + + "window created", WINDOW_REC + "window destroyed", WINDOW_REC diff --git a/stamp.h.in b/stamp.h.in new file mode 100644 index 00000000..e69de29b diff --git a/window-views-patch.diff b/window-views-patch.diff new file mode 100644 index 00000000..192b96b1 --- /dev/null +++ b/window-views-patch.diff @@ -0,0 +1,2672 @@ +diff -ru irssi-0.7.11/src/gui-gnome/Makefile.am irssi-0.7.11-new/src/gui-gnome/Makefile.am +--- irssi-0.7.11/src/gui-gnome/Makefile.am Sun Jun 6 18:48:07 1999 ++++ irssi-0.7.11-new/src/gui-gnome/Makefile.am Mon Jun 7 18:33:41 1999 +@@ -53,7 +52,8 @@ + gui-mainwindows.c \ + gui-printtext.c \ + gui-server.c \ +- gui-windows.c \ ++ gui-windowset.c \ ++ gui-windows-view.c \ + irssi.c \ + setup-appearance.c \ + setup-ircproxy.c \ +@@ -98,7 +98,8 @@ + gui-mainwindows.h \ + gui-printtext.h \ + gui-server.h \ +- gui-windows.h \ ++ gui-windowset.h \ ++ gui-windows-view.h \ + gtk-specific.h \ + gnome-specific.h \ + irssi.h \ +diff -ru irssi-0.7.11/src/gui-gnome/channels-newdata.c irssi-0.7.11-new/src/gui-gnome/channels-newdata.c +--- irssi-0.7.11/src/gui-gnome/channels-newdata.c Sat May 15 20:23:24 1999 ++++ irssi-0.7.11-new/src/gui-gnome/channels-newdata.c Sat Jun 12 17:55:06 1999 +@@ -57,7 +57,7 @@ + g_return_val_if_fail(channel != NULL, FALSE); + + label = gtk_notebook_get_tab_label(GTK_NOTEBOOK(WINDOW_GUI(CHANNEL_PARENT(channel))->parent->notebook), +- WINDOW_GUI(CHANNEL_PARENT(channel))->window); ++ WINDOW_GUI(CHANNEL_PARENT(channel))->windowset->window); + newdata_label_colorify(channel, label); + + return TRUE; +diff -ru irssi-0.7.11/src/gui-gnome/dialog-channels.c irssi-0.7.11-new/src/gui-gnome/dialog-channels.c +--- irssi-0.7.11/src/gui-gnome/dialog-channels.c Wed May 12 17:54:45 1999 ++++ irssi-0.7.11-new/src/gui-gnome/dialog-channels.c Mon Jun 7 18:57:46 1999 +@@ -617,7 +617,7 @@ + { + /* channel specific background pixmap */ + path = convert_home(rec->background); +- gui_window_set_background_pixmap(CHANNEL_PARENT(channel), path); ++ gui_window_view_set_background_pixmap(WINDOW_GUI(CHANNEL_PARENT(channel)), path); + g_free(path); + } + +diff -ru irssi-0.7.11/src/gui-gnome/dialog-textwidget.c irssi-0.7.11-new/src/gui-gnome/dialog-textwidget.c +--- irssi-0.7.11/src/gui-gnome/dialog-textwidget.c Thu May 13 14:46:51 1999 ++++ irssi-0.7.11-new/src/gui-gnome/dialog-textwidget.c Sat Jun 12 17:26:21 1999 +@@ -134,7 +134,7 @@ + return; + } + +- if (WINDOW_GUI(window->active)->zvt) ++ if (window->active->active->zvt) + { + gui_dialog(DIALOG_ERROR, "Find doesn't work with ZVT windows yet"); + return; +@@ -145,7 +145,7 @@ + GNOME_STOCK_BUTTON_CLOSE, NULL); + gtk_signal_connect(GTK_OBJECT(dialog), "delete_event", + GTK_SIGNAL_FUNC(gtk_widget_destroy), NULL); +- gui_widget_depends_data(dialog, "window destroyed", window->active); ++ gui_widget_depends_data(dialog, "window destroyed", window->active->active->window); + + hbox = gtk_hbox_new(FALSE, 0); + gtk_box_pack_start(GTK_BOX(GNOME_DIALOG(dialog)->vbox), hbox, TRUE, TRUE, 0); +@@ -160,8 +160,8 @@ + gnome_dialog_button_connect_object(GNOME_DIALOG(dialog), 1, sig_find_next, GTK_OBJECT(dialog)); + gnome_dialog_button_connect_object(GNOME_DIALOG(dialog), 2, GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(dialog)); + +- gtk_object_set_data(GTK_OBJECT(dialog), "text", WINDOW_GUI(window->active)->text); +- gtk_object_set_data(GTK_OBJECT(dialog), "window", window->active); ++ gtk_object_set_data(GTK_OBJECT(dialog), "text", window->active->active->text); ++ gtk_object_set_data(GTK_OBJECT(dialog), "window", window->active->active->window); + gtk_object_set_data(GTK_OBJECT(dialog), "entry", entry); + + gtk_widget_show_all(dialog); +@@ -220,13 +220,13 @@ + return; + } + +- if (WINDOW_GUI(window->active)->zvt) ++ if (window->active->active->zvt) + { + gui_dialog(DIALOG_ERROR, "Save doesn't work with ZVT windows yet"); + return; + } + +- if (gtk_text_get_length(GTK_TEXT(WINDOW_GUI(window->active)->text)) == 0) ++ if (gtk_text_get_length(GTK_TEXT(window->active->active->text)) == 0) + { + gui_dialog(DIALOG_OK, _("Window doesn't have any text")); + return; +@@ -236,12 +236,12 @@ + GNOME_STOCK_BUTTON_CANCEL, NULL); + gtk_signal_connect(GTK_OBJECT(dialog), "delete_event", + GTK_SIGNAL_FUNC(gtk_widget_destroy), NULL); +- gui_widget_depends_data(dialog, "window destroyed", window->active); ++ gui_widget_depends_data(dialog, "window destroyed", window->active->active->window); + + button = gtk_check_button_new_with_label(_("Save only selected text")); + gtk_box_pack_start(GTK_BOX(GNOME_DIALOG(dialog)->vbox), button, FALSE, FALSE, 0); + +- if (GTK_EDITABLE(WINDOW_GUI(window->active)->text)->has_selection) ++ if (GTK_EDITABLE(window->active->active->text)->has_selection) + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE); + else + gtk_widget_set_sensitive(button, FALSE); +@@ -258,7 +258,7 @@ + gnome_dialog_button_connect_object(GNOME_DIALOG(dialog), 0, sig_save_ok, GTK_OBJECT(dialog)); + gnome_dialog_button_connect_object(GNOME_DIALOG(dialog), 1, GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(dialog)); + +- gtk_object_set_data(GTK_OBJECT(dialog), "text", WINDOW_GUI(window->active)->text); ++ gtk_object_set_data(GTK_OBJECT(dialog), "text", window->active->active->text); + gtk_object_set_data(GTK_OBJECT(dialog), "selbut", button); + gtk_object_set_data(GTK_OBJECT(dialog), "entry", gnome_file_entry_gtk_entry(GNOME_FILE_ENTRY(entry))); + +diff -ru irssi-0.7.11/src/gui-gnome/dialog-window.c irssi-0.7.11-new/src/gui-gnome/dialog-window.c +--- irssi-0.7.11/src/gui-gnome/dialog-window.c Sun Jun 6 18:34:26 1999 ++++ irssi-0.7.11-new/src/gui-gnome/dialog-window.c Sat Jun 12 17:28:12 1999 +@@ -108,13 +108,13 @@ + hbox2 = gtk_hbox_new(FALSE, 5); + gtk_box_pack_start(GTK_BOX(hbox), hbox2, TRUE, TRUE, 0); + +- str = g_strdup_printf("%d", WINDOW_GUI(window->active)->text->allocation.width); ++ str = g_strdup_printf("%d", window->active->active->text->allocation.width); + entry = gui_create_labelentry(hbox2, _("Width"), str, TRUE); + gtk_object_set_data(GTK_OBJECT(dialog), "sizexentry", entry); + gtk_widget_set_usize(entry, 50, -1); + g_free(str); + +- str = g_strdup_printf("%d", WINDOW_GUI(window->active)->text->allocation.height); ++ str = g_strdup_printf("%d", window->active->active->text->allocation.height); + entry = gui_create_labelentry(hbox2, _("Height"), str, TRUE); + gtk_object_set_data(GTK_OBJECT(dialog), "sizeyentry", entry); + gtk_widget_set_usize(entry, 50, -1); +@@ -154,7 +154,7 @@ + gtk_widget_set_sensitive(hbox2, FALSE); + + /* window name */ +- channel = window->active->active; ++ channel = window->active->active->window->active; + name = gui_channel_get_name(channel); + if (name == NULL) name = "default"; + +diff -ru irssi-0.7.11/src/gui-gnome/gui-channels.c irssi-0.7.11-new/src/gui-gnome/gui-channels.c +--- irssi-0.7.11/src/gui-gnome/gui-channels.c Sat May 15 15:47:08 1999 ++++ irssi-0.7.11-new/src/gui-gnome/gui-channels.c Sat Jun 12 17:51:30 1999 +@@ -41,7 +41,7 @@ + GList *tmp; + + label = gtk_notebook_get_tab_label(GTK_NOTEBOOK(WINDOW_GUI(window)->parent->notebook), +- WINDOW_GUI(window)->window); ++ WINDOW_GUI(window)->windowset->window); + g_return_if_fail(label != NULL); + + str = g_string_new(NULL); +@@ -75,7 +75,7 @@ + if (channel->type == CHANNEL_TYPE_EMPTY) + rec->servermenu = TRUE; + if (channel->type == CHANNEL_TYPE_CHANNEL && toggle_show_nicklist) +- gtk_widget_show(WINDOW_GUI(window)->nickscrollbox); ++ gtk_widget_show(WINDOW_GUI(window)->windowset->nickscrollbox); + + name = gui_channel_get_name(channel); + +@@ -182,7 +182,7 @@ + /* create new window to use */ + window = !toggle_use_tabbed_windows ? NULL : + cur_channel != NULL ? CHANNEL_PARENT(cur_channel) : NULL; +- window = gui_window_create(window == NULL ? NULL : WINDOW_GUI(window)->parent); ++ window = gui_windowset_create(window == NULL ? NULL : WINDOW_GUI(window)->parent)->active->window; + } + + gui_channel_init(window, channel); +@@ -230,7 +230,7 @@ + else + { + /* window is useless, destroy it. */ +- gui_window_destroy(window); ++ gui_window_view_destroy(WINDOW_GUI(window)); + } + } + return TRUE; +@@ -253,16 +253,16 @@ + if (channel->topic == NULL || *channel->topic == '\0') + { + /* No topic in channel */ +- gtk_entry_set_text(GTK_ENTRY(WINDOW_GUI(window)->topicentry), ""); ++ gtk_entry_set_text(GTK_ENTRY(WINDOW_GUI(window)->windowset->topicentry), ""); + } + else + { +- gtk_entry_set_text(GTK_ENTRY(WINDOW_GUI(window)->topicentry), channel->topic); ++ gtk_entry_set_text(GTK_ENTRY(WINDOW_GUI(window)->windowset->topicentry), channel->topic); + g_string_sprintfa(tmp, " - %s", channel->topic); + } + } + +- if (window == WINDOW_GUI(window)->parent->active) ++ if (window == WINDOW_GUI(window)->parent->active->active->window) + gtk_window_set_title(GTK_WINDOW(WINDOW_GUI(window)->parent->window), tmp->str); + g_string_free(tmp, TRUE); + return TRUE; +@@ -276,7 +276,7 @@ + g_return_if_fail(channel->server != NULL); + + str = g_strconcat(channel->server->nick, " / ", channel->server->tag, NULL); +- gtk_label_set(GTK_LABEL(WINDOW_GUI(CHANNEL_PARENT(channel))->serverlabel), str); ++ gtk_label_set(GTK_LABEL(WINDOW_GUI(CHANNEL_PARENT(channel))->windowset->serverlabel), str); + g_free(str); + } + +@@ -322,7 +322,7 @@ + window = CHANNEL_PARENT(channel); + if (channel->type != CHANNEL_TYPE_CHANNEL || channel != window->active) + return TRUE; +- gui = WINDOW_GUI(window); ++ gui = WINDOW_GUI(window)->windowset; + + for (num = 0; num < 6; num++) + gtk_object_set_data(GTK_OBJECT(gui->modebuttons[num]), "toggling", GINT_TO_POINTER(TRUE)); +@@ -351,20 +351,21 @@ + + static gboolean signal_channel_open(CHANNEL_REC *channel) + { +- WINDOW_REC *window; ++ GUI_WINDOW_REC *gui; + + g_return_val_if_fail(channel != NULL, FALSE); + +- window = CHANNEL_PARENT(channel); +- if (WINDOW_GUI(window)->parent->active != window) ++ gui = WINDOW_GUI(CHANNEL_PARENT(channel))->windowset; ++ ++ if (gui->parent->active->active->window != CHANNEL_PARENT(channel)) + { + /* change to right window tab */ + gint page; + +- page = gtk_notebook_page_num(GTK_NOTEBOOK(WINDOW_GUI(window)->parent->notebook), WINDOW_GUI(window)->window); +- gtk_notebook_set_page(GTK_NOTEBOOK(WINDOW_GUI(window)->parent->notebook), page); ++ page = gtk_notebook_page_num(GTK_NOTEBOOK(gui->parent->notebook), gui->window); ++ gtk_notebook_set_page(GTK_NOTEBOOK(gui->parent->notebook), page); + } +- gdk_window_show(WINDOW_GUI(window)->parent->window->window); ++ gdk_window_show(gui->parent->window->window); + + if (CHANNEL_PARENT(channel)->active != channel) + { +diff -ru irssi-0.7.11/src/gui-gnome/gui-mainwindows.c irssi-0.7.11-new/src/gui-gnome/gui-mainwindows.c +--- irssi-0.7.11/src/gui-gnome/gui-mainwindows.c Thu May 13 15:17:33 1999 ++++ irssi-0.7.11-new/src/gui-gnome/gui-mainwindows.c Sat Jun 12 17:31:42 1999 +@@ -23,7 +23,7 @@ + + GList *mainwindows; + +-static WINDOW_REC *window_find_notebook_child(MAIN_WINDOW_REC *window, GtkWidget *child) ++static GUI_WINDOW_VIEW_REC *window_find_notebook_child(MAIN_WINDOW_REC *window, GtkWidget *child) + { + GList *tmp; + +@@ -32,9 +32,9 @@ + + for (tmp = g_list_first(window->children); tmp != NULL; tmp = tmp->next) + { +- WINDOW_REC *rec = tmp->data; ++ GUI_WINDOW_VIEW_REC *rec = tmp->data; + +- if (WINDOW_GUI(rec)->window == child) return rec; ++ if (rec->windowset->window == child) return rec; + } + + return NULL; +@@ -57,9 +57,9 @@ + { + g_return_val_if_fail(window != NULL, 0); + +- if (cur_channel != window->active->active) ++ if (cur_channel != window->active->active->window->active) + { +- cur_channel = window->active->active; ++ cur_channel = window->active->active->window->active; + signal_emit("channel changed", 1, cur_channel); + signal_emit("window focused", 1, window->active); + } +@@ -70,7 +70,7 @@ + /* notebook signal: switch_page */ + static void sig_switch_page(GtkWidget *notebook, GtkNotebookPage *child, guint pagenum, MAIN_WINDOW_REC *window) + { +- WINDOW_REC *subwin; ++ GUI_WINDOW_VIEW_REC *subwin; + + g_return_if_fail(child != NULL); + g_return_if_fail(window != NULL); +@@ -84,10 +84,10 @@ + return; + } + +- window->active = subwin; +- cur_channel = subwin->active; ++ window->active->active = subwin; ++ cur_channel = subwin->window->active; + signal_emit("channel changed", 1, cur_channel); +- signal_emit("window focused", 1, subwin); ++ signal_emit("window focused", 1, subwin->window); + } + + static void window_change_page(WINDOW_REC *window) +@@ -96,7 +96,7 @@ + + g_return_if_fail(window != NULL); + +- page = gtk_notebook_page_num(GTK_NOTEBOOK(WINDOW_GUI(window)->parent->notebook), WINDOW_GUI(window)->window); ++ page = gtk_notebook_page_num(GTK_NOTEBOOK(WINDOW_GUI(window)->parent->notebook), WINDOW_GUI(window)->windowset->window); + gtk_notebook_set_page(GTK_NOTEBOOK(WINDOW_GUI(window)->parent->notebook), page); + } + +@@ -105,15 +105,15 @@ + /* signal: key pressed (in entry field) */ + static gint sig_keypress(GtkWidget *widget, GdkEventKey *event, MAIN_WINDOW_REC *window) + { +- GUI_WINDOW_REC *guiwin; ++ GUI_WINDOW_VIEW_REC *view; + gchar *text; + + g_return_val_if_fail(event != NULL, 0); + g_return_val_if_fail(window != NULL, 0); + +- guiwin = window->active == NULL ? NULL : WINDOW_GUI(window->active); +- if (guiwin != NULL && guiwin->topicentry != NULL && GTK_WIDGET_HAS_FOCUS(guiwin->topicentry) && +- gtk_object_get_data(GTK_OBJECT(guiwin->topicentry), "editable")) ++ view = window->active == NULL ? NULL : window->active->active ; ++ if (view != NULL && view->windowset->topicentry != NULL && GTK_WIDGET_HAS_FOCUS(view->windowset->topicentry) && ++ gtk_object_get_data(GTK_OBJECT(view->windowset->topicentry), "editable")) + { + /* trying to write topic, don't disturb it.. */ + return 0; +@@ -143,11 +143,11 @@ + gint val; + + #ifdef HAVE_GNOME +- if (guiwin->zvt) +- adj = ZVT_TERM(guiwin->text)->adjustment; ++ if (view->zvt) ++ adj = ZVT_TERM(view->text)->adjustment; + else + #endif +- adj = GTK_TEXT(guiwin->text)->vadj; ++ adj = GTK_TEXT(view->text)->vadj; + val = adj->value - (adj->page_size/2); + gtk_adjustment_set_value(adj, val > 0 ? val : 0); + } +@@ -161,11 +161,11 @@ + gint val, max; + + #ifdef HAVE_GNOME +- if (guiwin->zvt) +- adj = ZVT_TERM(guiwin->text)->adjustment; ++ if (view->zvt) ++ adj = ZVT_TERM(view->text)->adjustment; + else + #endif +- adj = GTK_TEXT(guiwin->text)->vadj; ++ adj = GTK_TEXT(view->text)->vadj; + val = adj->value + (adj->page_size/2); + max = adj->upper - adj->lower - adj->page_size; + gtk_adjustment_set_value(adj, val <= max ? val : max); +@@ -179,7 +179,7 @@ + gint pos; + + pos = gtk_editable_get_position(GTK_EDITABLE(window->entry)); +- line = completion_line(window->active->active, gtk_entry_get_text(GTK_ENTRY(window->entry)), &pos); ++ line = completion_line(window->active->active->window->active, gtk_entry_get_text(GTK_ENTRY(window->entry)), &pos); + if (line != NULL) + { + gtk_entry_set_text(GTK_ENTRY(window->entry), line); +@@ -271,14 +271,14 @@ + + ui_history_add(str, FALSE); + +- if (cur_channel != window->active->active) ++ if (cur_channel != window->active->active->window->active) + { + /* we get here at least when using click-to-focus and keyboard + focus being in different window than mouse. Is there some + event we could use instead of enter_notify_event to find out + what window really has the focus? .. probably is, I'm too lazy + to find out what it is .. */ +- cur_channel = window->active->active; ++ cur_channel = window->active->active->window->active; + signal_emit("channel changed", 1, cur_channel); + } + signal_emit("send command", 3, str, cur_channel->server, cur_channel); +@@ -386,7 +403,7 @@ + + window->destroying = TRUE; + while (window->children != NULL) +- gui_window_destroy(window->children->data); ++ gui_windowset_destroy(window->children->data); + window->destroying = FALSE; + + gtk_widget_destroy(window->window); +diff -ru irssi-0.7.11/src/gui-gnome/gui-mainwindows.h irssi-0.7.11-new/src/gui-gnome/gui-mainwindows.h +--- irssi-0.7.11/src/gui-gnome/gui-mainwindows.h Sun Apr 11 23:40:07 1999 ++++ irssi-0.7.11-new/src/gui-gnome/gui-mainwindows.h Sat Jun 12 17:23:49 1999 +@@ -1,6 +1,9 @@ + #ifndef __GUI_MAINWINDOWS_H + #define __GUI_MAINWINDOWS_H + ++typedef struct _GUI_WINDOW_REC GUI_WINDOW_REC; ++typedef struct _GUI_WINDOW_VIEW_REC GUI_WINDOW_VIEW_REC; ++ + typedef struct + { + GtkWidget *window; +@@ -17,7 +20,7 @@ + guint destroying:1; + + GList *children; +- WINDOW_REC *active; ++ GUI_WINDOW_REC *active; + } + MAIN_WINDOW_REC; + +diff -ru irssi-0.7.11/src/gui-gnome/gui-printtext.c irssi-0.7.11-new/src/gui-gnome/gui-printtext.c +--- irssi-0.7.11/src/gui-gnome/gui-printtext.c Sun Jun 6 12:28:08 1999 ++++ irssi-0.7.11-new/src/gui-gnome/gui-printtext.c Mon Jun 7 18:44:44 1999 +@@ -51,7 +51,7 @@ + /* Write text to ZVT window */ + static gboolean gui_printtext_zvt(CHANNEL_REC *channel, gint fgcolor, gint bgcolor, gint flags, gchar *str) + { +- GUI_WINDOW_REC *gui; ++ GUI_WINDOW_VIEW_REC *view; + WINDOW_REC *window; + gint fg, bg; + GString *out; +@@ -59,7 +59,7 @@ + g_return_val_if_fail(str != NULL, FALSE); + + window = CHANNEL_PARENT(channel); +- gui = WINDOW_GUI(window); ++ view = WINDOW_GUI(window); + + if (flags & PRINTFLAG_BEEP) + gdk_beep(); +@@ -75,7 +75,7 @@ + } + + if (*str == '\n') +- zvt_term_feed(ZVT_TERM(gui->text), "\r", 1); ++ zvt_term_feed(ZVT_TERM(view->text), "\r", 1); + + out = g_string_new("\033[0;"); + +@@ -87,8 +87,8 @@ + g_string_sprintfa(out, "3%dm", ansitab[fg & 7]); + + g_string_append(out, str); +- zvt_term_feed(ZVT_TERM(gui->text), out->str, out->len); +- vt_cursor_state(gui->text, 0); /* hide the ugly cursor */ ++ zvt_term_feed(ZVT_TERM(view->text), out->str, out->len); ++ vt_cursor_state(view->text, 0); /* hide the ugly cursor */ + + g_string_free(out, TRUE); + +@@ -99,7 +99,7 @@ + /* Write text to window */ + static gboolean gui_printtext(CHANNEL_REC *channel, gpointer fgcolor, gpointer bgcolor, gpointer flags, gchar *str) + { +- GUI_WINDOW_REC *gui; ++ GUI_WINDOW_VIEW_REC *view; + WINDOW_REC *window; + GdkColor *fg, *bg; + GdkFont *font; +@@ -109,10 +109,10 @@ + g_return_val_if_fail(str != NULL, FALSE); + + window = CHANNEL_PARENT(channel); +- gui = WINDOW_GUI(window); ++ view = WINDOW_GUI(window); + + #ifdef HAVE_GNOME +- if (gui->zvt) ++ if (view->zvt) + { + /* Use ZVT widget */ + return gui_printtext_zvt(channel, GPOINTER_TO_INT(fgcolor), +@@ -126,13 +126,13 @@ + will happen.. (and this code even looks awful ...) */ + if (*str == '\n') + { +- gui->linepos = g_list_append(gui->linepos, GINT_TO_POINTER(gui->lastlinelen)+1); +- gui->lastlinelen = 0; ++ view->linepos = g_list_append(view->linepos, GINT_TO_POINTER(view->lastlinelen)+1); ++ view->lastlinelen = 0; + } + else +- gui->lastlinelen += strlen(str); ++ view->lastlinelen += strlen(str); + +- gtk_text_freeze(GTK_TEXT(gui->text)); ++ gtk_text_freeze(GTK_TEXT(view->text)); + if (*str == '\n' && max_textwidget_lines > 0 && + max_textwidget_lines+block_remove_lines <= window->lines && + channel->type != CHANNEL_TYPE_SETUP) +@@ -143,15 +143,15 @@ + { + GList *link; + +- link = g_list_first(gui->linepos); ++ link = g_list_first(view->linepos); + len += GPOINTER_TO_INT(link->data); +- gui->linepos = g_list_remove_link(gui->linepos, link); ++ view->linepos = g_list_remove_link(view->linepos, link); + g_list_free_1(link); + window->lines--; + } +- gtk_text_set_point(GTK_TEXT(gui->text), 0); +- gtk_text_forward_delete(GTK_TEXT(gui->text), len); +- gtk_text_set_point(GTK_TEXT(gui->text), gtk_text_get_length(GTK_TEXT(gui->text))); ++ gtk_text_set_point(GTK_TEXT(view->text), 0); ++ gtk_text_forward_delete(GTK_TEXT(view->text), len); ++ gtk_text_set_point(GTK_TEXT(view->text), gtk_text_get_length(GTK_TEXT(view->text))); + } + + if (GPOINTER_TO_INT(flags) & PRINTFLAG_BOLD) +@@ -178,8 +178,8 @@ + fg = bg != NULL ? bg : &bg_color; + bg = tmp; + } +- gtk_text_insert(GTK_TEXT(gui->text), font, fg, bg, str, -1); +- gtk_text_thaw(GTK_TEXT(gui->text)); ++ gtk_text_insert(GTK_TEXT(view->text), font, fg, bg, str, -1); ++ gtk_text_thaw(GTK_TEXT(view->text)); + + if (sb_down) set_sb_down(window); + +diff -ru irssi-0.7.11/src/gui-gnome/irssi.c irssi-0.7.11-new/src/gui-gnome/irssi.c +--- irssi-0.7.11/src/gui-gnome/irssi.c Mon May 10 20:32:28 1999 ++++ irssi-0.7.11-new/src/gui-gnome/irssi.c Mon Jun 7 19:06:20 1999 +@@ -38,7 +38,8 @@ + + gui_printtext_init(); + mainwindows_init(); +- gui_windows_init(); ++ gui_windowset_init(); ++ gui_windows_view_init(); + gui_channels_init(); + gui_dcc_init(); + gui_events_init(); +@@ -86,7 +87,8 @@ + gui_events_deinit(); + gui_server_deinit(); + mainwindows_deinit(); +- gui_windows_deinit(); ++ gui_windows_view_deinit(); ++ gui_windowset_deinit(); + gui_channels_deinit(); /* channels after mainwindows_deinit()! */ + gui_printtext_deinit(); + setup_deinit(); +diff -ru irssi-0.7.11/src/gui-gnome/irssi.h irssi-0.7.11-new/src/gui-gnome/irssi.h +--- irssi-0.7.11/src/gui-gnome/irssi.h Mon May 10 20:24:46 1999 ++++ irssi-0.7.11-new/src/gui-gnome/irssi.h Mon Jun 7 18:34:03 1999 +@@ -35,7 +35,8 @@ + #include "setup.h" + #include "gui-mainwindows.h" + #include "gui-channels.h" +-#include "gui-windows.h" ++#include "gui-windowset.h" ++#include "gui-windows-view.h" + + #include "channels-newdata.h" + #include "dialogs.h" +diff -ru irssi-0.7.11/src/gui-gnome/setup-appearance.c irssi-0.7.11-new/src/gui-gnome/setup-appearance.c +--- irssi-0.7.11/src/gui-gnome/setup-appearance.c Sun Jun 6 20:10:05 1999 ++++ irssi-0.7.11-new/src/gui-gnome/setup-appearance.c Mon Jun 7 19:07:22 1999 +@@ -49,16 +49,16 @@ + + static gchar *temp_font_name; + +-static void set_window_bg(GUI_WINDOW_REC *window) ++static void set_window_bg(GUI_WINDOW_VIEW_REC *view) + { + GtkStyle *style; + +- g_return_if_fail(window != NULL); ++ g_return_if_fail(view != NULL); + +- style = gtk_style_copy(window->text->style); ++ style = gtk_style_copy(view->text->style); + gtk_style_ref(style); + style->base[0] = temp_bg_color; +- gtk_widget_set_style(window->text, style); ++ gtk_widget_set_style(view->text, style); + gtk_style_unref(style); + + } +@@ -71,14 +71,14 @@ + static gboolean old_timestamps; + static gint oldlines, len; + +- GUI_WINDOW_REC *guiwin; ++ GUI_WINDOW_VIEW_REC *view; + WINDOW_REC *window; + gint n; + + g_return_if_fail(channel != NULL); + + window = CHANNEL_PARENT(channel); +- guiwin = WINDOW_GUI(window); ++ view = WINDOW_GUI(window); + + if (init) + { +@@ -90,16 +90,16 @@ + old_timestamps = toggle_show_timestamps; + toggle_show_timestamps = FALSE; + +- set_window_bg(guiwin); ++ set_window_bg(view); + + gui_printtext_configure(); + +- oldval = GTK_TEXT(guiwin->text)->vadj->value; ++ oldval = GTK_TEXT(view->text)->vadj->value; + oldlines = window->lines; +- len = gtk_text_get_length(GTK_TEXT(guiwin->text)); ++ len = gtk_text_get_length(GTK_TEXT(view->text)); + +- gtk_text_freeze(GTK_TEXT(guiwin->text)); +- gtk_text_set_point(GTK_TEXT(guiwin->text), len); ++ gtk_text_freeze(GTK_TEXT(view->text)); ++ gtk_text_set_point(GTK_TEXT(view->text), len); + } + else + { +@@ -108,10 +108,10 @@ + window->lines = oldlines; + + /*FIXME: this doesn't remove the lines from linelen list*/ +- gtk_text_set_point(GTK_TEXT(guiwin->text), 0); +- gtk_text_forward_delete(GTK_TEXT(guiwin->text), len); +- gtk_text_thaw(GTK_TEXT(guiwin->text)); +- gtk_adjustment_set_value(GTK_TEXT(guiwin->text)->vadj, oldval); ++ gtk_text_set_point(GTK_TEXT(view->text), 0); ++ gtk_text_forward_delete(GTK_TEXT(view->text), len); ++ gtk_text_thaw(GTK_TEXT(view->text)); ++ gtk_adjustment_set_value(GTK_TEXT(view->text)->vadj, oldval); + + bg_color = old_bg_color; + memcpy(setup_colors, old_colors, sizeof(setup_colors)); +diff -ru irssi-0.7.11/src/gui-gnome/snapshot.c irssi-0.7.11-new/src/gui-gnome/snapshot.c +--- irssi-0.7.11/src/gui-gnome/snapshot.c Thu May 13 16:03:54 1999 ++++ irssi-0.7.11-new/src/gui-gnome/snapshot.c Mon Jun 7 19:08:17 1999 +@@ -24,25 +24,25 @@ + + static void snapshot_show(WINDOW_REC *window) + { +- GUI_WINDOW_REC *gui; ++ GUI_WINDOW_VIEW_REC *view; + GtkWidget *scrollbox; + GtkAdjustment *adj; + gint x, y, xsize, ysize; + + g_return_if_fail(window != NULL); + +- gui = WINDOW_GUI(window); ++ view = WINDOW_GUI(window); + gdk_window_get_pointer (NULL, &x, &y, NULL); + +- gui->snapshot = gtk_window_new(GTK_WINDOW_POPUP); ++ view->snapshot = gtk_window_new(GTK_WINDOW_POPUP); + + scrollbox = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollbox), + GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); +- gtk_container_add(GTK_CONTAINER(gui->snapshot), scrollbox); ++ gtk_container_add(GTK_CONTAINER(view->snapshot), scrollbox); + +- xsize = gui->text->allocation.width; +- ysize = gui->text->allocation.height; ++ xsize = view->text->allocation.width; ++ ysize = view->text->allocation.height; + + if (xsize <= 1) xsize = gdk_screen_width()/2; + if (ysize <= 1) ysize = gdk_screen_height()*2/5; +@@ -58,18 +58,18 @@ + else + y += 5; + +- gtk_widget_set_uposition(gui->snapshot, x, y); ++ gtk_widget_set_uposition(view->snapshot, x, y); + +- gtk_object_set_data(GTK_OBJECT(gui->text), "parent", gui->text->parent); +- gtk_widget_reparent(gui->text, scrollbox); +- gtk_widget_show_all(gui->snapshot); ++ gtk_object_set_data(GTK_OBJECT(view->text), "parent", view->text->parent); ++ gtk_widget_reparent(view->text, scrollbox); ++ gtk_widget_show_all(view->snapshot); + + #ifdef HAVE_GNOME +- if (gui->zvt) +- adj = ZVT_TERM(gui->text)->adjustment; ++ if (view->zvt) ++ adj = ZVT_TERM(view->text)->adjustment; + else + #endif +- adj = GTK_TEXT(gui->text)->vadj; ++ adj = GTK_TEXT(view->text)->vadj; + gtk_adjustment_set_value(adj, adj->upper - adj->lower - adj->page_size); + + signal_emit("window focused", 1, window); +@@ -77,18 +77,18 @@ + + static void snapshot_hide(WINDOW_REC *window) + { +- GUI_WINDOW_REC *gui; ++ GUI_WINDOW_VIEW_REC *view; + GtkWidget *parent; + + g_return_if_fail(window != NULL); + +- gui = WINDOW_GUI(window); +- parent = gtk_object_get_data(GTK_OBJECT(gui->text), "parent"); ++ view = WINDOW_GUI(window); ++ parent = gtk_object_get_data(GTK_OBJECT(view->text), "parent"); + g_return_if_fail(parent != NULL); + +- gtk_widget_reparent(gui->text, parent); +- gtk_widget_destroy(gui->snapshot); +- gui->snapshot = NULL; ++ gtk_widget_reparent(view->text, parent); ++ gtk_widget_destroy(view->snapshot); ++ view->snapshot = NULL; + + signal_emit("window focused", 1, ((MAIN_WINDOW_REC *) mainwindows->data)->active); + } +diff -ru irssi-0.7.11/src/gui-gnome/window-menus.c irssi-0.7.11-new/src/gui-gnome/window-menus.c +--- irssi-0.7.11/src/gui-gnome/window-menus.c Sat May 15 22:08:20 1999 ++++ irssi-0.7.11-new/src/gui-gnome/window-menus.c Sat Jun 12 17:34:53 1999 +@@ -280,7 +280,7 @@ + window = gtk_object_get_data(GTK_OBJECT(menuitem->parent), "window"); + g_return_if_fail(window != NULL); + +- window->active->active->server = server; ++ window->active->active->window->active->server = server; + signal_emit("window server changed", 1, window->active); + } + +@@ -330,7 +330,7 @@ + gtk_menu_append(GTK_MENU(menu), menuitem); + + if (window->active != NULL) +- gtk_option_menu_set_history(GTK_OPTION_MENU(window->servermenu), g_list_index(servers, window->active->active->server)); ++ gtk_option_menu_set_history(GTK_OPTION_MENU(window->servermenu), g_list_index(servers, window->active->active->window->active->server)); + } + + return TRUE; +@@ -381,19 +381,19 @@ + + static void menu_chan_toggle_nicklist(GtkWidget *menuitem, CHANNEL_REC *channel) + { +- GUI_WINDOW_REC *window; ++ GtkWidget *nickscrollbox; + + g_return_if_fail(menuitem != NULL); + if (channel == NULL) return; + +- window = WINDOW_GUI(CHANNEL_PARENT(channel)); +- if (window->nickscrollbox == NULL) ++ nickscrollbox = WINDOW_GUI(CHANNEL_PARENT(channel))->windowset->nickscrollbox; ++ if (nickscrollbox == NULL) + return; /* this function was called from window_create().. */ + + if (GTK_CHECK_MENU_ITEM(menuitem)->active) +- gtk_widget_show(window->nickscrollbox); ++ gtk_widget_show(nickscrollbox); + else +- gtk_widget_hide(window->nickscrollbox); ++ gtk_widget_hide(nickscrollbox); + } + + static void menu_query_close(GtkWidget *menuitem, CHANNEL_REC *channel) +@@ -433,7 +433,7 @@ + toggling = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(menuitem), "toggling")); + if (toggling) return; + +- server = window->active->active->server; ++ server = window->active->active->window->active->server; + gtk_object_set_data(GTK_OBJECT(menuitem), "toggling", GINT_TO_POINTER(TRUE)); + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem), + server == NULL ? FALSE : server->usermode_away); +@@ -478,9 +478,9 @@ + g_return_if_fail(menuitem != NULL); + if (window == NULL) return; + +- server = window->active->active->server; ++ server = window->active->active->window->active->server; + usermode_set(menuitem, 'i', server == NULL ? FALSE : +- server->usermode_invisible, window->active->active); ++ server->usermode_invisible, window->active->active->window->active); + } + + static void menu_usermode_wallops(GtkWidget *menuitem, MAIN_WINDOW_REC *window) +@@ -490,9 +490,9 @@ + g_return_if_fail(menuitem != NULL); + if (window == NULL) return; + +- server = window->active->active->server; ++ server = window->active->active->window->active->server; + usermode_set(menuitem, 'w', server == NULL ? FALSE : +- server->usermode_wallops, window->active->active); ++ server->usermode_wallops, window->active->active->window->active); + } + + static void menu_usermode_snotes(GtkWidget *menuitem, MAIN_WINDOW_REC *window) +@@ -502,19 +502,19 @@ + g_return_if_fail(menuitem != NULL); + if (window == NULL) return; + +- server = window->active->active->server; ++ server = window->active->active->window->active->server; + usermode_set(menuitem, 's', server == NULL ? FALSE : +- server->usermode_servernotes, window->active->active); ++ server->usermode_servernotes, window->active->active->window->active); + } + + static void menu_dcc_chat(GtkWidget *menuitem, MAIN_WINDOW_REC *window) + { +- gui_dcc_chat(window->active->active != NULL ? window->active->active->server : window->active->active->server); ++ gui_dcc_chat(window->active->active != NULL ? window->active->active->window->active->server : window->active->active->window->active->server); + } + + static void menu_dcc_send(GtkWidget *menuitem, MAIN_WINDOW_REC *window) + { +- gui_dcc_send(window->active->active != NULL ? window->active->active->server : window->active->active->server, NULL, NULL); ++ gui_dcc_send(window->active->active != NULL ? window->active->active->window->active->server : window->active->active->window->active->server, NULL, NULL); + } + + static void menu_window_new(GtkWidget *menuitem, MAIN_WINDOW_REC *window) +@@ -526,7 +526,7 @@ + + old = toggle_use_tabbed_windows; + toggle_use_tabbed_windows = FALSE; +- channel_create(window->active->active->server, _("(empty)"), CHANNEL_TYPE_EMPTY); ++ channel_create(window->active->active->window->active->server, _("(empty)"), CHANNEL_TYPE_EMPTY); + toggle_use_tabbed_windows = old; + } + +@@ -539,7 +539,7 @@ + + old = toggle_use_tabbed_windows; + toggle_use_tabbed_windows = TRUE; +- channel_create(window->active->active->server, _("(empty)"), CHANNEL_TYPE_EMPTY); ++ channel_create(window->active->active->window->active->server, _("(empty)"), CHANNEL_TYPE_EMPTY); + toggle_use_tabbed_windows = old; + } + +@@ -554,7 +554,7 @@ + toggling = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(menuitem), "toggling")); + if (toggling) return; + +- gui = CHANNEL_GUI(window->active->active); ++ gui = CHANNEL_GUI(window->active->active->window->active); + gui->autoraise = GTK_CHECK_MENU_ITEM(menuitem)->active; /* FIXME: better way for this? gtk needs a function for this.. */ + + gtk_object_set_data(GTK_OBJECT(menuitem), "toggling", GINT_TO_POINTER(TRUE)); +@@ -567,7 +567,7 @@ + g_return_if_fail(menuitem != NULL); + if (window == NULL) return; + +- gui_window_destroy(window->active); ++ gui_windowset_destroy(window->active); + } + + static void menu_settings_preferences(void) +@@ -657,7 +657,7 @@ + switch (channel->type) + { + case CHANNEL_TYPE_CHANNEL: +- gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(channel_submenu[2].widget), GTK_WIDGET_VISIBLE(WINDOW_GUI(CHANNEL_PARENT(channel))->nickscrollbox)); ++ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(channel_submenu[2].widget), GTK_WIDGET_VISIBLE(WINDOW_GUI(CHANNEL_PARENT(channel))->windowset->nickscrollbox)); + break; + + case CHANNEL_TYPE_QUERY: +Only in irssi-0.7.11-new/src/gui-gnome: window-menus.o +diff -ru irssi-0.7.11/src/gui-gnome/window-nicklist.c irssi-0.7.11-new/src/gui-gnome/window-nicklist.c +--- irssi-0.7.11/src/gui-gnome/window-nicklist.c Thu May 13 15:15:09 1999 ++++ irssi-0.7.11-new/src/gui-gnome/window-nicklist.c Mon Jun 7 19:11:02 1999 +@@ -93,7 +93,7 @@ + g_return_if_fail(nick != NULL); + + if (CHANNEL_PARENT(channel)->active != channel) return; +- gui = WINDOW_GUI(CHANNEL_PARENT(channel)); ++ gui = WINDOW_GUI(CHANNEL_PARENT(channel))->windowset; + + list = GTK_CLIST(gui->nicklist)->row_list; + for (row = 0; list != NULL; row++, list = list->next) +@@ -130,9 +130,9 @@ + window = CHANNEL_PARENT(channel); + if (window->active != channel) return; + +- row = gtk_clist_find_row_from_data(GTK_CLIST(WINDOW_GUI(window)->nicklist), nick); ++ row = gtk_clist_find_row_from_data(GTK_CLIST(WINDOW_GUI(window)->windowset->nicklist), nick); + if (row != -1) +- gtk_clist_remove(GTK_CLIST(WINDOW_GUI(window)->nicklist), row); ++ gtk_clist_remove(GTK_CLIST(WINDOW_GUI(window)->windowset->nicklist), row); + } + + void window_nicklist_redraw(CHANNEL_REC *channel) +@@ -141,7 +141,7 @@ + GList *tmp; + + if (CHANNEL_PARENT(channel)->active != channel) return; +- gui = WINDOW_GUI(CHANNEL_PARENT(channel)); ++ gui = WINDOW_GUI(CHANNEL_PARENT(channel))->windowset; + + gtk_clist_freeze(GTK_CLIST(gui->nicklist)); + gtk_clist_clear(GTK_CLIST(gui->nicklist)); +@@ -443,7 +443,7 @@ + g_return_val_if_fail(window != NULL, FALSE); + + /* create op and voice pixmaps */ +- gui = WINDOW_GUI(window); ++ gui = WINDOW_GUI(window)->windowset; + gtk_widget_realize(gui->window); + gui->op_pixmap = gdk_pixmap_create_from_xpm_d(gui->window->window, &gui->op_mask, NULL, op_xpm); + gui->voice_pixmap = gdk_pixmap_create_from_xpm_d(gui->window->window, &gui->voice_mask, NULL, voice_xpm); +@@ -477,7 +477,7 @@ + + chanrec = channel_find(server, channel); + if (chanrec != NULL && !server->names_coming) +- gtk_clist_freeze(GTK_CLIST(WINDOW_GUI(CHANNEL_PARENT(chanrec))->nicklist)); ++ gtk_clist_freeze(GTK_CLIST(WINDOW_GUI(CHANNEL_PARENT(chanrec))->windowset->nicklist)); + + g_free(params); + return TRUE; +@@ -494,7 +494,7 @@ + + chanrec = channel_find(server, channel); + if (chanrec != NULL) +- gtk_clist_thaw(GTK_CLIST(WINDOW_GUI(CHANNEL_PARENT(chanrec))->nicklist)); ++ gtk_clist_thaw(GTK_CLIST(WINDOW_GUI(CHANNEL_PARENT(chanrec))->windowset->nicklist)); + + g_free(params); + return TRUE; +diff -Nru irssi-0.7.11/src/gui-gnome/gui-windowset.c irssi-0.7.11-new/src/gui-gnome/gui-windowset.c +--- irssi-0.7.11/src/gui-gnome/gui-windowset.c Thu Jan 1 02:00:00 1970 ++++ irssi-0.7.11-new/src/gui-gnome/gui-windowset.c Sat Jun 12 17:39:10 1999 +@@ -0,0 +1,385 @@ ++/* ++ gui-windowset.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 "irssi.h" ++ ++static gchar mode_flags[] = "spmint"; ++static gchar *mode_tooltips[] = ++{ ++ N_("Secret"), ++ N_("Private"), ++ N_("Moderated"), ++ N_("Joining needs an invitation"), ++ N_("No external messages"), ++ N_("Only operators can change the topic") ++}; ++ ++static gint sig_topicentry_press(GtkWidget *entry, GdkEventButton *event) ++{ ++ gboolean editable; ++ ++ g_return_val_if_fail(entry != NULL, 0); ++ g_return_val_if_fail(event != NULL, 0); ++ ++ if (event->type == GDK_2BUTTON_PRESS) ++ { ++ editable = !(gboolean) GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(entry), "editable")); ++ gtk_object_set_data(GTK_OBJECT(entry), "editable", GINT_TO_POINTER((gint) editable)); ++ gtk_entry_set_editable(GTK_ENTRY(entry), editable); ++ } ++ ++ return 0; ++} ++ ++static void sig_topicentry_activated(GtkWidget *entry, WINDOW_REC *window) ++{ ++ CHANNEL_REC *channel; ++ ++ g_return_if_fail(entry != NULL); ++ g_return_if_fail(window != NULL); ++ ++ channel = window->active; ++ if (channel == NULL || (!channel->chanop && channel->mode_optopic)) ++ { ++ /* can't change topic. */ ++ gtk_entry_set_text(GTK_ENTRY(entry), ++ (channel == NULL || channel->topic == NULL) ? ++ "" : channel->topic); ++ return; ++ } ++ ++ signal_emit("command topic", 3, gtk_entry_get_text(GTK_ENTRY(entry)), ++ window->active->server, window->active); ++} ++ ++static void sig_modebutton_toggled(GtkToggleButton *button, gint mode) ++{ ++ WINDOW_REC *window; ++ NICK_REC *nick; ++ GString *str; ++ ++ g_return_if_fail(button != NULL); ++ if (gtk_object_get_data(GTK_OBJECT(button), "toggling")) return; ++ ++ window = gtk_object_get_data(GTK_OBJECT(button), "window"); ++ g_return_if_fail(window->active != NULL); ++ ++ nick = nicklist_find(window->active, window->active->server->nick); ++ if (!window->active->chanop) ++ { ++ /* can't change mode */ ++ gtk_object_set_data(GTK_OBJECT(button), "toggling", GINT_TO_POINTER(TRUE)); ++ gtk_toggle_button_set_active(button, !button->active); ++ gtk_object_set_data(GTK_OBJECT(button), "toggling", GINT_TO_POINTER(FALSE)); ++ return; ++ } ++ ++ str = g_string_new(NULL); ++ g_string_sprintf(str, "* %c%c", button->active ? '+' : '-', mode_flags[mode]); ++ ++ gtk_object_set_data(GTK_OBJECT(button), "toggling", GINT_TO_POINTER(TRUE)); ++ signal_emit("command mode", 3, str->str, window->active->server, window->active); ++ g_string_free(str, TRUE); ++ gtk_object_set_data(GTK_OBJECT(button), "toggling", GINT_TO_POINTER(FALSE)); ++} ++ ++GUI_WINDOW_REC *gui_windowset_create(MAIN_WINDOW_REC *parent) ++{ ++ WINDOW_REC *rec; ++ GUI_WINDOW_REC *gui; ++ GUI_WINDOW_VIEW_REC *view; ++ GtkWidget *hbox, *label; ++ GtkTooltips *tooltips; ++ gint num; ++ ++ if (parent == NULL) parent = mainwindow_create(); ++ ++ rec = ui_window_create(); ++ g_return_val_if_fail(rec != NULL, NULL); ++ ++ gui = g_new0(GUI_WINDOW_REC, 1); ++ gui->parent = parent; ++ ++ if (parent->children == NULL) parent->active = gui; ++ parent->children = g_list_append(parent->children, gui); ++ ++ gui->window = gtk_vbox_new(FALSE, 2); ++ gtk_container_border_width(GTK_CONTAINER(gui->window), 2); ++ ++ /* Add channel topic and modes */ ++ gui->channelwidget = gtk_hbox_new(FALSE, 0); ++ gtk_box_pack_start(GTK_BOX(gui->window), gui->channelwidget, FALSE, FALSE, 0); ++ ++ gui->serverlabel = gtk_label_new(""); ++ gtk_box_pack_start(GTK_BOX(gui->channelwidget), gui->serverlabel, FALSE, FALSE, 0); ++ ++ gui->topicentry = gtk_entry_new(); ++ gtk_entry_set_editable(GTK_ENTRY(gui->topicentry), FALSE); ++ gtk_signal_connect(GTK_OBJECT(gui->topicentry), "button_press_event", ++ GTK_SIGNAL_FUNC(sig_topicentry_press), rec); ++ gtk_signal_connect(GTK_OBJECT(gui->topicentry), "activate", ++ GTK_SIGNAL_FUNC(sig_topicentry_activated), rec); ++ gtk_box_pack_start(GTK_BOX(gui->channelwidget), gui->topicentry, TRUE, TRUE, 3); ++ ++ tooltips = gtk_tooltips_new(); ++ ++ for (num = 0; num < 6; num++) ++ { ++ gchar str[2]; ++ ++ str[0] = toupper(mode_flags[num]); str[1] = '\0'; ++ gui->modebuttons[num] = gtk_toggle_button_new_with_label(str); ++ gtk_tooltips_set_tip(tooltips, gui->modebuttons[num], mode_tooltips[num], NULL); ++ gtk_widget_set_usize(gui->modebuttons[num], 20, -1); ++ gtk_object_set_data(GTK_OBJECT(gui->modebuttons[num]), "window", rec); ++ gtk_signal_connect(GTK_OBJECT(gui->modebuttons[num]), "toggled", ++ GTK_SIGNAL_FUNC(sig_modebutton_toggled), GINT_TO_POINTER(num)); ++ gtk_box_pack_start(GTK_BOX(gui->channelwidget), gui->modebuttons[num], FALSE, FALSE, 0); ++ } ++ ++ /* create view for window */ ++ hbox = gtk_hbox_new(FALSE, 3); ++ gtk_box_pack_start(GTK_BOX(gui->window), hbox, TRUE, TRUE, 0); ++ ++ view = gui_window_view_create(rec, gui, hbox); ++ gui->active = view; ++ ++ gtk_widget_show_all(gui->window); ++ ++ /* Add nick list */ ++ gui->nickscrollbox = gtk_scrolled_window_new(NULL, NULL); ++ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(gui->nickscrollbox), ++ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); ++ gtk_box_pack_start(GTK_BOX(hbox), gui->nickscrollbox, FALSE, FALSE, 0); ++ ++ gui->nicklist = gtk_clist_new(1); ++ gtk_container_add(GTK_CONTAINER(gui->nickscrollbox), gui->nicklist); ++ gtk_widget_show(gui->nicklist); ++ ++ gtk_widget_set_usize(gui->nickscrollbox, 120, -1); ++ ++ label = gtk_label_new(_("(none)")); ++ gtk_widget_show(label); ++ ++ if (g_list_first(parent->children)->next == NULL) ++ { ++ /* only one child, don't show the notebook tabs.. */ ++ gtk_notebook_set_show_tabs(GTK_NOTEBOOK(parent->notebook), FALSE); ++ gtk_notebook_set_show_border(GTK_NOTEBOOK(parent->notebook), FALSE); ++ } ++ else if (g_list_first(parent->children)->next->next == NULL) ++ { ++ /* two children, show the notebook tabs.. */ ++ gtk_notebook_set_show_tabs(GTK_NOTEBOOK(parent->notebook), TRUE); ++ gtk_notebook_set_show_border(GTK_NOTEBOOK(parent->notebook), TRUE); ++ } ++ ++ gtk_notebook_append_page(GTK_NOTEBOOK(parent->notebook), gui->window, label); ++ ++ gtk_widget_hide(gui->channelwidget); ++ ++ signal_emit("gui window created", 1, rec); ++ return gui; ++} ++ ++void gui_windowset_destroy(GUI_WINDOW_REC *window) ++{ ++ MAIN_WINDOW_REC *parent; ++ gint page; ++ ++ g_return_if_fail(window != NULL); ++ ++ if (window->destroying) return; ++ ++ parent = window->parent; ++ parent->children = g_list_remove(parent->children, window); ++ ++ signal_emit("gui window destroyed", 1, window); ++ ++ window->destroying = TRUE; ++ ++ page = gtk_notebook_page_num(GTK_NOTEBOOK(parent->notebook), window->window); ++ gtk_notebook_remove_page(GTK_NOTEBOOK(parent->notebook), page); ++ ++ while (window->views != NULL) ++ gui_window_view_destroy(window->views->data); ++ ++ g_free(window); ++ ++ if (parent->children == NULL) ++ mainwindow_destroy(parent); ++ else if (g_list_length(parent->children) == 1) ++ { ++ /* only one child left, hide the notebook tabs.. */ ++ gtk_notebook_set_show_tabs(GTK_NOTEBOOK(parent->notebook), FALSE); ++ gtk_notebook_set_show_border(GTK_NOTEBOOK(parent->notebook), FALSE); ++ } ++} ++ ++static gboolean gui_window_server_changed(WINDOW_REC *window) ++{ ++ MAIN_WINDOW_REC *parent; ++ SERVER_REC *server; ++ gint num; ++ ++ g_return_val_if_fail(window != NULL, FALSE); ++ ++ parent = WINDOW_GUI(window)->parent; ++ server = window->active->server; ++ ++ if (parent->usermodes[0] == NULL) return TRUE; ++ ++ for (num = 0; num < 4; num++) ++ gtk_object_set_data(GTK_OBJECT(parent->usermodes[num]), "toggling", GINT_TO_POINTER(TRUE)); ++ ++ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(parent->usermodes[0]), ++ server == NULL ? FALSE : server->usermode_away); ++ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(parent->usermodes[1]), ++ server == NULL ? FALSE : server->usermode_invisible); ++ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(parent->usermodes[2]), ++ server == NULL ? FALSE : server->usermode_wallops); ++ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(parent->usermodes[3]), ++ server == NULL ? FALSE : server->usermode_servernotes); ++ ++ for (num = 0; num < 4; num++) ++ gtk_object_set_data(GTK_OBJECT(parent->usermodes[num]), "toggling", GINT_TO_POINTER(FALSE)); ++ ++ return TRUE; ++} ++ ++static gboolean gui_windows_usermode_changed(SERVER_REC *server) ++{ ++ GList *winlist; ++ ++ for (winlist = g_list_first(mainwindows); winlist != NULL; winlist = winlist->next) ++ { ++ MAIN_WINDOW_REC *rec = winlist->data; ++ ++ if (server == rec->active->active->window->active->server) ++ signal_emit("window server changed", 1, rec->active); ++ } ++ ++ return TRUE; ++} ++ ++static gboolean signal_window_focused(WINDOW_REC *window) ++{ ++ MAIN_WINDOW_REC *mainwindow; ++ GUI_WINDOW_REC *gui; ++ CHANNEL_REC *channel; ++ ++ g_return_val_if_fail(window != NULL, FALSE); ++ ++ mainwindow = WINDOW_GUI(window)->parent; ++ channel = window->active; ++ ++ gui = mainwindow->active; ++ ++ /* remove old extra menus */ ++ if (mainwindow->extramenu != NULL) ++ { ++ window_menus_remove(mainwindow, mainwindow->extramenu); ++ g_free(mainwindow->extramenu); ++ mainwindow->extramenu = NULL; ++ } ++ if (channel == NULL) return TRUE; ++ ++ if (channel->type == CHANNEL_TYPE_CHANNEL) ++ { ++ /* Add channel menu */ ++ mainwindow->extramenu = g_strdup(channel_menu[0].label); ++ window_menus_insert(mainwindow, NULL, channel_menu, channel); ++ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(channel_submenu[2].widget), ++ GTK_WIDGET_VISIBLE(gui->nickscrollbox)); ++ gtk_widget_show(gui->channelwidget); ++ } ++ else ++ { ++ gtk_widget_hide(gui->nickscrollbox); ++ gtk_widget_hide(gui->channelwidget); ++ if (channel->type == CHANNEL_TYPE_QUERY) ++ { ++ /* Add query menu */ ++ mainwindow->extramenu = g_strdup(query_menu[0].label); ++ window_menus_insert(mainwindow, NULL, query_menu, channel); ++ } ++ } ++ ++ if (CHANNEL_GUI(channel)->servermenu) ++ { ++ /* change server selection */ ++ gtk_option_menu_set_history(GTK_OPTION_MENU(mainwindow->servermenu), ++ g_list_index(servers, channel->server)); ++ gtk_widget_show(mainwindow->servermenu); ++ } ++ else ++ gtk_widget_hide(mainwindow->servermenu); ++ ++ /* draw title bar */ ++ signal_emit("channel topic changed", 1, window->active); ++ ++ return TRUE; ++} ++ ++static gboolean gui_server_looking(SERVER_REC *server) ++{ ++ GList *tmp, *sub; ++ ++ g_return_val_if_fail(server != NULL, FALSE); ++ ++ /* try to keep some server assigned to server menus.. */ ++ for (tmp = g_list_first(windows); tmp != NULL; tmp = tmp->next) ++ { ++ WINDOW_REC *win = tmp->data; ++ gboolean changed; ++ ++ changed = FALSE; ++ for (sub = g_list_first(win->channels); sub != NULL; sub = sub->next) ++ { ++ CHANNEL_REC *chan = sub->data; ++ ++ if (chan->server == NULL) ++ { ++ chan->server = server; ++ if (!changed) ++ signal_emit("window server changed", 1, win); ++ changed = TRUE; ++ } ++ } ++ } ++ ++ return TRUE; ++} ++ ++void gui_windowset_init(void) ++{ ++ signal_add("user mode changed", (SIGNAL_FUNC) gui_windows_usermode_changed); ++ signal_add("window server changed", (SIGNAL_FUNC) gui_window_server_changed); ++ signal_add("window focused", (SIGNAL_FUNC) signal_window_focused); ++ signal_add("server looking", (SIGNAL_FUNC) gui_server_looking); ++} ++ ++void gui_windowset_deinit(void) ++{ ++ signal_remove("user mode changed", (SIGNAL_FUNC) gui_windows_usermode_changed); ++ signal_remove("window server changed", (SIGNAL_FUNC) gui_window_server_changed); ++ signal_remove("window focused", (SIGNAL_FUNC) signal_window_focused); ++ signal_remove("server looking", (SIGNAL_FUNC) gui_server_looking); ++} +diff -Nru irssi-0.7.11/src/gui-gnome/gui-windowset.h irssi-0.7.11-new/src/gui-gnome/gui-windowset.h +--- irssi-0.7.11/src/gui-gnome/gui-windowset.h Thu Jan 1 02:00:00 1970 ++++ irssi-0.7.11-new/src/gui-gnome/gui-windowset.h Sat Jun 12 17:22:55 1999 +@@ -0,0 +1,32 @@ ++#ifndef __GUI_WINDOWSET_H ++#define __GUI_WINDOWSET_H ++ ++struct _GUI_WINDOW_REC ++{ ++ MAIN_WINDOW_REC *parent; ++ ++ GtkWidget *window; ++ GList *views; ++ GUI_WINDOW_VIEW_REC *active; ++ ++ GtkWidget *channelwidget; ++ GtkWidget *serverlabel; ++ GtkWidget *topicentry; ++ GtkWidget *modebuttons[6]; ++ ++ /* nicklist */ ++ GtkWidget *nickscrollbox; ++ GtkWidget *nicklist; ++ GdkPixmap *op_pixmap, *voice_pixmap; ++ GdkBitmap *op_mask, *voice_mask; ++ ++ gboolean destroying; ++}; ++ ++void gui_windowset_init(void); ++void gui_windowset_deinit(void); ++ ++GUI_WINDOW_REC *gui_windowset_create(MAIN_WINDOW_REC *parent); ++void gui_windowset_destroy(GUI_WINDOW_REC *window); ++ ++#endif +diff -Nru irssi-0.7.11/src/gui-gnome/gui-windows-view.c irssi-0.7.11-new/src/gui-gnome/gui-windows-view.c +--- irssi-0.7.11/src/gui-gnome/gui-windows-view.c Thu Jan 1 02:00:00 1970 ++++ irssi-0.7.11-new/src/gui-gnome/gui-windows-view.c Sat Jun 12 17:16:29 1999 +@@ -0,0 +1,454 @@ ++/* ++ gui-windows-view.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 "irssi.h" ++ ++#define iswordcut(a) (isspace((gint) a) || \ ++ (a) == '\n' || (a) == '\0' || (a) == '"' || \ ++ (a) == '(' || (a) == ')' || (a) == '[' || (a) == ']' || \ ++ (a) == '<' || (a) == '>') ++ ++#define URL_MAX_LENGTH 200 /*FIXME: no max. limits*/ ++ ++GList *window_views; ++ ++void gui_window_view_set_background_pixmap(GUI_WINDOW_VIEW_REC *view, gchar *path) ++{ ++ GtkStyle *style; ++ GdkPixmap *pixmap; ++ GdkBitmap *mask; ++#if defined (HAVE_IMLIB) || defined (HAVE_GNOME) ++ GdkImlibImage *img; ++#endif ++ ++ g_return_if_fail(view != NULL); ++ g_return_if_fail(path != NULL); ++ ++ if (view->pixmap != NULL && strcmp(view->pixmap, path) == 0) ++ { ++ /* same pixmap already set for this view.. */ ++ return; ++ } ++ if (view->pixmap != NULL) ++ g_free(view->pixmap); ++ view->pixmap = g_strdup(path); ++ ++#ifdef HAVE_GNOME ++ if (view->zvt) ++ { ++ zvt_term_set_background(ZVT_TERM(view->text), path, FALSE, FALSE); ++ return; ++ } ++#endif ++ ++ if (*path == '\0') ++ pixmap = NULL; ++ else ++ { ++#if defined (HAVE_IMLIB) || defined (HAVE_GNOME) ++ mask = NULL; ++ img = gdk_imlib_load_image(path); ++ if (img == NULL) ++ pixmap = NULL; ++ else ++ { ++ gdk_imlib_render(img, img->rgb_width, img->rgb_height); ++ pixmap = gdk_imlib_move_image(img); ++ gdk_imlib_destroy_image(img); ++ } ++#else ++ pixmap = gdk_pixmap_create_from_xpm(view->text->window, &mask, NULL, path); ++#endif ++ } ++ ++ style = gtk_style_copy(view->text->style); ++ gtk_style_ref(style); ++ style->bg_pixmap[GTK_STATE_NORMAL] = pixmap; ++ gtk_widget_set_style(view->text, style); ++ gtk_style_unref(style); ++} ++ ++static void gui_window_view_set_background(GUI_WINDOW_VIEW_REC *view) ++{ ++ GtkStyle *style; ++ gchar *path; ++ ++ g_return_if_fail(view != NULL); ++ ++#ifdef HAVE_GNOME ++ if (view->zvt) ++ { ++ if (toggle_use_transparency) ++ { ++ zvt_term_set_background(ZVT_TERM(view->text), 0, TRUE, toggle_shaded_transparency); ++ if (view->pixmap != NULL) ++ { ++ g_free(view->pixmap); ++ view->pixmap = NULL; ++ } ++ return; ++ } ++ } ++ else ++#endif ++ { ++ style = gtk_style_copy(view->text->style); ++ gtk_style_ref(style); ++ style->base[GTK_STATE_NORMAL] = bg_color;; ++ gtk_widget_set_style(view->text, style); ++ gtk_style_unref(style); ++ } ++ ++ path = convert_home(background_pixmap); ++ gui_window_view_set_background_pixmap(view, path); ++ g_free(path); ++} ++ ++static void init_colors(GtkWidget *window) ++{ ++ gint n; ++ ++ g_return_if_fail(window != NULL); ++ ++ for (n = 0; n < sizeof(setup_colors)/sizeof(setup_colors[0]); n++) ++ { ++ setup_colors[n].pixel = ++ (gulong)((setup_colors[n].red & 0xff00)*256 + ++ (setup_colors[n].green & 0xff00) + ++ (setup_colors[n].blue & 0xff00)/256); ++ gdk_color_alloc(gtk_widget_get_colormap(window), &setup_colors[n]); ++ } ++ ++ bg_color.pixel = ++ (gulong)((bg_color.red & 0xff00)*256 + ++ (bg_color.green & 0xff00) + ++ (bg_color.blue & 0xff00)/256); ++ gdk_color_alloc(gtk_widget_get_colormap(window), &bg_color); ++} ++ ++#ifdef HAVE_GNOME ++static void init_zvt_colors(ZvtTerm *zvt) ++{ ++ static gchar ansitab[16] = { 0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15 }; ++ gushort zvt_red[18], zvt_green[18], zvt_blue[18]; ++ gint num; ++ ++ for (num = 0; num < 16; num++) ++ { ++ zvt_red[num] = (gushort) setup_colors[(gint) ansitab[num]].red; ++ zvt_green[num] = (gushort) setup_colors[(gint) ansitab[num]].green; ++ zvt_blue[num] = (gushort) setup_colors[(gint) ansitab[num]].blue; ++ } ++ ++ zvt_red[16] = zvt_green[16] = zvt_blue[16] = 0xffff; ++ zvt_red[17] = zvt_green[17] = zvt_blue[17] = 0; ++ ++ zvt_term_set_color_scheme(zvt, zvt_red, zvt_green, zvt_blue); ++} ++ ++/* signal: button pressed in text window */ ++static gint sig_text_butpress_zvt(GtkWidget *widget, GdkEventButton *event, WINDOW_REC *window) ++{ ++ gint x, y, len; ++ gchar *text, *word; ++ ++ g_return_val_if_fail(widget != NULL, 0); ++ g_return_val_if_fail(event != NULL, 0); ++ g_return_val_if_fail(window != NULL, 0); ++ ++ x = event->x / ZVT_TERM(widget)->charwidth; ++ y = event->y / ZVT_TERM(widget)->charheight; ++ ++ word = NULL; ++ ++ text = zvt_term_get_buffer(ZVT_TERM(widget), &len, VT_SELTYPE_CHAR, ++ 0, y, ZVT_TERM(widget)->grid_width-1, y); ++ if (text != NULL && len > 0) ++ { ++ len = x; ++ if (!iswordcut(text[x])) ++ while (x > 0 && !iswordcut(text[x-1])) x--; ++ while (!iswordcut(text[len])) len++; len -= x; ++ ++ word = g_new(gchar, len+1); ++ memcpy(word, text+x, len); word[len] = '\0'; ++ } ++ ++ if (event->button == 3 && toggle_show_menubar) ++ { ++ /* create popup menu */ ++ window_popupmenu_create(window->active, word, event); ++ gtk_signal_emit_stop_by_name(GTK_OBJECT(widget), "button_press_event"); ++ } ++ else if (word != NULL) ++ { ++ /* left mouse button clicked */ ++ word_clicked(window, word, event->type == GDK_2BUTTON_PRESS, event->button, NULL); ++ } ++ ++ if (word != NULL) g_free(word); ++ return 0; ++} ++#endif ++ ++/* signal: button pressed in text window */ ++static gint sig_text_butpress(GtkWidget *widget, GdkEventButton *event, GUI_WINDOW_VIEW_REC *view) ++{ ++ static gboolean cludging = FALSE; ++ GdkEventButton kludge_event; ++ ++ guint pos, spos, len; ++ gchar *text, *word; ++ ++ g_return_val_if_fail(widget != NULL, 0); ++ g_return_val_if_fail(event != NULL, 0); ++ g_return_val_if_fail(view != NULL, 0); ++ ++ /* so, here's the problem: we need know what word was just clicked, but ++ text widget haven't get button_press_event yet so cursor position is ++ still in the last clicked position.. We could use ++ gtk_signal_connect_after(), but if we create a popup menu with it, ++ text widget's selection gets broken, it never receives the ++ button_release_event .. We could also create the popup menu in ++ button_release_event but it seems to work in some weird way too .. ++ So this kludge seems to work best. */ ++ if (cludging) return 0; ++ ++ /* send faked left button click to text widget */ ++ cludging = TRUE; ++ memcpy(&kludge_event, event, sizeof(kludge_event)); ++ kludge_event.button = 1; ++ kludge_event.type = GDK_BUTTON_PRESS; ++ gtk_widget_event(widget, (GdkEvent *) &kludge_event); ++ kludge_event.type = GDK_BUTTON_RELEASE; ++ gtk_widget_event(widget, (GdkEvent *) &kludge_event); ++ cludging = FALSE; ++ ++ /* finished, cursor is now in right position! */ ++ ++ len = gtk_text_get_length(GTK_TEXT(view->text)); ++ pos = gtk_editable_get_position(GTK_EDITABLE(view->text)); ++ ++ word = NULL; ++ if (pos < len) ++ { ++ text = gtk_editable_get_chars(GTK_EDITABLE(view->text), pos < URL_MAX_LENGTH ? 0 : pos-URL_MAX_LENGTH, ++ pos+URL_MAX_LENGTH > len ? len : pos+URL_MAX_LENGTH); ++ len = spos = pos < URL_MAX_LENGTH ? pos : URL_MAX_LENGTH; ++ if (!iswordcut(text[spos])) ++ while (spos > 0 && !iswordcut(text[spos-1])) spos--; ++ while (!iswordcut(text[len])) len++; len -= spos; ++ ++ word = g_new(gchar, len+1); ++ memcpy(word, text+spos, len); word[len] = '\0'; ++ g_free(text); ++ } ++ ++ if (event->button == 3 && toggle_show_menubar) ++ { ++ /* create popup menu */ ++ window_popupmenu_create(view->window->active, word, event); ++ gtk_signal_emit_stop_by_name(GTK_OBJECT(widget), "button_press_event"); ++ } ++ else if (word != NULL) ++ { ++ /* left mouse button clicked */ ++ word_clicked(view->window, word, event->type == GDK_2BUTTON_PRESS, event->button, NULL); ++ } ++ ++ if (word != NULL) g_free(word); ++ return 0; ++} ++ ++GUI_WINDOW_VIEW_REC *gui_window_view_create(WINDOW_REC *window, GUI_WINDOW_REC *parent, GtkWidget *box) ++{ ++ GUI_WINDOW_VIEW_REC *rec; ++ GtkWidget *scrollwin; ++ ++ g_return_val_if_fail(parent != NULL, NULL); ++ ++ rec = g_new0(GUI_WINDOW_VIEW_REC, 1); ++ parent->views = g_list_append(parent->views, rec); ++ window_views = g_list_append(window_views, rec); ++ window->gui_data = rec; ++ ++ rec->window = window; ++ rec->windowset = parent; ++ rec->parent = parent->parent;; ++ ++ /* Text window */ ++ rec->zvt = toggle_use_zvt; ++#ifdef HAVE_GNOME ++ if (toggle_use_zvt) ++ { ++ GtkWidget *scrollbar; ++ ++ rec->text = zvt_term_new(); ++ gtk_signal_connect(GTK_OBJECT(rec->text), "button_press_event", ++ GTK_SIGNAL_FUNC(sig_text_butpress_zvt), window); ++ zvt_term_set_scrollback(ZVT_TERM(rec->text), max_textwidget_lines); ++ zvt_term_set_fonts(ZVT_TERM(rec->text), font_normal, font_bold); ++ zvt_term_set_blink(ZVT_TERM(rec->text), FALSE); ++ gtk_box_pack_start(GTK_BOX(box), rec->text, TRUE, TRUE, 0); ++ ++ scrollbar = gtk_vscrollbar_new(ZVT_TERM(rec->text)->adjustment); ++ gtk_box_pack_start(GTK_BOX(box), scrollbar, FALSE, FALSE, 0); ++ } ++ else ++#endif ++ { ++ rec->text = gtk_text_new(NULL, NULL); ++ gtk_signal_connect(GTK_OBJECT(rec->text), "button_press_event", ++ GTK_SIGNAL_FUNC(sig_text_butpress), rec); ++ gtk_text_set_word_wrap(GTK_TEXT(rec->text), TRUE); ++ ++ scrollwin = gtk_scrolled_window_new(NULL, NULL); ++ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin), ++ GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); ++ gtk_box_pack_start(GTK_BOX(box), scrollwin, TRUE, TRUE, 0); ++ gtk_container_add(GTK_CONTAINER(scrollwin), rec->text); ++ ++ init_colors(rec->text); ++ } ++ ++ gui_window_view_set_background(rec); ++ return rec; ++} ++ ++static gboolean gui_window_created(WINDOW_REC *window) ++{ ++ GUI_WINDOW_VIEW_REC *view; ++ GtkWidget *popup; ++ ++ g_return_val_if_fail(window != NULL, TRUE); ++ ++ /* there's only one view after window is created.. */ ++ view = WINDOW_GUI(window); ++ ++#ifdef HAVE_GNOME ++ if (view->zvt) ++ { ++ gtk_widget_realize(view->text); ++ init_zvt_colors(ZVT_TERM(view->text)); ++ vt_cursor_state(view->text, 0); ++ } ++#endif ++ ++ if (!toggle_show_menubar) ++ { ++ /* add popup menu created by mainwindow */ ++ popup = gtk_object_get_data(GTK_OBJECT(WINDOW_GUI(window)->parent->window), "popup"); ++ if (popup != NULL) gnome_popup_menu_attach(popup, view->text, view->parent); ++ } ++ ++ return TRUE; ++} ++ ++void gui_window_view_destroy(GUI_WINDOW_VIEW_REC *view) ++{ ++ WINDOW_REC *window; ++ GUI_WINDOW_REC *gui; ++ ++ if (view->destroying) return; ++ ++ window = view->window; ++ gui = view->windowset; ++ signal_emit("gui window view destroyed", 1, view); ++ ++ view->destroying = TRUE; ++ ui_window_destroy(window); ++ ++ gui->views = g_list_remove(gui->views, view); ++ window_views = g_list_remove(window_views, view); ++ ++ if (view->pixmap != NULL) g_free(view->pixmap); ++ g_list_free(view->linepos); ++ g_free(view); ++ ++ window->gui_data = NULL; ++ ++ if (gui->views == NULL) ++ gui_windowset_destroy(gui); ++} ++ ++static gboolean cmd_clear(gchar *data, SERVER_REC *server, CHANNEL_REC *channel) ++{ ++ WINDOW_REC *window; ++ GUI_WINDOW_VIEW_REC *view; ++ ++ g_return_val_if_fail(channel != NULL, FALSE); ++ ++ window = CHANNEL_PARENT(channel); ++ view = WINDOW_GUI(window); ++ ++#ifdef HAVE_GNOME ++ if (view->zvt) ++ { ++ zvt_term_set_scrollback(ZVT_TERM(view->text), 0); ++ zvt_term_feed(ZVT_TERM(view->text), "\033[H\033[2J", 7); ++ zvt_term_set_scrollback(ZVT_TERM(view->text), max_textwidget_lines); ++ } ++ else ++#endif ++ { ++ g_list_free(view->linepos); ++ view->linepos = NULL; ++ gtk_text_set_point(GTK_TEXT(view->text), 0); ++ gtk_text_forward_delete(GTK_TEXT(view->text), gtk_text_get_length(GTK_TEXT(view->text))); ++ } ++ window->lines = 0; ++ ++ return TRUE; ++} ++ ++static gboolean setup_changed(void) ++{ ++ GList *tmp; ++ ++ for (tmp = g_list_first(window_views); tmp != NULL; tmp = tmp->next) ++ { ++ GUI_WINDOW_VIEW_REC *view = tmp->data; ++ ++ gui_window_view_set_background(view); ++#ifdef HAVE_GNOME ++ if (view->zvt) ++ { ++ zvt_term_set_fonts(ZVT_TERM(view->text), font_normal, font_bold); ++ init_zvt_colors(ZVT_TERM(view->text)); ++ } ++#endif ++ } ++ ++ return TRUE; ++} ++ ++void gui_windows_view_init(void) ++{ ++ signal_add("gui window created", (SIGNAL_FUNC) gui_window_created); ++ signal_add("setup changed", (SIGNAL_FUNC) setup_changed); ++ signal_add("command clear", (SIGNAL_FUNC) cmd_clear); ++} ++ ++void gui_windows_view_deinit(void) ++{ ++ signal_remove("gui window created", (SIGNAL_FUNC) gui_window_created); ++ signal_remove("setup changed", (SIGNAL_FUNC) setup_changed); ++ signal_remove("command clear", (SIGNAL_FUNC) cmd_clear); ++} +diff -Nru irssi-0.7.11/src/gui-gnome/gui-windows-view.h irssi-0.7.11-new/src/gui-gnome/gui-windows-view.h +--- irssi-0.7.11/src/gui-gnome/gui-windows-view.h Thu Jan 1 02:00:00 1970 ++++ irssi-0.7.11-new/src/gui-gnome/gui-windows-view.h Sat Jun 12 17:23:39 1999 +@@ -0,0 +1,34 @@ ++#ifndef __GUI_WINDOWS_VIEW_H ++#define __GUI_WINDOWS_VIEW_H ++ ++#define WINDOW_GUI(a) ((GUI_WINDOW_VIEW_REC *) ((a)->gui_data)) ++ ++struct _GUI_WINDOW_VIEW_REC ++{ ++ WINDOW_REC *window; ++ GUI_WINDOW_REC *windowset; ++ MAIN_WINDOW_REC *parent; ++ ++ GtkWidget *text; ++ ++ gboolean zvt; /* text is a zvt widget */ ++ gchar *pixmap; /* current background pixmap */ ++ ++ GList *linepos; ++ gint lastlinelen; ++ ++ GtkWidget *snapshot; ++ gboolean destroying; ++}; ++ ++extern GList *window_views; ++ ++void gui_windows_view_init(void); ++void gui_windows_view_deinit(void); ++ ++GUI_WINDOW_VIEW_REC *gui_window_view_create(WINDOW_REC *window, GUI_WINDOW_REC *parent, GtkWidget *box); ++void gui_window_view_destroy(GUI_WINDOW_VIEW_REC *view); ++ ++void gui_window_view_set_background_pixmap(GUI_WINDOW_VIEW_REC *view, gchar *path); ++ ++#endif +diff -Nru irssi-0.7.11/src/gui-gnome/gui-windows.c irssi-0.7.11-new/src/gui-gnome/gui-windows.c +--- irssi-0.7.11/src/gui-gnome/gui-windows.c Sat May 15 21:38:30 1999 ++++ irssi-0.7.11-new/src/gui-gnome/gui-windows.c Thu Jan 1 02:00:00 1970 +@@ -1,750 +0,0 @@ +- /* +- gui-windows.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 "irssi.h" +- +-#define iswordcut(a) (isspace((gint) a) || \ +- (a) == '\n' || (a) == '\0' || (a) == '"' || \ +- (a) == '(' || (a) == ')' || (a) == '[' || (a) == ']' || \ +- (a) == '<' || (a) == '>') +- +-#define URL_MAX_LENGTH 200 /*FIXME: no max. limits*/ +- +-static gchar mode_flags[] = "spmint"; +-static gchar *mode_tooltips[] = +-{ +- N_("Secret"), +- N_("Private"), +- N_("Moderated"), +- N_("Joining needs an invitation"), +- N_("No external messages"), +- N_("Only operators can change the topic") +-}; +- +-static void init_colors(GtkWidget *window) +-{ +- gint n; +- +- g_return_if_fail(window != NULL); +- +- for (n = 0; n < sizeof(setup_colors)/sizeof(setup_colors[0]); n++) +- { +- setup_colors[n].pixel = +- (gulong)((setup_colors[n].red & 0xff00)*256 + +- (setup_colors[n].green & 0xff00) + +- (setup_colors[n].blue & 0xff00)/256); +- gdk_color_alloc(gtk_widget_get_colormap(window), &setup_colors[n]); +- } +- +- bg_color.pixel = +- (gulong)((bg_color.red & 0xff00)*256 + +- (bg_color.green & 0xff00) + +- (bg_color.blue & 0xff00)/256); +- gdk_color_alloc(gtk_widget_get_colormap(window), &bg_color); +-} +- +-void gui_window_set_background_pixmap(WINDOW_REC *window, gchar *path) +-{ +- GUI_WINDOW_REC *gui; +- GtkStyle *style; +- GdkPixmap *pixmap; +- GdkBitmap *mask; +-#if defined (HAVE_IMLIB) || defined (HAVE_GNOME) +- GdkImlibImage *img; +-#endif +- +- g_return_if_fail(window != NULL); +- g_return_if_fail(path != NULL); +- +- gui = WINDOW_GUI(window); +- if (gui->pixmap != NULL && strcmp(gui->pixmap, path) == 0) +- { +- /* same pixmap already set for this window.. */ +- return; +- } +- if (gui->pixmap != NULL) +- g_free(gui->pixmap); +- gui->pixmap = g_strdup(path); +- +-#ifdef HAVE_GNOME +- if (gui->zvt) +- { +- zvt_term_set_background(ZVT_TERM(gui->text), path, FALSE, FALSE); +- return; +- } +-#endif +- +- if (*path == '\0') +- pixmap = NULL; +- else +- { +-#if defined (HAVE_IMLIB) || defined (HAVE_GNOME) +- mask = NULL; +- img = gdk_imlib_load_image(path); +- if (img == NULL) +- pixmap = NULL; +- else +- { +- gdk_imlib_render(img, img->rgb_width, img->rgb_height); +- pixmap = gdk_imlib_move_image(img); +- gdk_imlib_destroy_image(img); +- } +-#else +- pixmap = gdk_pixmap_create_from_xpm(gui->text->window, &mask, NULL, path); +-#endif +- } +- +- style = gtk_style_copy(gui->text->style); +- gtk_style_ref(style); +- style->bg_pixmap[GTK_STATE_NORMAL] = pixmap; +- gtk_widget_set_style(gui->text, style); +- gtk_style_unref(style); +-} +- +-static void gui_window_set_background(WINDOW_REC *window) +-{ +- GUI_WINDOW_REC *gui; +- GtkStyle *style; +- gchar *path; +- +- g_return_if_fail(window != NULL); +- +- gui = WINDOW_GUI(window); +-#ifdef HAVE_GNOME +- if (gui->zvt) +- { +- if (toggle_use_transparency) +- { +- zvt_term_set_background(ZVT_TERM(gui->text), 0, TRUE, toggle_shaded_transparency); +- if (gui->pixmap != NULL) +- { +- g_free(gui->pixmap); +- gui->pixmap = NULL; +- } +- return; +- } +- } +- else +-#endif +- { +- style = gtk_style_copy(gui->text->style); +- gtk_style_ref(style); +- style->base[GTK_STATE_NORMAL] = bg_color;; +- gtk_widget_set_style(gui->text, style); +- gtk_style_unref(style); +- } +- +- path = convert_home(background_pixmap); +- gui_window_set_background_pixmap(window, path); +- g_free(path); +-} +- +-#ifdef HAVE_GNOME +-static void init_zvt_colors(ZvtTerm *zvt) +-{ +- static gchar ansitab[16] = { 0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15 }; +- gushort zvt_red[18], zvt_green[18], zvt_blue[18]; +- gint num; +- +- for (num = 0; num < 16; num++) +- { +- zvt_red[num] = (gushort) setup_colors[(gint) ansitab[num]].red; +- zvt_green[num] = (gushort) setup_colors[(gint) ansitab[num]].green; +- zvt_blue[num] = (gushort) setup_colors[(gint) ansitab[num]].blue; +- } +- +- zvt_red[16] = zvt_green[16] = zvt_blue[16] = 0xffff; +- zvt_red[17] = zvt_green[17] = zvt_blue[17] = 0; +- +- zvt_term_set_color_scheme(zvt, zvt_red, zvt_green, zvt_blue); +-} +- +-/* signal: button pressed in text window */ +-static gint sig_text_butpress_zvt(GtkWidget *widget, GdkEventButton *event, WINDOW_REC *window) +-{ +- gint x, y, len; +- gchar *text, *word; +- +- g_return_val_if_fail(widget != NULL, 0); +- g_return_val_if_fail(event != NULL, 0); +- g_return_val_if_fail(window != NULL, 0); +- +- x = event->x / ZVT_TERM(widget)->charwidth; +- y = event->y / ZVT_TERM(widget)->charheight; +- +- word = NULL; +- +- text = zvt_term_get_buffer(ZVT_TERM(widget), &len, VT_SELTYPE_CHAR, +- 0, y, ZVT_TERM(widget)->grid_width-1, y); +- if (text != NULL && len > 0) +- { +- len = x; +- if (!iswordcut(text[x])) +- while (x > 0 && !iswordcut(text[x-1])) x--; +- while (!iswordcut(text[len])) len++; len -= x; +- +- word = g_new(gchar, len+1); +- memcpy(word, text+x, len); word[len] = '\0'; +- } +- +- if (event->button == 3 && toggle_show_menubar) +- { +- /* create popup menu */ +- window_popupmenu_create(window->active, word, event); +- gtk_signal_emit_stop_by_name(GTK_OBJECT(widget), "button_press_event"); +- } +- else if (word != NULL) +- { +- /* left mouse button clicked */ +- word_clicked(window, word, event->type == GDK_2BUTTON_PRESS, event->button, NULL); +- } +- +- if (word != NULL) g_free(word); +- return 0; +-} +-#endif +- +-/* signal: button pressed in text window */ +-static gint sig_text_butpress(GtkWidget *widget, GdkEventButton *event, WINDOW_REC *window) +-{ +- static gboolean cludging = FALSE; +- GdkEventButton kludge_event; +- +- guint pos, spos, len; +- gchar *text, *word; +- +- g_return_val_if_fail(widget != NULL, 0); +- g_return_val_if_fail(event != NULL, 0); +- g_return_val_if_fail(window != NULL, 0); +- +- /* so, here's the problem: we need know what word was just clicked, but +- text widget haven't get button_press_event yet so cursor position is +- still in the last clicked position.. We could use +- gtk_signal_connect_after(), but if we create a popup menu with it, +- text widget's selection gets broken, it never receives the +- button_release_event .. We could also create the popup menu in +- button_release_event but it seems to work in some weird way too .. +- So this kludge seems to work best. */ +- if (cludging) return 0; +- +- /* send faked left button click to text widget */ +- cludging = TRUE; +- memcpy(&kludge_event, event, sizeof(kludge_event)); +- kludge_event.button = 1; +- kludge_event.type = GDK_BUTTON_PRESS; +- gtk_widget_event(widget, (GdkEvent *) &kludge_event); +- kludge_event.type = GDK_BUTTON_RELEASE; +- gtk_widget_event(widget, (GdkEvent *) &kludge_event); +- cludging = FALSE; +- +- /* finished, cursor is now in right position! */ +- +- len = gtk_text_get_length(GTK_TEXT(WINDOW_GUI(window)->text)); +- pos = gtk_editable_get_position(GTK_EDITABLE(WINDOW_GUI(window)->text)); +- +- word = NULL; +- if (pos < len) +- { +- text = gtk_editable_get_chars(GTK_EDITABLE(WINDOW_GUI(window)->text), pos < URL_MAX_LENGTH ? 0 : pos-URL_MAX_LENGTH, +- pos+URL_MAX_LENGTH > len ? len : pos+URL_MAX_LENGTH); +- len = spos = pos < URL_MAX_LENGTH ? pos : URL_MAX_LENGTH; +- if (!iswordcut(text[spos])) +- while (spos > 0 && !iswordcut(text[spos-1])) spos--; +- while (!iswordcut(text[len])) len++; len -= spos; +- +- word = g_new(gchar, len+1); +- memcpy(word, text+spos, len); word[len] = '\0'; +- g_free(text); +- } +- +- if (event->button == 3 && toggle_show_menubar) +- { +- /* create popup menu */ +- window_popupmenu_create(window->active, word, event); +- gtk_signal_emit_stop_by_name(GTK_OBJECT(widget), "button_press_event"); +- } +- else if (word != NULL) +- { +- /* left mouse button clicked */ +- word_clicked(window, word, event->type == GDK_2BUTTON_PRESS, event->button, NULL); +- } +- +- if (word != NULL) g_free(word); +- return 0; +-} +- +-static gint sig_topicentry_press(GtkWidget *entry, GdkEventButton *event) +-{ +- gboolean editable; +- +- g_return_val_if_fail(entry != NULL, 0); +- g_return_val_if_fail(event != NULL, 0); +- +- if (event->type == GDK_2BUTTON_PRESS) +- { +- editable = !(gboolean) GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(entry), "editable")); +- gtk_object_set_data(GTK_OBJECT(entry), "editable", GINT_TO_POINTER((gint) editable)); +- gtk_entry_set_editable(GTK_ENTRY(entry), editable); +- } +- +- return 0; +-} +- +-static void sig_topicentry_activated(GtkWidget *entry, WINDOW_REC *window) +-{ +- CHANNEL_REC *channel; +- +- g_return_if_fail(entry != NULL); +- g_return_if_fail(window != NULL); +- +- channel = window->active; +- if (channel == NULL || (!channel->chanop && channel->mode_optopic)) +- { +- /* can't change topic. */ +- gtk_entry_set_text(GTK_ENTRY(entry), +- (channel == NULL || channel->topic == NULL) ? +- "" : channel->topic); +- return; +- } +- +- signal_emit("command topic", 3, gtk_entry_get_text(GTK_ENTRY(entry)), +- window->active->server, window->active); +-} +- +-static void sig_modebutton_toggled(GtkToggleButton *button, gint mode) +-{ +- WINDOW_REC *window; +- NICK_REC *nick; +- GString *str; +- +- g_return_if_fail(button != NULL); +- if (gtk_object_get_data(GTK_OBJECT(button), "toggling")) return; +- +- window = gtk_object_get_data(GTK_OBJECT(button), "window"); +- g_return_if_fail(window->active != NULL); +- +- nick = nicklist_find(window->active, window->active->server->nick); +- if (!window->active->chanop) +- { +- /* can't change mode */ +- gtk_object_set_data(GTK_OBJECT(button), "toggling", GINT_TO_POINTER(TRUE)); +- gtk_toggle_button_set_active(button, !button->active); +- gtk_object_set_data(GTK_OBJECT(button), "toggling", GINT_TO_POINTER(FALSE)); +- return; +- } +- +- str = g_string_new(NULL); +- g_string_sprintf(str, "* %c%c", button->active ? '+' : '-', mode_flags[mode]); +- +- gtk_object_set_data(GTK_OBJECT(button), "toggling", GINT_TO_POINTER(TRUE)); +- signal_emit("command mode", 3, str->str, window->active->server, window->active); +- g_string_free(str, TRUE); +- gtk_object_set_data(GTK_OBJECT(button), "toggling", GINT_TO_POINTER(FALSE)); +-} +- +-WINDOW_REC *gui_window_create(MAIN_WINDOW_REC *parent) +-{ +- WINDOW_REC *rec; +- GUI_WINDOW_REC *gui; +- GtkWidget *hbox, *scrollwin, *label; +- GtkTooltips *tooltips; +- gint num; +- +- if (parent == NULL) parent = mainwindow_create(); +- +- rec = ui_window_create(); +- g_return_val_if_fail(rec != NULL, NULL); +- +- gui = g_new0(GUI_WINDOW_REC, 1); +- rec->gui_data = gui; +- gui->parent = parent; +- +- if (parent->children == NULL) parent->active = rec; +- parent->children = g_list_append(parent->children, rec); +- +- gui->window = gtk_vbox_new(FALSE, 2); +- gtk_container_border_width(GTK_CONTAINER(gui->window), 2); +- +- /* Add channel topic and modes */ +- gui->channelwidget = gtk_hbox_new(FALSE, 0); +- gtk_box_pack_start(GTK_BOX(gui->window), gui->channelwidget, FALSE, FALSE, 0); +- +- gui->serverlabel = gtk_label_new(""); +- gtk_box_pack_start(GTK_BOX(gui->channelwidget), gui->serverlabel, FALSE, FALSE, 0); +- +- gui->topicentry = gtk_entry_new(); +- gtk_entry_set_editable(GTK_ENTRY(gui->topicentry), FALSE); +- gtk_signal_connect(GTK_OBJECT(gui->topicentry), "button_press_event", +- GTK_SIGNAL_FUNC(sig_topicentry_press), rec); +- gtk_signal_connect(GTK_OBJECT(gui->topicentry), "activate", +- GTK_SIGNAL_FUNC(sig_topicentry_activated), rec); +- gtk_box_pack_start(GTK_BOX(gui->channelwidget), gui->topicentry, TRUE, TRUE, 3); +- +- tooltips = gtk_tooltips_new(); +- +- for (num = 0; num < 6; num++) +- { +- gchar str[2]; +- +- str[0] = toupper(mode_flags[num]); str[1] = '\0'; +- gui->modebuttons[num] = gtk_toggle_button_new_with_label(str); +- gtk_tooltips_set_tip(tooltips, gui->modebuttons[num], mode_tooltips[num], NULL); +- gtk_widget_set_usize(gui->modebuttons[num], 20, -1); +- gtk_object_set_data(GTK_OBJECT(gui->modebuttons[num]), "window", rec); +- gtk_signal_connect(GTK_OBJECT(gui->modebuttons[num]), "toggled", +- GTK_SIGNAL_FUNC(sig_modebutton_toggled), GINT_TO_POINTER(num)); +- gtk_box_pack_start(GTK_BOX(gui->channelwidget), gui->modebuttons[num], FALSE, FALSE, 0); +- } +- +- /* Text window */ +- hbox = gtk_hbox_new(FALSE, 3); +- gtk_box_pack_start(GTK_BOX(gui->window), hbox, TRUE, TRUE, 0); +- +- gui->zvt = toggle_use_zvt; +-#ifdef HAVE_GNOME +- if (toggle_use_zvt) +- { +- GtkWidget *scrollbar; +- +- gui->text = zvt_term_new(); +- gtk_signal_connect(GTK_OBJECT(gui->text), "button_press_event", +- GTK_SIGNAL_FUNC(sig_text_butpress_zvt), rec); +- zvt_term_set_scrollback(ZVT_TERM(gui->text), max_textwidget_lines); +- zvt_term_set_fonts(ZVT_TERM(gui->text), font_normal, font_bold); +- zvt_term_set_blink(ZVT_TERM(gui->text), FALSE); +- gtk_box_pack_start(GTK_BOX(hbox), gui->text, TRUE, TRUE, 0); +- +- scrollbar = gtk_vscrollbar_new(ZVT_TERM(gui->text)->adjustment); +- gtk_box_pack_start(GTK_BOX(hbox), scrollbar, FALSE, FALSE, 0); +- } +- else +-#endif +- { +- gui->text = gtk_text_new(NULL, NULL); +- gtk_signal_connect(GTK_OBJECT(gui->text), "button_press_event", +- GTK_SIGNAL_FUNC(sig_text_butpress), rec); +- gtk_text_set_word_wrap(GTK_TEXT(gui->text), TRUE); +- +- scrollwin = gtk_scrolled_window_new(NULL, NULL); +- gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin), +- GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); +- gtk_box_pack_start(GTK_BOX(hbox), scrollwin, TRUE, TRUE, 0); +- gtk_container_add(GTK_CONTAINER(scrollwin), gui->text); +- +- init_colors(gui->text); +- } +- gui_window_set_background(rec); +- +- gtk_widget_show_all(gui->window); +- +- /* Add nick list */ +- gui->nickscrollbox = gtk_scrolled_window_new(NULL, NULL); +- gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(gui->nickscrollbox), +- GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); +- gtk_box_pack_start(GTK_BOX(hbox), gui->nickscrollbox, FALSE, FALSE, 0); +- +- gui->nicklist = gtk_clist_new(1); +- gtk_container_add(GTK_CONTAINER(gui->nickscrollbox), gui->nicklist); +- gtk_widget_show(gui->nicklist); +- +- gtk_widget_set_usize(gui->nickscrollbox, 120, -1); +- +- label = gtk_label_new(_("(none)")); +- gtk_widget_show(label); +- +- if (g_list_first(parent->children)->next == NULL) +- { +- /* only one child, don't show the notebook tabs.. */ +- gtk_notebook_set_show_tabs(GTK_NOTEBOOK(parent->notebook), FALSE); +- gtk_notebook_set_show_border(GTK_NOTEBOOK(parent->notebook), FALSE); +- } +- else if (g_list_first(parent->children)->next->next == NULL) +- { +- /* two children, show the notebook tabs.. */ +- gtk_notebook_set_show_tabs(GTK_NOTEBOOK(parent->notebook), TRUE); +- gtk_notebook_set_show_border(GTK_NOTEBOOK(parent->notebook), TRUE); +- } +- +- gtk_notebook_append_page(GTK_NOTEBOOK(parent->notebook), gui->window, label); +- +-#ifdef HAVE_GNOME +- if (gui->zvt) +- { +- gtk_widget_realize(gui->text); +- init_zvt_colors(ZVT_TERM(gui->text)); +- vt_cursor_state(gui->text, 0); +- } +-#endif +- +- if (!toggle_show_menubar) +- { +- GtkWidget *popup; +- +- /* add popup menu created by mainwindow */ +- popup = gtk_object_get_data(GTK_OBJECT(parent->window), "popup"); +- if (popup != NULL) gnome_popup_menu_attach(popup, gui->text, parent); +- } +- +- gtk_widget_hide(gui->channelwidget); +- +- signal_emit("gui window created", 1, rec); +- return rec; +-} +- +-void gui_window_destroy(WINDOW_REC *window) +-{ +- MAIN_WINDOW_REC *parent; +- GUI_WINDOW_REC *gui; +- gint page; +- +- g_return_if_fail(window != NULL); +- if (WINDOW_GUI(window)->destroying) return; +- +- gui = WINDOW_GUI(window); +- parent = gui->parent; +- parent->children = g_list_remove(parent->children, window); +- +- signal_emit("gui window destroyed", 1, window); +- +- gui->destroying = TRUE; +- ui_window_destroy(window); +- +- page = gtk_notebook_page_num(GTK_NOTEBOOK(parent->notebook), gui->window); +- gtk_notebook_remove_page(GTK_NOTEBOOK(parent->notebook), page); +- +- if (gui->pixmap != NULL) g_free(gui->pixmap); +- g_free(gui); +- window->gui_data = NULL; +- +- if (parent->children == NULL) +- mainwindow_destroy(parent); +- else if (g_list_length(parent->children) == 1) +- { +- /* only one child left, hide the notebook tabs.. */ +- gtk_notebook_set_show_tabs(GTK_NOTEBOOK(parent->notebook), FALSE); +- gtk_notebook_set_show_border(GTK_NOTEBOOK(parent->notebook), FALSE); +- } +-} +- +-static gboolean gui_window_server_changed(WINDOW_REC *window) +-{ +- MAIN_WINDOW_REC *parent; +- SERVER_REC *server; +- gint num; +- +- g_return_val_if_fail(window != NULL, FALSE); +- +- parent = WINDOW_GUI(window)->parent; +- server = window->active->server; +- +- if (parent->usermodes[0] == NULL) return TRUE; +- +- for (num = 0; num < 4; num++) +- gtk_object_set_data(GTK_OBJECT(parent->usermodes[num]), "toggling", GINT_TO_POINTER(TRUE)); +- +- gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(parent->usermodes[0]), +- server == NULL ? FALSE : server->usermode_away); +- gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(parent->usermodes[1]), +- server == NULL ? FALSE : server->usermode_invisible); +- gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(parent->usermodes[2]), +- server == NULL ? FALSE : server->usermode_wallops); +- gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(parent->usermodes[3]), +- server == NULL ? FALSE : server->usermode_servernotes); +- +- for (num = 0; num < 4; num++) +- gtk_object_set_data(GTK_OBJECT(parent->usermodes[num]), "toggling", GINT_TO_POINTER(FALSE)); +- +- return TRUE; +-} +- +-static gboolean gui_windows_usermode_changed(SERVER_REC *server) +-{ +- GList *winlist; +- +- for (winlist = g_list_first(mainwindows); winlist != NULL; winlist = winlist->next) +- { +- MAIN_WINDOW_REC *rec = winlist->data; +- +- if (server == rec->active->active->server) +- signal_emit("window server changed", 1, rec->active); +- } +- +- return TRUE; +-} +- +-static gboolean cmd_clear(gchar *data, SERVER_REC *server, CHANNEL_REC *channel) +-{ +- WINDOW_REC *window; +- GUI_WINDOW_REC *gui; +- +- g_return_val_if_fail(channel != NULL, FALSE); +- +- window = CHANNEL_PARENT(channel); +- gui = WINDOW_GUI(window); +- +-#ifdef HAVE_GNOME +- if (gui->zvt) +- { +- zvt_term_set_scrollback(ZVT_TERM(gui->text), 0); +- zvt_term_feed(ZVT_TERM(gui->text), "\033[H\033[2J", 7); +- zvt_term_set_scrollback(ZVT_TERM(gui->text), max_textwidget_lines); +- } +- else +-#endif +- { +- g_list_free(gui->linepos); +- gui->linepos = NULL; +- gtk_text_set_point(GTK_TEXT(gui->text), 0); +- gtk_text_forward_delete(GTK_TEXT(gui->text), gtk_text_get_length(GTK_TEXT(gui->text))); +- } +- window->lines = 0; +- +- return TRUE; +-} +- +-static gboolean signal_window_focused(WINDOW_REC *window) +-{ +- MAIN_WINDOW_REC *mainwindow; +- GUI_WINDOW_REC *gui; +- CHANNEL_REC *channel; +- +- g_return_val_if_fail(window != NULL, FALSE); +- +- mainwindow = WINDOW_GUI(window)->parent; +- channel = window->active; +- +- gui = WINDOW_GUI(mainwindow->active); +- +- /* remove old extra menus */ +- if (mainwindow->extramenu != NULL) +- { +- window_menus_remove(mainwindow, mainwindow->extramenu); +- g_free(mainwindow->extramenu); +- mainwindow->extramenu = NULL; +- } +- if (channel == NULL) return TRUE; +- +- if (channel->type == CHANNEL_TYPE_CHANNEL) +- { +- /* Add channel menu */ +- mainwindow->extramenu = g_strdup(channel_menu[0].label); +- window_menus_insert(mainwindow, NULL, channel_menu, channel); +- gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(channel_submenu[2].widget), +- GTK_WIDGET_VISIBLE(gui->nickscrollbox)); +- gtk_widget_show(gui->channelwidget); +- } +- else +- { +- gtk_widget_hide(gui->nickscrollbox); +- gtk_widget_hide(gui->channelwidget); +- if (channel->type == CHANNEL_TYPE_QUERY) +- { +- /* Add query menu */ +- mainwindow->extramenu = g_strdup(query_menu[0].label); +- window_menus_insert(mainwindow, NULL, query_menu, channel); +- } +- } +- +- if (CHANNEL_GUI(channel)->servermenu) +- { +- /* change server selection */ +- gtk_option_menu_set_history(GTK_OPTION_MENU(mainwindow->servermenu), +- g_list_index(servers, channel->server)); +- gtk_widget_show(mainwindow->servermenu); +- } +- else +- gtk_widget_hide(mainwindow->servermenu); +- +- /* draw title bar */ +- signal_emit("channel topic changed", 1, window->active); +- +- return TRUE; +-} +- +-static gboolean gui_windows_setup_changed(void) +-{ +- GList *tmp; +- +- for (tmp = g_list_first(windows); tmp != NULL; tmp = tmp->next) +- { +- WINDOW_REC *rec = tmp->data; +- +- gui_window_set_background(rec); +-#ifdef HAVE_GNOME +- if (WINDOW_GUI(rec)->zvt) +- { +- zvt_term_set_fonts(ZVT_TERM(WINDOW_GUI(rec)->text), font_normal, font_bold); +- init_zvt_colors(ZVT_TERM(WINDOW_GUI(rec)->text)); +- } +-#endif +- } +- +- return TRUE; +-} +- +-static gboolean gui_server_looking(SERVER_REC *server) +-{ +- GList *tmp, *sub; +- +- g_return_val_if_fail(server != NULL, FALSE); +- +- /* try to keep some server assigned to server menus.. */ +- for (tmp = g_list_first(windows); tmp != NULL; tmp = tmp->next) +- { +- WINDOW_REC *win = tmp->data; +- gboolean changed; +- +- changed = FALSE; +- for (sub = g_list_first(win->channels); sub != NULL; sub = sub->next) +- { +- CHANNEL_REC *chan = sub->data; +- +- if (chan->server == NULL) +- { +- chan->server = server; +- if (!changed) +- signal_emit("window server changed", 1, win); +- changed = TRUE; +- } +- } +- } +- +- return TRUE; +-} +- +-void gui_windows_init(void) +-{ +- signal_add("setup changed", (SIGNAL_FUNC) gui_windows_setup_changed); +- signal_add("user mode changed", (SIGNAL_FUNC) gui_windows_usermode_changed); +- signal_add("window server changed", (SIGNAL_FUNC) gui_window_server_changed); +- signal_add("window focused", (SIGNAL_FUNC) signal_window_focused); +- signal_add("command clear", (SIGNAL_FUNC) cmd_clear); +- signal_add("server looking", (SIGNAL_FUNC) gui_server_looking); +-} +- +-void gui_windows_deinit(void) +-{ +- signal_remove("setup changed", (SIGNAL_FUNC) gui_windows_setup_changed); +- signal_remove("user mode changed", (SIGNAL_FUNC) gui_windows_usermode_changed); +- signal_remove("window server changed", (SIGNAL_FUNC) gui_window_server_changed); +- signal_remove("window focused", (SIGNAL_FUNC) signal_window_focused); +- signal_remove("command clear", (SIGNAL_FUNC) cmd_clear); +- signal_remove("server looking", (SIGNAL_FUNC) gui_server_looking); +-} +diff -Nru irssi-0.7.11/src/gui-gnome/gui-windows.h irssi-0.7.11-new/src/gui-gnome/gui-windows.h +--- irssi-0.7.11/src/gui-gnome/gui-windows.h Thu May 13 13:24:58 1999 ++++ irssi-0.7.11-new/src/gui-gnome/gui-windows.h Thu Jan 1 02:00:00 1970 +@@ -1,44 +0,0 @@ +-#ifndef __GUI_WINDOWS_H +-#define __GUI_WINDOWS_H +- +-#define WINDOW_GUI(a) ((GUI_WINDOW_REC *) ((a)->gui_data)) +- +-typedef struct +-{ +- MAIN_WINDOW_REC *parent; +- +- GtkWidget *window; +- GtkWidget *text; +- +- gboolean zvt; /* text is a zvt widget */ +- gchar *pixmap; /* current background pixmap */ +- +- GtkWidget *channelwidget; +- GtkWidget *serverlabel; +- GtkWidget *topicentry; +- GtkWidget *modebuttons[6]; +- +- /* nicklist */ +- GtkWidget *nickscrollbox; +- GtkWidget *nicklist; +- GdkPixmap *op_pixmap, *voice_pixmap; +- GdkBitmap *op_mask, *voice_mask; +- +- GList *linepos; +- gint lastlinelen; +- +- GtkWidget *snapshot; +- gboolean destroying; +- gfloat sb_value; /* to fix those scrollbar problems... */ +-} +-GUI_WINDOW_REC; +- +-void gui_windows_init(void); +-void gui_windows_deinit(void); +- +-WINDOW_REC *gui_window_create(MAIN_WINDOW_REC *parent); +-void gui_window_destroy(WINDOW_REC *window); +- +-void gui_window_set_background_pixmap(WINDOW_REC *window, gchar *path); +- +-#endif