Index: irc.c
===================================================================
--- irc.c	(revision e54112f152c375df81a21181f755ced5f57165bc)
+++ irc.c	(revision 6a9d068e73b6d08056302fdc85dd706a2dd647a5)
@@ -640,4 +640,8 @@
 			irc_channel_add_user( ic, irc->user );
 			
+			if( strcmp( set_getstr( &irc->b->set, "ops" ), "both" ) == 0 ||
+			    strcmp( set_getstr( &irc->b->set, "ops" ), "user" ) == 0 )
+				irc_channel_user_set_mode( ic, irc->user, IRC_CHANNEL_USER_OP );
+			
 			irc->last_root_cmd = g_strdup( ROOT_CHAN );
 			
Index: irc.h
===================================================================
--- irc.h	(revision e54112f152c375df81a21181f755ced5f57165bc)
+++ irc.h	(revision 6a9d068e73b6d08056302fdc85dd706a2dd647a5)
@@ -196,4 +196,5 @@
 irc_channel_user_t *irc_channel_has_user( irc_channel_t *ic, irc_user_t *iu );
 int irc_channel_set_topic( irc_channel_t *ic, const char *topic, const irc_user_t *who );
+void irc_channel_user_set_mode( irc_channel_t *ic, irc_user_t *iu, irc_channel_user_flags_t flags );
 gboolean irc_channel_name_ok( const char *name );
 
@@ -216,4 +217,6 @@
 void irc_send_msg_f( irc_user_t *iu, const char *type, const char *dst, const char *format, ... ) G_GNUC_PRINTF( 4, 5 );
 void irc_send_nick( irc_user_t *iu, const char *new );
+void irc_send_channel_user_mode_diff( irc_channel_t *ic, irc_user_t *iu,
+                                      irc_channel_user_flags_t old, irc_channel_user_flags_t new );
 
 /* irc_user.c */
Index: irc_channel.c
===================================================================
--- irc_channel.c	(revision e54112f152c375df81a21181f755ced5f57165bc)
+++ irc_channel.c	(revision 6a9d068e73b6d08056302fdc85dd706a2dd647a5)
@@ -43,4 +43,7 @@
 	
 	irc_channel_add_user( ic, irc->root );
+	if( strcmp( set_getstr( &irc->b->set, "ops" ), "both" ) == 0 ||
+	    strcmp( set_getstr( &irc->b->set, "ops" ), "root" ) == 0 )
+		irc_channel_user_set_mode( ic, irc->root, IRC_CHANNEL_USER_OP );
 	
 	irc->channels = g_slist_prepend( irc->channels, ic );
@@ -157,4 +160,17 @@
 	
 	return 1;
+}
+
+void irc_channel_user_set_mode( irc_channel_t *ic, irc_user_t *iu, irc_channel_user_flags_t flags )
+{
+	irc_channel_user_t *icu = irc_channel_has_user( ic, iu );
+	
+	if( icu->flags == flags )
+		return;
+	
+	if( ic->flags & IRC_CHANNEL_JOINED )
+		irc_send_channel_user_mode_diff( ic, iu, icu->flags, flags );
+	
+	icu->flags = flags;
 }
 
Index: irc_im.c
===================================================================
--- irc_im.c	(revision e54112f152c375df81a21181f755ced5f57165bc)
+++ irc_im.c	(revision 6a9d068e73b6d08056302fdc85dd706a2dd647a5)
@@ -92,4 +92,8 @@
 			
 			irc_channel_add_user( ic, iu );
+			
+			if( set_getbool( &bee->set, "away_devoice" ) )
+				irc_channel_user_set_mode( ic, iu, ( bu->flags & BEE_USER_AWAY ) ?
+				                           0 : IRC_CHANNEL_USER_VOICE );
 		}
 		else
Index: irc_send.c
===================================================================
--- irc_send.c	(revision e54112f152c375df81a21181f755ced5f57165bc)
+++ irc_send.c	(revision 6a9d068e73b6d08056302fdc85dd706a2dd647a5)
@@ -157,5 +157,4 @@
 	GSList *l;
 	char namelist[385] = "";
-	//char *ops = set_getstr( &ic->irc->b->set, "ops" );
 	
 	/* RFCs say there is no error reply allowed on NAMES, so when the
@@ -172,11 +171,10 @@
 		}
 		
-		/*
-		if( u->ic && !u->away && set_getbool( &irc->set, "away_devoice" ) )
+		if( icu->flags & IRC_CHANNEL_USER_OP )
+			strcat( namelist, "@" );
+		else if( icu->flags & IRC_CHANNEL_USER_HALFOP )
+			strcat( namelist, "%" );
+		else if( icu->flags & IRC_CHANNEL_USER_VOICE )
 			strcat( namelist, "+" );
-		else if( ( strcmp( u->nick, irc->mynick ) == 0 && ( strcmp( ops, "root" ) == 0 || strcmp( ops, "both" ) == 0 ) ) ||
-		         ( strcmp( u->nick, irc->nick ) == 0 && ( strcmp( ops, "user" ) == 0 || strcmp( ops, "both" ) == 0 ) ) )
-			strcat( namelist, "@" );
-		*/
 		
 		strcat( namelist, iu->nick );
@@ -327,2 +325,51 @@
 	           iu->nick, iu->user, iu->host, new );
 }
+
+/* Send an update of a user's mode inside a channel, compared to what it was. */
+void irc_send_channel_user_mode_diff( irc_channel_t *ic, irc_user_t *iu,
+	irc_channel_user_flags_t old, irc_channel_user_flags_t new )
+{
+	char changes[3*(5+strlen(iu->nick))];
+	char from[strlen(ic->irc->root->nick)+strlen(ic->irc->root->user)+strlen(ic->irc->root->host)+3];
+	int n;
+	
+	*changes = '\0'; n = 0;
+	if( ( old & IRC_CHANNEL_USER_OP ) != ( new & IRC_CHANNEL_USER_OP ) )
+	{
+		n ++;
+		if( new & IRC_CHANNEL_USER_OP )
+			strcat( changes, "+o" );
+		else
+			strcat( changes, "-o" );
+	}
+	if( ( old & IRC_CHANNEL_USER_HALFOP ) != ( new & IRC_CHANNEL_USER_HALFOP ) )
+	{
+		n ++;
+		if( new & IRC_CHANNEL_USER_HALFOP )
+			strcat( changes, "+h" );
+		else
+			strcat( changes, "-h" );
+	}
+	if( ( old & IRC_CHANNEL_USER_VOICE ) != ( new & IRC_CHANNEL_USER_VOICE ) )
+	{
+		n ++;
+		if( new & IRC_CHANNEL_USER_VOICE )
+			strcat( changes, "+v" );
+		else
+			strcat( changes, "-v" );
+	}
+	while( n )
+	{
+		strcat( changes, " " );
+		strcat( changes, iu->nick );
+		n --;
+	}
+	
+	if( set_getbool( &ic->irc->b->set, "simulate_netsplit" ) )
+		g_snprintf( from, sizeof( from ), "%s", ic->irc->root->host );
+	else
+		g_snprintf( from, sizeof( from ), "%s!%s@%s", ic->irc->root->nick,
+		            ic->irc->root->user, ic->irc->root->host );
+	
+	irc_write( ic->irc, ":%s MODE %s %s", from, ic->name, changes );
+}
