Code cleanup: each decoder was moved from the processNormalProtocol()
method to a separate function. Cleanups in "throws" statements.


git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@2518 3789f03b-4d11-0410-bbf8-ca57d06f2519
diff --git a/java/src/com/tightvnc/rfbplayer/VncCanvas.java b/java/src/com/tightvnc/rfbplayer/VncCanvas.java
index b87763e..953e61d 100644
--- a/java/src/com/tightvnc/rfbplayer/VncCanvas.java
+++ b/java/src/com/tightvnc/rfbplayer/VncCanvas.java
@@ -205,11 +205,11 @@
   }
 
   //
-  // processNormalProtocol() - executed by the rfbThread to deal with the
-  // RFB socket.
+  // processNormalProtocol() - executed by the rfbThread to deal with
+  // the RFB data.
   //
 
-  public void processNormalProtocol() throws IOException {
+  public void processNormalProtocol() throws Exception {
 
     zlibInflater = new Inflater();
     tightInflaters = new Inflater[4];
@@ -228,6 +228,8 @@
 
 	for (int i = 0; i < rfb.updateNRects; i++) {
 	  rfb.readFramebufferUpdateRectHdr();
+	  int rx = rfb.updateRectX, ry = rfb.updateRectY;
+	  int rw = rfb.updateRectW, rh = rfb.updateRectH;
 
 	  if (rfb.updateRectEncoding == rfb.EncodingLastRect)
 	    break;
@@ -240,228 +242,41 @@
 
 	  if (rfb.updateRectEncoding == rfb.EncodingXCursor ||
 	      rfb.updateRectEncoding == rfb.EncodingRichCursor) {
-	    throw new IOException("Sorry, no support for" +
-				  " cursor shape updates yet");
+	    throw new Exception("Sorry, no support for" +
+				" cursor shape updates yet");
 	  }
 
 	  switch (rfb.updateRectEncoding) {
-
 	  case RfbProto.EncodingRaw:
-	  {
-	    handleRawRect(rfb.updateRectX, rfb.updateRectY,
-			  rfb.updateRectW, rfb.updateRectH);
+	    handleRawRect(rx, ry, rw, rh);
 	    break;
-	  }
-
 	  case RfbProto.EncodingCopyRect:
-	  {
-	    rfb.readCopyRect();
-
-	    int sx = rfb.copyRectSrcX, sy = rfb.copyRectSrcY;
-	    int rx = rfb.updateRectX, ry = rfb.updateRectY;
-	    int rw = rfb.updateRectW, rh = rfb.updateRectH;
-
-	    memGraphics.copyArea(sx, sy, rw, rh, rx - sx, ry - sy);
-
-	    scheduleRepaint(rx, ry, rw, rh);
+	    handleCopyRect(rx, ry, rw, rh);
 	    break;
-	  }
-
 	  case RfbProto.EncodingRRE:
-	  {
-	    byte[] buf = new byte[4];
-
-	    int rx = rfb.updateRectX, ry = rfb.updateRectY;
-	    int rw = rfb.updateRectW, rh = rfb.updateRectH;
-	    int nSubrects = rfb.is.readInt();
-	    int x, y, w, h;
-
-	    rfb.is.readFully(buf);
-	    Color pixel = new Color(buf[2] & 0xFF,
-				    buf[1] & 0xFF,
-				    buf[0] & 0xFF);
-	    memGraphics.setColor(pixel);
-	    memGraphics.fillRect(rx, ry, rw, rh);
-
-	    for (int j = 0; j < nSubrects; j++) {
-	      rfb.is.readFully(buf);
-	      pixel = new Color(buf[2] & 0xFF, buf[1] & 0xFF, buf[0] & 0xFF);
-	      x = rx + rfb.is.readUnsignedShort();
-	      y = ry + rfb.is.readUnsignedShort();
-	      w = rfb.is.readUnsignedShort();
-	      h = rfb.is.readUnsignedShort();
-
-	      memGraphics.setColor(pixel);
-	      memGraphics.fillRect(x, y, w, h);
-	    }
-
-	    scheduleRepaint(rx, ry, rw, rh);
+	    handleRRERect(rx, ry, rw, rh);
 	    break;
-	  }
-
 	  case RfbProto.EncodingCoRRE:
-	  {
-	    byte[] buf = new byte[4];
-
-	    int rx = rfb.updateRectX, ry = rfb.updateRectY;
-	    int rw = rfb.updateRectW, rh = rfb.updateRectH;
-	    int nSubrects = rfb.is.readInt();
-	    int x, y, w, h;
-
-	    rfb.is.readFully(buf);
-	    Color pixel = new Color(buf[2] & 0xFF,
-				    buf[1] & 0xFF,
-				    buf[0] & 0xFF);
-	    memGraphics.setColor(pixel);
-	    memGraphics.fillRect(rx, ry, rw, rh);
-
-	    for (int j = 0; j < nSubrects; j++) {
-	      rfb.is.readFully(buf);
-	      pixel = new Color(buf[2] & 0xFF, buf[1] & 0xFF, buf[0] & 0xFF);
-	      x = rx + rfb.is.readUnsignedByte();
-	      y = ry + rfb.is.readUnsignedByte();
-	      w = rfb.is.readUnsignedByte();
-	      h = rfb.is.readUnsignedByte();
-
-	      memGraphics.setColor(pixel);
-	      memGraphics.fillRect(x, y, w, h);
-	    }
-
-	    scheduleRepaint(rx, ry, rw, rh);
+	    handleCoRRERect(rx, ry, rw, rh);
 	    break;
-	  }
-
 	  case RfbProto.EncodingHextile:
-	  {
-	    byte[] buf = new byte[256 * 4];
-
-	    int rx = rfb.updateRectX, ry = rfb.updateRectY;
-	    int rw = rfb.updateRectW, rh = rfb.updateRectH;
-	    Color bg = new Color(0, 0, 0), fg = new Color(0, 0, 0);
-
-	    for (int ty = ry; ty < ry + rh; ty += 16) {
-
-	      int th = 16;
-	      if (ry + rh - ty < 16)
-		th = ry + rh - ty;
-
-	      for (int tx = rx; tx < rx + rw; tx += 16) {
-
-		int tw = 16;
-		if (rx + rw - tx < 16)
-		  tw = rx + rw - tx;
-
-		int subencoding = rfb.is.readUnsignedByte();
-
-		// Is it a raw-encoded sub-rectangle?
-		if ((subencoding & rfb.HextileRaw) != 0) {
-		  int count, offset;
-		  for (int j = ty; j < ty + th; j++) {
-		    rfb.is.readFully(buf, 0, tw * 4);
-		    offset = j * rfb.framebufferWidth + tx;
-		    for (count = 0; count < tw; count++) {
-		      pixels24[offset + count] =
-			(buf[count * 4 + 2] & 0xFF) << 16 |
-			(buf[count * 4 + 1] & 0xFF) << 8 |
-			(buf[count * 4] & 0xFF);
-		    }
-		  }
-		  handleUpdatedPixels(tx, ty, tw, th);
-		  continue;
-		}
-
-		// Read and draw the background if specified.
-		if ((subencoding & rfb.HextileBackgroundSpecified) != 0) {
-		  rfb.is.readFully(buf, 0, 4);
-		  bg = new Color(buf[2] & 0xFF, buf[1] & 0xFF, buf[0] & 0xFF);
-		}
-		memGraphics.setColor(bg);
-		memGraphics.fillRect(tx, ty, tw, th);
-
-		// Read the foreground color if specified.
-		if ((subencoding & rfb.HextileForegroundSpecified) != 0) {
-		  rfb.is.readFully(buf, 0, 4);
-		  fg = new Color(buf[2] & 0xFF, buf[1] & 0xFF, buf[0] & 0xFF);
-		}
-
-		// Done with this tile if there is no sub-rectangles.
-		if ((subencoding & rfb.HextileAnySubrects) == 0)
-		  continue;
-
-		int nSubrects = rfb.is.readUnsignedByte();
-
-		int b1, b2, sx, sy, sw, sh;
-		if ((subencoding & rfb.HextileSubrectsColoured) != 0) {
-		  for (int j = 0; j < nSubrects; j++) {
-		    rfb.is.readFully(buf, 0, 4);
-		    fg = new Color(buf[2] & 0xFF,
-				   buf[1] & 0xFF,
-				   buf[0] & 0xFF);
-		    b1 = rfb.is.readUnsignedByte();
-		    b2 = rfb.is.readUnsignedByte();
-		    sx = tx + (b1 >> 4);
-		    sy = ty + (b1 & 0xf);
-		    sw = (b2 >> 4) + 1;
-		    sh = (b2 & 0xf) + 1;
-		    memGraphics.setColor(fg);
-		    memGraphics.fillRect(sx, sy, sw, sh);
-		  }
-		} else {
-		  memGraphics.setColor(fg);
-		  for (int j = 0; j < nSubrects; j++) {
-		    b1 = rfb.is.readUnsignedByte();
-		    b2 = rfb.is.readUnsignedByte();
-		    sx = tx + (b1 >> 4);
-		    sy = ty + (b1 & 0xf);
-		    sw = (b2 >> 4) + 1;
-		    sh = (b2 & 0xf) + 1;
-		    memGraphics.fillRect(sx, sy, sw, sh);
-		  }
-		}
-
-	      }
-	      // Finished with a row of tiles, now let's show it.
-	      scheduleRepaint(rx, ty, rw, th);
-	    }
+	    handleHextileRect(rx, ry, rw, rh);
 	    break;
-	  }
-
 	  case RfbProto.EncodingZlib:
-	  {
-	    int nBytes = rfb.is.readInt();
-
-            if (zlibBuf == null || zlibBufLen < nBytes) {
-              zlibBufLen = nBytes * 2;
-              zlibBuf = new byte[zlibBufLen];
-            }
-
-            rfb.is.readFully(zlibBuf, 0, nBytes);
-            zlibInflater.setInput(zlibBuf, 0, nBytes);
-
-            handleZlibRect(rfb.updateRectX, rfb.updateRectY,
-			   rfb.updateRectW, rfb.updateRectH);
-
+            handleZlibRect(rx, ry, rw, rh);
 	    break;
-	  }
-
 	  case RfbProto.EncodingTight:
-	  {
-	    handleTightRect(rfb.updateRectX, rfb.updateRectY,
-			    rfb.updateRectW, rfb.updateRectH);
-
+	    handleTightRect(rx, ry, rw, rh);
 	    break;
-	  }
-
 	  default:
-	    throw new IOException("Unknown RFB rectangle encoding " +
-				  rfb.updateRectEncoding);
+	    throw new Exception("Unknown RFB rectangle encoding " +
+				rfb.updateRectEncoding);
 	  }
-
 	}
 	break;
 
       case RfbProto.SetColourMapEntries:
-	throw new IOException("Can't handle SetColourMapEntries message");
+	throw new Exception("Can't handle SetColourMapEntries message");
 
       case RfbProto.Bell:
         Toolkit.getDefaultToolkit().beep();
@@ -472,7 +287,7 @@
 	break;
 
       default:
-	throw new IOException("Unknown RFB message type " + msgType);
+	throw new Exception("Unknown RFB message type " + msgType);
       }
 
       player.updatePos();
@@ -505,11 +320,199 @@
 
 
   //
+  // Handle a CopyRect rectangle.
+  //
+
+  void handleCopyRect(int x, int y, int w, int h) throws IOException {
+
+    rfb.readCopyRect();
+    memGraphics.copyArea(rfb.copyRectSrcX, rfb.copyRectSrcY, w, h,
+			 x - rfb.copyRectSrcX, y - rfb.copyRectSrcY);
+
+    scheduleRepaint(x, y, w, h);
+  }
+
+  //
+  // Handle an RRE-encoded rectangle.
+  //
+
+  void handleRRERect(int x, int y, int w, int h) throws IOException {
+
+    int nSubrects = rfb.is.readInt();
+    int sx, sy, sw, sh;
+
+    byte[] buf = new byte[4];
+    rfb.is.readFully(buf);
+    Color pixel = new Color(buf[2] & 0xFF, buf[1] & 0xFF, buf[0] & 0xFF);
+    memGraphics.setColor(pixel);
+    memGraphics.fillRect(x, y, w, h);
+
+    for (int j = 0; j < nSubrects; j++) {
+      rfb.is.readFully(buf);
+      pixel = new Color(buf[2] & 0xFF, buf[1] & 0xFF, buf[0] & 0xFF);
+      sx = x + rfb.is.readUnsignedShort();
+      sy = y + rfb.is.readUnsignedShort();
+      sw = rfb.is.readUnsignedShort();
+      sh = rfb.is.readUnsignedShort();
+
+      memGraphics.setColor(pixel);
+      memGraphics.fillRect(sx, sy, sw, sh);
+    }
+
+    scheduleRepaint(x, y, w, h);
+  }
+
+  //
+  // Handle a CoRRE-encoded rectangle.
+  //
+
+  void handleCoRRERect(int x, int y, int w, int h) throws IOException {
+
+    int nSubrects = rfb.is.readInt();
+    int sx, sy, sw, sh;
+
+    byte[] buf = new byte[4];
+    rfb.is.readFully(buf);
+    Color pixel = new Color(buf[2] & 0xFF, buf[1] & 0xFF, buf[0] & 0xFF);
+    memGraphics.setColor(pixel);
+    memGraphics.fillRect(x, y, w, h);
+
+    for (int j = 0; j < nSubrects; j++) {
+      rfb.is.readFully(buf);
+      pixel = new Color(buf[2] & 0xFF, buf[1] & 0xFF, buf[0] & 0xFF);
+      sx = x + rfb.is.readUnsignedByte();
+      sy = y + rfb.is.readUnsignedByte();
+      sw = rfb.is.readUnsignedByte();
+      sh = rfb.is.readUnsignedByte();
+
+      memGraphics.setColor(pixel);
+      memGraphics.fillRect(sx, sy, sw, sh);
+    }
+
+    scheduleRepaint(x, y, w, h);
+  }
+
+  //
+  // Handle a Hextile-encoded rectangle.
+  //
+
+  // These colors should be kept between handleHextileSubrect() calls.
+  private Color hextile_bg, hextile_fg;
+
+  void handleHextileRect(int x, int y, int w, int h) throws IOException {
+
+    hextile_bg = new Color(0, 0, 0);
+    hextile_fg = new Color(0, 0, 0);
+
+    for (int ty = y; ty < y + h; ty += 16) {
+      int th = 16;
+      if (y + h - ty < 16)
+	th = y + h - ty;
+
+      for (int tx = x; tx < x + w; tx += 16) {
+	int tw = 16;
+	if (x + w - tx < 16)
+	  tw = x + w - tx;
+
+	handleHextileSubrect(tx, ty, tw, th);
+      }
+
+      // Finished with a row of tiles, now let's show it.
+      scheduleRepaint(x, y, w, h);
+    }
+  }
+
+  //
+  // Handle one tile in the Hextile-encoded data.
+  //
+
+  void handleHextileSubrect(int tx, int ty, int tw, int th)
+    throws IOException {
+
+    byte[] buf = new byte[256 * 4];
+
+    int subencoding = rfb.is.readUnsignedByte();
+
+    // Is it a raw-encoded sub-rectangle?
+    if ((subencoding & rfb.HextileRaw) != 0) {
+      int count, offset;
+      for (int j = ty; j < ty + th; j++) {
+	rfb.is.readFully(buf, 0, tw * 4);
+	offset = j * rfb.framebufferWidth + tx;
+	for (count = 0; count < tw; count++) {
+	  pixels24[offset + count] =
+	    (buf[count * 4 + 2] & 0xFF) << 16 |
+	    (buf[count * 4 + 1] & 0xFF) << 8 |
+	    (buf[count * 4] & 0xFF);
+	}
+      }
+      handleUpdatedPixels(tx, ty, tw, th);
+      return;
+    }
+
+    // Read and draw the background if specified.
+    if ((subencoding & rfb.HextileBackgroundSpecified) != 0) {
+      rfb.is.readFully(buf, 0, 4);
+      hextile_bg = new Color(buf[2] & 0xFF, buf[1] & 0xFF, buf[0] & 0xFF);
+    }
+    memGraphics.setColor(hextile_bg);
+    memGraphics.fillRect(tx, ty, tw, th);
+
+    // Read the foreground color if specified.
+    if ((subencoding & rfb.HextileForegroundSpecified) != 0) {
+      rfb.is.readFully(buf, 0, 4);
+      hextile_fg = new Color(buf[2] & 0xFF, buf[1] & 0xFF, buf[0] & 0xFF);
+    }
+
+    // Done with this tile if there is no sub-rectangles.
+    if ((subencoding & rfb.HextileAnySubrects) == 0)
+      return;
+
+    int nSubrects = rfb.is.readUnsignedByte();
+
+    int b1, b2, sx, sy, sw, sh;
+    if ((subencoding & rfb.HextileSubrectsColoured) != 0) {
+      for (int j = 0; j < nSubrects; j++) {
+	rfb.is.readFully(buf, 0, 4);
+	hextile_fg = new Color(buf[2] & 0xFF, buf[1] & 0xFF, buf[0] & 0xFF);
+	b1 = rfb.is.readUnsignedByte();
+	b2 = rfb.is.readUnsignedByte();
+	sx = tx + (b1 >> 4);
+	sy = ty + (b1 & 0xf);
+	sw = (b2 >> 4) + 1;
+	sh = (b2 & 0xf) + 1;
+	memGraphics.setColor(hextile_fg);
+	memGraphics.fillRect(sx, sy, sw, sh);
+      }
+    } else {
+      memGraphics.setColor(hextile_fg);
+      for (int j = 0; j < nSubrects; j++) {
+	b1 = rfb.is.readUnsignedByte();
+	b2 = rfb.is.readUnsignedByte();
+	sx = tx + (b1 >> 4);
+	sy = ty + (b1 & 0xf);
+	sw = (b2 >> 4) + 1;
+	sh = (b2 & 0xf) + 1;
+	memGraphics.fillRect(sx, sy, sw, sh);
+      }
+    }
+  }
+
+  //
   // Handle a Zlib-encoded rectangle.
   //
 
-  void handleZlibRect(int x, int y, int w, int h)
-    throws IOException {
+  void handleZlibRect(int x, int y, int w, int h) throws Exception {
+
+    int nBytes = rfb.is.readInt();
+
+    if (zlibBuf == null || zlibBufLen < nBytes) {
+      zlibBufLen = nBytes * 2;
+      zlibBuf = new byte[zlibBufLen];
+    }
+
+    rfb.is.readFully(zlibBuf, 0, nBytes);
+    zlibInflater.setInput(zlibBuf, 0, nBytes);
 
     try {
       byte[] buf = new byte[w * 4];
@@ -526,19 +529,18 @@
       }
     }
     catch (DataFormatException dfe) {
-      throw new IOException(dfe.toString());
+      throw new Exception(dfe.toString());
     }
 
     handleUpdatedPixels(x, y, w, h);
     scheduleRepaint(x, y, w, h);
   }
 
-
   //
-  // Handle a tight rectangle.
+  // Handle a Tight-encoded rectangle.
   //
 
-  void handleTightRect(int x, int y, int w, int h) throws IOException {
+  void handleTightRect(int x, int y, int w, int h) throws Exception {
 
     int comp_ctl = rfb.is.readUnsignedByte();
 
@@ -552,7 +554,7 @@
 
     // Check correctness of subencoding value.
     if (comp_ctl > rfb.TightMaxSubencoding) {
-      throw new IOException("Incorrect tight subencoding: " + comp_ctl);
+      throw new Exception("Incorrect tight subencoding: " + comp_ctl);
     }
 
     // Handle solid-color rectangles.
@@ -586,7 +588,7 @@
 	  // Wait no longer than three seconds.
 	  jpegRect.wait(3000);
 	} catch (InterruptedException e) {
-	  throw new IOException("Interrupted while decoding JPEG image");
+	  throw new Exception("Interrupted while decoding JPEG image");
 	}
       }
 
@@ -617,7 +619,7 @@
       } else if (filter_id == rfb.TightFilterGradient) {
 	useGradient = true;
       } else if (filter_id != rfb.TightFilterCopy) {
-	throw new IOException("Incorrect tight filter id: " + filter_id);
+	throw new Exception("Incorrect tight filter id: " + filter_id);
       }
     }
     if (numColors == 0)
@@ -715,7 +717,7 @@
 	}
       }
       catch(DataFormatException dfe) {
-	throw new IOException(dfe.toString());
+	throw new Exception(dfe.toString());
       }
     }
 
@@ -727,8 +729,7 @@
   // Decode 1bpp-encoded bi-color rectangle.
   //
 
-  void decodeMonoData(int x, int y, int w, int h, byte[] src, int[] palette)
-    throws IOException {
+  void decodeMonoData(int x, int y, int w, int h, byte[] src, int[] palette) {
 
     int dx, dy, n;
     int i = y * rfb.framebufferWidth + x;
@@ -752,8 +753,7 @@
   // Decode data processed with the "Gradient" filter.
   //
 
-  void decodeGradientData (int x, int y, int w, int h, byte[] buf)
-    throws IOException {
+  void decodeGradientData (int x, int y, int w, int h, byte[] buf) {
 
     int dx, dy, c;
     byte[] prevRow = new byte[w * 3];