summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSøren Sandmann Pedersen <ssp@redhat.com>2011-01-23 14:10:23 -0500
committerSøren Sandmann Pedersen <ssp@redhat.com>2011-01-23 14:10:23 -0500
commit6a27897a9b966c5c28f593cc4ad47a19e8f98752 (patch)
tree0562288713f2d8d3cf9679d8097297b0fa35a8c8
initial checkinHEADmaster
-rw-r--r--channel-buffer.c132
-rw-r--r--channel-buffer.h32
-rw-r--r--chatterbox.glade2297
-rw-r--r--irc.c931
-rw-r--r--irc.h70
-rw-r--r--main.c41
6 files changed, 3503 insertions, 0 deletions
diff --git a/channel-buffer.c b/channel-buffer.c
new file mode 100644
index 0000000..5390439
--- /dev/null
+++ b/channel-buffer.c
@@ -0,0 +1,132 @@
+/*
+ * This data structure purpose in life is to maintain a GtkTextBuffer
+ * with these properies:
+ *
+ * - The channel is not editable:
+ *
+ * - There is an area after channel area where the user can enter new
+ * messages
+ *
+ * - You can add messages, and they will be displayed in gray in the
+ * channel area.
+ *
+ * - You can /commit/ messages which means they will turn black
+ *
+ * - Messages will be added to the channel area in the order they
+ * are committed
+ *
+ * - The user displays as either
+ *
+ * - The users nickname, followed by a colon, followed by a space,
+ * followed by the text that the user has entered in a normal
+ * typeface
+ *
+ * or
+ *
+ * - The users nickname in italic, followed by a apsce, followed
+ * by the text the user has entered, in italics
+ *
+ * The first style is used for nomal messages, the second for
+ * 'third person messages', ie. 'ssp thinks blah blah .... '
+ * as opposed to 'ssp: blaah blah blah'
+ *
+ * The channel buffer also maintains a topic
+ *
+ */
+#include "channel-buffer.h"
+
+struct ChannelBuffer
+{
+ const char *user_nick;
+
+ GtkTextBuffer *text_buffer;
+ GtkTextTag *nick_tag;
+
+ GtkTextMark *mid_point;
+ GtkTextMark *nick_end;
+};
+
+static void
+set_mid_point_gravity (ChannelBuffer *buffer,
+ gboolean left_gravity)
+{
+ GtkTextIter iter;
+
+ if (gtk_text_mark_get_left_gravity (buffer->mid_point) == left_gravity)
+ return;
+
+ gtk_text_buffer_get_iter_at_mark (buffer->text_buffer, &iter,
+ buffer->mid_point);
+ gtk_text_buffer_delete_mark (buffer->text_buffer, buffer->midpoint);
+ buffer->mid_point = gtk_text_buffer_create_mark (
+ buffer->text_buffer, "mid_point", &iter, lelft_gravity);
+}
+
+static void
+channel_buffer_change_nick_text (ChannelBuffer *buffer,
+ const char *text,
+ gboolean italic)
+{
+
+ gtk_text_buffer_insert (buffer->text_buffer, &iter,
+ buffer->user_nick, -1);
+}
+
+ChannelBuffer *
+channel_buffer_new (const char *user_nick)
+{
+ ChannelBuffer *buffer = g_new (ChannelBuffer, 1);
+ GtkTextIter iter;
+
+ g_return_val_if_fail (g_utf8_validate (user_nick, -1, NULL), NULL);
+
+ buffer->user_nick = g_strdup (user_nick);
+
+ /* TextBuffer stuff */
+ buffer->text_buffer = gtk_text_buffer_new (NULL);
+ buffer->nick_tag =
+ gtk_text_buffer_create_tag (buffer->text_buffer, "nick",
+ "weight", PANGO_WEIGHT_BOLD,
+ NULL);
+
+ gtk_text_buffer_get_start_iter (buffer->text_buffer, &iter);
+
+ buffer->mid_point = gtk_text_buffer_create_mark (
+ buffer->text_buffer, "nick_begin", &iter, FALSE);
+
+ buffer->nick_end = gtk_text_buffer_create_mark (
+ buffer->text_buffer, "nick_end", &iter, TRUE);
+
+ gtk_text_buffer_get_start_iter (buffer->text_buffer, &iter);
+
+ buffer->channel_area_begin = gtk_text_buffer_create_mark (
+ buffer->text_buffer, "channel_area_begin", &iter, TRUE);
+
+ buffer->channel_area_end = gtk_text_buffer_create_mark (
+ buffer->text_buffer, "channel_area_end", &iter, FALSE);
+
+ return buffer;
+}
+
+void channel_buffer_free (ChannelBuffer *buffer);
+ChannelMessage *channel_buffer_add_message (ChannelBuffer *buffer,
+ const char *nick,
+ const char *message);
+void channel_buffer_commit_message (ChannelMessage *message);
+void channel_buffer_set_user_nick (ChannelBuffer *buffer,
+ const char *nick);
+const char * channel_buffer_get_user_text (ChannelBuffer *buffer);
+void channel_buffer_set_action_mode (ChannelBuffer *buffer,
+ gboolean action_mode);
+gboolean channel_buffer_get_action_mode (ChannelBuffer *buffer);
+#if 0
+void channel_buffer_set_topic (ChannelBuffer *buffer,
+ const char *topic);
+const char * channel_buffer_get_topic (ChannelBuffer *buffer);
+#endif
+
+GtkTextBuffer *
+channel_buffer_get_text_buffer (ChannelBuffer *buffer)
+{
+ return buffer->text_buffer;
+}
diff --git a/channel-buffer.h b/channel-buffer.h
new file mode 100644
index 0000000..416c761
--- /dev/null
+++ b/channel-buffer.h
@@ -0,0 +1,32 @@
+#include <gtk/gtk.h>
+
+typedef struct ChannelBuffer ChannelBuffer;
+typedef struct ChannelMessage ChannelMessage;
+
+typedef union
+{
+
+} ChannelBufferEvent;
+
+typedef void (* ChannelBufferEventFunc) (ChannelBuffer *buffer,
+ const ChannelBufferEvent *event);
+
+ChannelBuffer *channel_buffer_new ();
+void channel_buffer_free (ChannelBuffer *buffer);
+ChannelMessage *channel_buffer_add_message (ChannelBuffer *buffer,
+ const char *nick,
+ const char *message);
+void channel_buffer_commit_message (ChannelMessage *message);
+void channel_buffer_set_user_nick (ChannelBuffer *buffer,
+ const char *nick);
+const char * channel_buffer_get_user_text (ChannelBuffer *buffer);
+void channel_buffer_set_action_mode (ChannelBuffer *buffer,
+ gboolean action_mode);
+gboolean channel_buffer_get_action_mode (ChannelBuffer *buffer);
+#if 0
+void channel_buffer_set_topic (ChannelBuffer *buffer,
+ const char *topic);
+const char * channel_buffer_get_topic (ChannelBuffer *buffer);
+#endif
+
+GtkTextBuffer *channel_buffer_get_text_buffer (ChannelBuffer *buffer);
diff --git a/chatterbox.glade b/chatterbox.glade
new file mode 100644
index 0000000..d487cf8
--- /dev/null
+++ b/chatterbox.glade
@@ -0,0 +1,2297 @@
+<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
+<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
+
+<glade-interface>
+<requires lib="gnome"/>
+
+<widget class="GtkWindow" id="startup-window">
+ <property name="border_width">12</property>
+ <property name="visible">True</property>
+ <property name="title" translatable="yes">Connecting</property>
+ <property name="type">GTK_WINDOW_TOPLEVEL</property>
+ <property name="window_position">GTK_WIN_POS_NONE</property>
+ <property name="modal">False</property>
+ <property name="resizable">True</property>
+ <property name="destroy_with_parent">False</property>
+ <property name="decorated">True</property>
+ <property name="skip_taskbar_hint">False</property>
+ <property name="skip_pager_hint">False</property>
+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
+ <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+
+ <child>
+ <widget class="GtkVBox" id="vbox3">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">18</property>
+
+ <child>
+ <widget class="GtkVBox" id="vbox4">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">12</property>
+
+ <child>
+ <widget class="GtkHBox" id="hbox1">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">12</property>
+
+ <child>
+ <widget class="GtkHBox" id="hbox2">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">6</property>
+
+ <child>
+ <widget class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;b&gt;_Server:&lt;/b&gt;</property>
+ <property name="use_underline">True</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="mnemonic_widget">combo-entry1</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkCombo" id="combo1">
+ <property name="visible">True</property>
+ <property name="value_in_list">False</property>
+ <property name="allow_empty">True</property>
+ <property name="case_sensitive">False</property>
+ <property name="enable_arrow_keys">True</property>
+ <property name="enable_arrows_always">False</property>
+
+ <child internal-child="entry">
+ <widget class="GtkEntry" id="combo-entry1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">True</property>
+ <property name="visibility">True</property>
+ <property name="max_length">0</property>
+ <property name="text" translatable="yes">irc.gimp.org</property>
+ <property name="has_frame">True</property>
+ <property name="invisible_char" translatable="yes">*</property>
+ <property name="activates_default">False</property>
+ </widget>
+ </child>
+
+ <child internal-child="list">
+ <widget class="GtkList" id="combo-list1">
+ <property name="visible">True</property>
+ <property name="selection_mode">GTK_SELECTION_BROWSE</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHBox" id="hbox3">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">6</property>
+
+ <child>
+ <widget class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;b&gt;_Port:&lt;/b&gt;</property>
+ <property name="use_underline">True</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="mnemonic_widget">entry2</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkEntry" id="entry2">
+ <property name="width_request">91</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">True</property>
+ <property name="visibility">True</property>
+ <property name="max_length">0</property>
+ <property name="text" translatable="yes">6667</property>
+ <property name="has_frame">True</property>
+ <property name="invisible_char" translatable="yes">*</property>
+ <property name="activates_default">False</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkVBox" id="vbox1">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">6</property>
+
+ <child>
+ <widget class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;b&gt;_Channels&lt;/b&gt;</property>
+ <property name="use_underline">True</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkScrolledWindow" id="scrolledwindow2">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_ALWAYS</property>
+ <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property>
+ <property name="shadow_type">GTK_SHADOW_IN</property>
+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+ <child>
+ <widget class="GtkTreeView" id="treeview2">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="headers_visible">True</property>
+ <property name="rules_hint">False</property>
+ <property name="reorderable">False</property>
+ <property name="enable_search">True</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHButtonBox" id="hbuttonbox1">
+ <property name="visible">True</property>
+ <property name="layout_style">GTK_BUTTONBOX_END</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkButton" id="button1">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">_Connect</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+</widget>
+
+<widget class="GtkWindow" id="main-window">
+ <property name="visible">True</property>
+ <property name="title" translatable="yes">irc.gimp.org</property>
+ <property name="type">GTK_WINDOW_TOPLEVEL</property>
+ <property name="window_position">GTK_WIN_POS_NONE</property>
+ <property name="modal">False</property>
+ <property name="resizable">True</property>
+ <property name="destroy_with_parent">False</property>
+ <property name="decorated">True</property>
+ <property name="skip_taskbar_hint">False</property>
+ <property name="skip_pager_hint">False</property>
+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
+ <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+
+ <child>
+ <widget class="GtkVBox" id="vbox5">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkMenuBar" id="menubar1">
+ <property name="visible">True</property>
+
+ <child>
+ <widget class="GtkMenuItem" id="menuitem1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Chat</property>
+ <property name="use_underline">True</property>
+
+ <child>
+ <widget class="GtkMenu" id="menuitem1_menu">
+
+ <child>
+ <widget class="GtkImageMenuItem" id="join_channel1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Join Channel...</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_join_channel1_activate" last_modification_time="Tue, 03 Sep 2002 19:14:39 GMT"/>
+ <accelerator key="J" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+
+ <child internal-child="image">
+ <widget class="GtkImage" id="image28">
+ <property name="visible">True</property>
+ <property name="stock">gtk-new</property>
+ <property name="icon_size">1</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkImageMenuItem" id="leave_channel1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Leave Channel...</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_leave_channel1_activate" last_modification_time="Mon, 11 Nov 2002 23:51:32 GMT"/>
+ <accelerator key="w" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+
+ <child internal-child="image">
+ <widget class="GtkImage" id="image29">
+ <property name="visible">True</property>
+ <property name="stock">gtk-close</property>
+ <property name="icon_size">1</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkMenuItem" id="separator4">
+ <property name="visible">True</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkMenuItem" id="servers1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Servers...</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_servers1_activate" last_modification_time="Tue, 03 Sep 2002 19:14:39 GMT"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkMenuItem" id="separator3">
+ <property name="visible">True</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkImageMenuItem" id="save1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">gtk-quit</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_save1_activate" last_modification_time="Tue, 03 Sep 2002 19:14:39 GMT"/>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkMenuItem" id="menuitem2">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Edit</property>
+ <property name="use_underline">True</property>
+
+ <child>
+ <widget class="GtkMenu" id="menuitem2_menu">
+
+ <child>
+ <widget class="GtkImageMenuItem" id="cut1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">gtk-cut</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_cut1_activate" last_modification_time="Tue, 03 Sep 2002 19:14:39 GMT"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkImageMenuItem" id="copy1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">gtk-copy</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_copy1_activate" last_modification_time="Tue, 03 Sep 2002 19:14:39 GMT"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkImageMenuItem" id="paste1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">gtk-paste</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_paste1_activate" last_modification_time="Tue, 03 Sep 2002 19:14:39 GMT"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkImageMenuItem" id="delete1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">gtk-clear</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_delete1_activate" last_modification_time="Tue, 03 Sep 2002 19:14:39 GMT"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkMenuItem" id="separator1">
+ <property name="visible">True</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkImageMenuItem" id="find_1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Find ...</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_find_1_activate" last_modification_time="Mon, 11 Nov 2002 23:46:21 GMT"/>
+ <accelerator key="F" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+
+ <child internal-child="image">
+ <widget class="GtkImage" id="image30">
+ <property name="visible">True</property>
+ <property name="stock">gtk-find</property>
+ <property name="icon_size">1</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkImageMenuItem" id="find_next1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Find Ne_xt</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_find_next1_activate" last_modification_time="Mon, 11 Nov 2002 23:46:21 GMT"/>
+ <accelerator key="G" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+
+ <child internal-child="image">
+ <widget class="GtkImage" id="image31">
+ <property name="visible">True</property>
+ <property name="stock">gtk-find</property>
+ <property name="icon_size">1</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkMenuItem" id="separator2">
+ <property name="visible">True</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkImageMenuItem" id="preferences1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">gtk-preferences</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_preferences1_activate" last_modification_time="Mon, 11 Nov 2002 23:47:06 GMT"/>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkMenuItem" id="menuitem3">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Action</property>
+ <property name="use_underline">True</property>
+
+ <child>
+ <widget class="GtkMenu" id="menuitem3_menu">
+
+ <child>
+ <widget class="GtkMenuItem" id="talk_in_the_third_person1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Talk in the Third Person...</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_talk_in_the_third_person1_activate" last_modification_time="Mon, 11 Nov 2002 23:55:47 GMT"/>
+ <accelerator key="m" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkMenuItem" id="change_nickname1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Change _Nickname...</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_change_nickname1_activate" last_modification_time="Mon, 11 Nov 2002 23:55:47 GMT"/>
+ <accelerator key="n" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkMenuItem" id="separator5">
+ <property name="visible">True</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkCheckMenuItem" id="marked_away1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Marked A_way</property>
+ <property name="use_underline">True</property>
+ <property name="active">False</property>
+ <signal name="activate" handler="on_marked_away1_activate" last_modification_time="Mon, 11 Nov 2002 23:55:47 GMT"/>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkMenuItem" id="menuitem4">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Help</property>
+ <property name="use_underline">True</property>
+
+ <child>
+ <widget class="GtkMenu" id="menuitem4_menu">
+
+ <child>
+ <widget class="GtkImageMenuItem" id="about1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">gnome-stock-about</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_about1_activate" last_modification_time="Tue, 03 Sep 2002 19:14:39 GMT"/>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkNotebook" id="notebook1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="show_tabs">True</property>
+ <property name="show_border">True</property>
+ <property name="tab_pos">GTK_POS_TOP</property>
+ <property name="scrollable">False</property>
+ <property name="enable_popup">False</property>
+
+ <child>
+ <widget class="GtkVBox" id="vbox6">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkHPaned" id="hpaned1">
+ <property name="border_width">6</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="position">0</property>
+
+ <child>
+ <widget class="GtkVBox" id="vbox7">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">6</property>
+
+ <child>
+ <widget class="GtkHBox" id="hbox8">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">6</property>
+
+ <child>
+ <widget class="GtkLabel" id="label11">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Topic:</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkScrolledWindow" id="scrolledwindow9">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
+ <property name="vscrollbar_policy">GTK_POLICY_NEVER</property>
+ <property name="shadow_type">GTK_SHADOW_IN</property>
+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+ <child>
+ <widget class="GtkTextView" id="textview3">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">False</property>
+ <property name="overwrite">False</property>
+ <property name="accepts_tab">True</property>
+ <property name="justification">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap_mode">GTK_WRAP_NONE</property>
+ <property name="cursor_visible">False</property>
+ <property name="pixels_above_lines">0</property>
+ <property name="pixels_below_lines">0</property>
+ <property name="pixels_inside_wrap">0</property>
+ <property name="left_margin">0</property>
+ <property name="right_margin">0</property>
+ <property name="indent">0</property>
+ <property name="text" translatable="yes"></property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="button4">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">_Change Topic...</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkScrolledWindow" id="scrolledwindow3">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
+ <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property>
+ <property name="shadow_type">GTK_SHADOW_IN</property>
+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+ <child>
+ <widget class="GtkTextView" id="textview5">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">False</property>
+ <property name="overwrite">False</property>
+ <property name="accepts_tab">True</property>
+ <property name="justification">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap_mode">GTK_WRAP_NONE</property>
+ <property name="cursor_visible">False</property>
+ <property name="pixels_above_lines">0</property>
+ <property name="pixels_below_lines">0</property>
+ <property name="pixels_inside_wrap">0</property>
+ <property name="left_margin">0</property>
+ <property name="right_margin">0</property>
+ <property name="indent">0</property>
+ <property name="text" translatable="yes"></property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="shrink">True</property>
+ <property name="resize">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkVBox" id="vbox10">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkVBox" id="vbox14">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">4</property>
+
+ <child>
+ <widget class="GtkScrolledWindow" id="scrolledwindow3">
+ <property name="height_request">0</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
+ <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="shadow_type">GTK_SHADOW_IN</property>
+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+ <child>
+ <widget class="GtkTreeView" id="treeview3">
+ <property name="border_width">6</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="headers_visible">True</property>
+ <property name="rules_hint">False</property>
+ <property name="reorderable">False</property>
+ <property name="enable_search">True</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="shrink">True</property>
+ <property name="resize">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="tab_expand">False</property>
+ <property name="tab_fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHBox" id="hbox15">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkImage" id="image37">
+ <property name="visible">True</property>
+ <property name="stock">gnome-stock-about</property>
+ <property name="icon_size">1</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label4">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;b&gt;&lt;span color=&quot;#004784&quot;&gt;#gtk&lt;/span&gt;&lt;/b&gt;</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">6</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="type">tab</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHPaned" id="hpaned2">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="position">0</property>
+
+ <child>
+ <widget class="GtkVBox" id="vbox8">
+ <property name="border_width">6</property>
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">6</property>
+
+ <child>
+ <widget class="GtkScrolledWindow" id="scrolledwindow4">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
+ <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property>
+ <property name="shadow_type">GTK_SHADOW_IN</property>
+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+ <child>
+ <widget class="GtkTextView" id="textview2">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">True</property>
+ <property name="overwrite">False</property>
+ <property name="accepts_tab">True</property>
+ <property name="justification">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap_mode">GTK_WRAP_NONE</property>
+ <property name="cursor_visible">True</property>
+ <property name="pixels_above_lines">0</property>
+ <property name="pixels_below_lines">0</property>
+ <property name="pixels_inside_wrap">0</property>
+ <property name="left_margin">0</property>
+ <property name="right_margin">0</property>
+ <property name="indent">0</property>
+ <property name="text" translatable="yes"></property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHBox" id="hbox6">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">6</property>
+
+ <child>
+ <widget class="GtkLabel" id="label10">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;b&gt;sandmann:&lt;/b&gt;</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkEntry" id="entry4">
+ <property name="height_request">30</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">True</property>
+ <property name="visibility">True</property>
+ <property name="max_length">0</property>
+ <property name="text" translatable="yes"></property>
+ <property name="has_frame">True</property>
+ <property name="invisible_char" translatable="yes">*</property>
+ <property name="activates_default">False</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="button3">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-ok</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="shrink">True</property>
+ <property name="resize">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHBox" id="hbox7">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">12</property>
+
+ <child>
+ <widget class="GtkScrolledWindow" id="scrolledwindow5">
+ <property name="border_width">6</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
+ <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="shadow_type">GTK_SHADOW_IN</property>
+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+ <child>
+ <widget class="GtkTreeView" id="treeview4">
+ <property name="border_width">6</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="headers_visible">True</property>
+ <property name="rules_hint">False</property>
+ <property name="reorderable">False</property>
+ <property name="enable_search">True</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="shrink">True</property>
+ <property name="resize">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="tab_expand">False</property>
+ <property name="tab_fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHBox" id="hbox16">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkLabel" id="label21">
+ <property name="width_request">16</property>
+ <property name="height_request">16</property>
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"></property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label5">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">#gnome</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">6</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="type">tab</property>
+ </packing>
+ </child>
+
+ <child>
+ <placeholder/>
+ </child>
+
+ <child>
+ <widget class="GtkHBox" id="hbox17">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkLabel" id="label22">
+ <property name="width_request">16</property>
+ <property name="height_request">16</property>
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;b&gt;|&lt;/b&gt;</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label6">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;b&gt;#usability&lt;/b&gt;</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">6</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="type">tab</property>
+ </packing>
+ </child>
+
+ <child>
+ <placeholder/>
+ </child>
+
+ <child>
+ <widget class="GtkHBox" id="hbox18">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkLabel" id="label23">
+ <property name="width_request">16</property>
+ <property name="height_request">16</property>
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"></property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label7">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">#danmark</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">6</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="type">tab</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+</widget>
+
+<widget class="GtkDialog" id="start-up-window-3">
+ <property name="visible">True</property>
+ <property name="title" translatable="yes">Connecting</property>
+ <property name="type">GTK_WINDOW_TOPLEVEL</property>
+ <property name="window_position">GTK_WIN_POS_NONE</property>
+ <property name="modal">False</property>
+ <property name="resizable">True</property>
+ <property name="destroy_with_parent">False</property>
+ <property name="decorated">True</property>
+ <property name="skip_taskbar_hint">False</property>
+ <property name="skip_pager_hint">False</property>
+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
+ <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+ <property name="has_separator">False</property>
+
+ <child internal-child="vbox">
+ <widget class="GtkVBox" id="dialog-vbox2">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child internal-child="action_area">
+ <widget class="GtkHButtonBox" id="dialog-action_area2">
+ <property name="visible">True</property>
+ <property name="layout_style">GTK_BUTTONBOX_END</property>
+
+ <child>
+ <widget class="GtkButton" id="button6">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">_Connect</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="response_id">0</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">GTK_PACK_END</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkVBox" id="vbox13">
+ <property name="border_width">6</property>
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">12</property>
+
+ <child>
+ <widget class="GtkVBox" id="vbox22">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">3</property>
+
+ <child>
+ <widget class="GtkLabel" id="label14">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;b&gt;_Servers&lt;/b&gt;</property>
+ <property name="use_underline">True</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHBox" id="hbox10">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">12</property>
+
+ <child>
+ <widget class="GtkScrolledWindow" id="scrolledwindow8">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="shadow_type">GTK_SHADOW_IN</property>
+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+ <child>
+ <widget class="GtkTreeView" id="treeview7">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="headers_visible">False</property>
+ <property name="rules_hint">False</property>
+ <property name="reorderable">False</property>
+ <property name="enable_search">True</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkVButtonBox" id="vbuttonbox1">
+ <property name="visible">True</property>
+ <property name="layout_style">GTK_BUTTONBOX_START</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkButton" id="button8">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+
+ <child>
+ <widget class="GtkAlignment" id="alignment4">
+ <property name="visible">True</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xscale">0</property>
+ <property name="yscale">0</property>
+ <property name="top_padding">0</property>
+ <property name="bottom_padding">0</property>
+ <property name="left_padding">0</property>
+ <property name="right_padding">0</property>
+
+ <child>
+ <widget class="GtkHBox" id="hbox13">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">2</property>
+
+ <child>
+ <widget class="GtkImage" id="image35">
+ <property name="visible">True</property>
+ <property name="stock">gtk-new</property>
+ <property name="icon_size">4</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label18">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_New Server...</property>
+ <property name="use_underline">True</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="button9">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+
+ <child>
+ <widget class="GtkAlignment" id="alignment5">
+ <property name="visible">True</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xscale">0</property>
+ <property name="yscale">0</property>
+ <property name="top_padding">0</property>
+ <property name="bottom_padding">0</property>
+ <property name="left_padding">0</property>
+ <property name="right_padding">0</property>
+
+ <child>
+ <widget class="GtkHBox" id="hbox14">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">3</property>
+
+ <child>
+ <widget class="GtkImage" id="image36">
+ <property name="visible">True</property>
+ <property name="stock">gtk-properties</property>
+ <property name="icon_size">4</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label19">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Properties...</property>
+ <property name="use_underline">True</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="button10">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-delete</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkVBox" id="vbox21">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">3</property>
+
+ <child>
+ <widget class="GtkLabel" id="label34">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;b&gt;_Channels&lt;/b&gt;</property>
+ <property name="use_underline">True</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkScrolledWindow" id="scrolledwindow17">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="shadow_type">GTK_SHADOW_IN</property>
+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+ <child>
+ <widget class="GtkTreeView" id="treeview10">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="headers_visible">False</property>
+ <property name="rules_hint">False</property>
+ <property name="reorderable">False</property>
+ <property name="enable_search">True</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+</widget>
+
+<widget class="GtkWindow" id="window1">
+ <property name="visible">True</property>
+ <property name="title" translatable="yes">irc.gimp.org</property>
+ <property name="type">GTK_WINDOW_TOPLEVEL</property>
+ <property name="window_position">GTK_WIN_POS_NONE</property>
+ <property name="modal">False</property>
+ <property name="resizable">True</property>
+ <property name="destroy_with_parent">False</property>
+ <property name="decorated">True</property>
+ <property name="skip_taskbar_hint">False</property>
+ <property name="skip_pager_hint">False</property>
+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
+ <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+
+ <child>
+ <widget class="GtkVBox" id="vbox15">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkMenuBar" id="menubar2">
+ <property name="visible">True</property>
+
+ <child>
+ <widget class="GtkMenuItem" id="menuitem5">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Chat</property>
+ <property name="use_underline">True</property>
+
+ <child>
+ <widget class="GtkMenu" id="menu1">
+
+ <child>
+ <widget class="GtkImageMenuItem" id="imagemenuitem1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Join Channel...</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_join_channel1_activate" last_modification_time="Tue, 03 Sep 2002 19:14:39 GMT"/>
+ <accelerator key="J" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+
+ <child internal-child="image">
+ <widget class="GtkImage" id="image38">
+ <property name="visible">True</property>
+ <property name="stock">gtk-new</property>
+ <property name="icon_size">1</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkImageMenuItem" id="imagemenuitem2">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Leave Channel...</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_leave_channel1_activate" last_modification_time="Mon, 11 Nov 2002 23:51:32 GMT"/>
+ <accelerator key="w" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+
+ <child internal-child="image">
+ <widget class="GtkImage" id="image39">
+ <property name="visible">True</property>
+ <property name="stock">gtk-close</property>
+ <property name="icon_size">1</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkMenuItem" id="menuitem6">
+ <property name="visible">True</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkMenuItem" id="menuitem7">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Servers...</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_servers1_activate" last_modification_time="Tue, 03 Sep 2002 19:14:39 GMT"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkMenuItem" id="menuitem8">
+ <property name="visible">True</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkImageMenuItem" id="imagemenuitem3">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">gtk-quit</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_save1_activate" last_modification_time="Tue, 03 Sep 2002 19:14:39 GMT"/>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkMenuItem" id="menuitem9">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Edit</property>
+ <property name="use_underline">True</property>
+
+ <child>
+ <widget class="GtkMenu" id="menu2">
+
+ <child>
+ <widget class="GtkImageMenuItem" id="imagemenuitem4">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">gtk-cut</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_cut1_activate" last_modification_time="Tue, 03 Sep 2002 19:14:39 GMT"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkImageMenuItem" id="imagemenuitem5">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">gtk-copy</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_copy1_activate" last_modification_time="Tue, 03 Sep 2002 19:14:39 GMT"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkImageMenuItem" id="imagemenuitem6">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">gtk-paste</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_paste1_activate" last_modification_time="Tue, 03 Sep 2002 19:14:39 GMT"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkImageMenuItem" id="imagemenuitem7">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">gtk-clear</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_delete1_activate" last_modification_time="Tue, 03 Sep 2002 19:14:39 GMT"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkMenuItem" id="menuitem10">
+ <property name="visible">True</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkImageMenuItem" id="imagemenuitem8">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Find ...</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_find_1_activate" last_modification_time="Mon, 11 Nov 2002 23:46:21 GMT"/>
+ <accelerator key="F" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+
+ <child internal-child="image">
+ <widget class="GtkImage" id="image40">
+ <property name="visible">True</property>
+ <property name="stock">gtk-find</property>
+ <property name="icon_size">1</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkImageMenuItem" id="imagemenuitem9">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Find Ne_xt</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_find_next1_activate" last_modification_time="Mon, 11 Nov 2002 23:46:21 GMT"/>
+ <accelerator key="G" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+
+ <child internal-child="image">
+ <widget class="GtkImage" id="image41">
+ <property name="visible">True</property>
+ <property name="stock">gtk-find</property>
+ <property name="icon_size">1</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkMenuItem" id="menuitem11">
+ <property name="visible">True</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkImageMenuItem" id="imagemenuitem10">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">gtk-preferences</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_preferences1_activate" last_modification_time="Mon, 11 Nov 2002 23:47:06 GMT"/>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkMenuItem" id="menuitem12">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Action</property>
+ <property name="use_underline">True</property>
+
+ <child>
+ <widget class="GtkMenu" id="menu3">
+
+ <child>
+ <widget class="GtkMenuItem" id="menuitem13">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Talk in the Third Person...</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_talk_in_the_third_person1_activate" last_modification_time="Mon, 11 Nov 2002 23:55:47 GMT"/>
+ <accelerator key="m" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkMenuItem" id="menuitem14">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Change _Nickname...</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_change_nickname1_activate" last_modification_time="Mon, 11 Nov 2002 23:55:47 GMT"/>
+ <accelerator key="n" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkMenuItem" id="menuitem15">
+ <property name="visible">True</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkCheckMenuItem" id="checkmenuitem1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Marked A_way</property>
+ <property name="use_underline">True</property>
+ <property name="active">False</property>
+ <signal name="activate" handler="on_marked_away1_activate" last_modification_time="Mon, 11 Nov 2002 23:55:47 GMT"/>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkMenuItem" id="menuitem16">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Help</property>
+ <property name="use_underline">True</property>
+
+ <child>
+ <widget class="GtkMenu" id="menu4">
+
+ <child>
+ <widget class="GtkImageMenuItem" id="imagemenuitem11">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">gnome-stock-about</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_about1_activate" last_modification_time="Tue, 03 Sep 2002 19:14:39 GMT"/>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkNotebook" id="notebook2">
+ <property name="width_request">0</property>
+ <property name="height_request">0</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="show_tabs">True</property>
+ <property name="show_border">True</property>
+ <property name="tab_pos">GTK_POS_LEFT</property>
+ <property name="scrollable">False</property>
+ <property name="enable_popup">False</property>
+
+ <child>
+ <widget class="GtkAlignment" id="alignment7">
+ <property name="visible">True</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xscale">1</property>
+ <property name="yscale">1</property>
+ <property name="top_padding">0</property>
+ <property name="bottom_padding">0</property>
+ <property name="left_padding">6</property>
+ <property name="right_padding">6</property>
+
+ <child>
+ <widget class="GtkVBox" id="vbox17">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkScrolledWindow" id="scrolledwindow18">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
+ <property name="vscrollbar_policy">GTK_POLICY_NEVER</property>
+ <property name="shadow_type">GTK_SHADOW_IN</property>
+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+ <child>
+ <widget class="GtkTextView" id="textview11">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">True</property>
+ <property name="overwrite">False</property>
+ <property name="accepts_tab">True</property>
+ <property name="justification">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap_mode">GTK_WRAP_NONE</property>
+ <property name="cursor_visible">True</property>
+ <property name="pixels_above_lines">0</property>
+ <property name="pixels_below_lines">0</property>
+ <property name="pixels_inside_wrap">0</property>
+ <property name="left_margin">0</property>
+ <property name="right_margin">0</property>
+ <property name="indent">0</property>
+ <property name="text" translatable="yes"></property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">6</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkScrolledWindow" id="scrolledwindow12">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
+ <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property>
+ <property name="shadow_type">GTK_SHADOW_IN</property>
+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+ <child>
+ <widget class="GtkTextView" id="textview8">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">False</property>
+ <property name="overwrite">False</property>
+ <property name="accepts_tab">True</property>
+ <property name="justification">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap_mode">GTK_WRAP_NONE</property>
+ <property name="cursor_visible">False</property>
+ <property name="pixels_above_lines">0</property>
+ <property name="pixels_below_lines">0</property>
+ <property name="pixels_inside_wrap">0</property>
+ <property name="left_margin">0</property>
+ <property name="right_margin">0</property>
+ <property name="indent">0</property>
+ <property name="text" translatable="yes"></property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="tab_expand">False</property>
+ <property name="tab_fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHBox" id="hbox21">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkImage" id="image42">
+ <property name="visible">True</property>
+ <property name="stock">gnome-stock-about</property>
+ <property name="icon_size">1</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label26">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;b&gt;&lt;span color=&quot;#004784&quot;&gt;#gtk&lt;/span&gt;&lt;/b&gt;</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">6</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="type">tab</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkVBox" id="vbox23">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">6</property>
+
+ <child>
+ <widget class="GtkScrolledWindow" id="scrolledwindow19">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
+ <property name="vscrollbar_policy">GTK_POLICY_NEVER</property>
+ <property name="shadow_type">GTK_SHADOW_IN</property>
+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+ <child>
+ <widget class="GtkTextView" id="textview12">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">True</property>
+ <property name="overwrite">False</property>
+ <property name="accepts_tab">True</property>
+ <property name="justification">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap_mode">GTK_WRAP_NONE</property>
+ <property name="cursor_visible">True</property>
+ <property name="pixels_above_lines">0</property>
+ <property name="pixels_below_lines">0</property>
+ <property name="pixels_inside_wrap">0</property>
+ <property name="left_margin">0</property>
+ <property name="right_margin">0</property>
+ <property name="indent">0</property>
+ <property name="text" translatable="yes"></property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkScrolledWindow" id="scrolledwindow20">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
+ <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property>
+ <property name="shadow_type">GTK_SHADOW_IN</property>
+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+ <child>
+ <widget class="GtkTextView" id="textview13">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">False</property>
+ <property name="overwrite">False</property>
+ <property name="accepts_tab">True</property>
+ <property name="justification">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap_mode">GTK_WRAP_NONE</property>
+ <property name="cursor_visible">False</property>
+ <property name="pixels_above_lines">0</property>
+ <property name="pixels_below_lines">0</property>
+ <property name="pixels_inside_wrap">0</property>
+ <property name="left_margin">0</property>
+ <property name="right_margin">0</property>
+ <property name="indent">0</property>
+ <property name="text" translatable="yes"></property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="tab_expand">False</property>
+ <property name="tab_fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHBox" id="hbox24">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkLabel" id="label28">
+ <property name="width_request">16</property>
+ <property name="height_request">16</property>
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"></property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label29">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">#gnome</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">6</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="type">tab</property>
+ </packing>
+ </child>
+
+ <child>
+ <placeholder/>
+ </child>
+
+ <child>
+ <widget class="GtkHBox" id="hbox25">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkLabel" id="label30">
+ <property name="width_request">16</property>
+ <property name="height_request">16</property>
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;b&gt;|&lt;/b&gt;</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label31">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;b&gt;#usability&lt;/b&gt;</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">6</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="type">tab</property>
+ </packing>
+ </child>
+
+ <child>
+ <placeholder/>
+ </child>
+
+ <child>
+ <widget class="GtkHBox" id="hbox26">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkLabel" id="label32">
+ <property name="width_request">16</property>
+ <property name="height_request">16</property>
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"></property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label33">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">#danmark</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">6</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="type">tab</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+</widget>
+
+</glade-interface>
diff --git a/irc.c b/irc.c
new file mode 100644
index 0000000..565a00d
--- /dev/null
+++ b/irc.c
@@ -0,0 +1,931 @@
+#include "irc.h"
+#include <lac.h>
+#include <string.h>
+
+typedef struct IrcMessage IrcMessage;
+typedef struct CommandInfo CommandInfo;
+
+typedef enum
+{
+ /* Errors */
+ ERR_NOSUCHNICK = 401,
+ ERR_NOSUCHSERVER = 402,
+ ERR_NOSUCHCHANNEL = 403,
+ ERR_CANNOTSENDTOCHAN = 404,
+ ERR_TOOMANYCHANNELS = 405,
+ ERR_WASNOSUCHNICK = 406,
+ ERR_TOOMANYTARGETS = 407,
+ ERR_NOORIGIN = 409,
+ ERR_NORECIPIENT = 411,
+ ERR_NOTEXTTOSEND = 412,
+ ERR_NOTOPLEVEL = 413,
+ ERR_WILDTOPLEVEL = 414,
+ ERR_UNKNOWNCOMMAND = 421,
+ ERR_NOMOTD = 422,
+ ERR_NOADMININFO = 423,
+ ERR_FILEERROR = 424,
+ ERR_NONICKNAMEGIVEN = 431,
+ ERR_ERRONEUSNICKNAME = 432,
+ ERR_NICKNAMEINUSE = 433,
+ ERR_NICKCOLLISION = 436,
+ ERR_USERNOTINCHANNEL = 441,
+ ERR_NOTONCHANNEL = 442,
+ ERR_USERONCHANNEL = 443,
+ ERR_NOLOGIN = 444,
+ ERR_SUMMONDISABLED = 445,
+ ERR_USERSDISABLED = 446,
+ ERR_NOTREGISTERED = 451,
+ ERR_NEEDMOREPARAMS = 461,
+ ERR_ALREADYREGISTRED = 462,
+ ERR_NOPERMFORHOST = 463,
+ ERR_PASSWDMISMATCH = 464,
+ ERR_YOUREBANNEDCREEP = 465,
+ ERR_KEYSET = 467,
+ ERR_CHANNELISFULL = 471,
+ ERR_UNKNOWNMODE = 472,
+ ERR_INVITEONLYCHAN = 473,
+ ERR_BANNEDFROMCHAN = 474,
+ ERR_BADCHANNELKEY = 475,
+ ERR_NOPRIVILEGES = 481,
+ ERR_CHANOPRIVSNEEDED = 482,
+ ERR_CANTKILLSERVER = 483,
+ ERR_NOOPERHOST = 491,
+ ERR_UMODEUNKNOWNFLAG = 501,
+ ERR_USERSDONTMATCH = 502,
+
+ /* Replies */
+ RPL_NONE = 300,
+ RPL_USERHOST = 302,
+ RPL_ISON = 303,
+ RPL_AWAY = 301,
+ RPL_UNAWAY = 305,
+ RPL_NOWAWAY = 306,
+ RPL_WHOISUSER = 311,
+ RPL_WHOISSERVER = 312,
+ RPL_WHOISOPERATOR = 313,
+ RPL_WHOISIDLE = 317,
+ RPL_ENDOFWHOIS = 318,
+ RPL_WHOWASUSER = 314,
+ RPL_ENDOFWHOWAS = 369,
+ RPL_LISTSTART = 321,
+ RPL_LIST = 322,
+ RPL_LISTEND = 323,
+ RPL_CHANNELMODEIS = 324,
+ RPL_NOTOPIC = 331,
+ RPL_TOPIC = 332,
+ RPL_INVITING = 341,
+ RPL_SUMMONING = 342,
+ RPL_VERSION = 351,
+ RPL_WHOREPLY = 352,
+ RPL_ENDOFWHO = 315,
+ RPL_NAMREPLY = 353,
+ RPL_ENDOFNAMES = 366,
+ RPL_LINKS = 364,
+ RPL_ENDOFLINKS = 365,
+ RPL_BANLIST = 367,
+ RPL_ENDOFBANLIST = 368,
+ RPL_INFO = 371,
+ RPL_ENDOFINFO = 374,
+ RPL_MOTDSTART = 375,
+ RPL_MOTD = 372,
+ RPL_ENDOFMOTD = 376,
+ RPL_YOUREOPER = 381,
+ RPL_REHASHING = 382,
+ RPL_TIME = 391,
+ RPL_USERSSTART = 392,
+ RPL_USERS = 393,
+ RPL_ENDOFUSERS = 394,
+ RPL_NOUSERS = 395,
+ RPL_TRACELINK = 200,
+ RPL_TRACECONNECTING = 201,
+ RPL_TRACEHANDSHAKE = 202,
+ RPL_TRACEUNKNOWN = 203,
+ RPL_TRACEOPERATOR = 204,
+ RPL_TRACEUSER = 205,
+ RPL_TRACESERVER = 206,
+ RPL_TRACENEWTYPE = 208,
+ RPL_TRACELOG = 261,
+ RPL_STATSLINKINFO = 211,
+ RPL_STATSCOMMANDS = 212,
+ RPL_STATSCLINE = 213,
+ RPL_STATSNLINE = 214,
+ RPL_STATSILINE = 215,
+ RPL_STATSKLINE = 216,
+ RPL_STATSYLINE = 218,
+ RPL_ENDOFSTATS = 219,
+ RPL_STATSLLINE = 241,
+ RPL_STATSUPTIME = 242,
+ RPL_STATSOLINE = 243,
+ RPL_STATSHLINE = 244,
+ RPL_UMODEIS = 221,
+ RPL_LUSERCLIENT = 251,
+ RPL_LUSEROP = 252,
+ RPL_LUSERUNKNOWN = 253,
+ RPL_LUSERCHANNELS = 254,
+ RPL_LUSERME = 255,
+ RPL_ADMINME = 256,
+ RPL_ADMINLOC1 = 257,
+ RPL_ADMINLOC2 = 258,
+ RPL_ADMINEMAIL = 259,
+
+ /* These codes are not specified by the RFC spec, just
+ * used internally. (IRC can't use them, because they
+ * have more than three digits)
+ */
+ CMD_NOTICE = 9001,
+ CMD_PRIVMSG = 9002,
+ CMD_PASS = 9003,
+ CMD_NICK = 9004,
+ CMD_USER = 9005,
+
+ CMD_UNKNOWN = 10000, /* message not understood */
+} ReplyCode;
+
+#define CR 0x0d
+#define LF 0x0a
+#define NUL 0x00
+#define BELL 0x07
+#define SPACE 0x20
+#define COMMA 0x2c
+
+static const gchar CRLF[] = { CR, LF, '\0' };
+
+struct CommandInfo
+{
+ const ReplyCode code;
+ const char *text;
+};
+
+static const CommandInfo commands[] =
+{
+ { CMD_NOTICE, "NOTICE" },
+ { CMD_PRIVMSG, "PRIVMSG" },
+ { CMD_USER, "USER" },
+ { CMD_PASS, "PASS" },
+ { CMD_NICK, "NICK" },
+ { CMD_UNKNOWN, "Unknown command" }
+};
+
+static ReplyCode
+command_to_code (const char *start, const char *end)
+{
+ char *command = g_strndup (start, end - start);
+ ReplyCode code = CMD_UNKNOWN;
+ int i;
+
+ for (i = 0; i < G_N_ELEMENTS (commands); ++i)
+ {
+ if (strcmp (command, commands[i].text) == 0)
+ {
+ code = commands[i].code;
+ break;
+ }
+ }
+
+ return code;
+}
+
+static const char *
+code_to_command (ReplyCode code)
+{
+ const char *cmd = NULL;
+ int i;
+
+ for (i = 0; i < G_N_ELEMENTS (commands); ++i)
+ {
+ if (commands[i].code == code)
+ {
+ cmd = commands[i].text;
+ break;
+ }
+ }
+
+ return cmd;
+}
+
+struct IrcMessage
+{
+ char * prefix;
+ ReplyCode code;
+ GQueue * parameters;
+
+ GList * free_list;
+};
+
+static IrcMessage *message_new_parsed (const char **input,
+ int *length);
+static void message_free (IrcMessage *msg);
+
+static gpointer trace (gpointer data,
+ gpointer free_func,
+ GList **freelist);
+
+/*
+ * Message parser
+ */
+static int
+eat_spaces (const char **input, int *length)
+{
+ int n_spaces;
+
+ n_spaces = 0;
+ while (**input == SPACE)
+ {
+ *input += 1;
+ *length -= 1;
+
+ n_spaces++;
+ }
+
+ return n_spaces;
+}
+
+static const char *
+find_char (const char *input, int length, char c)
+{
+ int i;
+ for (i = 0; i < length; ++i)
+ {
+ if (input[i] == c)
+ return input + i;
+ }
+ return NULL;
+}
+
+static char *
+parse_prefix (const char **input,
+ int *length,
+ GList **free_list,
+ gboolean *error)
+{
+ const char *space;
+
+ space = find_char (*input, *length, SPACE);
+ if (!space || space == *input)
+ {
+ *error = TRUE;
+ return NULL;
+ }
+ else
+ {
+ int prefix_len = space - *input;
+ char *result = g_strndup (*input, prefix_len);
+
+ *input += prefix_len;
+ *length -= prefix_len;
+
+ return trace (result, g_free, free_list);
+ }
+}
+
+static ReplyCode
+parse_command (const char **input,
+ int *length,
+ GList **free_list,
+ gboolean *err)
+{
+ ReplyCode result;
+
+ if (*length < 1)
+ goto error;
+
+ if (g_ascii_isalpha (**input))
+ {
+ const char *start = *input;
+
+ while (*length > 0 && g_ascii_isalpha (**input))
+ {
+ *input += 1;
+ *length -= 1;
+ }
+
+ return command_to_code (start, *input);
+ }
+ else if (g_ascii_isdigit (**input));
+ {
+ int d1, d2, d3;
+
+ if (*length < 3)
+ goto error;
+
+ d1 = (*input)[0] - '0';
+ d2 = (*input)[1] - '0';
+ d3 = (*input)[2] - '0';
+
+ if (d1 < 0 || d1 > 9 ||
+ d2 < 0 || d2 > 9 ||
+ d3 < 0 || d3 > 9)
+ {
+ goto error;
+ }
+
+ *input += 3;
+ *length -= 3;
+
+ return (ReplyCode) d1 * 100 + d2 * 10 + d3;
+ }
+
+ return result;
+
+error:
+ *err = TRUE;
+ return -1;
+}
+
+static gboolean
+is_trailing_char (char c)
+{
+ return c != NUL && c != CR && c != LF;
+}
+
+static gboolean
+is_middle_char (char c)
+{
+ return c != SPACE && c != NUL && c != CR && c != LF;
+}
+
+static char *
+parse_trailing (const char **input,
+ int *length,
+ GList **free_list,
+ gboolean *err)
+{
+ const char *start = *input;
+
+ while (*length > 0 && is_trailing_char (**input))
+ {
+ *input += 1;
+ *length -= 1;
+ }
+
+ if (*input != start)
+ return trace (g_strndup (start, *input - start), g_free, free_list);
+ else
+ return NULL;
+}
+
+static char *
+parse_middle (const char **input,
+ int *length,
+ GList **free_list,
+ gboolean *err)
+{
+ const char *start = *input;
+
+ while (*length > 0 && is_middle_char (**input))
+ {
+ *input += 1;
+ *length -= 1;
+ }
+
+ if (*input == start)
+ goto error;
+
+ return trace (g_strndup (start, *input - start), g_free, free_list);
+
+error:
+ *err = TRUE;
+ return NUL;
+}
+
+static GQueue *
+parse_params (const char **input,
+ int *length,
+ GList **free_list,
+ gboolean *err)
+{
+ GQueue *params = NULL;
+
+ if (*length < 1)
+ goto error;
+
+ if (**input == SPACE)
+ eat_spaces (input, length);
+
+ if (*length > 0)
+ {
+ char *trailing;
+
+ if (**input == ':')
+ {
+ *input += 1;
+ *length -= 1;
+
+ /* <trailing> */
+ trailing = parse_trailing (input, length, free_list, err);
+ if (*err)
+ goto error;
+
+ if (trailing)
+ {
+ params = trace (g_queue_new(), g_queue_free, free_list);
+
+ g_queue_push_tail (params, trailing);
+ }
+ }
+ else if (is_middle_char (**input))
+ {
+ char *middle;
+
+ /* <middle> */
+ middle = parse_middle (input, length, free_list, err);
+ if (*err)
+ goto error;
+
+ /* <params> */
+
+ /* The RFC states that parameters always start with SPACE,
+ * but that is a lie: The final params following a <middle>
+ * can be the empty string
+ */
+ if (**input == SPACE)
+ {
+ params = parse_params (input, length, free_list, err);
+ if (*err)
+ goto error;
+ }
+ else
+ {
+ params = trace (g_queue_new(), g_queue_free, free_list);
+
+ g_queue_push_head (params, middle);
+ }
+ }
+ }
+
+ if (!params)
+ params = trace (g_queue_new(), g_queue_free, free_list);
+
+ return params;
+
+error:
+ *err = TRUE;
+ return NULL;
+}
+
+/* Returns NULL if *input is not a valid message. This will also
+ * happen if we just haven't received enough data yet.
+ */
+static IrcMessage *
+message_new_parsed (const char **input,
+ int *length)
+{
+ IrcMessage *msg = g_new (IrcMessage, 1);
+ const char *crlf;
+ gboolean err = FALSE;
+
+ msg->free_list = NULL;
+
+ if (*length < 2)
+ goto error;
+
+ crlf = strstr (*input, CRLF);
+
+ if (!crlf)
+ goto error;
+
+ if (crlf - *input > 510)
+ goto error;
+
+ msg->prefix = NULL;
+ if (**input == ':')
+ {
+ *input += 1;
+ *length -= 1;
+
+ msg->prefix = parse_prefix (input, length, &msg->free_list, &err);
+
+ if (err)
+ goto error;
+
+ if (eat_spaces (input, length) < 1)
+ goto error;
+ }
+
+ msg->code = parse_command (input, length, &msg->free_list, &err);
+ if (err)
+ goto error;
+
+ msg->parameters = parse_params (input, length, &msg->free_list, &err);
+
+ if (err)
+ goto error;
+
+ if (*length < 2)
+ goto error;
+
+ if (strncmp (*input, CRLF, 2) != 0)
+ goto error;
+
+ *input += 2;
+ *length -= 2;
+
+ return msg;
+
+error:
+ message_free (msg);
+ return NULL;
+}
+
+static void
+message_free (IrcMessage *msg)
+{
+ GList *list;
+
+ for (list = msg->free_list; list != NULL; list = list->next->next)
+ {
+ GDestroyNotify free_func = list->data;
+ gpointer alloc = list->next->data;
+
+ (* free_func) (alloc);
+ }
+
+ g_list_free (msg->free_list);
+
+ g_free (msg);
+}
+
+typedef enum
+{
+ NOT_CONNECTED,
+ CONNECTING,
+ CONNECTED
+} IrcServerState;
+
+struct IrcServer
+{
+ /* information about server */
+ char * hostname;
+ gint port;
+
+ /* information about user */
+ char * local_user_name;
+ char * local_host_name;
+ char * local_domain_name;
+ char * real_name;
+ char * nickname;
+ char * password;
+
+ /* state */
+ IrcServerState state;
+ LacConnection * connection;
+ IrcServerFunc func;
+ gpointer data;
+ GString * unparsed;
+ GQueue * messages;
+};
+
+IrcServer *
+irc_server_new (const char *hostname,
+ gint port,
+ IrcServerFunc func,
+ gpointer data)
+{
+ IrcServer *server;
+
+ g_return_val_if_fail (hostname != NULL, NULL);
+ g_return_val_if_fail (port > 0, NULL);
+ g_return_val_if_fail (func != NULL, NULL);
+
+ server = g_new (IrcServer, 1);
+
+ server->hostname = g_strdup (hostname);
+ server->port = port;
+
+ server->local_user_name = NULL;
+ server->local_host_name = NULL;
+ server->local_domain_name = NULL;
+ server->real_name = NULL;
+ server->nickname = NULL;
+ server->password = NULL;
+
+ server->state = NOT_CONNECTED;
+ server->connection = NULL;
+ server->func = func;
+ server->data = data;
+ server->unparsed = g_string_new ("");
+ server->messages = g_queue_new ();
+
+ return server;
+}
+
+gpointer
+irc_server_get_data (IrcServer *server)
+{
+ g_return_val_if_fail (server != NULL, NULL);
+
+ return server->data;
+}
+
+static void
+server_emit_dns_complete (IrcServer *server)
+{
+}
+
+static void
+server_emit_error (IrcServer *server,
+ const GError *err)
+{
+
+}
+
+static void
+server_emit_connect (IrcServer *server)
+{
+
+}
+
+static void
+server_emit_close (IrcServer *server)
+{
+
+}
+
+static void
+emit_malformed_error (IrcServer *server, const char *msg)
+{
+ GError *error = NULL;
+
+ g_set_error (&error,
+ IRC_ERROR,
+ IRC_ERROR_MALFORMED_MESSAGE,
+ "Server %s sent an unparsable message (%s) "
+ "(This is most likely a bug in ChatterBox)",
+ server->hostname,
+ msg);
+
+ server_emit_error (server, error);
+
+ g_error_free (error);
+}
+
+static gboolean
+process_data (IrcServer *server)
+{
+ char *crlf = strstr (server->unparsed->str, CRLF);
+
+ if (!crlf && server->unparsed->len > 510)
+ {
+ /* We have seen 510 bytes in a row without
+ * a CRLF. This means the server is sending
+ * garbage
+ */
+ emit_malformed_error (server, "No CRLF");
+ lac_connection_close (server->connection);
+ return FALSE;
+ }
+ else if (crlf)
+ {
+ IrcMessage *msg;
+ const char *s = server->unparsed->str;
+ int len = server->unparsed->len;
+
+ msg = message_new_parsed (&s, &len);
+
+ if (!msg)
+ {
+ emit_malformed_error (server, "parse error");
+ lac_connection_close (server->connection);
+ return FALSE;
+ }
+
+ g_string_erase (server->unparsed, 0, server->unparsed->len - len);
+
+ /* process message */
+#if 0
+ g_print ("\ncommand: %s - %d ", msg->prefix? msg->prefix : "", msg->code);
+ for (list = msg->parameters->head; list != NULL; list = list->next)
+ {
+ g_print ("%s ", (char *)list->data);
+ }
+ g_print ("\n");
+#endif
+
+ message_free (msg);
+ return TRUE;
+ }
+ else
+ {
+ g_print ("no data/not enough data\n");
+ /* No CRLF and less than 510 bytes: not enough
+ * data yet
+ */
+ return FALSE;
+ }
+}
+
+static void
+server_handle_read (IrcServer *server,
+ const LacConnectionReadEvent *read)
+{
+ int i;
+
+ for (i = 0; i < read->len; ++i)
+ g_print ("%c", read->data[i]);
+
+ g_string_append_len (server->unparsed, read->data, read->len);
+
+ while (process_data (server))
+ ;
+}
+
+static void
+server_handle_disconnect (IrcServer *server)
+{
+ server->state = NOT_CONNECTED;
+ lac_connection_unref (server->connection);
+ server->connection = NULL;
+}
+
+static void
+server_send_command (IrcServer *server,
+ const char *prefix,
+ ReplyCode code,
+ const char *param,
+ ...)
+{
+ va_list var_args;
+ GQueue *params = g_queue_new ();
+ const char *command;
+ GList *list;
+ GString *message;
+
+ command = code_to_command (code);
+
+ g_return_if_fail (command != NULL);
+
+ va_start (var_args, param);
+
+ while (param != NULL)
+ {
+ g_queue_push_tail (params, (gpointer)param);
+
+ param = va_arg (var_args, char *);
+ }
+
+ va_end (var_args);
+
+ message = g_string_new ("");
+
+ if (prefix)
+ {
+ g_string_append (message, ":");
+ g_string_append (message, prefix);
+ g_string_append (message, " ");
+ }
+
+ g_string_append (message, command);
+
+ for (list = params->head; list != NULL; list = list->next)
+ {
+ g_string_append (message, " ");
+ if (!list->next)
+ g_string_append (message, ":");
+ g_string_append (message, list->data);
+ }
+
+ g_string_append (message, CRLF);
+
+ lac_connection_write (server->connection, message->str, message->len);
+
+ g_string_free (message, TRUE);
+}
+
+static void
+server_send_registration (IrcServer *server)
+{
+ server_send_command (server, NULL, CMD_PASS, server->password, NULL);
+ server_send_command (server, NULL, CMD_NICK, server->nickname, NULL);
+ server_send_command (
+ server, NULL, CMD_USER,
+ server->local_user_name? server->local_user_name : "unknown",
+ server->local_host_name? server->local_host_name : "unknown",
+ server->local_domain_name? server->local_domain_name : "unknown",
+ server->real_name? server->real_name : "Unknown",
+ NULL);
+}
+
+static void
+connection_callback (LacConnection *connection,
+ const LacConnectionEvent *event)
+{
+ IrcServer *server = lac_connection_get_data (connection);
+
+ g_assert (server);
+
+ switch (event->type)
+ {
+ case LAC_CONNECTION_EVENT_CONNECT: /* connect successful */
+ server_emit_connect (server);
+ server->state = CONNECTED;
+ server_send_registration (server);
+ break;
+
+ case LAC_CONNECTION_EVENT_READ:
+ server_handle_read (server, &(event->read));
+ break; /* data to read */
+
+ case LAC_CONNECTION_EVENT_CLOSE: /* Connection closed */
+ if (event->close.remote_closed)
+ server_emit_close (server);
+ server_handle_disconnect (server);
+ break;
+
+ case LAC_CONNECTION_EVENT_ERROR: /* error */
+ server_emit_error (server, event->error.err);
+ server_handle_disconnect (server);
+ break;
+ }
+}
+
+static void
+address_callback (const LacAddress * address,
+ gpointer data,
+ const GError * err)
+{
+ IrcServer *server = data;
+
+ if (err)
+ {
+ server_emit_error (server, err);
+ }
+ else
+ {
+ server_emit_dns_complete (server);
+ server->connection = lac_connection_new (
+ address, server->port, connection_callback, server);
+ }
+}
+
+static char *
+generate_password (void)
+{
+ return g_strdup_printf ("CH%x%x%x",
+ g_random_int(),
+ g_random_int(),
+ g_random_int());
+}
+
+void
+irc_server_connect (IrcServer *server,
+ const char *nick,
+ const char *password)
+{
+ char *orig_pw, *orig_nick;
+
+ g_return_if_fail (server != NULL);
+ g_return_if_fail (server->state == NOT_CONNECTED);
+ g_return_if_fail (nick != NULL);
+
+ if (server->state != NOT_CONNECTED)
+ return;
+
+ orig_pw = server->password;
+ orig_nick = server->nickname;
+
+ if (password)
+ server->password = g_strdup (password);
+ else
+ server->password = generate_password ();
+
+ server->nickname = g_strdup (nick);
+
+ if (orig_pw)
+ g_free (orig_pw);
+ if (orig_nick)
+ g_free (orig_nick);
+
+ server->state = CONNECTING;
+ lac_address_new_lookup_from_name (
+ server->hostname, address_callback, server);
+}
+
+void
+irc_server_disconnect (IrcServer *server)
+{
+}
+
+/* Tracing memory
+ */
+
+static gpointer
+trace (gpointer data,
+ gpointer free_func,
+ GList **free_list)
+{
+ *free_list = g_list_prepend (*free_list, data);
+ *free_list = g_list_prepend (*free_list, free_func);
+ return data;
+}
+
+GQuark
+irc_error_quark (void)
+{
+ static GQuark q = 0;
+
+ if (q == 0)
+ q = g_quark_from_static_string ("irc-error-quark");
+
+ return q;
+}
+
diff --git a/irc.h b/irc.h
new file mode 100644
index 0000000..a9a3520
--- /dev/null
+++ b/irc.h
@@ -0,0 +1,70 @@
+#include <glib.h>
+
+/*
+ * Irc utilities
+ */
+
+/*
+ * IrcServer
+ */
+
+typedef struct IrcServer IrcServer;
+typedef struct IrcChannel IrcChannel;
+
+#define IRC_ERROR irc_error_quark ()
+
+typedef enum
+{
+ IRC_ERROR_MALFORMED_MESSAGE
+} IrcError;
+
+GQuark irc_error_quark (void);
+
+typedef enum
+{
+ IRC_SERVER_LOOKING_UP_HOSTNAME,
+ IRC_SERVER_FOUND_HOST_NAME,
+ IRC_SERVER_CONNECTING,
+ IRC_SERVER_CONNECTED,
+ IRC_SERVER_DISCONNECT,
+ IRC_SERVER_ERROR
+} IrcServerEvent;
+
+typedef enum
+{
+ IRC_CHANNEL_MESSAGE,
+ IRC_TOPIC_CHANGED,
+ IRC_USER_JOINED,
+} IrcChannelEvent;
+
+typedef void (* IrcServerFunc) (IrcServer *server,
+ const IrcServerEvent *event);
+
+typedef void (* IrcChannelListFunc) (GList *channels, gpointer data);
+
+IrcServer *irc_server_new (const char *name,
+ gint port,
+ IrcServerFunc func,
+ gpointer data);
+gpointer irc_server_get_data (IrcServer *server);
+
+void irc_server_list_channels (IrcServer *server,
+ IrcChannelListFunc func,
+ gpointer data);
+
+void irc_server_connect (IrcServer *server,
+ const char *nickname,
+ const char *password);
+void irc_server_disconnect (IrcServer *server);
+
+typedef void (* IrcChannelFunc) (IrcChannel *channel,
+ const IrcChannelEvent *event,
+ gpointer data);
+
+IrcChannel *irc_server_join_channel (IrcServer *server,
+ const char *name,
+ IrcChannelFunc func,
+ gpointer data);
+
+
+/* Channel operations */
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..9df80f9
--- /dev/null
+++ b/main.c
@@ -0,0 +1,41 @@
+#include "channel-buffer.h"
+#include "irc.h"
+
+static void
+irc_func (IrcServer *server,
+ const IrcServerEvent *event)
+{
+
+}
+
+int
+main (int argc, char **argv)
+{
+#if 0
+ GMainLoop *loop;
+ IrcServer *server = irc_server_new ("irc.gimp.org", 6667, irc_func, "hej");
+
+ loop = g_main_loop_new (NULL, FALSE);
+
+ irc_server_connect (server, "ssp", "birnan");
+
+ g_main_loop_run (loop);
+#endif
+ gtk_init (&argc, &argv);
+
+ ChannelBuffer *buffer = channel_buffer_new ("ssp");
+
+ GtkWindow *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ GtkWidget *text = gtk_text_view_new ();
+
+ gtk_text_view_set_buffer (GTK_TEXT_VIEW (text),
+ channel_buffer_get_text_buffer (buffer));
+
+ gtk_container_add (GTK_CONTAINER (window), text);
+
+ gtk_widget_show_all (window);
+
+ gtk_main ();
+
+ return 0;
+}