remove telnet_send_telopt() as it has no real purpose and using it can have surprising results; added telnet_begin_subnegotiation and telnet_finish_subnegotiation
diff --git a/README b/README
index 81af3cd..b643bc2 100644
--- a/README
+++ b/README
@@ -112,11 +112,6 @@
    Sends a single "simple" TELNET command, such as the GO-AHEAD
    commands (255 249).
 
- void telnet_send_telopt(telnet_t *telnet, unsigned char cmd,
-     unsigned char telopt);
-   Sends a TELNET command with an option code following.  This is
-   only useful for the WILL, WONT, DO, DONT, and SB commands.
-
  void telnet_send_negotiate(telnet_t *telnet, unsigned char cmd,
      unsigned char opt);
    Sends a TELNET negotiation command.  The cmd parameter must be one
@@ -135,20 +130,38 @@
 
    For sending regular text is may be more convenient to use
    telnet_printf().
+ 
+ void telnet_begin_subnegotiation(telnet_t *telnet, unsigned char
+     telopt);
+   Sends the header for a TELNET sub-negotiation command for the
+   specified option.  All send data following this command will be
+   part of the sub-negotiation data until a call is made to
+   telnet_finish_subnegotiation().
+
+   You should not use telnet_printf() for sending subnegotiation
+   data as it will perform newline translations that usually do not
+   need to be done for subnegotiation data, and may cause problems.
+
+ void telnet_finish_subnegotiation(telnet_t *telnet);
+   Sends the end marker for a TELNET sub-negotiation command.  This
+   must be called after (and only after) a call has been made to
+   telnet_begin_subnegotiation() and any negotiation data has been
+   sent.
 
  void telnet_send_subnegotiation(telnet_t *telnet,
      unsigned char telopt, const char *buffer, unsigned int size);
    Sends a TELNET sub-negotiation command.  The telopt parameter is
    the sub-negotiation option.
 
-   Note that the above function is just a shorthand for:
-    telnet_send_telopt(telnet, TELNET_SB, telopt);
+   Note that this function is just a shorthand for:
+    telnet_begin_subnegotiation(telnet, telopt);
     telnet_send_data(telnet, buffer, size);
-    telnet_send_command(telnet, TELNET_SE);
+    telnet_end_subnegotiation(telnet);
 
    For some subnegotiations that involve a lot of complex formatted
-   data to be sent, it may be easier to manually send the SB telopt
-   header and SE footer around mulitple calls to send_data.
+   data to be sent, it may be easier to make calls to both
+   telnet_begin_negotiation() and telnet_end_subnegotiation() and
+   using telnet_send_data() or telnet_printf2() to format the data.
 
    NOTE: telnet_send_subnegotiation() does have special behavior in
    PROXY mode, as in that mode this function will automatically
diff --git a/libtelnet.c b/libtelnet.c
index 212bf0f..aee0bc5 100644
--- a/libtelnet.c
+++ b/libtelnet.c
@@ -22,6 +22,12 @@
 
 #include "libtelnet.h"
 
+/* RFC1143 option negotiation state */
+typedef struct telnet_rfc1143_t {
+	unsigned char telopt;
+	char us:4, him:4;
+} telnet_rfc1143_t;
+
 /* RFC1143 state names */
 #define RFC1143_NO 0x00
 #define RFC1143_YES 0x01
@@ -208,6 +214,13 @@
 	telnet->q[telnet->q_size++] = q;
 }
 
+/* send negotiation bytes */
+static void _send_negotiate(telnet_t *telnet, unsigned char cmd,
+		unsigned char telopt) {
+	char bytes[3] = { TELNET_IAC, cmd, telopt };
+	_send(telnet, bytes, 3);
+}
+
 /* negotiation handling magic for RFC1143 */
 static void _negotiate(telnet_t *telnet, unsigned char cmd,
 		unsigned char telopt) {
@@ -244,9 +257,9 @@
 			if (_event(telnet, TELNET_EV_WILL, cmd, telopt, 0, 0) == 1) {
 				q.him = RFC1143_YES;
 				_set_rfc1143(telnet, q);
-				telnet_send_telopt(telnet, TELNET_DO, telopt);
+				_send_negotiate(telnet, TELNET_DO, telopt);
 			} else
-				telnet_send_telopt(telnet, TELNET_DONT, telopt);
+				_send_negotiate(telnet, TELNET_DONT, telopt);
 			break;
 		case RFC1143_YES:
 			break;
@@ -272,7 +285,7 @@
 		case RFC1143_WANTYES_OP:
 			q.him = RFC1143_WANTNO;
 			_set_rfc1143(telnet, q);
-			telnet_send_telopt(telnet, TELNET_DONT, telopt);
+			_send_negotiate(telnet, TELNET_DONT, telopt);
 			_event(telnet, TELNET_EV_WILL, cmd, telopt, 0, 0);
 			break;
 		}
@@ -286,7 +299,7 @@
 		case RFC1143_YES:
 			q.him = RFC1143_NO;
 			_set_rfc1143(telnet, q);
-			telnet_send_telopt(telnet, TELNET_DONT, telopt);
+			_send_negotiate(telnet, TELNET_DONT, telopt);
 			_event(telnet, TELNET_EV_WONT, 0, telopt, 0, 0);
 			break;
 		case RFC1143_WANTNO:
@@ -314,9 +327,9 @@
 			if (_event(telnet, TELNET_EV_DO, cmd, telopt, 0, 0) == 1) {
 				q.us = RFC1143_YES;
 				_set_rfc1143(telnet, q);
-				telnet_send_telopt(telnet, TELNET_WILL, telopt);
+				_send_negotiate(telnet, TELNET_WILL, telopt);
 			} else
-				telnet_send_telopt(telnet, TELNET_WONT, telopt);
+				_send_negotiate(telnet, TELNET_WONT, telopt);
 			break;
 		case RFC1143_YES:
 			break;
@@ -342,7 +355,7 @@
 		case RFC1143_WANTYES_OP:
 			q.us = RFC1143_WANTNO;
 			_set_rfc1143(telnet, q);
-			telnet_send_telopt(telnet, TELNET_WONT, telopt);
+			_send_negotiate(telnet, TELNET_WONT, telopt);
 			_event(telnet, TELNET_EV_DO, cmd, telopt, 0, 0);
 			break;
 		}
@@ -356,7 +369,7 @@
 		case RFC1143_YES:
 			q.us = RFC1143_NO;
 			_set_rfc1143(telnet, q);
-			telnet_send_telopt(telnet, TELNET_WONT, telopt);
+			_send_negotiate(telnet, TELNET_WONT, telopt);
 			_event(telnet, TELNET_EV_DONT, 0, telopt, 0, 0);
 			break;
 		case RFC1143_WANTNO:
@@ -675,13 +688,6 @@
 	_send(telnet, bytes, 2);
 }
 
-/* send an iac command with telopt */
-void telnet_send_telopt(telnet_t *telnet, unsigned char cmd,
-		unsigned char telopt) {
-	char bytes[3] = { TELNET_IAC, cmd, telopt };
-	_send(telnet, bytes, 3);
-}
-
 /* send negotiation */
 void telnet_send_negotiate(telnet_t *telnet, unsigned char cmd,
 		unsigned char telopt) {
@@ -704,7 +710,7 @@
 		case RFC1143_NO:
 			q.us = RFC1143_WANTYES;
 			_set_rfc1143(telnet, q);
-			telnet_send_telopt(telnet, TELNET_WILL, telopt);
+			_send_negotiate(telnet, TELNET_WILL, telopt);
 			break;
 		case RFC1143_YES:
 			break;
@@ -731,7 +737,7 @@
 		case RFC1143_YES:
 			q.us = RFC1143_WANTNO;
 			_set_rfc1143(telnet, q);
-			telnet_send_telopt(telnet, TELNET_WONT, telopt);
+			_send_negotiate(telnet, TELNET_WONT, telopt);
 			break;
 		case RFC1143_WANTNO:
 			break;
@@ -754,7 +760,7 @@
 		case RFC1143_NO:
 			q.him = RFC1143_WANTYES;
 			_set_rfc1143(telnet, q);
-			telnet_send_telopt(telnet, TELNET_DO, telopt);
+			_send_negotiate(telnet, TELNET_DO, telopt);
 			break;
 		case RFC1143_YES:
 			break;
@@ -781,7 +787,7 @@
 		case RFC1143_YES:
 			q.him = RFC1143_WANTNO;
 			_set_rfc1143(telnet, q);
-			telnet_send_telopt(telnet, TELNET_DONT, telopt);
+			_send_negotiate(telnet, TELNET_DONT, telopt);
 			break;
 		case RFC1143_WANTNO:
 			break;
@@ -826,9 +832,12 @@
 /* send sub-request */
 void telnet_send_subnegotiation(telnet_t *telnet, unsigned char telopt,
 		const char *buffer, size_t size) {
-	telnet_send_telopt(telnet, TELNET_SB, telopt);
+	const char sb[3] = { TELNET_IAC, TELNET_SB, telopt };
+	static const char se[2] = { TELNET_IAC, TELNET_SE };
+
+	_send(telnet, sb, 3);
 	telnet_send_data(telnet, buffer, size);
-	telnet_send_command(telnet, TELNET_SE);
+	_send(telnet, se, 2);
 
 #ifdef HAVE_ZLIB
 	/* if we're a proxy and we just sent the COMPRESS2 marker, we must
diff --git a/libtelnet.h b/libtelnet.h
index bfa57e4..37b1350 100644
--- a/libtelnet.h
+++ b/libtelnet.h
@@ -15,7 +15,6 @@
 /* forward declarations */
 typedef struct telnet_t telnet_t;
 typedef struct telnet_event_t telnet_event_t;
-typedef struct telnet_rfc1143_t telnet_rfc1143_t;
 
 /* telnet special values */
 #define TELNET_IAC 255
@@ -147,12 +146,6 @@
 	unsigned char accept;
 };
 
-/* option negotiation state (RFC 1143) */
-struct telnet_rfc1143_t {
-	unsigned char telopt;
-	char us:4, him:4;
-};
-
 /* event handler declaration */
 typedef void (*telnet_event_handler_t)(telnet_t *telnet,
 		telnet_event_t *event, void *user_data);
@@ -199,10 +192,6 @@
 /* send an iac command */
 extern void telnet_send_command(telnet_t *telnet, unsigned char cmd);
 
-/* send an iac command with a telopt */
-extern void telnet_send_telopt(telnet_t *telnet, unsigned char cmd,
-		unsigned char telopt);
-
 /* send negotiation, with RFC1143 checking.
  * will not actually send unless necessary, but will update internal
  * negotiation queue.
@@ -214,15 +203,22 @@
 extern void telnet_send_data(telnet_t *telnet,
 		const char *buffer, size_t size);
 
-/* send sub-request, equivalent to:
- *   telnet_send_telopt(telnet, TELNET_SB, telopt)
+/* send IAC SB followed by the telopt code */
+extern void telnet_begin_subnegotiation(telnet_t *telnet,
+		unsigned char telopt);
+
+/* send IAC SE */
+#define telnet_finish_subnegotiation(telnet) \
+		telnet_command((telnet), TELNET_SE)
+
+/* shortcut for sending a complete subnegotiation buffer.
+ * equivalent to:
+ *   telnet_begin_subnegotiation(telnet, telopt);
  *   telnet_send_data(telnet, buffer, size);
- *   telnet_send_command(telnet, TELNET_SE);
- * manually generating sequence may be easier for complex subnegotiations
- * thare are most easily implemented with a series of send_data calls.
+ *   telnet_finish_subnegotiation(telnet);
  */
-extern void telnet_send_subnegotiation(telnet_t *telnet,
-		unsigned char telopt, const char *buffer, size_t size);
+extern void telnet_send_subnegotiation(telnet_t *telnet, unsigned char telopt,
+		const char *buffer, size_t size);
 
 /* begin sending compressed data (server only) */
 extern void telnet_begin_compress2(telnet_t *telnet);