Create a proper interface base class for the viewport's framebuffer

This allows us to gracefully fall back to the FLTK code in case the
platform specific code cannot be used.
diff --git a/vncviewer/CMakeLists.txt b/vncviewer/CMakeLists.txt
index c1facc6..9b815a3 100644
--- a/vncviewer/CMakeLists.txt
+++ b/vncviewer/CMakeLists.txt
@@ -7,9 +7,11 @@
   menukey.cxx
   CConn.cxx
   DesktopWindow.cxx
+  FLTKPixelBuffer.cxx
   UserDialog.cxx
   ServerDialog.cxx
   OptionsDialog.cxx
+  PlatformPixelBuffer.cxx
   Viewport.cxx
   parameters.cxx
   keysym2ucs.c
diff --git a/vncviewer/FLTKPixelBuffer.cxx b/vncviewer/FLTKPixelBuffer.cxx
new file mode 100644
index 0000000..91ff787
--- /dev/null
+++ b/vncviewer/FLTKPixelBuffer.cxx
@@ -0,0 +1,52 @@
+/* Copyright 2011-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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This software 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 software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
+ * USA.
+ */
+
+#include <FL/fl_draw.H>
+
+#include <rfb/Exception.h>
+
+#include "FLTKPixelBuffer.h"
+
+FLTKPixelBuffer::FLTKPixelBuffer(int width, int height) :
+  PlatformPixelBuffer(rfb::PixelFormat(32, 24, false, true,
+                                       255, 255, 255, 0, 8, 16),
+                      width, height, NULL)
+{
+  data = new rdr::U8[width * height * format.bpp/8];
+  if (data == NULL)
+    throw rfb::Exception("Error: Not enough memory for framebuffer");
+}
+
+FLTKPixelBuffer::~FLTKPixelBuffer()
+{
+  delete [] data;
+}
+
+void FLTKPixelBuffer::draw(int src_x, int src_y, int x, int y, int w, int h)
+{
+  int pixel_bytes, stride_bytes;
+  const uchar *buf_start;
+
+  pixel_bytes = format.bpp/8;
+  stride_bytes = pixel_bytes * getStride();
+  buf_start = data +
+              pixel_bytes * src_x +
+              stride_bytes * src_y;
+
+  fl_draw_image(buf_start, x, y, w, h, pixel_bytes, stride_bytes);
+}
diff --git a/vncviewer/FLTKPixelBuffer.h b/vncviewer/FLTKPixelBuffer.h
new file mode 100644
index 0000000..148c626
--- /dev/null
+++ b/vncviewer/FLTKPixelBuffer.h
@@ -0,0 +1,33 @@
+/* Copyright 2011-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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This software 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 software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
+ * USA.
+ */
+
+#ifndef __FLTKPIXELBUFFER_H__
+#define __FLTKPIXELBUFFER_H__
+
+#include "PlatformPixelBuffer.h"
+
+class FLTKPixelBuffer: public PlatformPixelBuffer {
+public:
+  FLTKPixelBuffer(int width, int height);
+  ~FLTKPixelBuffer();
+
+  virtual void draw(int src_x, int src_y, int x, int y, int w, int h);
+};
+
+
+#endif
diff --git a/vncviewer/OSXPixelBuffer.cxx b/vncviewer/OSXPixelBuffer.cxx
index 0e03fc9..fc216a1 100644
--- a/vncviewer/OSXPixelBuffer.cxx
+++ b/vncviewer/OSXPixelBuffer.cxx
@@ -1,4 +1,4 @@
-/* Copyright 2011 Pierre Ossman <ossman@cendio.se> for Cendio AB
+/* Copyright 2011-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
@@ -34,16 +34,20 @@
 
 using namespace rfb;
 
-static rfb::LogWriter vlog("PlatformPixelBuffer");
+static rfb::LogWriter vlog("OSXPixelBuffer");
 
-PlatformPixelBuffer::PlatformPixelBuffer(int width, int height) :
-  ManagedPixelBuffer(rfb::PixelFormat(32, 24, false, true,
-                                      255, 255, 255, 16, 8, 0),
-                     width, height),
+OSXPixelBuffer::OSXPixelBuffer(int width, int height) :
+  PlatformPixelBuffer(rfb::PixelFormat(32, 24, false, true,
+                                       255, 255, 255, 16, 8, 0),
+                      width, height, NULL),
   bitmap(NULL)
 {
   CGColorSpaceRef lut;
 
+  data = new rdr::U8[width * height * format.bpp/8];
+  if (data == NULL)
+    throw rfb::Exception("Error: Not enough memory for framebuffer");
+
   lut = CGColorSpaceCreateDeviceRGB();
   assert(lut);
 
@@ -55,13 +59,14 @@
 }
 
 
-PlatformPixelBuffer::~PlatformPixelBuffer()
+OSXPixelBuffer::~OSXPixelBuffer()
 {
   CFRelease((CGContextRef)bitmap);
+  delete [] data;
 }
 
 
-void PlatformPixelBuffer::draw(int src_x, int src_y, int x, int y, int w, int h)
+void OSXPixelBuffer::draw(int src_x, int src_y, int x, int y, int w, int h)
 {
   CGRect rect;
   CGContextRef gc;
diff --git a/vncviewer/OSXPixelBuffer.h b/vncviewer/OSXPixelBuffer.h
index e59015e..8ae0184 100644
--- a/vncviewer/OSXPixelBuffer.h
+++ b/vncviewer/OSXPixelBuffer.h
@@ -1,4 +1,4 @@
-/* Copyright 2011 Pierre Ossman <ossman@cendio.se> for Cendio AB
+/* Copyright 2011-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
@@ -19,14 +19,14 @@
 #ifndef __OSXPIXELBUFFER_H__
 #define __OSXPIXELBUFFER_H__
 
-#include <rfb/PixelBuffer.h>
+#include "PlatformPixelBuffer.h"
 
-class PlatformPixelBuffer: public rfb::ManagedPixelBuffer {
+class OSXPixelBuffer: public PlatformPixelBuffer {
 public:
-  PlatformPixelBuffer(int width, int height);
-  ~PlatformPixelBuffer();
+  OSXPixelBuffer(int width, int height);
+  ~OSXPixelBuffer();
 
-  void draw(int src_x, int src_y, int x, int y, int w, int h);
+  virtual void draw(int src_x, int src_y, int x, int y, int w, int h);
 
 protected:
   // This is really a CGContextRef, but Apple headers conflict with FLTK
diff --git a/vncviewer/PlatformPixelBuffer.cxx b/vncviewer/PlatformPixelBuffer.cxx
new file mode 100644
index 0000000..8a24690
--- /dev/null
+++ b/vncviewer/PlatformPixelBuffer.cxx
@@ -0,0 +1,26 @@
+/* Copyright 2011-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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This software 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 software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
+ * USA.
+ */
+
+#include "PlatformPixelBuffer.h"
+
+PlatformPixelBuffer::PlatformPixelBuffer(const rfb::PixelFormat& pf,
+                                         int width, int height,
+                                         rdr::U8* data) :
+  FullFramePixelBuffer(pf, width, height, data)
+{
+}
diff --git a/vncviewer/PlatformPixelBuffer.h b/vncviewer/PlatformPixelBuffer.h
index f634ccd..28d085a 100644
--- a/vncviewer/PlatformPixelBuffer.h
+++ b/vncviewer/PlatformPixelBuffer.h
@@ -1,4 +1,4 @@
-/* Copyright 2011 Pierre Ossman <ossman@cendio.se> for Cendio AB
+/* Copyright 2011-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
@@ -21,31 +21,15 @@
 
 #include <rfb/PixelBuffer.h>
 
-#include <FL/fl_draw.H>
-
-class PlatformPixelBuffer: public rfb::ManagedPixelBuffer {
+class PlatformPixelBuffer: public rfb::FullFramePixelBuffer {
 public:
-  PlatformPixelBuffer(int width, int height) :
-    rfb::ManagedPixelBuffer(rfb::PixelFormat(32, 24, false, true,
-                                             255, 255, 255, 0, 8, 16),
-                            width, height)
-    {};
+  PlatformPixelBuffer(const rfb::PixelFormat& pf, int width, int height,
+                      rdr::U8* data);
 
-  inline void draw(int src_x, int src_y, int x, int y, int w, int h);
+  virtual void draw(int src_x, int src_y, int x, int y, int w, int h) = 0;
+
+protected:
+  int stride;
 };
 
-inline void PlatformPixelBuffer::draw(int src_x, int src_y, int x, int y, int w, int h)
-{
-  int pixel_bytes, stride_bytes;
-  const uchar *buf_start;
-
-  pixel_bytes = getPF().bpp/8;
-  stride_bytes = pixel_bytes * getStride();
-  buf_start = data +
-              pixel_bytes * src_x +
-              stride_bytes * src_y;
-
-  fl_draw_image(buf_start, x, y, w, h, pixel_bytes, stride_bytes);
-}
-
 #endif
diff --git a/vncviewer/Viewport.cxx b/vncviewer/Viewport.cxx
index a7296e9..a930cf8 100644
--- a/vncviewer/Viewport.cxx
+++ b/vncviewer/Viewport.cxx
@@ -51,6 +51,9 @@
 #include "menukey.h"
 #include "vncviewer.h"
 
+#include "PlatformPixelBuffer.h"
+#include "FLTKPixelBuffer.h"
+
 #if defined(WIN32)
 #include "Win32PixelBuffer.h"
 #elif defined(__APPLE__)
@@ -59,11 +62,6 @@
 #include "X11PixelBuffer.h"
 #endif
 
-// We also have a generic version of the above, using pure FLTK:
-//
-// #include "PlatformPixelBuffer.h"
-//
-
 #include <FL/fl_draw.H>
 #include <FL/fl_ask.H>
 
@@ -100,7 +98,7 @@
   Fl::add_clipboard_notify(handleClipboardChange, this);
 #endif
 
-  frameBuffer = new PlatformPixelBuffer(w, h);
+  frameBuffer = createFramebuffer(w, h);
   assert(frameBuffer);
 
   setServerPF(serverPF);
@@ -358,7 +356,7 @@
   vlog.debug("Resizing framebuffer from %dx%d to %dx%d",
              frameBuffer->width(), frameBuffer->height(), w, h);
 
-  newBuffer = new PlatformPixelBuffer(w, h);
+  newBuffer = createFramebuffer(w, h);
   assert(newBuffer);
 
   rect.setXYWH(0, 0,
@@ -500,6 +498,26 @@
 }
 
 
+PlatformPixelBuffer* Viewport::createFramebuffer(int w, int h)
+{
+  PlatformPixelBuffer *fb;
+
+  try {
+#if defined(WIN32)
+    fb = new Win32PixelBuffer(w, h);
+#elif defined(__APPLE__)
+    fb = new OSXPixelBuffer(w, h);
+#else
+    fb = new X11PixelBuffer(w, h);
+#endif
+  } catch (rdr::Exception& e) {
+    fb = new FLTKPixelBuffer(w, h);
+  }
+
+  return fb;
+}
+
+
 void Viewport::handleUpdateTimeout(void *data)
 {
   Viewport *self = (Viewport *)data;
diff --git a/vncviewer/Viewport.h b/vncviewer/Viewport.h
index 7859db6..bd17655 100644
--- a/vncviewer/Viewport.h
+++ b/vncviewer/Viewport.h
@@ -72,6 +72,8 @@
 
 private:
 
+  PlatformPixelBuffer* createFramebuffer(int w, int h);
+
   static void handleUpdateTimeout(void *data);
 
   static void handleClipboardChange(int source, void *data);
diff --git a/vncviewer/Win32PixelBuffer.cxx b/vncviewer/Win32PixelBuffer.cxx
index 4ee15ce..429f63f 100644
--- a/vncviewer/Win32PixelBuffer.cxx
+++ b/vncviewer/Win32PixelBuffer.cxx
@@ -1,5 +1,5 @@
 /* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
- * Copyright 2011 Pierre Ossman <ossman@cendio.se> for Cendio AB
+ * Copyright 2011-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
@@ -35,12 +35,12 @@
 
 using namespace rfb;
 
-static rfb::LogWriter vlog("PlatformPixelBuffer");
+static rfb::LogWriter vlog("Win32PixelBuffer");
 
-PlatformPixelBuffer::PlatformPixelBuffer(int width, int height) :
-  FullFramePixelBuffer(rfb::PixelFormat(32, 24, false, true,
-                                        255, 255, 255, 16, 8, 0),
-                       width, height, NULL),
+Win32PixelBuffer::Win32PixelBuffer(int width, int height) :
+  PlatformPixelBuffer(rfb::PixelFormat(32, 24, false, true,
+                                       255, 255, 255, 16, 8, 0),
+                      width, height, NULL),
   bitmap(NULL)
 {
   BITMAPINFOHEADER bih;
@@ -64,13 +64,13 @@
 }
 
 
-PlatformPixelBuffer::~PlatformPixelBuffer()
+Win32PixelBuffer::~Win32PixelBuffer()
 {
   DeleteObject(bitmap);
 }
 
 
-void PlatformPixelBuffer::draw(int src_x, int src_y, int x, int y, int w, int h)
+void Win32PixelBuffer::draw(int src_x, int src_y, int x, int y, int w, int h)
 {
   HDC dc;
 
diff --git a/vncviewer/Win32PixelBuffer.h b/vncviewer/Win32PixelBuffer.h
index 7d91e09..728e594 100644
--- a/vncviewer/Win32PixelBuffer.h
+++ b/vncviewer/Win32PixelBuffer.h
@@ -1,4 +1,4 @@
-/* Copyright 2011 Pierre Ossman <ossman@cendio.se> for Cendio AB
+/* Copyright 2011-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
@@ -21,14 +21,14 @@
 
 #include <windows.h>
 
-#include <rfb/PixelBuffer.h>
+#include "PlatformPixelBuffer.h"
 
-class PlatformPixelBuffer: public rfb::FullFramePixelBuffer {
+class Win32PixelBuffer: public PlatformPixelBuffer {
 public:
-  PlatformPixelBuffer(int width, int height);
-  ~PlatformPixelBuffer();
+  Win32PixelBuffer(int width, int height);
+  ~Win32PixelBuffer();
 
-  void draw(int src_x, int src_y, int x, int y, int w, int h);
+  virtual void draw(int src_x, int src_y, int x, int y, int w, int h);
 
 protected:
   HBITMAP bitmap;
diff --git a/vncviewer/X11PixelBuffer.cxx b/vncviewer/X11PixelBuffer.cxx
index f834003..3675eb5 100644
--- a/vncviewer/X11PixelBuffer.cxx
+++ b/vncviewer/X11PixelBuffer.cxx
@@ -1,5 +1,5 @@
 /* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
- * Copyright 2011 Pierre Ossman <ossman@cendio.se> for Cendio AB
+ * Copyright 2011-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
@@ -33,7 +33,7 @@
 
 using namespace rfb;
 
-static rfb::LogWriter vlog("PlatformPixelBuffer");
+static rfb::LogWriter vlog("X11PixelBuffer");
 
 static PixelFormat display_pf()
 {
@@ -93,8 +93,8 @@
                      redShift, greenShift, blueShift);
 }
 
-PlatformPixelBuffer::PlatformPixelBuffer(int width, int height) :
-  FullFramePixelBuffer(display_pf(), width, height, NULL),
+X11PixelBuffer::X11PixelBuffer(int width, int height) :
+  PlatformPixelBuffer(display_pf(), width, height, NULL),
   shminfo(NULL), xim(NULL)
 {
   // Might not be open at this point
@@ -113,7 +113,7 @@
 }
 
 
-PlatformPixelBuffer::~PlatformPixelBuffer()
+X11PixelBuffer::~X11PixelBuffer()
 {
   if (shminfo) {
     vlog.debug("Freeing shared memory XImage");
@@ -130,7 +130,7 @@
 }
 
 
-void PlatformPixelBuffer::draw(int src_x, int src_y, int x, int y, int w, int h)
+void X11PixelBuffer::draw(int src_x, int src_y, int x, int y, int w, int h)
 {
   if (shminfo)
     XShmPutImage(fl_display, fl_window, fl_gc, xim, src_x, src_y, x, y, w, h, False);
@@ -139,7 +139,7 @@
 }
 
 
-int PlatformPixelBuffer::getStride() const
+int X11PixelBuffer::getStride() const
 {
   return xim->bytes_per_line / (getPF().bpp/8);
 }
@@ -152,7 +152,7 @@
   return 0;
 }
 
-int PlatformPixelBuffer::setupShm()
+int X11PixelBuffer::setupShm()
 {
   int major, minor;
   Bool pixmaps;
diff --git a/vncviewer/X11PixelBuffer.h b/vncviewer/X11PixelBuffer.h
index 0b0cee0..6d54165 100644
--- a/vncviewer/X11PixelBuffer.h
+++ b/vncviewer/X11PixelBuffer.h
@@ -1,4 +1,4 @@
-/* Copyright 2011 Pierre Ossman <ossman@cendio.se> for Cendio AB
+/* Copyright 2011-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
@@ -24,14 +24,14 @@
 #include <sys/shm.h>
 #include <X11/extensions/XShm.h>
 
-#include <rfb/PixelBuffer.h>
+#include "PlatformPixelBuffer.h"
 
-class PlatformPixelBuffer: public rfb::FullFramePixelBuffer {
+class X11PixelBuffer: public PlatformPixelBuffer {
 public:
-  PlatformPixelBuffer(int width, int height);
-  ~PlatformPixelBuffer();
+  X11PixelBuffer(int width, int height);
+  ~X11PixelBuffer();
 
-  void draw(int src_x, int src_y, int x, int y, int w, int h);
+  virtual void draw(int src_x, int src_y, int x, int y, int w, int h);
 
   int getStride() const;