Push encoder and decoder handling down into the connection objects

This keeps the reader and writer objects clean and simple protocol
decoders/encoders.
diff --git a/vncviewer/CConn.cxx b/vncviewer/CConn.cxx
index d7f57b5..f542062 100644
--- a/vncviewer/CConn.cxx
+++ b/vncviewer/CConn.cxx
@@ -1,6 +1,6 @@
 /* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
- * Copyright 2009-2011 Pierre Ossman <ossman@cendio.se> for Cendio AB
  * Copyright (C) 2011 D. R. Commander.  All Rights Reserved.
+ * Copyright 2009-2014 Pierre Ossman for Cendio AB
  * 
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -29,6 +29,7 @@
 
 #include <rfb/CMsgWriter.h>
 #include <rfb/encodings.h>
+#include <rfb/Decoder.h>
 #include <rfb/Hostname.h>
 #include <rfb/LogWriter.h>
 #include <rfb/util.h>
@@ -80,6 +81,8 @@
   setShared(::shared);
   sock = socket;
 
+  memset(decoders, 0, sizeof(decoders));
+
   int encNum = encodingNum(preferredEncoding);
   if (encNum != -1)
     currentEncoding = encNum;
@@ -131,6 +134,9 @@
 {
   OptionsDialog::removeCallback(handleOptions);
 
+  for (int i = 0; i < sizeof(decoders)/sizeof(decoders[0]); i++)
+    delete decoders[i];
+
   if (desktop)
     delete desktop;
 
@@ -380,19 +386,27 @@
   delete [] buffer;
 }
 
-// We start timing on beginRect and stop timing on endRect, to
-// avoid skewing the bandwidth estimation as a result of the server
-// being slow or the network having high latency
-void CConn::beginRect(const Rect& r, int encoding)
+void CConn::dataRect(const Rect& r, int encoding)
 {
   sock->inStream().startTiming();
-  if (encoding != encodingCopyRect) {
-    lastServerEncoding = encoding;
-  }
-}
 
-void CConn::endRect(const Rect& r, int encoding)
-{
+  if (encoding != encodingCopyRect)
+    lastServerEncoding = encoding;
+
+  if (!Decoder::supported(encoding)) {
+    fprintf(stderr, "Unknown rect encoding %d\n", encoding);
+    throw Exception("Unknown rect encoding");
+  }
+
+  if (!decoders[encoding]) {
+    decoders[encoding] = Decoder::createDecoder(encoding, reader());
+    if (!decoders[encoding]) {
+      fprintf(stderr, "Unknown rect encoding %d\n", encoding);
+      throw Exception("Unknown rect encoding");
+    }
+  }
+  decoders[encoding]->readRect(r, this);
+
   sock->inStream().stopTiming();
 }
 
diff --git a/vncviewer/CConn.h b/vncviewer/CConn.h
index 286a09e..f7f560b 100644
--- a/vncviewer/CConn.h
+++ b/vncviewer/CConn.h
@@ -1,5 +1,5 @@
 /* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
- * Copyright 2009-2011 Pierre Ossman <ossman@cendio.se> for Cendio AB
+ * Copyright 2009-2014 Pierre Ossman for Cendio AB
  * 
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -23,8 +23,11 @@
 #include <FL/Fl.H>
 
 #include <rfb/CConnection.h>
+#include <rfb/encodings.h>
 #include <network/Socket.h>
 
+namespace rfb { class Decoder; }
+
 class DesktopWindow;
 
 class CConn : public rfb::CConnection,
@@ -62,8 +65,7 @@
   void framebufferUpdateStart();
   void framebufferUpdateEnd();
 
-  void beginRect(const rfb::Rect& r, int encoding);
-  void endRect(const rfb::Rect& r, int encoding);
+  void dataRect(const rfb::Rect& r, int encoding);
 
   void fillRect(const rfb::Rect& r, rfb::Pixel p);
   void imageRect(const rfb::Rect& r, void* p);
@@ -102,6 +104,8 @@
   bool pendingPFChange;
   rfb::PixelFormat pendingPF;
 
+  rfb::Decoder *decoders[rfb::encodingMax+1];
+
   int currentEncoding, lastServerEncoding;
 
   bool formatChange;