Merge the "V3" message classes into the normal ones

We have no need for this abstraction so let's keep things simple.
diff --git a/common/rfb/CMsgReader.cxx b/common/rfb/CMsgReader.cxx
index 63d31d1..8466c68 100644
--- a/common/rfb/CMsgReader.cxx
+++ b/common/rfb/CMsgReader.cxx
@@ -1,4 +1,5 @@
 /* Copyright (C) 2002-2005 RealVNC Ltd.  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
@@ -16,17 +17,19 @@
  * USA.
  */
 #include <stdio.h>
+#include <rfb/msgTypes.h>
 #include <rdr/InStream.h>
 #include <rfb/Exception.h>
 #include <rfb/util.h>
 #include <rfb/CMsgHandler.h>
 #include <rfb/CMsgReader.h>
+#include <rfb/Decoder.h>
 
 using namespace rfb;
 
 CMsgReader::CMsgReader(CMsgHandler* handler_, rdr::InStream* is_)
   : imageBufIdealSize(0), handler(handler_), is(is_),
-    imageBuf(0), imageBufSize(0)
+    imageBuf(0), imageBufSize(0), nUpdateRectsLeft(0)
 {
   for (int i = 0; i <= encodingMax; i++) {
     decoders[i] = 0;
@@ -41,6 +44,81 @@
   delete [] imageBuf;
 }
 
+void CMsgReader::readServerInit()
+{
+  int width = is->readU16();
+  int height = is->readU16();
+  handler->setDesktopSize(width, height);
+  PixelFormat pf;
+  pf.read(is);
+  handler->setPixelFormat(pf);
+  CharArray name(is->readString());
+  handler->setName(name.buf);
+  handler->serverInit();
+}
+
+void CMsgReader::readMsg()
+{
+  if (nUpdateRectsLeft == 0) {
+    int type = is->readU8();
+
+    switch (type) {
+    case msgTypeSetColourMapEntries:
+      readSetColourMapEntries();
+      break;
+    case msgTypeBell:
+      readBell();
+      break;
+    case msgTypeServerCutText:
+      readServerCutText();
+      break;
+    case msgTypeFramebufferUpdate:
+      readFramebufferUpdate();
+      break;
+    case msgTypeServerFence:
+      readFence();
+      break;
+    case msgTypeEndOfContinuousUpdates:
+      readEndOfContinuousUpdates();
+      break;
+    default:
+      fprintf(stderr, "unknown message type %d\n", type);
+      throw Exception("unknown message type");
+    }
+  } else {
+    int x = is->readU16();
+    int y = is->readU16();
+    int w = is->readU16();
+    int h = is->readU16();
+    int encoding = is->readS32();
+
+    switch (encoding) {
+    case pseudoEncodingLastRect:
+      nUpdateRectsLeft = 1;     // this rectangle is the last one
+      break;
+    case pseudoEncodingCursor:
+      readSetCursor(w, h, Point(x,y));
+      break;
+    case pseudoEncodingDesktopName:
+      readSetDesktopName(x, y, w, h);
+      break;
+    case pseudoEncodingDesktopSize:
+      handler->setDesktopSize(w, h);
+      break;
+    case pseudoEncodingExtendedDesktopSize:
+      readExtendedDesktopSize(x, y, w, h);
+      break;
+    default:
+      readRect(Rect(x, y, x+w, y+h), encoding);
+      break;
+    };
+
+    nUpdateRectsLeft--;
+    if (nUpdateRectsLeft == 0)
+      handler->framebufferUpdateEnd();
+  }
+}
+
 void CMsgReader::readSetColourMapEntries()
 {
   is->skip(1);
@@ -72,14 +150,38 @@
   handler->serverCutText(ca.buf, len);
 }
 
-void CMsgReader::readFramebufferUpdateStart()
+void CMsgReader::readFence()
 {
-  handler->framebufferUpdateStart();
+  rdr::U32 flags;
+  rdr::U8 len;
+  char data[64];
+
+  is->skip(3);
+
+  flags = is->readU32();
+
+  len = is->readU8();
+  if (len > sizeof(data)) {
+    fprintf(stderr, "Ignoring fence with too large payload\n");
+    is->skip(len);
+    return;
+  }
+
+  is->readBytes(data, len);
+
+  handler->fence(flags, len, data);
 }
 
-void CMsgReader::readFramebufferUpdateEnd()
+void CMsgReader::readEndOfContinuousUpdates()
 {
-  handler->framebufferUpdateEnd();
+  handler->endOfContinuousUpdates();
+}
+
+void CMsgReader::readFramebufferUpdate()
+{
+  is->skip(1);
+  nUpdateRectsLeft = is->readU16();
+  handler->framebufferUpdateStart();
 }
 
 void CMsgReader::readRect(const Rect& r, int encoding)
@@ -138,6 +240,43 @@
   handler->setCursor(width, height, hotspot, data.buf, mask.buf);
 }
 
+void CMsgReader::readSetDesktopName(int x, int y, int w, int h)
+{
+  char* name = is->readString();
+
+  if (x || y || w || h) {
+    fprintf(stderr, "Ignoring DesktopName rect with non-zero position/size\n");
+  } else {
+    handler->setName(name);
+  }
+
+  delete [] name;
+}
+
+void CMsgReader::readExtendedDesktopSize(int x, int y, int w, int h)
+{
+  unsigned int screens, i;
+  rdr::U32 id, flags;
+  int sx, sy, sw, sh;
+  ScreenSet layout;
+
+  screens = is->readU8();
+  is->skip(3);
+
+  for (i = 0;i < screens;i++) {
+    id = is->readU32();
+    sx = is->readU16();
+    sy = is->readU16();
+    sw = is->readU16();
+    sh = is->readU16();
+    flags = is->readU32();
+
+    layout.add_screen(Screen(id, sx, sy, sw, sh, flags));
+  }
+
+  handler->setExtendedDesktopSize(x, y, w, h, layout);
+}
+
 rdr::U8* CMsgReader::getImageBuf(int required, int requested, int* nPixels)
 {
   int requiredBytes = required * (handler->cp.pf().bpp / 8);