gnome-mud r670 - trunk/src



Author: lharris
Date: Wed Jun 25 08:04:06 2008
New Revision: 670
URL: http://svn.gnome.org/viewvc/gnome-mud?rev=670&view=rev

Log:
Added telnet option support, fixed locale rendering.


Added:
   trunk/src/mud-telnet-handlers.c
   trunk/src/mud-telnet-handlers.h
Modified:
   trunk/src/Makefile.am
   trunk/src/gnome-mud.c
   trunk/src/mud-connection-view.c
   trunk/src/mud-connection-view.h
   trunk/src/mud-telnet.c
   trunk/src/mud-telnet.h
   trunk/src/mud-window.c

Modified: trunk/src/Makefile.am
==============================================================================
--- trunk/src/Makefile.am	(original)
+++ trunk/src/Makefile.am	Wed Jun 25 08:04:06 2008
@@ -47,6 +47,8 @@
 	mud-regex.h					\
 	mud-telnet.c                \
 	mud-telnet.h                \
+	mud-telnet-handlers.c		\
+	mud-telnet-handlers.h		\
 	mud-tray.c					\
 	mud-tray.h					\
 	mud-window.c				\

Modified: trunk/src/gnome-mud.c
==============================================================================
--- trunk/src/gnome-mud.c	(original)
+++ trunk/src/gnome-mud.c	Wed Jun 25 08:04:06 2008
@@ -90,7 +90,7 @@
 	bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
 	textdomain(GETTEXT_PACKAGE);
 #endif
-  
+
 	/* Initialize the GConf library */
 	if (!gconf_init(argc, argv, &err))
 	{

Modified: trunk/src/mud-connection-view.c
==============================================================================
--- trunk/src/mud-connection-view.c	(original)
+++ trunk/src/mud-connection-view.c	Wed Jun 25 08:04:06 2008
@@ -237,6 +237,8 @@
 void
 mud_connection_view_add_text(MudConnectionView *view, gchar *message, enum MudConnectionColorType type)
 {
+    vte_terminal_set_encoding(VTE_TERMINAL(view->priv->terminal), "ISO-8859-1");
+    
 	switch (type)
 	{
 		case Sent:
@@ -260,7 +262,7 @@
 	mud_connection_view_feed_text(view, "\e[0m");
 }
 
-
+                                                        
 static void
 mud_connection_view_init (MudConnectionView *connection_view)
 {
@@ -278,6 +280,8 @@
 	box = gtk_hbox_new(FALSE, 0);
 	
 	connection_view->priv->terminal = vte_terminal_new();
+	vte_terminal_set_encoding(VTE_TERMINAL(connection_view->priv->terminal), "ISO-8859-1");
+	
 	gtk_box_pack_start(GTK_BOX(box), connection_view->priv->terminal, TRUE, TRUE, 0);
 	g_signal_connect(G_OBJECT(connection_view->priv->terminal),
 					 "button_press_event",
@@ -381,7 +385,11 @@
 	GList *commands, *command;
 	gchar *text;
 
-    g_queue_push_head(view->priv->history, (gpointer)g_strdup(data));
+    if(view->local_echo) // Prevent password from being cached.
+        g_queue_push_head(view->priv->history, (gpointer)g_strdup(data));
+    else
+        g_queue_push_head(view->priv->history, (gpointer)g_strdup(" "));
+    
     view->priv->current_history_index = 0;
     
 	commands = mud_profile_process_commands(view->priv->profile, data);
@@ -396,7 +404,7 @@
 		    
 		gnet_conn_write(view->connection, text, strlen(text));
 		
-		if (view->priv->profile->preferences->EchoText)
+		if (view->priv->profile->preferences->EchoText && view->local_echo)
 			mud_connection_view_add_text(view, text, Sent);
 		g_free(text);
 	}
@@ -450,8 +458,18 @@
 static void
 mud_connection_view_set_terminal_font(MudConnectionView *view)
 {
-	vte_terminal_set_font_from_string(VTE_TERMINAL(view->priv->terminal),
-									  view->priv->profile->preferences->FontName);
+    PangoFontDescription *desc = NULL;
+    char *name;
+    
+    name = view->priv->profile->preferences->FontName;
+    
+    if(name)
+        desc = pango_font_description_from_string(name);
+    
+    if(!desc)
+        desc = pango_font_description_from_string("Monospace 10");
+    
+    vte_terminal_set_font(VTE_TERMINAL(view->priv->terminal), desc);
 }
 
 static void
@@ -510,7 +528,7 @@
 							  popup_menu_detach);
 
 	append_menuitem(view->priv->popup_menu,
-					_("Close tab or window, whatever :)"),
+					_("Close"),
 					NULL,
 					view);
 
@@ -623,10 +641,14 @@
 	gnet_conn_ref(view->connection);
 	gnet_conn_set_watch_error(view->connection, TRUE);
 	
+	view->naws_enabled = FALSE;
+	
 	view->priv->telnet = mud_telnet_new(view, view->connection);
+	
+	view->local_echo = TRUE;
 
 	mud_connection_view_set_profile(view, mud_profile_new(profile));
-
+    
 	/* Let us resize the gnome-mud window */
 	vte_terminal_get_padding(VTE_TERMINAL(view->priv->terminal), &xpad, &ypad);
 	char_width = VTE_TERMINAL(view->priv->terminal)->char_width;
@@ -654,9 +676,15 @@
 	buf = g_strdup_printf(_("*** Making connection to %s, port %d.\n"), 
 	    view->priv->hostname, view->priv->port);
 	mud_connection_view_add_text(view, buf, System);
+	g_free(buf);
+	buf = NULL;
 	
 	gnet_conn_connect(view->connection);
-
+	
+	buf = g_strdup_printf("Encoding: %s\n", vte_terminal_get_encoding(VTE_TERMINAL(view->priv->terminal)));
+    mud_connection_view_add_text(view, buf, System);
+    g_free(buf);
+    
 	return view;
 }
 
@@ -791,7 +819,6 @@
 
                 if (view->priv->connect_hook) {
                     mud_connection_view_send (view, view->priv->connect_string);
-                    g_free(view->priv->connect_string);
                     view->priv->connect_hook = FALSE;
                }
             
@@ -813,3 +840,31 @@
     }
 }
 
+void 
+mud_connection_view_get_term_size(MudConnectionView *view, gint *w, gint *h)
+{
+    VteTerminal *term = VTE_TERMINAL(view->priv->terminal);
+    *w = term->column_count;
+    *h = term->row_count;
+}
+ 
+void
+mud_connection_view_set_naws(MudConnectionView *view, gint enabled)
+{
+    view->naws_enabled = enabled;
+}
+
+void
+mud_connection_view_send_naws(MudConnectionView *view)
+{
+    if(view && view->naws_enabled)
+    {
+        mud_telnet_send_naws(view->priv->telnet, 
+                VTE_TERMINAL(view->priv->terminal)->column_count, 
+                VTE_TERMINAL(view->priv->terminal)->row_count);
+                
+        g_message("Sending NAWS %d/%d", (gint)VTE_TERMINAL(view->priv->terminal)->column_count
+        ,(gint)VTE_TERMINAL(view->priv->terminal)->row_count);
+    }
+}   
+

Modified: trunk/src/mud-connection-view.h
==============================================================================
--- trunk/src/mud-connection-view.h	(original)
+++ trunk/src/mud-connection-view.h	Wed Jun 25 08:04:06 2008
@@ -25,6 +25,10 @@
 	MudConnectionViewPrivate *priv;
 
 	GConn *connection;
+	
+	gint naws_enabled;
+	
+	gint local_echo;
 };
 
 struct _MudConnectionViewClass
@@ -59,6 +63,9 @@
 void mud_connection_view_add_text(MudConnectionView *view, gchar *message, enum MudConnectionColorType type);
 gchar *mud_connection_view_get_history_item(MudConnectionView *view, enum
 MudConnectionHistoryDirection direction);
+void mud_connection_view_get_term_size(MudConnectionView *view, gint *w, gint *h);
+void mud_connection_view_set_naws(MudConnectionView *view, gint enabled);
+void mud_connection_view_send_naws(MudConnectionView *view);
 
 #include "mud-profile.h"
 void mud_connection_view_set_profile(MudConnectionView *view, MudProfile *profile);

Added: trunk/src/mud-telnet-handlers.c
==============================================================================
--- (empty file)
+++ trunk/src/mud-telnet-handlers.c	Wed Jun 25 08:04:06 2008
@@ -0,0 +1,133 @@
+/* GNOME-Mud - A simple Mud CLient
+ * Copyright (C) 1998-2006 Robin Ericsson <lobbin localhost nu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* Code originally from wxMUD. Converted to a GObject by Les Harris.
+ * wxMUD - an open source cross-platform MUD client.
+ * Copyright (C) 2003-2008 Mart Raudsepp and Gabriel Levin
+ */
+ 
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#include <glib.h>
+#include <gnet.h>
+
+#include "gnome-mud.h"
+#include "mud-telnet.h"
+#include "mud-telnet-handlers.h"
+
+/* TTYPE */
+
+void 
+MudHandler_TType_Enable(MudTelnet *telnet, MudTelnetHandler *handler)
+{
+    handler->enabled = TRUE;
+}
+
+void 
+MudHandler_TType_Disable(MudTelnet *telnet, MudTelnetHandler *handler)
+{
+    handler->enabled = FALSE;
+}
+
+void 
+MudHandler_TType_HandleSubNeg(MudTelnet *telnet, guchar *buf,
+                              guint len, MudTelnetHandler *handler)
+{
+	if (len == 1 && buf[0] == TEL_TTYPE_SEND)
+	{
+	    mud_telnet_send_sub_req(telnet, 11, (guchar)TELOPT_TTYPE,
+	                                       (guchar)TEL_TTYPE_IS,
+	                                       'g','n','o','m','e','-','m','u','d');
+	}
+}
+
+/* NAWS */
+void 
+MudHandler_NAWS_Enable(MudTelnet *telnet, MudTelnetHandler *handler)
+{
+    gint w, h;
+    
+    mud_telnet_get_parent_size(telnet, &w, &h);
+    mud_telnet_set_parent_naws(telnet, TRUE);
+    
+    handler->enabled = TRUE;
+    
+    mud_telnet_send_naws(telnet, w, h);
+}
+
+void 
+MudHandler_NAWS_Disable(MudTelnet *telnet, MudTelnetHandler *handler)
+{
+    handler->enabled = FALSE;
+    mud_telnet_set_parent_naws(telnet, FALSE);
+    
+    g_message("Disabled NAWS.");
+}
+
+void 
+MudHandler_NAWS_HandleSubNeg(MudTelnet *telnet, guchar *buf, 
+    guint len, MudTelnetHandler *handler)
+{
+    return;   
+}
+
+/* ECHO */
+void 
+MudHandler_ECHO_Enable(MudTelnet *telnet, MudTelnetHandler *handler)
+{
+    mud_telnet_set_local_echo(telnet, FALSE);
+    g_message("Enabled Serverside ECHO");
+}
+
+void 
+MudHandler_ECHO_Disable(MudTelnet *telnet, MudTelnetHandler *handler)
+{
+    mud_telnet_set_local_echo(telnet, TRUE);
+    g_message("Disabled Serverside ECHO.");
+}
+
+void 
+MudHandler_ECHO_HandleSubNeg(MudTelnet *telnet, guchar *buf, 
+    guint len, MudTelnetHandler *handler)
+{
+    return;   
+}
+
+/* EOR */
+void 
+MudHandler_EOR_Enable(MudTelnet *telnet, MudTelnetHandler *handler)
+{
+    telnet->eor_enabled = TRUE;
+    g_message("Enabled EOR");
+}
+
+void 
+MudHandler_EOR_Disable(MudTelnet *telnet, MudTelnetHandler *handler)
+{
+    telnet->eor_enabled = FALSE;
+    g_message("Disabled EOR");
+}
+
+void 
+MudHandler_EOR_HandleSubNeg(MudTelnet *telnet, guchar *buf, 
+    guint len, MudTelnetHandler *handler)
+{
+    return;   
+}

Added: trunk/src/mud-telnet-handlers.h
==============================================================================
--- (empty file)
+++ trunk/src/mud-telnet-handlers.h	Wed Jun 25 08:04:06 2008
@@ -0,0 +1,54 @@
+/* GNOME-Mud - A simple Mud CLient
+ * Copyright (C) 1998-2006 Robin Ericsson <lobbin localhost nu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* Code originally from wxMUD. Converted to a GObject by Les Harris.
+ * wxMUD - an open source cross-platform MUD client.
+ * Copyright (C) 2003-2008 Mart Raudsepp and Gabriel Levin
+ */
+
+#ifndef MUD_TELNET_HANDLERS_H
+#define MUD_TELNET_HANDLERS_H
+
+#include "mud-telnet.h"
+
+/* TTYPE */
+void MudHandler_TType_Enable(MudTelnet *telnet, MudTelnetHandler *handler);
+void MudHandler_TType_Disable(MudTelnet *telnet, MudTelnetHandler *handler);
+void MudHandler_TType_HandleSubNeg(MudTelnet *telnet, guchar *buf, 
+    guint len, MudTelnetHandler *handler);
+    
+/* NAWS */
+void MudHandler_NAWS_Enable(MudTelnet *telnet, MudTelnetHandler *handler);
+void MudHandler_NAWS_Disable(MudTelnet *telnet, MudTelnetHandler *handler);
+void MudHandler_NAWS_HandleSubNeg(MudTelnet *telnet, guchar *buf, 
+    guint len, MudTelnetHandler *handler);
+    
+/* ECHO */
+void MudHandler_ECHO_Enable(MudTelnet *telnet, MudTelnetHandler *handler);
+void MudHandler_ECHO_Disable(MudTelnet *telnet, MudTelnetHandler *handler);
+void MudHandler_ECHO_HandleSubNeg(MudTelnet *telnet, guchar *buf, 
+    guint len, MudTelnetHandler *handler);
+    
+/* EOR */
+void MudHandler_EOR_Enable(MudTelnet *telnet, MudTelnetHandler *handler);
+void MudHandler_EOR_Disable(MudTelnet *telnet, MudTelnetHandler *handler);
+void MudHandler_EOR_HandleSubNeg(MudTelnet *telnet, guchar *buf, 
+    guint len, MudTelnetHandler *handler);
+    
+#endif // MUD_TELNET_HANDLERS_H
+

Modified: trunk/src/mud-telnet.c
==============================================================================
--- trunk/src/mud-telnet.c	(original)
+++ trunk/src/mud-telnet.c	Wed Jun 25 08:04:06 2008
@@ -32,6 +32,7 @@
 
 #include "gnome-mud.h"
 #include "mud-telnet.h"
+#include "mud-telnet-handlers.h"
 
 #define TELNET_TRACE_MASK _("telnet")
 
@@ -55,6 +56,7 @@
 static gint mud_telnet_get_telopt_queue(guchar *storage, const guint bitshift);
 static void  mud_telnet_set_telopt_state(guchar *storage, 
     const enum TelnetOptionState state, const guint bitshift);
+static gint mud_telnet_get_index_by_option(MudTelnet *telnet, guchar option_number);
 static void mud_telnet_set_telopt_queue(guchar *storage, 
     gint bit_on, const guint bitshift);
 static gint mud_telnet_handle_positive_nego(MudTelnet *telnet,
@@ -102,7 +104,6 @@
 mud_telnet_init (MudTelnet *telnet)
 {
 	telnet->priv = g_new0(MudTelnetPrivate, 1);
-	
 }
 
 static void
@@ -139,56 +140,111 @@
 	
 	telnet->parent = parent;
 	telnet->conn = connection;
-	// FIXME
+	telnet->tel_state = TEL_STATE_TEXT;
 	
 	memset(telnet->telopt_states, 0, sizeof(telnet->telopt_states));
-/*	memset(m_handlers, 0, sizeof(m_handlers));
-	*/
+	memset(telnet->handlers, 0, sizeof(telnet->handlers));
+	
+	mud_telnet_register_handlers(telnet);
 	
+	telnet->eor_enabled = FALSE;
+		
 	return telnet;	
 }
 
-gint
-mud_telnet_register_handler(MudTelnet *telnet, guint8 option_number, const gchar *classname)
+void
+mud_telnet_register_handlers(MudTelnet *telnet)
 {
-
-    // FIXME
-    /*
-	TeloptHandlersMap::const_iterator iter = telopt_handler_names.find(option_number);
-	if (iter == telopt_handler_names.end())
-	{
-		// FIXME: Leaks?
-		telopt_handler_names[option_number] = wxString(classname);
-		//wxPrintf(wxT("class '%s' registered as handling option %u\n"), classname, option_number);
-		return TRUE;
-	}
-	else
-		// Already registered.
-		// FIXME: Should we consider re-registering and handling properly the already existing
-		// FIXME: handler instances in m_handlers[option_number]?
-		return FALSE;
-	*/
-	
-	return FALSE;
+    gint i;
+    
+    for(i = 0; i < TEL_HANDLERS_SIZE; ++i)
+    {
+        telnet->handlers[i].type = HANDLER_NONE;
+        telnet->handlers[i].enabled = FALSE;
+        telnet->handlers[i].instance = NULL;
+        telnet->handlers[i].enable = NULL;
+        telnet->handlers[i].disable = NULL;
+        telnet->handlers[i].handle_sub_neg = NULL;
+    }
+    
+    /* TTYPE */
+    telnet->handlers[0].type = HANDLER_TTYPE;
+    telnet->handlers[0].option_number = (guchar)TELOPT_TTYPE;
+    telnet->handlers[0].enabled = TRUE;
+    telnet->handlers[0].enable = MudHandler_TType_Enable;
+    telnet->handlers[0].disable = MudHandler_TType_Disable;
+    telnet->handlers[0].handle_sub_neg = MudHandler_TType_HandleSubNeg;
+    
+    /* NAWS */
+    telnet->handlers[1].type = HANDLER_NAWS;
+    telnet->handlers[1].option_number = (guchar)TELOPT_NAWS;
+    telnet->handlers[1].enabled = TRUE;
+    telnet->handlers[1].enable = MudHandler_NAWS_Enable;
+    telnet->handlers[1].disable = MudHandler_NAWS_Disable;
+    telnet->handlers[1].handle_sub_neg = MudHandler_NAWS_HandleSubNeg;
+    
+    /* ECHO */
+    telnet->handlers[2].type = HANDLER_ECHO;
+    telnet->handlers[2].option_number = (guchar)TELOPT_ECHO;
+    telnet->handlers[2].enabled = TRUE;
+    telnet->handlers[2].enable = MudHandler_ECHO_Enable;
+    telnet->handlers[2].disable = MudHandler_ECHO_Disable;
+    telnet->handlers[2].handle_sub_neg = MudHandler_ECHO_HandleSubNeg;
+    
+    /* EOR */
+    telnet->handlers[3].type = HANDLER_EOR;
+    telnet->handlers[3].option_number = (guchar)TELOPT_EOR;
+    telnet->handlers[3].enabled = TRUE;
+    telnet->handlers[3].enable = MudHandler_EOR_Enable;
+    telnet->handlers[3].disable = MudHandler_EOR_Disable;
+    telnet->handlers[3].handle_sub_neg = MudHandler_EOR_HandleSubNeg;
 }
 
 gint
 mud_telnet_isenabled(MudTelnet *telnet, guint8 option_number, gint him)
 {
-    // FIXME!!
-	/*TeloptHandlersMap::const_iterator iter = telopt_handler_names.find(option_number);
+    gint i;
+    
+    for(i = 0; i < TEL_HANDLERS_SIZE; ++i)
+        if(telnet->handlers[i].type != HANDLER_NONE)
+            if(option_number == telnet->handlers[i].option_number)
+                return telnet->handlers[i].enabled;
+                
+    return FALSE;
+}
 
-	if (iter != telopt_handler_names.end() && (*iter).second)
-	{
-		if (!m_handlers[option_number])
-			m_handlers[option_number] = (TelnetHandler*)wxCreateDynamicObject((*iter).second);
+void 
+mud_telnet_get_parent_size(MudTelnet *telnet, gint *w, gint *h)
+{
+    mud_connection_view_get_term_size(telnet->parent, w, h);
+}
 
-		return m_handlers[option_number]->IsEnabled();
-	}
-	else
-		return FALSE;*/
-		
-	return FALSE;
+void 
+mud_telnet_set_parent_naws(MudTelnet *telnet, gint enabled)
+{
+    mud_connection_view_set_naws(telnet->parent, enabled);
+}
+
+void 
+mud_telnet_set_local_echo(MudTelnet *telnet, gint enabled)
+{
+    telnet->parent->local_echo = enabled;
+}
+
+void
+mud_telnet_send_naws(MudTelnet *telnet, gint width, gint height)
+{	
+    guchar w1, h1, w0, h0;
+    
+    w1 = (width >> 8) & 0xff;
+    w0 = width & 0xff;
+    
+    h1 = (height >> 8) & 0xff;
+    h0 = height & 0xff;
+    
+    mud_telnet_send_sub_req(telnet, 5, (guchar)TELOPT_NAWS, w1, w0, h1, h0);
+    
+    g_message("Sending NAWS: %d %d %d %d", w1, w0, h1, h0);
 }
 
 MudTelnetBuffer 
@@ -205,7 +261,6 @@
 		switch (telnet->tel_state)
 		{
 			case TEL_STATE_TEXT:
-			    g_message("Text state\n");
 				if (buf[i] == (guchar)TEL_IAC)
 					telnet->tel_state = TEL_STATE_IAC;
 				else
@@ -213,88 +268,103 @@
 				break;
 
 			case TEL_STATE_IAC:
-			    g_message("IAC\n");
+			    g_message("IAC");
 				switch (buf[i])
 				{
 					case (guchar)TEL_IAC:
-					    g_message("\tIAC\n");
+					    g_message("\tIAC");
 						processed[pos++] = buf[i];
 						telnet->tel_state = TEL_STATE_TEXT;
 						break;
 
 					case (guchar)TEL_DO:
-					    g_message("\tDO\n");
+					    g_message("\tDO");
 						telnet->tel_state = TEL_STATE_DO;
 						break;
 
 					case (guchar)TEL_DONT:
-					    g_message("\tDONT\n");
+					    g_message("\tDONT");
 						telnet->tel_state = TEL_STATE_DONT;
 						break;
 
 					case (guchar)TEL_WILL:
-					    g_message("\tWILL\n");
+					    g_message("\tWILL");
 						telnet->tel_state = TEL_STATE_WILL;
 						break;
+						
+					case (guchar)TEL_NOP:
+					    g_message("\tNOP");
+					    telnet->tel_state = TEL_STATE_TEXT;
+					    break;
+
+                    case (guchar)TEL_GA:
+                        g_message("\tGA");
+                        telnet->tel_state = TEL_STATE_TEXT;
+                        break;
+                        
+                    case (guchar)TEL_EOR_BYTE:
+                        g_message("\tEOR");
+                        telnet->tel_state = TEL_STATE_TEXT;
+                        break;
 
 					case (guchar)TEL_WONT:
-					    g_message("\tWONT\n");
+					    g_message("\tWONT");
 						telnet->tel_state = TEL_STATE_WONT;
 						break;
 
 					case (guchar)TEL_SB:
-						g_message("Receiving subrequest\n");
+						g_message("Receiving subrequest");
 						telnet->tel_state = TEL_STATE_SB;
 						telnet->subreq_pos = 0;
 						break;
 
 					default:
-						g_warning("Illegal IAC command %d received\n", buf[i]);
+						g_warning("Illegal IAC command %d received", buf[i]);
 						telnet->tel_state = TEL_STATE_TEXT;
 						break;
 				}
 				break;
 
 			case TEL_STATE_DO:
-			    g_message("STATE_DO\n");
+			    g_message("STATE_DO");
 				mud_telnet_handle_positive_nego(telnet, buf[i], 
 				    (guchar)TEL_WILL, (guchar)TEL_WONT, FALSE);
 				telnet->tel_state = TEL_STATE_TEXT;
 
 			case TEL_STATE_WILL:
-			    g_message("STATE_WILL\n");
+			    g_message("STATE_WILL");
 				mud_telnet_handle_positive_nego(telnet, buf[i], 
 				    (guchar)TEL_DO, (guchar)TEL_DONT, TRUE);
 				telnet->tel_state = TEL_STATE_TEXT;
 				break;
 
 			case TEL_STATE_DONT:
-			    g_message("STATE_DONT\n");
+			    g_message("STATE_DONT");
 				mud_telnet_handle_negative_nego(telnet, 
 				    buf[i], (guchar)TEL_WILL, (guchar)TEL_WONT, FALSE);
 				telnet->tel_state = TEL_STATE_TEXT;
 				break;
 
 			case TEL_STATE_WONT:
-			    g_message("STATE_WONT\n");
+			    g_message("STATE_WONT: Won't do telopt: %d", buf[i]);
 				mud_telnet_handle_negative_nego(telnet, 
 				    buf[i], (guchar)TEL_DO, (guchar)TEL_DONT, TRUE);
 				telnet->tel_state = TEL_STATE_TEXT;
 				break;
 
 			case TEL_STATE_SB:
-			    g_message("STATE_SB\n");
+			    g_message("STATE_SB");
 				if (buf[i] == (guchar)TEL_IAC)
 					telnet->tel_state = TEL_STATE_SB_IAC;
 				else
 				{
 					if (telnet->subreq_pos == 0)
-						g_message("Subrequest for option %d\n", buf[i]);
+						g_message("Subrequest for option %d", buf[i]);
 
 					// FIXME: Handle overflow
 					if (telnet->subreq_pos >= TEL_SUBREQ_BUFFER_SIZE)
 					{
-						g_warning("Subrequest buffer full. Oddities in output will happen. Sorry.\n");
+						g_warning("Subrequest buffer full. Oddities in output will happen. Sorry.");
 						telnet->subreq_pos = 0;
 						telnet->tel_state = TEL_STATE_TEXT;
 					}
@@ -304,12 +374,12 @@
 				break;
 
 			case TEL_STATE_SB_IAC:
-			    g_message("STATE_SB_IAC\n");
+			    g_message("STATE_SB_IAC");
 				if (buf[i] == (guchar)TEL_IAC)
 				{
 					if (telnet->subreq_pos >= TEL_SUBREQ_BUFFER_SIZE)
 					{
-						g_warning("Subrequest buffer full. Oddities in output will happen. Sorry.\n");
+						g_warning("Subrequest buffer full. Oddities in output will happen. Sorry.");
 						telnet->subreq_pos = 0;
 						telnet->tel_state = TEL_STATE_TEXT;
 					}
@@ -320,17 +390,17 @@
 				}
 				else if (buf[i] == (guchar)TEL_SE)
 				{
-				    g_message("STATE_TEL_SE\n");
-					g_message("Subrequest for option %d succesfully received with length %d\n", 
+				    g_message("STATE_TEL_SE");
+					g_message("Subrequest for option %d succesfully received with length %d", 
 					    telnet->subreq_buffer[0], telnet->subreq_pos-1);
-					g_message("Subreq buffer content: %d %d %d %d\n", 
+					g_message("Subreq buffer content: %d %d %d %d", 
 					    telnet->subreq_buffer[0], telnet->subreq_buffer[1], 
 					    telnet->subreq_buffer[2], telnet->subreq_buffer[3]);
 					    
 					mud_telnet_on_handle_subnego(telnet);
 					telnet->tel_state = TEL_STATE_TEXT;
 				} else {
-					g_warning("Erronous byte %d after an IAC inside a subrequest\n", buf[i]);
+					g_warning("Erronous byte %d after an IAC inside a subrequest", buf[i]);
 					telnet->subreq_pos = 0;
 					telnet->tel_state = TEL_STATE_TEXT;
 				}
@@ -443,6 +513,26 @@
 	gnet_conn_write(telnet->conn, (gchar *)&byte, 1);
 }
 
+void 
+mud_telnet_send_raw(MudTelnet *telnet, guint32 count, ...)
+{
+	guchar byte;
+	guint32 i;
+	va_list va;
+	va_start(va, count);
+
+	for (i = 0; i < count; ++i)
+	{
+		byte = (guchar)va_arg(va, gint);
+		gnet_conn_write(telnet->conn, (gchar *)&byte, 1);
+		
+		if (byte == (guchar)TEL_IAC)
+			gnet_conn_write(telnet->conn, (gchar *)&byte, 1);
+	}
+
+	va_end(va);
+}
+
 /*** Private Methods ***/
 static void 
 mud_telnet_send_iac(MudTelnet *telnet, guchar ch1, guchar ch2)
@@ -452,41 +542,55 @@
 	buf[1] = ch1;
 	buf[2] = ch2;
 	
-	// Replace with gnet equivalent
 	gnet_conn_write(telnet->conn, (gchar *)buf, 3);
 }
 
 static void
 mud_telnet_on_handle_subnego(MudTelnet *telnet)
 {
+    int index;
+    
 	if (telnet->subreq_pos < 1) 
 	    return;
-
-	/*if (mud_telnet_is_enabled(telnet, subreq_buffer[0], FALSE))
-		m_handlers[subreq_buffer[0]]->HandleSubNego(this, subreq_buffer + 1, subreq_pos - 1);
-	*/
+    
+    if((index = mud_telnet_get_index_by_option(telnet, telnet->subreq_buffer[0])) == -1)
+    {
+        g_warning("Invalid Telnet Option passed: %d", telnet->subreq_buffer[0]);
+        return;
+    }
+        
+    if (mud_telnet_isenabled(telnet, telnet->subreq_buffer[0], FALSE))
+        telnet->handlers[index].handle_sub_neg(telnet, telnet->subreq_buffer + 1,
+            telnet->subreq_pos - 1, &telnet->handlers[index]);
 }
 
 static void
 mud_telnet_on_enable_opt(MudTelnet *telnet, const guchar opt_no, gint him)
 {
-	if (telnet->subreq_pos < 1) 
-	    return;
-
-	/*if (mud_telnet_is_enabled(telnet, subreq_buffer[0], FALSE))
-		m_handlers[subreq_buffer[0]]->HandleSubNego(this, subreq_buffer + 1, subreq_pos - 1);
-	*/
+    int index;
+    
+    g_message("Trying to enable option %d", opt_no);
+    if((index = mud_telnet_get_index_by_option(telnet, opt_no)) == -1)
+    {
+        g_warning("Invalid Telnet Option passed: %d", opt_no);
+        return;
+    }
+    
+    telnet->handlers[index].enable(telnet, &telnet->handlers[index]);
 }
 
 static void
 mud_telnet_on_disable_opt(MudTelnet *telnet, const guchar opt_no, gint him)
 {
-	if (telnet->subreq_pos < 1) 
-	    return;
+    int index;
+    
+    if((index = mud_telnet_get_index_by_option(telnet, opt_no)) == -1)
+    {
+        g_warning("Invalid Telnet Option passed: %d", opt_no);
+        return;
+    }
 
-	/*if (mud_telnet_is_enabled(telnet, subreq_buffer[0], FALSE))
-		m_handlers[subreq_buffer[0]]->HandleSubNego(this, subreq_buffer + 1, subreq_pos - 1);
-	*/
+    telnet->handlers[index].disable(telnet, &telnet->handlers[index]);
 }
 
 static guchar
@@ -525,7 +629,7 @@
 {
 	const guint bitshift = him ? 4 : 0;
 	guchar * opt = &(telnet->telopt_states[opt_no]);
-
+    
 	switch (mud_telnet_get_telopt_state(opt, bitshift))
 	{
 		case TELOPT_STATE_NO:
@@ -540,7 +644,7 @@
 				mud_telnet_on_enable_opt(telnet, opt_no, him);
 				return TRUE;
 			} else {
-				// printf("Server, you DONT do %d\n", opt_no);
+				//printf("Server, you DONT do %d\n", opt_no);
 				mud_telnet_send_iac(telnet, negative, opt_no);
 				return FALSE;
 			}
@@ -568,6 +672,7 @@
 			if (mud_telnet_get_telopt_queue(opt, bitshift) == TELOPT_STATE_QUEUE_EMPTY)
 			{
 				mud_telnet_set_telopt_state(opt, TELOPT_STATE_YES, bitshift);
+				mud_telnet_send_iac(telnet, affirmative, opt_no);
 				mud_telnet_on_enable_opt(telnet, opt_no, him);
 				return TRUE;
 			} else { // The opposite is queued
@@ -592,7 +697,7 @@
 {
 	const guint bitshift = him ? 4 : 0;
 	guchar * opt = &(telnet->telopt_states[opt_no]);
-
+    
 	switch (mud_telnet_get_telopt_state(opt, bitshift))
 	{
 		case TELOPT_STATE_NO:
@@ -601,7 +706,7 @@
 
 		case TELOPT_STATE_YES:
 			mud_telnet_set_telopt_state(opt, TELOPT_STATE_NO, bitshift);
-			//printf("Ok, server, I ACK that you DONT do %d\n", opt_no);
+		    //printf("Ok, server, I ACK that you DONT do %d\n", opt_no);
 			mud_telnet_send_iac(telnet, negative, opt_no);
 			mud_telnet_on_disable_opt(telnet, opt_no, him);
 			return TRUE;
@@ -615,7 +720,7 @@
 				mud_telnet_set_telopt_state(opt, TELOPT_STATE_WANTYES, bitshift);
 				mud_telnet_set_telopt_queue(opt, TELOPT_STATE_QUEUE_EMPTY, bitshift);
 				//printf("Ok, server, you are making me angry. DO %d", opt_no);
-				mud_telnet_send_iac(telnet, affirmative, opt_no);
+			    mud_telnet_send_iac(telnet, affirmative, opt_no);
 				mud_telnet_on_enable_opt(telnet, opt_no, him); // FIXME: Is this correct?
 				return TRUE;
 			}
@@ -636,3 +741,16 @@
 	}
 }
 
+static gint 
+mud_telnet_get_index_by_option(MudTelnet *telnet, guchar option_number)
+{
+    gint i;
+    
+    for(i = 0; i < TEL_HANDLERS_SIZE; i++)
+        if(telnet->handlers[i].type != HANDLER_NONE)
+            if(telnet->handlers[i].option_number == option_number)
+                return i;
+                
+    return -1;
+}
+

Modified: trunk/src/mud-telnet.h
==============================================================================
--- trunk/src/mud-telnet.h	(original)
+++ trunk/src/mud-telnet.h	Wed Jun 25 08:04:06 2008
@@ -34,7 +34,7 @@
 #define MUD_TELNET_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), MUD_TYPE_TELNET, MudTelnetClass))
 
 #define TEL_SE				240	// End of subnegotiation parameters
-//#define TEL_NOP				241	// No operation - not yet supported
+#define TEL_NOP				241	// No operation
 #define TEL_GA				249	// Go ahead
 #define TEL_SB				250	// Indicates that what follows is subnegotiation of the indicated option
 #define TEL_WILL			251	// I will use option
@@ -49,6 +49,7 @@
 #	define TEL_TTYPE_IS		  0	// Terminal type IS ...
 #	define TEL_TTYPE_SEND	  1	// SEND me terminal type
 #define TELOPT_EOR			 25	// End of record		- RFC  885
+#   define TEL_EOR_BYTE     239 // End of record byte.
 #define TELOPT_NAWS			 31	// Window size			- RFC 1073
 #define TELOPT_CHARSET		 42	// Charset				- RFC 2066
 #define TELOPT_MCCP			 85	// MCCP
@@ -61,6 +62,7 @@
 
 // FIXME: What size should we use?
 #define TEL_SUBREQ_BUFFER_SIZE 256
+#define TEL_HANDLERS_SIZE 256
 #define TELOPT_STATE_QUEUE_EMPTY	FALSE
 #define TELOPT_STATE_QUEUE_OPPOSITE	TRUE
 
@@ -68,6 +70,12 @@
 typedef struct _MudTelnetClass       MudTelnetClass;
 typedef struct _MudTelnetPrivate     MudTelnetPrivate;
 typedef struct _MudTelnetBuffer      MudTelnetBuffer;
+typedef struct _MudTelnetHandler     MudTelnetHandler;
+
+typedef void(*MudTelnetOnEnableFunc)(MudTelnet *telnet, MudTelnetHandler *handler);
+typedef void(*MudTelnetOnDisableFunc)(MudTelnet *telnet, MudTelnetHandler *handler);
+typedef void(*MudTelnetOnHandleSubNegFunc)(MudTelnet *telnet, 
+    guchar *buf, guint len, MudTelnetHandler *handler);
 
 enum TelnetState
 {
@@ -89,6 +97,15 @@
 	TELOPT_STATE_YES = 3,     // bits 11
 };
 
+enum TelnetHandlerType
+{
+    HANDLER_NONE,
+    HANDLER_TTYPE,
+    HANDLER_NAWS,
+    HANDLER_ECHO,
+    HANDLER_EOR
+};
+
 struct _MudTelnetClass
 {
 	GObjectClass parent_class;
@@ -100,6 +117,20 @@
     size_t len;
 };
 
+struct _MudTelnetHandler
+{
+    enum TelnetHandlerType type;
+    guchar option_number;
+    
+    gint enabled;
+    
+    MudTelnet *instance;
+    
+    MudTelnetOnEnableFunc enable;
+    MudTelnetOnDisableFunc disable;
+    MudTelnetOnHandleSubNegFunc handle_sub_neg;
+};
+
 #include <gnet.h>
 #include <mud-connection-view.h>
 struct _MudTelnet
@@ -113,25 +144,27 @@
 	guint32 subreq_pos;
 	
 	guchar telopt_states[256];
+	gint eor_enabled;
 	
 	GConn *conn;
 	MudConnectionView *parent;
 
-	/**
-		Pointers to option handler instances. NULL if none is created yet.
-	*/
-	//TelnetHandler * m_handlers[256];
+	MudTelnetHandler handlers[TEL_HANDLERS_SIZE];
 };
 
 GType mud_telnet_get_type (void) G_GNUC_CONST;
 
 MudTelnet *mud_telnet_new(MudConnectionView *parent, GConn *connection);
 
-gint mud_telnet_register_handler(MudTelnet *telnet, 
-            guint8 option_number, const gchar *classname);
+void mud_telnet_register_handlers(MudTelnet *telnet);
 gint mud_telnet_isenabled(MudTelnet *telnet, guint8 option_number, gint him);
 MudTelnetBuffer mud_telnet_process(MudTelnet *telnet, guchar * buf, guint32 count);
 void mud_telnet_send_sub_req(MudTelnet *telnet, guint32 count, ...);
+void mud_telnet_get_parent_size(MudTelnet *telnet, gint *w, gint *h);
+void mud_telnet_send_raw(MudTelnet *telnet, guint32 count, ...);
+void mud_telnet_set_parent_naws(MudTelnet *telnet, gint enabled);
+void mud_telnet_send_naws(MudTelnet *telnet, gint w, gint h);
+void mud_telnet_set_local_echo(MudTelnet *telnet, gint enabled);
 
 G_END_DECLS
 

Modified: trunk/src/mud-window.c
==============================================================================
--- trunk/src/mud-window.c	(original)
+++ trunk/src/mud-window.c	Wed Jun 25 08:04:06 2008
@@ -453,6 +453,9 @@
 
 	gtk_widget_grab_focus(window->priv->textview);
 	
+	// FIXME: Should send naws to all views.
+	mud_connection_view_send_naws(MUD_CONNECTION_VIEW(window->priv->current_view));
+	
 	return FALSE;
 }
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]