diff options
-rw-r--r-- | .cvsignore | 31 | ||||
-rw-r--r-- | AUTHORS | 1 | ||||
-rw-r--r-- | COMMANDS | 383 | ||||
-rw-r--r-- | Makefile.am | 46 | ||||
-rw-r--r-- | NEWS | 0 | ||||
-rw-r--r-- | README | 82 | ||||
-rw-r--r-- | README-HEBREW | 43 | ||||
-rw-r--r-- | TODO | 140 | ||||
-rw-r--r-- | acconfig.h | 25 | ||||
-rwxr-xr-x | autogen.sh | 21 | ||||
-rw-r--r-- | colorless.theme | 101 | ||||
-rw-r--r-- | config | 36 | ||||
-rw-r--r-- | configure.in | 363 | ||||
-rwxr-xr-x | file2header.sh | 5 | ||||
-rw-r--r-- | irssi.desktop | 6 | ||||
-rw-r--r-- | irssi.gnorba | 5 | ||||
-rw-r--r-- | irssi.spec.in | 87 | ||||
-rw-r--r-- | servertest/.cvsignore | 8 | ||||
-rw-r--r-- | servertest/Makefile.am | 13 | ||||
-rw-r--r-- | servertest/server.c | 463 | ||||
-rw-r--r-- | src/.cvsignore | 2 | ||||
-rw-r--r-- | src/Makefile.am | 17 | ||||
-rw-r--r-- | src/common-setup.h | 125 | ||||
-rw-r--r-- | src/common.h | 114 | ||||
-rw-r--r-- | src/irssi-plugin-gui.h | 11 | ||||
-rw-r--r-- | src/irssi-plugin.h | 9 | ||||
-rw-r--r-- | src/signal.doc | 178 | ||||
-rw-r--r-- | stamp.h.in | 0 | ||||
-rw-r--r-- | window-views-patch.diff | 2672 |
29 files changed, 4987 insertions, 0 deletions
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 <address>[:port[:password]] + + Connect to specified server + +DISCONNECT <* / tag> [message] + + Disconnect from server + +SERVER <address>[: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 <channel> [key] [, channel...] + + Join to channel(s) + +PART [channel] [message] + + Leave from channel + +QUERY <nick> + + Create query window + +UNQUERY <nick> + + Close query window + +MSG <nick/channel> <message> + + Send message to nick/channel + +ME <message> + + Send action to channel (/me thinks..) + +NOTICE <nick/channel> <message> + + Send notice to nick/channel + +WHOIS [server/nick] <nick> + + Send WHOIS query, you can also specify from what server to ask the + information. If you type the nick twice it will ask from the same + server what nick is using. + +AWAY [message] + + Sets yourself away/unaway + +AWAYALL [message] + + Sets yourself away/unaway to all connected servers + +WHO <nick/channel> + + Show WHO list + +NAMES [channel] + + List nicks (in channel) + + + ** Bit more advanced commands + + +MODE <channel/nick> <mode> + + Get/set channel/nick mode. + + Get channel modes: + b - Get ban list + e - Get ban exception list + I - Get invite list + + Set channel modes (use +/- before these): + b *!ban@mask - Set/remove ban + e *!ban@mask - Set/remove ban exception + I *!ban@mask - Set/remove channel invite + o nick - Set/remove op status + v nick - Set/remove voice status + l limit - Set remove max. people limit in channel + k key - Set/remove channel key + s - Secret + p - Private + m - Moderated + i - Invite only + n - No external messages + t - Only ops can change topic + + User modes: + i - Invisible + w - Show wallops + s - Show server notices + +TOPIC [channel] [topic] + + Get/set channel topic + +INVITE <nick> [channel] + + Invite nick to channel + +CTCP <nick/channel> <command> + + Send CTCP request to nick/channel (PING, VERSION, ..) + +NCTCP <nick/channel> <reply> + + Send CTCP reply to nick/channel + +PING <nick> + + Send CTCP PING to nick and tell how long it took to receive the reply + +ISON [nick [nick...]] + + Ask if nicks are in IRC. + +WALL [channel] <message> + + Send notice message to all operators in channel. + +OP, DEOP, VOICE, DEVOICE [channel] [nick [nick...] + + Op/deop/voice/devoice nick(s) in channel + +KICK [channel] <nick> <reason> + + Kick nick from channel + +KICKBAN [channel] <nick> <reason> + + Kick+ban nick from channel + +KNOCKOUT [secs] <nick> <reason> + + Kick+ban+delay (default to 5min)+unban + +BAN [channel] [nick [nick...]] + + Ban nick(s) in channel + +UNBAN [channel] [mask [mask...]] + + Remove ban(s) from channel + +BANSTAT [channel] + + List bans and ban exceptions in channel + +BANTYPE <normal/host/domain/custom> + + Set ban type: + + Normal - *!user@*.domain.net + Host - *!*@host.domain.net + Domain - *!*@*.domain.net + Custom [nick] [user] [host] [domain] + eg. /bantype custom nick domain - nick!*@*.domain.net + eg. /bantype custom user host - *!user@host.domain.net + +INVITELIST [channel] + + List invites (+I) in channel + +VERSION [server] + + Displays irssi version and asks IRC server's version + +VER [nick/channel] + + Sends CTCP VERSION request to nick/channel + +SV [nick/channel] + + Sends irssi version text to nick/channel + +KILL <nick> <message> + + Kill nick from irc network. [irc ops only] + +WALLOPS <message> + + Write wallops message. [irc ops only] + +QUOTE <message> + + Send raw data to irc server - DON'T USE THIS unless you really know + what you're doing! + + + ** DCC handling + + +DCC + + List DCC connections (same as DCC LIST) + +DCC CHAT <nick> + + Open DCC chat + +DCC SEND <nick> <filename> + + Send file to nick + +DCC GET <nick> [filename] + + Get file offered by nick + +DCC RESUME <nick> [filename] + + (MIRC) Resume getting file offered by nick + +DCC CLOSE <type> <nick> [filename] + + Close DCC connection + +DCC LIST + + List DCC connections + +MIRCDCC [n] + + Set MIRC style CTCPs on/off + + + ** User interface handling + + +WINDOW <NEW/CLOSE/SERVER/PREV/NEXT/GOTO/LEVEL> + + NEW [HIDDEN/TAB] + + Create new window (in tab) + + CLOSE + + Close the current window + + SERVER <tag> + + Change which server to use in current window + + PREV/NEXT/GOTO <N> + + Go to previous/next/Nth window + + LEVEL <[+/-]pub/msgs/...> + + Change window level, eg. + /window level msgs - creates messages window + /window level all -msgs - creates status window + +CLEAR + + Clear screen + +ECHO <text> + + Print text to screen + +MODES + + Open channel modes dialog (GTK/GNOME version) + +GWHOIS <nick> + + Display WHOIS information in dialog (GTK/GNOME version) + +LAST [-pub -msgs...] <text> + + Display (only public/msgs/..) lines where <text> appears + (Text version only) + + + ** Configuration + + +SET [key [=value / [key [key..]] + + Get/set configuration + +ALIAS, UNALIAS <alias> [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 <mask> [level [level..]] + + Ignore/unignore specified level(s) or everything from nick + +NOTIFY <mask> [ircnet [ircnet..]] + + Add mask (nick) to notify list for specified ircnets.. + +UNNOTIFY <mask> + + Remove mask from notify list. + +LOG <CREATE/CLOSE/START/STOP/LIST> + + CREATE <filename> [<+/->level ...] [#channel/nick [ + [<+/->level ...] ...] + + Create and start logging to file + + Example: /log create mylog -all +msgs #linux +chan +public + (or simply #linux +all logs everything that appears in #linux + window). + + CLOSE <filename> + + Close log and remove from configuration + + START <filename> + + Start logging to file + + STOP <filename> + + Stop logging to file + + LIST + + List logs. + +LOAD <plugin> [arguments] + + Load plugin + +UNLOAD <plugin> + + Unload plugin + 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 <internationalization support> +#SUBDIRS = po intl macros support # <your subdirs here> +## 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 @@ -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=<path>. 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 <rtzur@shani.net> @@ -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 (<newline>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"; + }; + }; +} @@ -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 <rhcn-bugs@redhat.com> +Vendor: Timo Sirainen <cras@irccrew.org> +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 <jtraub@dragoncat.net> +- Updated to 0.7.15 sources +- Fixed config stuff that changed since last version. + +* Thu Mar 25 1999 JT Traub <jtraub@dragoncat.net> +- Updated sources + +* Sat Mar 13 1999 JT Traub <jtraub@dragoncat.net> +- Updated to 0.7.4 sources +- Added the irssi-text bin to the package. + +* Mon Feb 22 1999 JT Traub <jtraub@dragoncat.net> +- Made spec file compliant with RHCN guidelines. + +* Sun Feb 13 1999 JT Traub <jtraub@dragoncat.net> +- Updated to 0.6.0 sources. +- Cleaned up spec file to make it relocatable on install + +* Sun Feb 7 1999 JT Traub <jtraub@dragoncat.net> +- Updated sources to 0.5.0 +- removed obsolete patch lines + +* Sat Feb 3 1999 JT Traub <jtraub@dragoncat.net> +- Updated sources to 0.4.0 +- Deleted old patch line + +* Sat Jan 30 1999 JT Traub <jtraub@dragoncat.net> +- 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 <jtraub@dragoncat.net> +- Upgraded to 0.3.5 + +* Sun Jan 24 1999 JT Traub <jtraub@dragoncat.net> +- First attempt at building this + +%description +Irssi is a GTK based GUI IRC client by Timo Sirainen <cras@irccrew.org>. +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 <common.h> + +#include <irc-base/network.h> + +#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 <cras@irccrew.org>" +#define IRSSI_WEBSITE "http://xlife.dhs.org/irssi/" + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdarg.h> +#include <ctype.h> +# ifdef HAVE_STRING_H +#include <string.h> +#endif +#ifdef HAVE_STDLIB_H +# include <stdlib.h> +#endif +#include <errno.h> +#include <time.h> + +#include <sys/types.h> +#include <sys/time.h> +#include <sys/stat.h> +#include <sys/wait.h> +#include <sys/utsname.h> + +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif +#ifdef HAVE_DIRENT_H +# include <dirent.h> +#endif +#include <fcntl.h> + +#ifdef HAVE_SOCKS_H +#include <socks.h> +#endif + +#include <netdb.h> +#include <sys/socket.h> +#include <signal.h> +#include <sys/signal.h> +#include <sys/param.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include <glib.h> +#include <gmodule.h> + +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 "<cmd>, 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 "<cmd>, 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 "<cmd>, 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 "<cmd>, 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"<cmd>, gchar *args, DCC_REC + "default dcc ctcp", gchar *args, DCC_REC + "dcc unknown ctcp", gchar *args, gchar *sender, gchar *sendaddr + + "dcc reply"<cmd>, gchar *args, DCC_REC + "default dcc reply"<cmd>, 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 --- /dev/null +++ b/stamp.h.in 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 |