]> source.dussan.org Git - tigervnc.git/commitdiff
Rename java/src/com/tightvnc to java/src/com/tigervnc.
authorAdam Tkac <atkac@redhat.com>
Fri, 13 Mar 2009 13:11:51 +0000 (13:11 +0000)
committerAdam Tkac <atkac@redhat.com>
Fri, 13 Mar 2009 13:11:51 +0000 (13:11 +0000)
git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@3672 3789f03b-4d11-0410-bbf8-ca57d06f2519

74 files changed:
java/src/com/tigervnc/decoder/CoRREDecoder.java [new file with mode: 0644]
java/src/com/tigervnc/decoder/CopyRectDecoder.java [new file with mode: 0644]
java/src/com/tigervnc/decoder/HextileDecoder.java [new file with mode: 0644]
java/src/com/tigervnc/decoder/RREDecoder.java [new file with mode: 0644]
java/src/com/tigervnc/decoder/RawDecoder.java [new file with mode: 0644]
java/src/com/tigervnc/decoder/TightDecoder.java [new file with mode: 0644]
java/src/com/tigervnc/decoder/ZRLEDecoder.java [new file with mode: 0644]
java/src/com/tigervnc/decoder/ZlibDecoder.java [new file with mode: 0644]
java/src/com/tigervnc/decoder/common/Repaintable.java [new file with mode: 0644]
java/src/com/tigervnc/vncviewer/AuthPanel.java [new file with mode: 0644]
java/src/com/tigervnc/vncviewer/ButtonPanel.java [new file with mode: 0644]
java/src/com/tigervnc/vncviewer/CapabilityInfo.java [new file with mode: 0644]
java/src/com/tigervnc/vncviewer/CapsContainer.java [new file with mode: 0644]
java/src/com/tigervnc/vncviewer/ClipboardFrame.java [new file with mode: 0644]
java/src/com/tigervnc/vncviewer/DesCipher.java [new file with mode: 0644]
java/src/com/tigervnc/vncviewer/HTTPConnectSocket.java [new file with mode: 0644]
java/src/com/tigervnc/vncviewer/HTTPConnectSocketFactory.java [new file with mode: 0644]
java/src/com/tigervnc/vncviewer/InStream.java [new file with mode: 0644]
java/src/com/tigervnc/vncviewer/LICENCE.TXT [new file with mode: 0644]
java/src/com/tigervnc/vncviewer/MANIFEST.MF [new file with mode: 0644]
java/src/com/tigervnc/vncviewer/Makefile [new file with mode: 0644]
java/src/com/tigervnc/vncviewer/MemInStream.java [new file with mode: 0644]
java/src/com/tigervnc/vncviewer/OptionsFrame.java [new file with mode: 0644]
java/src/com/tigervnc/vncviewer/README [new file with mode: 0644]
java/src/com/tigervnc/vncviewer/RecordOutputStream.java [new file with mode: 0644]
java/src/com/tigervnc/vncviewer/RecordingFrame.java [new file with mode: 0644]
java/src/com/tigervnc/vncviewer/ReloginPanel.java [new file with mode: 0644]
java/src/com/tigervnc/vncviewer/RfbInputStream.java [new file with mode: 0644]
java/src/com/tigervnc/vncviewer/RfbProto.java [new file with mode: 0644]
java/src/com/tigervnc/vncviewer/SessionRecorder.java [new file with mode: 0644]
java/src/com/tigervnc/vncviewer/SocketFactory.java [new file with mode: 0644]
java/src/com/tigervnc/vncviewer/VncCanvas.java [new file with mode: 0644]
java/src/com/tigervnc/vncviewer/VncCanvas2.java [new file with mode: 0644]
java/src/com/tigervnc/vncviewer/VncViewer.java [new file with mode: 0644]
java/src/com/tigervnc/vncviewer/ZlibInStream.java [new file with mode: 0644]
java/src/com/tigervnc/vncviewer/index.html [new file with mode: 0644]
java/src/com/tigervnc/vncviewer/index.vnc [new file with mode: 0644]
java/src/com/tightvnc/decoder/CoRREDecoder.java [deleted file]
java/src/com/tightvnc/decoder/CopyRectDecoder.java [deleted file]
java/src/com/tightvnc/decoder/HextileDecoder.java [deleted file]
java/src/com/tightvnc/decoder/RREDecoder.java [deleted file]
java/src/com/tightvnc/decoder/RawDecoder.java [deleted file]
java/src/com/tightvnc/decoder/TightDecoder.java [deleted file]
java/src/com/tightvnc/decoder/ZRLEDecoder.java [deleted file]
java/src/com/tightvnc/decoder/ZlibDecoder.java [deleted file]
java/src/com/tightvnc/decoder/common/Repaintable.java [deleted file]
java/src/com/tightvnc/vncviewer/AuthPanel.java [deleted file]
java/src/com/tightvnc/vncviewer/ButtonPanel.java [deleted file]
java/src/com/tightvnc/vncviewer/CapabilityInfo.java [deleted file]
java/src/com/tightvnc/vncviewer/CapsContainer.java [deleted file]
java/src/com/tightvnc/vncviewer/ClipboardFrame.java [deleted file]
java/src/com/tightvnc/vncviewer/DesCipher.java [deleted file]
java/src/com/tightvnc/vncviewer/HTTPConnectSocket.java [deleted file]
java/src/com/tightvnc/vncviewer/HTTPConnectSocketFactory.java [deleted file]
java/src/com/tightvnc/vncviewer/InStream.java [deleted file]
java/src/com/tightvnc/vncviewer/LICENCE.TXT [deleted file]
java/src/com/tightvnc/vncviewer/MANIFEST.MF [deleted file]
java/src/com/tightvnc/vncviewer/Makefile [deleted file]
java/src/com/tightvnc/vncviewer/MemInStream.java [deleted file]
java/src/com/tightvnc/vncviewer/OptionsFrame.java [deleted file]
java/src/com/tightvnc/vncviewer/README [deleted file]
java/src/com/tightvnc/vncviewer/RecordOutputStream.java [deleted file]
java/src/com/tightvnc/vncviewer/RecordingFrame.java [deleted file]
java/src/com/tightvnc/vncviewer/ReloginPanel.java [deleted file]
java/src/com/tightvnc/vncviewer/RfbInputStream.java [deleted file]
java/src/com/tightvnc/vncviewer/RfbProto.java [deleted file]
java/src/com/tightvnc/vncviewer/SessionRecorder.java [deleted file]
java/src/com/tightvnc/vncviewer/SocketFactory.java [deleted file]
java/src/com/tightvnc/vncviewer/VncCanvas.java [deleted file]
java/src/com/tightvnc/vncviewer/VncCanvas2.java [deleted file]
java/src/com/tightvnc/vncviewer/VncViewer.java [deleted file]
java/src/com/tightvnc/vncviewer/ZlibInStream.java [deleted file]
java/src/com/tightvnc/vncviewer/index.html [deleted file]
java/src/com/tightvnc/vncviewer/index.vnc [deleted file]

diff --git a/java/src/com/tigervnc/decoder/CoRREDecoder.java b/java/src/com/tigervnc/decoder/CoRREDecoder.java
new file mode 100644 (file)
index 0000000..bc08668
--- /dev/null
@@ -0,0 +1,85 @@
+package com.tightvnc.decoder;
+
+import com.tightvnc.vncviewer.RfbInputStream;
+import java.awt.Graphics;
+import java.awt.Color;
+import java.io.IOException;
+
+//
+// Class that used for decoding CoRRE encoded data.
+//
+
+public class CoRREDecoder extends RawDecoder {
+
+  final static int EncodingCoRRE = 4;
+
+  public CoRREDecoder(Graphics g, RfbInputStream is) {
+    super(g, is);
+  }
+
+  public CoRREDecoder(Graphics g, RfbInputStream is, int frameBufferW,
+                      int frameBufferH) {
+    super(g, is, frameBufferW, frameBufferH);
+  }
+
+  //
+  // Override handleRect method to decode CoRRE encoded data insted of
+  // raw pixel data.
+  //
+
+  public void handleRect(int x, int y, int w, int h) throws IOException {
+
+    //
+    // Write encoding ID to record output stream
+    //
+
+    if (dos != null) {
+      dos.writeInt(CoRREDecoder.EncodingCoRRE);
+    }
+
+    int nSubrects = rfbis.readU32();
+
+    byte[] bg_buf = new byte[bytesPerPixel];
+    rfbis.readFully(bg_buf);
+    Color pixel;
+    if (bytesPerPixel == 1) {
+      pixel = getColor256()[bg_buf[0] & 0xFF];
+    } else {
+      pixel = new Color(bg_buf[2] & 0xFF, bg_buf[1] & 0xFF, bg_buf[0] & 0xFF);
+    }
+    graphics.setColor(pixel);
+    graphics.fillRect(x, y, w, h);
+
+    byte[] buf = new byte[nSubrects * (bytesPerPixel + 4)];
+    rfbis.readFully(buf);
+
+    //
+    // Save decoded data to data output stream
+    //
+
+    if (dos != null) {
+      dos.writeInt(nSubrects);
+      dos.write(bg_buf);
+      dos.write(buf);
+    }
+
+    int sx, sy, sw, sh;
+    int i = 0;
+
+    for (int j = 0; j < nSubrects; j++) {
+      if (bytesPerPixel == 1) {
+        pixel = getColor256()[buf[i++] & 0xFF];
+      } else {
+        pixel = new Color(buf[i+2] & 0xFF, buf[i+1] & 0xFF, buf[i] & 0xFF);
+        i += 4;
+      }
+      sx = x + (buf[i++] & 0xFF);
+      sy = y + (buf[i++] & 0xFF);
+      sw = buf[i++] & 0xFF;
+      sh = buf[i++] & 0xFF;
+
+      graphics.setColor(pixel);
+      graphics.fillRect(sx, sy, sw, sh);
+    }
+  }
+}
diff --git a/java/src/com/tigervnc/decoder/CopyRectDecoder.java b/java/src/com/tigervnc/decoder/CopyRectDecoder.java
new file mode 100644 (file)
index 0000000..07a14bd
--- /dev/null
@@ -0,0 +1,50 @@
+package com.tightvnc.decoder;
+
+import com.tightvnc.vncviewer.RfbInputStream;
+import java.awt.Graphics;
+import java.io.IOException;
+
+//
+// Class that used for decoding CopyRect encoded data.
+//
+
+public class CopyRectDecoder extends RawDecoder {
+
+  final static int EncodingCopyRect = 1;
+
+  public CopyRectDecoder(Graphics g, RfbInputStream is) {
+    super(g, is);
+  }
+
+  public CopyRectDecoder(Graphics g, RfbInputStream is, int frameBufferW,
+                         int frameBufferH) {
+    super(g, is, frameBufferW, frameBufferH);
+  }
+
+  //
+  // Override handleRect method handle CopyRect
+  //
+
+  public void handleRect(int x, int y, int w, int h) throws IOException {
+
+    //
+    // Write encoding ID to record output stream
+    //
+
+    if (dos != null) {
+      dos.writeInt(CopyRectDecoder.EncodingCopyRect);
+    }
+
+    int copyRectSrcX = rfbis.readU16();
+    int copyRectSrcY = rfbis.readU16();
+
+    // If the session is being recorded:
+    if (dos != null) {
+      dos.writeShort(copyRectSrcX);
+      dos.writeShort(copyRectSrcY);
+    }
+
+    graphics.copyArea(copyRectSrcX, copyRectSrcY, w, h,
+                      x - copyRectSrcX, y - copyRectSrcY);
+  }
+}
diff --git a/java/src/com/tigervnc/decoder/HextileDecoder.java b/java/src/com/tigervnc/decoder/HextileDecoder.java
new file mode 100644 (file)
index 0000000..da7e778
--- /dev/null
@@ -0,0 +1,228 @@
+package com.tightvnc.decoder;
+
+import com.tightvnc.decoder.common.Repaintable;
+import com.tightvnc.vncviewer.RfbInputStream;
+import java.awt.Color;
+import java.awt.Graphics;
+import java.io.IOException;
+
+//
+// Class that used for decoding hextile encoded data.
+//
+
+public class HextileDecoder extends RawDecoder {
+
+  final static int EncodingHextile = 5;
+
+  // Contstants used in the Hextile decoder
+  final static int
+    HextileRaw                 = 1,
+    HextileBackgroundSpecified = 2,
+    HextileForegroundSpecified = 4,
+    HextileAnySubrects         = 8,
+    HextileSubrectsColoured    = 16;
+
+  public HextileDecoder(Graphics g, RfbInputStream is) {
+    super(g, is);
+  }
+
+  public HextileDecoder(Graphics g, RfbInputStream is, int frameBufferW,
+                        int frameBufferH) {
+    super(g, is, frameBufferW, frameBufferH);
+  }
+
+  //
+  // Set private members methods
+  //
+
+  public void setRepainableControl(Repaintable r) {
+    repainableControl = r;
+  }
+
+  //
+  // Override handleRect method to decode Hextile encoded data insted of
+  // raw pixel data.
+  //
+
+  public void handleRect(int x, int y, int w, int h) throws IOException,
+                                                            Exception {
+
+    //
+    // Write encoding ID to record output stream
+    //
+
+    if (dos != null) {
+      dos.writeInt(HextileDecoder.EncodingHextile);
+    }
+
+    hextile_bg = new Color(0);
+    hextile_fg = new Color(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);
+      }
+      if (repainableControl != null)
+        repainableControl.scheduleRepaint(x, y, w, h);
+    }
+    if (repainableControl != null)
+      repainableControl.scheduleRepaint(x, y, w, h);
+  }
+
+  //
+  // Handle one tile in the Hextile-encoded data.
+  //
+
+  private void handleHextileSubrect(int tx, int ty, int tw, int th)
+    throws IOException, Exception {
+
+    int subencoding = rfbis.readU8();
+
+    //
+    // Save decoded data to data output stream
+    //
+
+    if (dos != null) {
+      dos.writeByte((byte)subencoding);
+    }
+
+    // Is it a raw-encoded sub-rectangle?
+    if ((subencoding & HextileRaw) != 0) {
+      //
+      // Disable encoding id writting to record stream
+      // in super (RawDecoder) class, cause we write subencoding ID
+      // in this class (see code above).
+      //
+
+      super.enableEncodingRecordWritting(false);
+      super.handleRect(tx, ty, tw, th);
+      super.handleUpdatedPixels(tx, ty, tw, th);
+      super.enableEncodingRecordWritting(true);
+      return;
+    }
+
+    // Read and draw the background if specified.
+    byte[] cbuf = new byte[bytesPerPixel];
+    if ((subencoding & HextileBackgroundSpecified) != 0) {
+      rfbis.readFully(cbuf);
+      if (bytesPerPixel == 1) {
+        hextile_bg = getColor256()[cbuf[0] & 0xFF];
+      } else {
+        hextile_bg = new Color(cbuf[2] & 0xFF, cbuf[1] & 0xFF, cbuf[0] & 0xFF);
+      }
+
+      //
+      // Save decoded data to data output stream
+      //
+
+      if (dos != null) {
+        dos.write(cbuf);
+      }
+    }
+    graphics.setColor(hextile_bg);
+    graphics.fillRect(tx, ty, tw, th);
+
+    // Read the foreground color if specified.
+    if ((subencoding & HextileForegroundSpecified) != 0) {
+      rfbis.readFully(cbuf);
+      if (bytesPerPixel == 1) {
+        hextile_fg = getColor256()[cbuf[0] & 0xFF];
+      } else {
+        hextile_fg = new Color(cbuf[2] & 0xFF, cbuf[1] & 0xFF, cbuf[0] & 0xFF);
+      }
+
+      //
+      // Save decoded data to data output stream
+      //
+
+      if (dos != null) {
+        dos.write(cbuf);
+      }
+    }
+
+    // Done with this tile if there is no sub-rectangles.
+    if ((subencoding & HextileAnySubrects) == 0)
+      return;
+
+    int nSubrects = rfbis.readU8();
+    int bufsize = nSubrects * 2;
+    if ((subencoding & HextileSubrectsColoured) != 0) {
+      bufsize += nSubrects * bytesPerPixel;
+    }
+    byte[] buf = new byte[bufsize];
+    rfbis.readFully(buf);
+
+    //
+    // Save decoded data to data output stream
+    //
+
+    if (dos != null) {
+      dos.writeByte((byte)nSubrects);
+      dos.write(buf);
+    }
+
+    int b1, b2, sx, sy, sw, sh;
+    int i = 0;
+
+    if ((subencoding & HextileSubrectsColoured) == 0) {
+
+      // Sub-rectangles are all of the same color.
+      graphics.setColor(hextile_fg);
+      for (int j = 0; j < nSubrects; j++) {
+        b1 = buf[i++] & 0xFF;
+        b2 = buf[i++] & 0xFF;
+        sx = tx + (b1 >> 4);
+        sy = ty + (b1 & 0xf);
+        sw = (b2 >> 4) + 1;
+        sh = (b2 & 0xf) + 1;
+        graphics.fillRect(sx, sy, sw, sh);
+      }
+    } else if (bytesPerPixel == 1) {
+
+      // BGR233 (8-bit color) version for colored sub-rectangles.
+      for (int j = 0; j < nSubrects; j++) {
+        hextile_fg = getColor256()[buf[i++] & 0xFF];
+        b1 = buf[i++] & 0xFF;
+        b2 = buf[i++] & 0xFF;
+        sx = tx + (b1 >> 4);
+        sy = ty + (b1 & 0xf);
+        sw = (b2 >> 4) + 1;
+        sh = (b2 & 0xf) + 1;
+        graphics.setColor(hextile_fg);
+        graphics.fillRect(sx, sy, sw, sh);
+      }
+
+    } else {
+
+      // Full-color (24-bit) version for colored sub-rectangles.
+      for (int j = 0; j < nSubrects; j++) {
+        hextile_fg = new Color(buf[i+2] & 0xFF,
+                               buf[i+1] & 0xFF,
+                               buf[i] & 0xFF);
+        i += 4;
+        b1 = buf[i++] & 0xFF;
+        b2 = buf[i++] & 0xFF;
+        sx = tx + (b1 >> 4);
+        sy = ty + (b1 & 0xf);
+        sw = (b2 >> 4) + 1;
+        sh = (b2 & 0xf) + 1;
+        graphics.setColor(hextile_fg);
+        graphics.fillRect(sx, sy, sw, sh);
+      }
+
+    }
+  }
+
+  // These colors should be kept between handleHextileSubrect() calls.
+  private Color hextile_bg, hextile_fg;
+  // Repaitable object
+  private Repaintable repainableControl = null;
+}
diff --git a/java/src/com/tigervnc/decoder/RREDecoder.java b/java/src/com/tigervnc/decoder/RREDecoder.java
new file mode 100644 (file)
index 0000000..02eb513
--- /dev/null
@@ -0,0 +1,85 @@
+package com.tightvnc.decoder;
+
+import com.tightvnc.vncviewer.RfbInputStream;
+import java.awt.Graphics;
+import java.awt.Color;
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+
+//
+// Class that used for decoding RRE encoded data.
+//
+
+public class RREDecoder extends RawDecoder {
+
+  final static int EncodingRRE = 2;
+
+  public RREDecoder(Graphics g, RfbInputStream is) {
+    super(g, is);
+  }
+
+  public RREDecoder(Graphics g, RfbInputStream is, int frameBufferW,
+                    int frameBufferH) {
+    super(g, is, frameBufferW, frameBufferH);
+  }
+
+  //
+  // Override handleRect method to decode RRE encoded data insted of
+  // raw pixel data.
+  //
+
+  public void handleRect(int x, int y, int w, int h) throws IOException {
+
+    //
+    // Write encoding ID to record output stream
+    //
+
+    if (dos != null) {
+      dos.writeInt(RREDecoder.EncodingRRE);
+    }
+
+    int nSubrects = rfbis.readU32();
+    byte[] bg_buf = new byte[bytesPerPixel];
+    rfbis.readFully(bg_buf);
+    Color pixel;
+    if (bytesPerPixel == 1) {
+      pixel = getColor256()[bg_buf[0] & 0xFF];
+    } else {
+      pixel = new Color(bg_buf[2] & 0xFF, bg_buf[1] & 0xFF, bg_buf[0] & 0xFF);
+    }
+    graphics.setColor(pixel);
+    graphics.fillRect(x, y, w, h);
+    byte[] buf = new byte[nSubrects * (bytesPerPixel + 8)];
+    rfbis.readFully(buf);
+    DataInputStream ds = new DataInputStream(new ByteArrayInputStream(buf));
+
+    //
+    // Save decoded data to data output stream
+    //
+    if (dos != null) {
+      dos.writeInt(nSubrects);
+      dos.write(bg_buf);
+      dos.write(buf);
+    }
+
+    int sx, sy, sw, sh;
+    for (int j = 0; j < nSubrects; j++) {
+      if (bytesPerPixel == 1) {
+        pixel = getColor256()[ds.readUnsignedByte()];
+      } else {
+        ds.skip(4);
+        pixel = new Color(buf[j*12+2] & 0xFF,
+                          buf[j*12+1] & 0xFF,
+                          buf[j*12]   & 0xFF);
+      }
+      sx = x + ds.readUnsignedShort();
+      sy = y + ds.readUnsignedShort();
+      sw = ds.readUnsignedShort();
+      sh = ds.readUnsignedShort();
+
+      graphics.setColor(pixel);
+      graphics.fillRect(sx, sy, sw, sh);
+    }
+  }
+}
diff --git a/java/src/com/tigervnc/decoder/RawDecoder.java b/java/src/com/tigervnc/decoder/RawDecoder.java
new file mode 100644 (file)
index 0000000..9ef167a
--- /dev/null
@@ -0,0 +1,223 @@
+package com.tightvnc.decoder;
+
+import com.tightvnc.vncviewer.RfbInputStream;
+import java.io.IOException;
+import java.io.DataOutput;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.image.ColorModel;
+import java.awt.image.DirectColorModel;
+import java.awt.image.MemoryImageSource;
+import java.awt.Color;
+import java.awt.Toolkit;
+
+//
+// This is base decoder class.
+// Other classes will be childs of RawDecoder.
+//
+
+public class RawDecoder {
+  final static int EncodingRaw = 0;
+
+  public RawDecoder(Graphics g, RfbInputStream is) {
+    setGraphics(g);
+    setRfbInputStream(is);
+  }
+
+  public RawDecoder(Graphics g, RfbInputStream is, int frameBufferW,
+                    int frameBufferH) {
+    setGraphics(g);
+    setRfbInputStream(is);
+    setFrameBufferSize(frameBufferW, frameBufferH);
+    // FIXME: cm24 created in getColorModel24.
+    // Remove if no bugs
+    cm24 = new DirectColorModel(24, 0xFF0000, 0x00FF00, 0x0000FF);
+  }
+
+  //
+  // Set methods to set value of non-static protected members of class
+  //
+
+  public void setRfbInputStream(RfbInputStream is) {
+    rfbis = is;
+  }
+
+  public void setGraphics(Graphics g) {
+    graphics = g;
+  }
+
+  public void setBPP(int bpp) {
+    bytesPerPixel = bpp;
+  }
+
+  public void setFrameBufferSize(int w, int h) {
+    framebufferWidth = w;
+    framebufferHeight = h;
+  }
+
+  //
+  // FIXME: Rename this method after we don't need RecordInterface
+  // in RawDecoder class to record session
+  //
+
+  public void setDataOutputStream(DataOutput os) {
+    dos = os;
+  }
+
+  //
+  // Decodes Raw Pixels data and draw it into graphics
+  //
+
+  public void handleRect(int x, int y, int w, int h) throws IOException, Exception {
+
+    //
+    // Write encoding ID to record output stream
+    //
+
+    if ((dos != null) && (enableEncodingRecordWritting)) {
+      dos.writeInt(RawDecoder.EncodingRaw);
+    }
+
+    if (bytesPerPixel == 1) {
+      for (int dy = y; dy < y + h; dy++) {
+        if (pixels8 != null) {
+          rfbis.readFully(pixels8, dy * framebufferWidth + x, w);
+        }
+        //
+        // Save decoded data to record output stream
+        //
+        if (dos != null) {
+          dos.write(pixels8, dy * framebufferWidth + x, w);
+        }
+      }
+    } else {
+      byte[] buf = new byte[w * 4];
+      int i, offset;
+      for (int dy = y; dy < y + h; dy++) {
+        rfbis.readFully(buf);
+        //
+        // Save decoded data to record output stream
+        //
+        if (dos != null) {
+          dos.write(buf);
+        }
+        offset = dy * framebufferWidth + x;
+        if (pixels24 != null) {
+          for (i = 0; i < w; i++) {
+            pixels24[offset + i] =
+              (buf[i * 4 + 2] & 0xFF) << 16 |
+              (buf[i * 4 + 1] & 0xFF) << 8 |
+              (buf[i * 4] & 0xFF);
+          } //for
+        } // if
+      } // for
+    } // else
+    handleUpdatedPixels(x, y, w, h);
+  } // void
+
+  //
+  // Display newly updated area of pixels.
+  //
+
+  protected void handleUpdatedPixels(int x, int y, int w, int h) {
+    // Draw updated pixels of the off-screen image.
+    pixelsSource.newPixels(x, y, w, h);
+    graphics.setClip(x, y, w, h);
+    graphics.drawImage(rawPixelsImage, 0, 0, null);
+    graphics.setClip(0, 0, framebufferWidth, framebufferHeight);
+  }
+
+  //
+  // Updates pixels data.
+  // This method must be called when framebuffer is resized
+  // or BPP is changed.
+  //
+
+  public void update() {
+    // Images with raw pixels should be re-allocated on every change
+    // of geometry or pixel format.
+    int fbWidth = framebufferWidth;
+    int fbHeight = framebufferHeight;
+
+    if (bytesPerPixel == 1) {
+      pixels24 = null;
+      pixels8 = new byte[fbWidth * fbHeight];
+      pixelsSource = new MemoryImageSource(fbWidth, fbHeight, getColorModel8(),
+                                           pixels8, 0, fbWidth);
+    } else {
+      pixels8 = null;
+      pixels24 = new int[fbWidth * fbHeight];
+      pixelsSource =
+        new MemoryImageSource(fbWidth, fbHeight, cm24, pixels24, 0, fbWidth);
+    }
+    pixelsSource.setAnimated(true);
+    rawPixelsImage = Toolkit.getDefaultToolkit().createImage(pixelsSource);
+  }
+
+  //
+  // Private static members access methods
+  //
+
+  protected ColorModel getColorModel8() {
+    if (cm8 == null) {
+      cm8 = cm8 = new DirectColorModel(8, 7, (7 << 3), (3 << 6));
+    }
+    return cm8;
+  }
+
+  protected ColorModel getColorModel24() {
+    if (cm24 == null) {
+      cm24 = new DirectColorModel(24, 0xFF0000, 0x00FF00, 0x0000FF);
+    }
+    return cm24;
+  }
+
+  protected Color[]getColor256() {
+    if (color256 == null) {
+      color256 = new Color[256];
+      for (int i = 0; i < 256; i++)
+        color256[i] = new Color(cm8.getRGB(i));
+    }
+    return color256;
+  }
+
+  //
+  // This method will be used by HextileDecoder to disable
+  // double writting encoding id to record stream.
+  //
+  // FIXME: Try to find better solution than this.
+  //
+
+  protected void enableEncodingRecordWritting(boolean enable) {
+    enableEncodingRecordWritting = enable;
+  }
+
+  //
+  // Unique data for every decoder (? maybe not ?)
+  //
+
+  protected int bytesPerPixel = 4;
+  protected int framebufferWidth = 0;
+  protected int framebufferHeight = 0;
+  protected RfbInputStream rfbis = null;
+  protected Graphics graphics = null;
+  protected DataOutput dos = null;
+  protected boolean enableEncodingRecordWritting = true;
+
+  //
+  // This data must be shared between decoders
+  //
+
+  protected static byte []pixels8 = null;
+  protected static int []pixels24 = null;
+  protected static MemoryImageSource pixelsSource = null;
+  protected static Image rawPixelsImage = null;
+
+  //
+  // Access to this static members only though protected methods
+  //
+
+  private static ColorModel cm8 = null;
+  private static ColorModel cm24 = null;
+  private static Color []color256 = null;
+}
diff --git a/java/src/com/tigervnc/decoder/TightDecoder.java b/java/src/com/tigervnc/decoder/TightDecoder.java
new file mode 100644 (file)
index 0000000..015f73c
--- /dev/null
@@ -0,0 +1,525 @@
+package com.tightvnc.decoder;
+
+import com.tightvnc.decoder.common.Repaintable;
+import com.tightvnc.vncviewer.RfbInputStream;
+import java.awt.Graphics;
+import java.awt.Color;
+import java.awt.Image;
+import java.awt.Rectangle;
+import java.awt.Toolkit;
+import java.awt.image.ImageObserver;
+import java.io.IOException;
+import java.util.zip.Deflater;
+import java.util.zip.Inflater;
+
+//
+// Class that used for decoding Tight encoded data.
+//
+
+public class TightDecoder extends RawDecoder implements ImageObserver {
+
+  final static int EncodingTight = 7;
+
+  //
+  // Tight decoder constants
+  //
+
+  final static int TightExplicitFilter = 0x04;
+  final static int TightFill = 0x08;
+  final static int TightJpeg = 0x09;
+  final static int TightMaxSubencoding = 0x09;
+  final static int TightFilterCopy = 0x00;
+  final static int TightFilterPalette = 0x01;
+  final static int TightFilterGradient = 0x02;
+  final static int TightMinToCompress = 12;
+
+  // Tight encoder's data.
+  final static int tightZlibBufferSize = 512;
+
+  public TightDecoder(Graphics g, RfbInputStream is) {
+    super(g, is);
+    tightInflaters = new Inflater[4];
+  }
+
+  public TightDecoder(Graphics g, RfbInputStream is, int frameBufferW,
+                      int frameBufferH) {
+    super(g, is, frameBufferW, frameBufferH);
+    tightInflaters = new Inflater[4];
+  }
+
+  //
+  // Set and get methods for private TightDecoder
+  //
+
+  public void setRepainableControl(Repaintable r) {
+    repainatableControl = r;
+  }
+
+  //
+  // JPEG processing statistic methods
+  //
+
+  public long getNumJPEGRects() {
+    return statNumRectsTightJPEG;
+  }
+
+  public void setNumJPEGRects(int v) {
+    statNumRectsTightJPEG = v;
+  }
+
+  //
+  // Tight processing statistic methods
+  //
+
+  public long getNumTightRects() {
+    return statNumRectsTight;
+  }
+
+  public void setNumTightRects(int v) {
+    statNumRectsTight = v;
+  }
+
+  //
+  // Handle a Tight-encoded rectangle.
+  //
+
+  public void handleRect(int x, int y, int w, int h) throws Exception {
+
+    //
+    // Write encoding ID to record output stream
+    //
+
+    if (dos != null) {
+      dos.writeInt(TightDecoder.EncodingTight);
+    }
+
+    int comp_ctl = rfbis.readU8();
+
+    if (dos != null) {
+      // Tell the decoder to flush each of the four zlib streams.
+      dos.writeByte(comp_ctl | 0x0F);
+    }
+
+    // Flush zlib streams if we are told by the server to do so.
+    for (int stream_id = 0; stream_id < 4; stream_id++) {
+      if ((comp_ctl & 1) != 0 && tightInflaters[stream_id] != null) {
+        tightInflaters[stream_id] = null;
+      }
+      comp_ctl >>= 1;
+    }
+
+    // Check correctness of subencoding value.
+    if (comp_ctl > TightDecoder.TightMaxSubencoding) {
+      throw new Exception("Incorrect tight subencoding: " + comp_ctl);
+    }
+
+    // Handle solid-color rectangles.
+    if (comp_ctl == TightDecoder.TightFill) {
+
+      if (bytesPerPixel == 1) {
+        int idx = rfbis.readU8();
+        graphics.setColor(getColor256()[idx]);
+        if (dos != null) {
+          dos.writeByte(idx);
+        }
+      } else {
+        byte[] buf = new byte[3];
+        rfbis.readFully(buf);
+        if (dos != null) {
+          dos.write(buf);
+        }
+        Color bg = new Color(0xFF000000 | (buf[0] & 0xFF) << 16 |
+                            (buf[1] & 0xFF) << 8 | (buf[2] & 0xFF));
+        graphics.setColor(bg);
+      }
+      graphics.fillRect(x, y, w, h);
+      repainatableControl.scheduleRepaint(x, y, w, h);
+      return;
+
+    }
+
+    if (comp_ctl == TightDecoder.TightJpeg) {
+
+      statNumRectsTightJPEG++;
+
+      // Read JPEG data.
+      byte[] jpegData = new byte[rfbis.readCompactLen()];
+      rfbis.readFully(jpegData);
+      if (dos != null) {
+        recordCompactLen(jpegData.length);
+        dos.write(jpegData);
+      }
+
+      // Create an Image object from the JPEG data.
+      Image jpegImage = Toolkit.getDefaultToolkit().createImage(jpegData);
+
+      // Remember the rectangle where the image should be drawn.
+      jpegRect = new Rectangle(x, y, w, h);
+
+      // Let the imageUpdate() method do the actual drawing, here just
+      // wait until the image is fully loaded and drawn.
+      synchronized(jpegRect) {
+        Toolkit.getDefaultToolkit().prepareImage(jpegImage, -1, -1, this);
+        try {
+          // Wait no longer than three seconds.
+          jpegRect.wait(3000);
+        } catch (InterruptedException e) {
+          throw new Exception("Interrupted while decoding JPEG image");
+        }
+      }
+
+      // Done, jpegRect is not needed any more.
+      jpegRect = null;
+      return;
+
+    } else {
+      statNumRectsTight++;
+    }
+
+    // Read filter id and parameters.
+    int numColors = 0, rowSize = w;
+    byte[] palette8 = new byte[2];
+    int[] palette24 = new int[256];
+    boolean useGradient = false;
+    if ((comp_ctl & TightDecoder.TightExplicitFilter) != 0) {
+      int filter_id = rfbis.readU8();
+      if (dos != null) {
+        dos.writeByte(filter_id);
+      }
+      if (filter_id == TightDecoder.TightFilterPalette) {
+        numColors = rfbis.readU8() + 1;
+        if (dos != null) {
+          dos.writeByte((numColors - 1));
+        }
+        if (bytesPerPixel == 1) {
+          if (numColors != 2) {
+            throw new Exception("Incorrect tight palette size: " + numColors);
+          }
+          rfbis.readFully(palette8);
+          if (dos != null) {
+            dos.write(palette8);
+          }
+        } else {
+          byte[] buf = new byte[numColors * 3];
+          rfbis.readFully(buf);
+          if (dos != null) {
+            dos.write(buf);
+          }
+          for (int i = 0; i < numColors; i++) {
+           palette24[i] = ((buf[i * 3] & 0xFF) << 16 |
+                           (buf[i * 3 + 1] & 0xFF) << 8 |
+                           (buf[i * 3 + 2] & 0xFF));
+          }
+        }
+        if (numColors == 2) {
+          rowSize = (w + 7) / 8;
+        }
+      } else if (filter_id == TightDecoder.TightFilterGradient) {
+        useGradient = true;
+      } else if (filter_id != TightDecoder.TightFilterCopy) {
+        throw new Exception("Incorrect tight filter id: " + filter_id);
+      }
+    }
+    if (numColors == 0 && bytesPerPixel == 4)
+      rowSize *= 3;
+
+    // Read, optionally uncompress and decode data.
+    int dataSize = h * rowSize;
+    if (dataSize < TightDecoder.TightMinToCompress) {
+      // Data size is small - not compressed with zlib.
+      if (numColors != 0) {
+        // Indexed colors.
+        byte[] indexedData = new byte[dataSize];
+        rfbis.readFully(indexedData);
+        if (dos != null) {
+          dos.write(indexedData);
+        }
+        if (numColors == 2) {
+          // Two colors.
+          if (bytesPerPixel == 1) {
+            decodeMonoData(x, y, w, h, indexedData, palette8);
+          } else {
+            decodeMonoData(x, y, w, h, indexedData, palette24);
+          }
+        } else {
+          // 3..255 colors (assuming bytesPixel == 4).
+          int i = 0;
+          for (int dy = y; dy < y + h; dy++) {
+            for (int dx = x; dx < x + w; dx++) {
+              pixels24[dy * framebufferWidth + dx] =
+                palette24[indexedData[i++] & 0xFF];
+            }
+          }
+        }
+      } else if (useGradient) {
+        // "Gradient"-processed data
+        byte[] buf = new byte[w * h * 3];
+        rfbis.readFully(buf);
+        if (dos != null) {
+          dos.write(buf);
+        }
+        decodeGradientData(x, y, w, h, buf);
+      } else {
+        // Raw truecolor data.
+        if (bytesPerPixel == 1) {
+          for (int dy = y; dy < y + h; dy++) {
+            rfbis.readFully(pixels8, dy * framebufferWidth + x, w);
+            if (dos != null) {
+              dos.write(pixels8, dy * framebufferWidth + x, w);
+            }
+          }
+        } else {
+          byte[] buf = new byte[w * 3];
+          int i, offset;
+          for (int dy = y; dy < y + h; dy++) {
+            rfbis.readFully(buf);
+            if (dos != null) {
+              dos.write(buf);
+            }
+            offset = dy * framebufferWidth + x;
+            for (i = 0; i < w; i++) {
+              pixels24[offset + i] =
+                (buf[i * 3] & 0xFF) << 16 |
+                (buf[i * 3 + 1] & 0xFF) << 8 |
+                (buf[i * 3 + 2] & 0xFF);
+            }
+          }
+        }
+      }
+    } else {
+      // Data was compressed with zlib.
+      int zlibDataLen = rfbis.readCompactLen();
+      byte[] zlibData = new byte[zlibDataLen];
+      rfbis.readFully(zlibData);
+      int stream_id = comp_ctl & 0x03;
+      if (tightInflaters[stream_id] == null) {
+        tightInflaters[stream_id] = new Inflater();
+      }
+      Inflater myInflater = tightInflaters[stream_id];
+      myInflater.setInput(zlibData);
+      byte[] buf = new byte[dataSize];
+      myInflater.inflate(buf);
+      if (dos != null) {
+        recordCompressedData(buf);
+      }
+
+      if (numColors != 0) {
+        // Indexed colors.
+        if (numColors == 2) {
+          // Two colors.
+          if (bytesPerPixel == 1) {
+            decodeMonoData(x, y, w, h, buf, palette8);
+          } else {
+            decodeMonoData(x, y, w, h, buf, palette24);
+          }
+        } else {
+          // More than two colors (assuming bytesPixel == 4).
+          int i = 0;
+          for (int dy = y; dy < y + h; dy++) {
+            for (int dx = x; dx < x + w; dx++) {
+              pixels24[dy * framebufferWidth + dx] =
+                palette24[buf[i++] & 0xFF];
+            }
+          }
+        }
+      } else if (useGradient) {
+        // Compressed "Gradient"-filtered data (assuming bytesPixel == 4).
+        decodeGradientData(x, y, w, h, buf);
+      } else {
+        // Compressed truecolor data.
+        if (bytesPerPixel == 1) {
+          int destOffset = y * framebufferWidth + x;
+          for (int dy = 0; dy < h; dy++) {
+            System.arraycopy(buf, dy * w, pixels8, destOffset, w);
+            destOffset += framebufferWidth;
+          }
+        } else {
+          int srcOffset = 0;
+          int destOffset, i;
+          for (int dy = 0; dy < h; dy++) {
+            myInflater.inflate(buf);
+            destOffset = (y + dy) * framebufferWidth + x;
+            for (i = 0; i < w; i++) {
+              RawDecoder.pixels24[destOffset + i] =
+                (buf[srcOffset] & 0xFF) << 16 |
+                (buf[srcOffset + 1] & 0xFF) << 8 |
+                (buf[srcOffset + 2] & 0xFF);
+              srcOffset += 3;
+            }
+          }
+        }
+      }
+    }
+    handleUpdatedPixels(x, y, w, h);
+  }
+
+  //
+  // Decode 1bpp-encoded bi-color rectangle (8-bit and 24-bit versions).
+  //
+
+  private void decodeMonoData(int x, int y, int w, int h, byte[] src, byte[] palette) {
+
+    int dx, dy, n;
+    int i = y * framebufferWidth + x;
+    int rowBytes = (w + 7) / 8;
+    byte b;
+
+    for (dy = 0; dy < h; dy++) {
+      for (dx = 0; dx < w / 8; dx++) {
+        b = src[dy*rowBytes+dx];
+        for (n = 7; n >= 0; n--)
+          pixels8[i++] = palette[b >> n & 1];
+      }
+      for (n = 7; n >= 8 - w % 8; n--) {
+        pixels8[i++] = palette[src[dy*rowBytes+dx] >> n & 1];
+      }
+      i += (framebufferWidth - w);
+    }
+  }
+
+  private void decodeMonoData(int x, int y, int w, int h, byte[] src, int[] palette) {
+
+    int dx, dy, n;
+    int i = y * framebufferWidth + x;
+    int rowBytes = (w + 7) / 8;
+    byte b;
+
+    for (dy = 0; dy < h; dy++) {
+      for (dx = 0; dx < w / 8; dx++) {
+        b = src[dy*rowBytes+dx];
+        for (n = 7; n >= 0; n--)
+          pixels24[i++] = palette[b >> n & 1];
+      }
+      for (n = 7; n >= 8 - w % 8; n--) {
+        pixels24[i++] = palette[src[dy*rowBytes+dx] >> n & 1];
+      }
+      i += (framebufferWidth - w);
+    }
+  }
+
+  //
+  // Decode data processed with the "Gradient" filter.
+  //
+
+  private void decodeGradientData (int x, int y, int w, int h, byte[] buf) {
+
+    int dx, dy, c;
+    byte[] prevRow = new byte[w * 3];
+    byte[] thisRow = new byte[w * 3];
+    byte[] pix = new byte[3];
+    int[] est = new int[3];
+
+    int offset = y * framebufferWidth + x;
+
+    for (dy = 0; dy < h; dy++) {
+
+      /* First pixel in a row */
+      for (c = 0; c < 3; c++) {
+        pix[c] = (byte)(prevRow[c] + buf[dy * w * 3 + c]);
+        thisRow[c] = pix[c];
+      }
+      pixels24[offset++] =
+         (pix[0] & 0xFF) << 16 | (pix[1] & 0xFF) << 8 | (pix[2] & 0xFF);
+
+      /* Remaining pixels of a row */
+      for (dx = 1; dx < w; dx++) {
+        for (c = 0; c < 3; c++) {
+          est[c] = ((prevRow[dx * 3 + c] & 0xFF) + (pix[c] & 0xFF) -
+                    (prevRow[(dx-1) * 3 + c] & 0xFF));
+          if (est[c] > 0xFF) {
+            est[c] = 0xFF;
+          } else if (est[c] < 0x00) {
+            est[c] = 0x00;
+          }
+          pix[c] = (byte)(est[c] + buf[(dy * w + dx) * 3 + c]);
+          thisRow[dx * 3 + c] = pix[c];
+        }
+        pixels24[offset++] =
+          (pix[0] & 0xFF) << 16 | (pix[1] & 0xFF) << 8 | (pix[2] & 0xFF);
+      }
+
+      System.arraycopy(thisRow, 0, prevRow, 0, w * 3);
+      offset += (framebufferWidth - w);
+    }
+  }
+
+  //
+  // Override the ImageObserver interface method to handle drawing of
+  // JPEG-encoded data.
+  //
+
+  public boolean imageUpdate(Image img, int infoflags,
+                             int x, int y, int width, int height) {
+    if ((infoflags & (ALLBITS | ABORT)) == 0) {
+      return true; // We need more image data.
+    } else {
+      // If the whole image is available, draw it now.
+      if ((infoflags & ALLBITS) != 0) {
+        if (jpegRect != null) {
+          synchronized(jpegRect) {
+            graphics.drawImage(img, jpegRect.x, jpegRect.y, null);
+            repainatableControl.scheduleRepaint(jpegRect.x, jpegRect.y,
+                                                jpegRect.width, jpegRect.height);
+            jpegRect.notify();
+          }
+        }
+      }
+      return false; // All image data was processed.
+    }
+  }
+
+  //
+  // Write an integer in compact representation (1..3 bytes) into the
+  // recorded session file.
+  //
+
+  void recordCompactLen(int len) throws IOException {
+    byte[] buf = new byte[3];
+    int bytes = 0;
+    buf[bytes++] = (byte)(len & 0x7F);
+    if (len > 0x7F) {
+      buf[bytes-1] |= 0x80;
+      buf[bytes++] = (byte)(len >> 7 & 0x7F);
+      if (len > 0x3FFF) {
+       buf[bytes-1] |= 0x80;
+       buf[bytes++] = (byte)(len >> 14 & 0xFF);
+      }
+    }
+    if (dos != null) dos.write(buf, 0, bytes);
+  }
+
+  //
+  // Compress and write the data into the recorded session file.
+  //
+
+  void recordCompressedData(byte[] data, int off, int len) throws IOException {
+    Deflater deflater = new Deflater();
+    deflater.setInput(data, off, len);
+    int bufSize = len + len / 100 + 12;
+    byte[] buf = new byte[bufSize];
+    deflater.finish();
+    int compressedSize = deflater.deflate(buf);
+    recordCompactLen(compressedSize);
+    if (dos != null) dos.write(buf, 0, compressedSize);
+  }
+
+  void recordCompressedData(byte[] data) throws IOException {
+    recordCompressedData(data, 0, data.length);
+  }
+
+  //
+  // Private members
+  //
+
+  private Inflater[] tightInflaters;
+  // Since JPEG images are loaded asynchronously, we have to remember
+  // their position in the framebuffer. Also, this jpegRect object is
+  // used for synchronization between the rfbThread and a JVM's thread
+  // which decodes and loads JPEG images.
+  private Rectangle jpegRect;
+  private Repaintable repainatableControl = null;
+  // Jpeg decoding statistics
+  private long statNumRectsTightJPEG = 0;
+  // Tight decoding statistics
+  private long statNumRectsTight = 0;
+}
diff --git a/java/src/com/tigervnc/decoder/ZRLEDecoder.java b/java/src/com/tigervnc/decoder/ZRLEDecoder.java
new file mode 100644 (file)
index 0000000..a22da90
--- /dev/null
@@ -0,0 +1,310 @@
+package com.tightvnc.decoder;
+
+import com.tightvnc.vncviewer.InStream;
+import com.tightvnc.vncviewer.RfbInputStream;
+import com.tightvnc.vncviewer.ZlibInStream;
+import java.awt.Graphics;
+import com.tightvnc.vncviewer.MemInStream;
+import java.awt.Color;
+import java.awt.Toolkit;
+import java.awt.image.MemoryImageSource;
+import java.io.IOException;
+
+//
+// Class that used for decoding ZRLE encoded data.
+//
+
+public class ZRLEDecoder extends RawDecoder {
+
+  final static int EncodingZRLE = 16;
+
+  public ZRLEDecoder(Graphics g, RfbInputStream is) {
+    super(g, is);
+  }
+
+  public ZRLEDecoder(Graphics g, RfbInputStream is, int frameBufferW,
+                     int frameBufferH) {
+    super(g, is, frameBufferW, frameBufferH);
+  }
+
+  //
+  // Handle a ZRLE-encoded rectangle.
+  //
+  // FIXME: Currently, session recording is not fully supported for ZRLE.
+  //
+
+  public void handleRect(int x, int y, int w, int h) throws IOException, Exception {
+
+    //
+    // Write encoding ID to record output stream
+    //
+
+    if (dos != null) {
+      dos.writeInt(ZRLEDecoder.EncodingZRLE);
+    }
+
+    if (zrleInStream == null)
+      zrleInStream = new ZlibInStream();
+
+    int nBytes = rfbis.readU32();
+    if (nBytes > 64 * 1024 * 1024)
+      throw new Exception("ZRLE decoder: illegal compressed data size");
+
+    if (zrleBuf == null || zrleBufLen < nBytes) {
+      zrleBufLen = nBytes + 4096;
+      zrleBuf = new byte[zrleBufLen];
+    }
+
+    // FIXME: Do not wait for all the data before decompression.
+    rfbis.readFully(zrleBuf, 0, nBytes);
+
+    //
+    // Override handleRect method to decode RRE encoded data insted of
+    // raw pixel data.
+    //
+
+    if (dos != null) {
+      if (!zrleRecWarningShown) {
+        System.out.println("Warning: ZRLE session can be recorded" +
+                           " only from the beginning");
+        System.out.println("Warning: Recorded file may be corrupted");
+        zrleRecWarningShown = true;
+      }
+    }
+
+    zrleInStream.setUnderlying(new MemInStream(zrleBuf, 0, nBytes), nBytes);
+
+    for (int ty = y; ty < y+h; ty += 64) {
+
+      int th = Math.min(y+h-ty, 64);
+
+      for (int tx = x; tx < x+w; tx += 64) {
+
+        int tw = Math.min(x+w-tx, 64);
+
+        int mode = zrleInStream.readU8();
+        boolean rle = (mode & 128) != 0;
+        int palSize = mode & 127;
+        int[] palette = new int[128];
+
+        readZrlePalette(palette, palSize);
+
+        if (palSize == 1) {
+          int pix = palette[0];
+          Color c = (bytesPerPixel == 1) ?
+            getColor256()[pix] : new Color(0xFF000000 | pix);
+          graphics.setColor(c);
+          graphics.fillRect(tx, ty, tw, th);
+          continue;
+        }
+
+        if (!rle) {
+          if (palSize == 0) {
+            readZrleRawPixels(tw, th);
+          } else {
+            readZrlePackedPixels(tw, th, palette, palSize);
+          }
+        } else {
+          if (palSize == 0) {
+            readZrlePlainRLEPixels(tw, th);
+          } else {
+            readZrlePackedRLEPixels(tw, th, palette);
+          }
+        }
+        handleUpdatedZrleTile(tx, ty, tw, th);
+      }
+    }
+    zrleInStream.reset();
+  }
+
+  //
+  // Override update() method cause we have own data that
+  // must be updated when framebuffer is resized or BPP is changed
+  //
+
+  public void update() {
+    // Images with raw pixels should be re-allocated on every change
+    // of geometry or pixel format.
+    int fbWidth = framebufferWidth;
+    int fbHeight = framebufferHeight;
+
+    if (bytesPerPixel == 1) {
+      RawDecoder.pixels24 = null;
+      RawDecoder.pixels8 = new byte[fbWidth * fbHeight];
+      RawDecoder.pixelsSource = new MemoryImageSource(fbWidth, fbHeight, getColorModel8(), pixels8, 0, fbWidth);
+      zrleTilePixels24 = null;
+      zrleTilePixels8 = new byte[64 * 64];
+    } else {
+      RawDecoder.pixels8 = null;
+      RawDecoder.pixels24 = new int[fbWidth * fbHeight];
+      RawDecoder.pixelsSource =
+        new MemoryImageSource(fbWidth, fbHeight, getColorModel24(), pixels24, 0, fbWidth);
+      zrleTilePixels8 = null;
+      zrleTilePixels24 = new int[64 * 64];
+    }
+    RawDecoder.pixelsSource.setAnimated(true);
+    RawDecoder.rawPixelsImage = Toolkit.getDefaultToolkit().createImage(pixelsSource);
+  }
+
+  //
+  // Copy pixels from zrleTilePixels8 or zrleTilePixels24, then update.
+  //
+
+  private void handleUpdatedZrleTile(int x, int y, int w, int h) {
+    Object src, dst;
+    if (bytesPerPixel == 1) {
+      src = zrleTilePixels8; dst = pixels8;
+    } else {
+      src = zrleTilePixels24; dst = pixels24;
+    }
+    int offsetSrc = 0;
+    int offsetDst = (y * framebufferWidth + x);
+    for (int j = 0; j < h; j++) {
+      System.arraycopy(src, offsetSrc, dst, offsetDst, w);
+      offsetSrc += w;
+      offsetDst += framebufferWidth;
+    }
+    handleUpdatedPixels(x, y, w, h);
+  }
+
+  //
+  // Private methods for reading ZRLE data
+  //
+
+  private int readPixel(InStream is) throws Exception {
+    int pix;
+    if (bytesPerPixel == 1) {
+      pix = is.readU8();
+    } else {
+      int p1 = is.readU8();
+      int p2 = is.readU8();
+      int p3 = is.readU8();
+      pix = (p3 & 0xFF) << 16 | (p2 & 0xFF) << 8 | (p1 & 0xFF);
+    }
+    return pix;
+  }
+
+  private void readPixels(InStream is, int[] dst, int count) throws Exception {
+    if (bytesPerPixel == 1) {
+      byte[] buf = new byte[count];
+      is.readBytes(buf, 0, count);
+      for (int i = 0; i < count; i++) {
+        dst[i] = (int)buf[i] & 0xFF;
+      }
+    } else {
+      byte[] buf = new byte[count * 3];
+      is.readBytes(buf, 0, count * 3);
+      for (int i = 0; i < count; i++) {
+        dst[i] = ((buf[i*3+2] & 0xFF) << 16 |
+                  (buf[i*3+1] & 0xFF) << 8 |
+                  (buf[i*3] & 0xFF));
+      }
+    }
+  }
+
+  private void readZrlePalette(int[] palette, int palSize) throws Exception {
+    readPixels(zrleInStream, palette, palSize);
+  }
+
+  private void readZrleRawPixels(int tw, int th) throws Exception {
+    if (bytesPerPixel == 1) {
+      zrleInStream.readBytes(zrleTilePixels8, 0, tw * th);
+    } else {
+      readPixels(zrleInStream, zrleTilePixels24, tw * th); ///
+    }
+  }
+
+  private void readZrlePackedPixels(int tw, int th, int[] palette, int palSize)
+    throws Exception {
+
+    int bppp = ((palSize > 16) ? 8 :
+                ((palSize > 4) ? 4 : ((palSize > 2) ? 2 : 1)));
+    int ptr = 0;
+
+    for (int i = 0; i < th; i++) {
+      int eol = ptr + tw;
+      int b = 0;
+      int nbits = 0;
+
+      while (ptr < eol) {
+        if (nbits == 0) {
+          b = zrleInStream.readU8();
+          nbits = 8;
+        }
+        nbits -= bppp;
+        int index = (b >> nbits) & ((1 << bppp) - 1) & 127;
+        if (bytesPerPixel == 1) {
+          zrleTilePixels8[ptr++] = (byte)palette[index];
+        } else {
+          zrleTilePixels24[ptr++] = palette[index];
+        }
+      }
+    }
+  }
+
+  private void readZrlePlainRLEPixels(int tw, int th) throws Exception {
+    int ptr = 0;
+    int end = ptr + tw * th;
+    while (ptr < end) {
+      int pix = readPixel(zrleInStream);
+      int len = 1;
+      int b;
+      do {
+        b = zrleInStream.readU8();
+        len += b;
+      } while (b == 255);
+
+      if (!(len <= end - ptr))
+        throw new Exception("ZRLE decoder: assertion failed" +
+                            " (len <= end-ptr)");
+
+      if (bytesPerPixel == 1) {
+        while (len-- > 0) zrleTilePixels8[ptr++] = (byte)pix;
+      } else {
+        while (len-- > 0) zrleTilePixels24[ptr++] = pix;
+      }
+    }
+  }
+
+  private void readZrlePackedRLEPixels(int tw, int th, int[] palette)
+    throws Exception {
+
+    int ptr = 0;
+    int end = ptr + tw * th;
+    while (ptr < end) {
+      int index = zrleInStream.readU8();
+      int len = 1;
+      if ((index & 128) != 0) {
+        int b;
+        do {
+          b = zrleInStream.readU8();
+          len += b;
+        } while (b == 255);
+
+        if (!(len <= end - ptr))
+          throw new Exception("ZRLE decoder: assertion failed" +
+                              " (len <= end - ptr)");
+      }
+
+      index &= 127;
+      int pix = palette[index];
+
+      if (bytesPerPixel == 1) {
+        while (len-- > 0) zrleTilePixels8[ptr++] = (byte)pix;
+      } else {
+        while (len-- > 0) zrleTilePixels24[ptr++] = pix;
+      }
+    }
+  }
+
+  //
+  // ZRLE encoder's data.
+  //
+
+  private byte[] zrleBuf;
+  private int zrleBufLen = 0;
+  private byte[] zrleTilePixels8;
+  private int[] zrleTilePixels24;
+  private ZlibInStream zrleInStream;
+  private boolean zrleRecWarningShown = false;
+}
diff --git a/java/src/com/tigervnc/decoder/ZlibDecoder.java b/java/src/com/tigervnc/decoder/ZlibDecoder.java
new file mode 100644 (file)
index 0000000..1370da1
--- /dev/null
@@ -0,0 +1,103 @@
+package com.tightvnc.decoder;
+
+import com.tightvnc.vncviewer.RfbInputStream;
+import java.awt.Graphics;
+import java.io.IOException;
+import java.util.zip.DataFormatException;
+import java.util.zip.Inflater;
+
+//
+// Class that used for decoding ZLib encoded data.
+//
+
+public class ZlibDecoder extends RawDecoder {
+
+  final static int EncodingZlib = 6;
+
+  public ZlibDecoder(Graphics g, RfbInputStream is) {
+    super(g, is);
+  }
+
+  public ZlibDecoder(Graphics g, RfbInputStream is, int frameBufferW,
+                     int frameBufferH) {
+    super(g, is, frameBufferW, frameBufferH);
+  }
+
+  //
+  // Override handleRect method to decode ZLib encoded data insted of
+  // raw pixel data.
+  //
+
+  public void handleRect(int x, int y, int w, int h) throws IOException  {
+
+    //
+    // Write encoding ID to record output stream.
+    // Remark: we forced changed encoding from zlib to raw
+    // cause at this moment we cannot save data in zlib encoding.
+    //
+
+    if (dos != null) {
+      dos.writeInt(RawDecoder.EncodingRaw);
+    }
+
+    int nBytes = rfbis.readU32();
+
+    if (zlibBuf == null || zlibBufLen < nBytes) {
+      zlibBufLen = nBytes * 2;
+      zlibBuf = new byte[zlibBufLen];
+    }
+
+    rfbis.readFully(zlibBuf, 0, nBytes);
+
+    if (zlibInflater == null) {
+      zlibInflater = new Inflater();
+    }
+    zlibInflater.setInput(zlibBuf, 0, nBytes);
+
+    try {
+      if (bytesPerPixel == 1) {
+        for (int dy = y; dy < y + h; dy++) {
+          zlibInflater.inflate(pixels8, dy * framebufferWidth + x, w);
+
+          //
+          // Save decoded raw data to data output stream
+          //
+
+          if (dos != null)
+            dos.write(pixels8, dy * framebufferWidth + x, w);
+        }
+      } else {
+        byte[] buf = new byte[w * 4];
+        int i, offset;
+        for (int dy = y; dy < y + h; dy++) {
+          zlibInflater.inflate(buf);
+          offset = dy * framebufferWidth + x;
+          for (i = 0; i < w; i++) {
+            RawDecoder.pixels24[offset + i] =
+              (buf[i * 4 + 2] & 0xFF) << 16 |
+              (buf[i * 4 + 1] & 0xFF) << 8 |
+              (buf[i * 4] & 0xFF);
+          }
+
+          //
+          // Save decoded raw data to data output stream
+          //
+
+          if (dos != null)
+            dos.write(buf);
+        }
+      }
+    } catch (DataFormatException ex) {
+      ex.printStackTrace();
+    }
+    handleUpdatedPixels(x, y, w, h);
+  }
+
+  //
+  // Zlib encoder's data.
+  //
+
+  protected byte[] zlibBuf;
+  protected int zlibBufLen = 0;
+  protected Inflater zlibInflater;
+}
diff --git a/java/src/com/tigervnc/decoder/common/Repaintable.java b/java/src/com/tigervnc/decoder/common/Repaintable.java
new file mode 100644 (file)
index 0000000..de11f4c
--- /dev/null
@@ -0,0 +1,7 @@
+package com.tightvnc.decoder.common;
+
+public interface Repaintable {
+
+  public void scheduleRepaint(int x, int y, int w, int h);
+
+}
diff --git a/java/src/com/tigervnc/vncviewer/AuthPanel.java b/java/src/com/tigervnc/vncviewer/AuthPanel.java
new file mode 100644 (file)
index 0000000..28be721
--- /dev/null
@@ -0,0 +1,118 @@
+//
+//  Copyright (C) 1999 AT&T Laboratories Cambridge.  All Rights Reserved.
+//  Copyright (C) 2002-2006 Constantin Kaplinsky.  All Rights Reserved.
+//
+//  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.
+//
+
+package com.tightvnc.vncviewer;
+
+import java.awt.*;
+import java.awt.event.*;
+
+//
+// The panel which implements the user authentication scheme
+//
+
+class AuthPanel extends Panel implements ActionListener {
+
+  TextField passwordField;
+  Button okButton;
+
+  //
+  // Constructor.
+  //
+
+  public AuthPanel(VncViewer viewer)
+  {
+    Label titleLabel = new Label("VNC Authentication", Label.CENTER);
+    titleLabel.setFont(new Font("Helvetica", Font.BOLD, 18));
+
+    Label promptLabel = new Label("Password:", Label.CENTER);
+
+    passwordField = new TextField(10);
+    passwordField.setForeground(Color.black);
+    passwordField.setBackground(Color.white);
+    passwordField.setEchoChar('*');
+
+    okButton = new Button("OK");
+
+    GridBagLayout gridbag = new GridBagLayout();
+    GridBagConstraints gbc = new GridBagConstraints();
+
+    setLayout(gridbag);
+
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    gbc.insets = new Insets(0,0,20,0);
+    gridbag.setConstraints(titleLabel,gbc);
+    add(titleLabel);
+
+    gbc.fill = GridBagConstraints.NONE;
+    gbc.gridwidth = 1;
+    gbc.insets = new Insets(0,0,0,0);
+    gridbag.setConstraints(promptLabel,gbc);
+    add(promptLabel);
+
+    gridbag.setConstraints(passwordField,gbc);
+    add(passwordField);
+    passwordField.addActionListener(this);
+
+    // gbc.ipady = 10;
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    gbc.fill = GridBagConstraints.BOTH;
+    gbc.insets = new Insets(0,20,0,0);
+    gbc.ipadx = 30;
+    gridbag.setConstraints(okButton,gbc);
+    add(okButton);
+    okButton.addActionListener(this);
+  }
+
+  //
+  // Move keyboard focus to the default object, that is, the password
+  // text field.
+  //
+
+  public void moveFocusToDefaultField()
+  {
+    passwordField.requestFocus();
+  }
+
+  //
+  // This method is called when a button is pressed or return is
+  // pressed in the password text field.
+  //
+
+  public synchronized void actionPerformed(ActionEvent evt)
+  {
+    if (evt.getSource() == passwordField || evt.getSource() == okButton) {
+      passwordField.setEnabled(false);
+      notify();
+    }
+  }
+
+  //
+  // Wait for user entering a password, and return it as String.
+  //
+
+  public synchronized String getPassword() throws Exception
+  {
+    try {
+      wait();
+    } catch (InterruptedException e) { }
+    return passwordField.getText();
+  }
+
+}
diff --git a/java/src/com/tigervnc/vncviewer/ButtonPanel.java b/java/src/com/tigervnc/vncviewer/ButtonPanel.java
new file mode 100644 (file)
index 0000000..985a9c2
--- /dev/null
@@ -0,0 +1,222 @@
+//
+//  Copyright (C) 2001,2002 HorizonLive.com, Inc.  All Rights Reserved.
+//  Copyright (C) 1999 AT&T Laboratories Cambridge.  All Rights Reserved.
+//
+//  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.
+//
+
+//
+// ButtonPanel class implements panel with four buttons in the
+// VNCViewer desktop window.
+//
+
+package com.tightvnc.vncviewer;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+
+class ButtonPanel extends Panel implements ActionListener {
+
+  VncViewer viewer;
+  Button disconnectButton;
+  Button optionsButton;
+  Button recordButton;
+  Button clipboardButton;
+  Button ctrlAltDelButton;
+  Button refreshButton;
+  Button selectButton;
+  Button videoFreezeButton;
+
+  final String enableVideoFreezeLabel = "Ignore Video";
+  final String disableVideoFreezeLabel = "Enable Video";
+  final String selectEnterLabel = "Select Video Area";
+  final String selectLeaveLabel = "Hide Selection";
+
+  ButtonPanel(VncViewer v) {
+    viewer = v;
+
+    setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
+    disconnectButton = new Button("Disconnect");
+    disconnectButton.setEnabled(false);
+    add(disconnectButton);
+    disconnectButton.addActionListener(this);
+    optionsButton = new Button("Options");
+    add(optionsButton);
+    optionsButton.addActionListener(this);
+    clipboardButton = new Button("Clipboard");
+    clipboardButton.setEnabled(false);
+    add(clipboardButton);
+    clipboardButton.addActionListener(this);
+    if (viewer.rec != null) {
+      recordButton = new Button("Record");
+      add(recordButton);
+      recordButton.addActionListener(this);
+    }
+    ctrlAltDelButton = new Button("Send Ctrl-Alt-Del");
+    ctrlAltDelButton.setEnabled(false);
+    add(ctrlAltDelButton);
+    ctrlAltDelButton.addActionListener(this);
+    refreshButton = new Button("Refresh");
+    refreshButton.setEnabled(false);
+    add(refreshButton);
+    refreshButton.addActionListener(this);
+  }
+
+  /**
+   * Add video selection button to the ButtonPanel.
+   */
+  public void addSelectButton() {
+    selectButton = new Button(selectEnterLabel);
+    selectButton.setEnabled(false);
+    add(selectButton);
+    selectButton.addActionListener(this);
+  }
+
+  /**
+   * Add video ignore button to the ButtonPanel.
+   */
+  public void addVideoFreezeButton() {
+    videoFreezeButton = new Button(enableVideoFreezeLabel);
+    add(videoFreezeButton);
+    videoFreezeButton.addActionListener(this);
+  }
+
+  //
+  // Enable buttons on successful connection.
+  //
+
+  public void enableButtons() {
+    disconnectButton.setEnabled(true);
+    clipboardButton.setEnabled(true);
+    refreshButton.setEnabled(true);
+    if (selectButton != null) {
+      selectButton.setEnabled(true);
+    }
+  }
+
+  //
+  // Disable all buttons on disconnect.
+  //
+
+  public void disableButtonsOnDisconnect() {
+    remove(disconnectButton);
+    disconnectButton = new Button("Hide desktop");
+    disconnectButton.setEnabled(true);
+    add(disconnectButton, 0);
+    disconnectButton.addActionListener(this);
+
+    optionsButton.setEnabled(false);
+    clipboardButton.setEnabled(false);
+    ctrlAltDelButton.setEnabled(false);
+    refreshButton.setEnabled(false);
+    if (selectButton != null) {
+      selectButton.setEnabled(false);
+    }
+  }
+
+  //
+  // Enable/disable controls that should not be available in view-only
+  // mode.
+  //
+
+  public void enableRemoteAccessControls(boolean enable) {
+    ctrlAltDelButton.setEnabled(enable);
+  }
+
+  //
+  // Event processing.
+  //
+
+  public void actionPerformed(ActionEvent evt) {
+
+    viewer.moveFocusToDesktop();
+
+    if (evt.getSource() == disconnectButton) {
+      viewer.disconnect();
+
+    } else if (evt.getSource() == optionsButton) {
+      viewer.options.setVisible(!viewer.options.isVisible());
+
+    } else if (evt.getSource() == recordButton) {
+      viewer.rec.setVisible(!viewer.rec.isVisible());
+
+    } else if (evt.getSource() == clipboardButton) {
+      viewer.clipboard.setVisible(!viewer.clipboard.isVisible());
+    } else if (evt.getSource() == videoFreezeButton) {
+
+      //
+      // Send video freeze message to server and change caption of button
+      //
+
+      //
+      // TODO: Move this code to another place.
+      //
+
+      boolean sendOk = true;
+      boolean currentFreezeState =
+              videoFreezeButton.getLabel().equals(disableVideoFreezeLabel);
+      try {
+        viewer.rfb.trySendVideoFreeze(!currentFreezeState);
+      } catch (IOException ex) {
+        sendOk = false;
+        ex.printStackTrace();
+      }
+      if (sendOk) {
+        if (!currentFreezeState) {
+            videoFreezeButton.setLabel(disableVideoFreezeLabel);
+        } else {
+            videoFreezeButton.setLabel(enableVideoFreezeLabel);
+        }
+      }
+    } else if (evt.getSource() == ctrlAltDelButton) {
+      try {
+        final int modifiers = InputEvent.CTRL_MASK | InputEvent.ALT_MASK;
+
+        KeyEvent ctrlAltDelEvent =
+          new KeyEvent(this, KeyEvent.KEY_PRESSED, 0, modifiers, 127);
+        viewer.rfb.writeKeyEvent(ctrlAltDelEvent);
+
+        ctrlAltDelEvent =
+          new KeyEvent(this, KeyEvent.KEY_RELEASED, 0, modifiers, 127);
+        viewer.rfb.writeKeyEvent(ctrlAltDelEvent);
+
+      } catch (IOException e) {
+        e.printStackTrace();
+      }
+    } else if (evt.getSource() == refreshButton) {
+      try {
+       RfbProto rfb = viewer.rfb;
+       rfb.writeFramebufferUpdateRequest(0, 0, rfb.framebufferWidth,
+                                         rfb.framebufferHeight, false);
+      } catch (IOException e) {
+        e.printStackTrace();
+      }
+    } else if (selectButton != null && evt.getSource() == selectButton) {
+      if (viewer.vc != null) {
+        boolean isSelecting = viewer.vc.isInSelectionMode();
+        if (!isSelecting) {
+          selectButton.setLabel(selectLeaveLabel);
+          viewer.vc.enableSelection(true);
+        } else {
+          selectButton.setLabel(selectEnterLabel);
+          viewer.vc.enableSelection(false);
+        }
+      }
+    }
+  }
+}
+
diff --git a/java/src/com/tigervnc/vncviewer/CapabilityInfo.java b/java/src/com/tigervnc/vncviewer/CapabilityInfo.java
new file mode 100644 (file)
index 0000000..092f53e
--- /dev/null
@@ -0,0 +1,89 @@
+//
+//  Copyright (C) 2003 Constantin Kaplinsky.  All Rights Reserved.
+//
+//  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.
+//
+
+//
+// CapabilityInfo.java - A class to hold information about a
+// particular capability as used in the RFB protocol 3.130.
+//
+
+package com.tightvnc.vncviewer;
+
+class CapabilityInfo {
+
+  // Public methods
+
+  public CapabilityInfo(int code,
+                       String vendorSignature,
+                       String nameSignature,
+                       String description) {
+    this.code = code;
+    this.vendorSignature = vendorSignature;
+    this.nameSignature = nameSignature;
+    this.description = description;
+    enabled = false;
+  }
+
+  public CapabilityInfo(int code,
+                       byte[] vendorSignature,
+                       byte[] nameSignature) {
+    this.code = code;
+    this.vendorSignature = new String(vendorSignature);
+    this.nameSignature = new String(nameSignature);
+    this.description = null;
+    enabled = false;
+  }
+
+  public int getCode() {
+    return code;
+  }
+
+  public String getDescription() {
+    return description;
+  }
+
+  public boolean isEnabled() {
+    return enabled;
+  }
+
+  public void enable() {
+    enabled = true;
+  }
+
+  public boolean equals(CapabilityInfo other) {
+    return (other != null && this.code == other.code &&
+           this.vendorSignature.equals(other.vendorSignature) &&
+           this.nameSignature.equals(other.nameSignature));
+  }
+
+  public boolean enableIfEquals(CapabilityInfo other) {
+    if (this.equals(other))
+      enable();
+
+    return isEnabled();
+  }
+
+  // Protected data
+
+  protected int code;
+  protected String vendorSignature;
+  protected String nameSignature;
+
+  protected String description;
+  protected boolean enabled;
+}
diff --git a/java/src/com/tigervnc/vncviewer/CapsContainer.java b/java/src/com/tigervnc/vncviewer/CapsContainer.java
new file mode 100644 (file)
index 0000000..b9acbf4
--- /dev/null
@@ -0,0 +1,105 @@
+//
+//  Copyright (C) 2003 Constantin Kaplinsky.  All Rights Reserved.
+//
+//  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.
+//
+
+//
+// CapsContainer.java - A container of capabilities as used in the RFB
+// protocol 3.130
+//
+
+package com.tightvnc.vncviewer;
+
+import java.util.Vector;
+import java.util.Hashtable;
+
+class CapsContainer {
+
+  // Public methods
+
+  public CapsContainer() {
+    infoMap = new Hashtable(64, (float)0.25);
+    orderedList = new Vector(32, 8);
+  }
+
+  public void add(CapabilityInfo capinfo) {
+    Integer key = new Integer(capinfo.getCode());
+    infoMap.put(key, capinfo);
+  }
+
+  public void add(int code, String vendor, String name, String desc) {
+    Integer key = new Integer(code);
+    infoMap.put(key, new CapabilityInfo(code, vendor, name, desc));
+  }
+
+  public boolean isKnown(int code) {
+    return infoMap.containsKey(new Integer(code));
+  }
+
+  public CapabilityInfo getInfo(int code) {
+    return (CapabilityInfo)infoMap.get(new Integer(code));
+  }
+
+  public String getDescription(int code) {
+    CapabilityInfo capinfo = (CapabilityInfo)infoMap.get(new Integer(code));
+    if (capinfo == null)
+      return null;
+
+    return capinfo.getDescription();
+  }
+
+  public boolean enable(CapabilityInfo other) {
+    Integer key = new Integer(other.getCode());
+    CapabilityInfo capinfo = (CapabilityInfo)infoMap.get(key);
+    if (capinfo == null)
+      return false;
+
+    boolean enabled = capinfo.enableIfEquals(other);
+    if (enabled)
+      orderedList.addElement(key);
+
+    return enabled;
+  }
+
+  public boolean isEnabled(int code) {
+    CapabilityInfo capinfo = (CapabilityInfo)infoMap.get(new Integer(code));
+    if (capinfo == null)
+      return false;
+
+    return capinfo.isEnabled();
+  }
+
+  public int numEnabled() {
+    return orderedList.size();
+  }
+
+  public int getByOrder(int idx) {
+    int code;
+    try {
+      code = ((Integer)orderedList.elementAt(idx)).intValue();
+    } catch (ArrayIndexOutOfBoundsException e) {
+      code = 0;
+    }
+    return code;
+  }
+
+  // Protected data
+
+  protected Hashtable infoMap;
+  protected Vector orderedList;
+}
+
diff --git a/java/src/com/tigervnc/vncviewer/ClipboardFrame.java b/java/src/com/tigervnc/vncviewer/ClipboardFrame.java
new file mode 100644 (file)
index 0000000..2b11eb8
--- /dev/null
@@ -0,0 +1,135 @@
+//
+//  Copyright (C) 2001 HorizonLive.com, Inc.  All Rights Reserved.
+//  Copyright (C) 1999 AT&T Laboratories Cambridge.  All Rights Reserved.
+//
+//  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.
+//
+
+//
+// Clipboard frame.
+//
+
+package com.tightvnc.vncviewer;
+
+import java.awt.*;
+import java.awt.event.*;
+
+class ClipboardFrame extends Frame
+  implements WindowListener, ActionListener {
+
+  TextArea textArea;
+  Button clearButton, closeButton;
+  String selection;
+  VncViewer viewer;
+
+  //
+  // Constructor.
+  //
+
+  ClipboardFrame(VncViewer v) {
+    super("TigerVNC Clipboard");
+
+    viewer = v;
+
+    GridBagLayout gridbag = new GridBagLayout();
+    setLayout(gridbag);
+
+    GridBagConstraints gbc = new GridBagConstraints();
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    gbc.fill = GridBagConstraints.BOTH;
+    gbc.weighty = 1.0;
+
+    textArea = new TextArea(5, 40);
+    gridbag.setConstraints(textArea, gbc);
+    add(textArea);
+
+    gbc.fill = GridBagConstraints.HORIZONTAL;
+    gbc.weightx = 1.0;
+    gbc.weighty = 0.0;
+    gbc.gridwidth = 1;
+
+    clearButton = new Button("Clear");
+    gridbag.setConstraints(clearButton, gbc);
+    add(clearButton);
+    clearButton.addActionListener(this);
+
+    closeButton = new Button("Close");
+    gridbag.setConstraints(closeButton, gbc);
+    add(closeButton);
+    closeButton.addActionListener(this);
+
+    pack();
+
+    addWindowListener(this);
+  }
+
+
+  //
+  // Set the cut text from the RFB server.
+  //
+
+  void setCutText(String text) {
+    selection = text;
+    textArea.setText(text);
+    if (isVisible()) {
+      textArea.selectAll();
+    }
+  }
+
+
+  //
+  // When the focus leaves the window, see if we have new cut text and
+  // if so send it to the RFB server.
+  //
+
+  public void windowDeactivated (WindowEvent evt) {
+    if (selection != null && !selection.equals(textArea.getText())) {
+      selection = textArea.getText();
+      viewer.setCutText(selection);
+    }
+  }
+
+  //
+  // Close our window properly.
+  //
+
+  public void windowClosing(WindowEvent evt) {
+    setVisible(false);
+  }
+
+  //
+  // Ignore window events we're not interested in.
+  //
+
+  public void windowActivated(WindowEvent evt) {}
+  public void windowOpened(WindowEvent evt) {}
+  public void windowClosed(WindowEvent evt) {}
+  public void windowIconified(WindowEvent evt) {}
+  public void windowDeiconified(WindowEvent evt) {}
+
+
+  //
+  // Respond to button presses
+  //
+
+  public void actionPerformed(ActionEvent evt) {
+    if (evt.getSource() == clearButton) {
+      textArea.setText("");
+    } else if (evt.getSource() == closeButton) {
+      setVisible(false);
+    }
+  }
+}
diff --git a/java/src/com/tigervnc/vncviewer/DesCipher.java b/java/src/com/tigervnc/vncviewer/DesCipher.java
new file mode 100644 (file)
index 0000000..9ebeaa8
--- /dev/null
@@ -0,0 +1,498 @@
+//
+// This DES class has been extracted from package Acme.Crypto for use in VNC.
+// The bytebit[] array has been reversed so that the most significant bit
+// in each byte of the key is ignored, not the least significant.  Also the
+// unnecessary odd parity code has been removed.
+//
+// These changes are:
+//  Copyright (C) 1999 AT&T Laboratories Cambridge.  All Rights Reserved.
+//
+// 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.
+//
+
+// DesCipher - the DES encryption method
+//
+// The meat of this code is by Dave Zimmerman <dzimm@widget.com>, and is:
+//
+// Copyright (c) 1996 Widget Workshop, Inc. All Rights Reserved.
+//
+// Permission to use, copy, modify, and distribute this software
+// and its documentation for NON-COMMERCIAL or COMMERCIAL purposes and
+// without fee is hereby granted, provided that this copyright notice is kept 
+// intact. 
+// 
+// WIDGET WORKSHOP MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY
+// OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE, OR NON-INFRINGEMENT. WIDGET WORKSHOP SHALL NOT BE LIABLE
+// FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+// DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
+// 
+// THIS SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE OR RESALE AS ON-LINE
+// CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE
+// PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT
+// NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT LIFE
+// SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE
+// SOFTWARE COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE
+// PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH RISK ACTIVITIES").  WIDGET WORKSHOP
+// SPECIFICALLY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR
+// HIGH RISK ACTIVITIES.
+//
+//
+// The rest is:
+//
+// Copyright (C) 1996 by Jef Poskanzer <jef@acme.com>.  All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+//
+// Visit the ACME Labs Java page for up-to-date versions of this and other
+// fine Java utilities: http://www.acme.com/java/
+
+
+package com.tightvnc.vncviewer;
+
+import java.io.*;
+
+/// The DES encryption method.
+// <P>
+// This is surprisingly fast, for pure Java.  On a SPARC 20, wrapped
+// in Acme.Crypto.EncryptedOutputStream or Acme.Crypto.EncryptedInputStream,
+// it does around 7000 bytes/second.
+// <P>
+// Most of this code is by Dave Zimmerman <dzimm@widget.com>, and is
+// Copyright (c) 1996 Widget Workshop, Inc.  See the source file for details.
+// <P>
+// <A HREF="/resources/classes/Acme/Crypto/DesCipher.java">Fetch the software.</A><BR>
+// <A HREF="/resources/classes/Acme.tar.Z">Fetch the entire Acme package.</A>
+// <P>
+// @see Des3Cipher
+// @see EncryptedOutputStream
+// @see EncryptedInputStream
+
+public class DesCipher
+    {
+
+    // Constructor, byte-array key.
+    public DesCipher( byte[] key )
+       {
+       setKey( key );
+       }
+
+    // Key routines.
+
+    private int[] encryptKeys = new int[32];
+    private int[] decryptKeys = new int[32];
+
+    /// Set the key.
+    public void setKey( byte[] key )
+       {
+       deskey( key, true, encryptKeys );
+       deskey( key, false, decryptKeys );
+       }
+
+    // Turn an 8-byte key into internal keys.
+    private void deskey( byte[] keyBlock, boolean encrypting, int[] KnL )
+       {
+       int i, j, l, m, n;
+       int[] pc1m = new int[56];
+       int[] pcr = new int[56];
+       int[] kn = new int[32];
+
+       for ( j = 0; j < 56; ++j )
+           {
+           l = pc1[j];
+           m = l & 07;
+           pc1m[j] = ( (keyBlock[l >>> 3] & bytebit[m]) != 0 )? 1: 0;
+           }
+
+       for ( i = 0; i < 16; ++i )
+           {
+           if ( encrypting )
+               m = i << 1;
+           else
+               m = (15-i) << 1;
+           n = m+1;
+           kn[m] = kn[n] = 0;
+           for ( j = 0; j < 28; ++j )
+               {
+               l = j+totrot[i];
+               if ( l < 28 )
+                   pcr[j] = pc1m[l];
+               else
+                   pcr[j] = pc1m[l-28];
+               }
+           for ( j=28; j < 56; ++j )
+               {
+               l = j+totrot[i];
+               if ( l < 56 )
+                   pcr[j] = pc1m[l];
+               else
+                   pcr[j] = pc1m[l-28];
+               }
+           for ( j = 0; j < 24; ++j )
+               {
+               if ( pcr[pc2[j]] != 0 )
+                   kn[m] |= bigbyte[j];
+               if ( pcr[pc2[j+24]] != 0 )
+                   kn[n] |= bigbyte[j];
+               }
+           }
+       cookey( kn, KnL );
+       }
+
+    private void cookey( int[] raw, int KnL[] )
+       {
+       int raw0, raw1;
+       int rawi, KnLi;
+       int i;
+
+       for ( i = 0, rawi = 0, KnLi = 0; i < 16; ++i )
+           {
+           raw0 = raw[rawi++];
+           raw1 = raw[rawi++];
+           KnL[KnLi]  = (raw0 & 0x00fc0000) <<   6;
+           KnL[KnLi] |= (raw0 & 0x00000fc0) <<  10;
+           KnL[KnLi] |= (raw1 & 0x00fc0000) >>> 10;
+           KnL[KnLi] |= (raw1 & 0x00000fc0) >>>  6;
+           ++KnLi;
+           KnL[KnLi]  = (raw0 & 0x0003f000) <<  12;
+           KnL[KnLi] |= (raw0 & 0x0000003f) <<  16;
+           KnL[KnLi] |= (raw1 & 0x0003f000) >>>  4;
+           KnL[KnLi] |= (raw1 & 0x0000003f);
+           ++KnLi;
+           }
+       }
+
+
+    // Block encryption routines.
+
+    private int[] tempInts = new int[2];
+
+    /// Encrypt a block of eight bytes.
+    public void encrypt( byte[] clearText, int clearOff, byte[] cipherText, int cipherOff )
+       {
+       squashBytesToInts( clearText, clearOff, tempInts, 0, 2 );
+       des( tempInts, tempInts, encryptKeys );
+       spreadIntsToBytes( tempInts, 0, cipherText, cipherOff, 2 );
+       }
+
+    /// Decrypt a block of eight bytes.
+    public void decrypt( byte[] cipherText, int cipherOff, byte[] clearText, int clearOff )
+       {
+       squashBytesToInts( cipherText, cipherOff, tempInts, 0, 2 );
+       des( tempInts, tempInts, decryptKeys );
+       spreadIntsToBytes( tempInts, 0, clearText, clearOff, 2 );
+       }
+
+    // The DES function.
+    private void des( int[] inInts, int[] outInts, int[] keys )
+       {
+       int fval, work, right, leftt;
+       int round;
+       int keysi = 0;
+
+       leftt = inInts[0];
+       right = inInts[1];
+
+       work   = ((leftt >>>  4) ^ right) & 0x0f0f0f0f;
+       right ^= work;
+       leftt ^= (work << 4);
+
+       work   = ((leftt >>> 16) ^ right) & 0x0000ffff;
+       right ^= work;
+       leftt ^= (work << 16);
+
+       work   = ((right >>>  2) ^ leftt) & 0x33333333;
+       leftt ^= work;
+       right ^= (work << 2);
+
+       work   = ((right >>>  8) ^ leftt) & 0x00ff00ff;
+       leftt ^= work;
+       right ^= (work << 8);
+       right  = (right << 1) | ((right >>> 31) & 1);
+
+       work   = (leftt ^ right) & 0xaaaaaaaa;
+       leftt ^= work;
+       right ^= work;
+       leftt  = (leftt << 1) | ((leftt >>> 31) & 1);
+
+       for ( round = 0; round < 8; ++round )
+           {
+           work   = (right << 28) | (right >>> 4);
+           work  ^= keys[keysi++];
+           fval   = SP7[ work         & 0x0000003f ];
+           fval  |= SP5[(work >>>  8) & 0x0000003f ];
+           fval  |= SP3[(work >>> 16) & 0x0000003f ];
+           fval  |= SP1[(work >>> 24) & 0x0000003f ];
+           work   = right ^ keys[keysi++];
+           fval  |= SP8[ work         & 0x0000003f ];
+           fval  |= SP6[(work >>>  8) & 0x0000003f ];
+           fval  |= SP4[(work >>> 16) & 0x0000003f ];
+           fval  |= SP2[(work >>> 24) & 0x0000003f ];
+           leftt ^= fval;
+           work   = (leftt << 28) | (leftt >>> 4);
+           work  ^= keys[keysi++];
+           fval   = SP7[ work         & 0x0000003f ];
+           fval  |= SP5[(work >>>  8) & 0x0000003f ];
+           fval  |= SP3[(work >>> 16) & 0x0000003f ];
+           fval  |= SP1[(work >>> 24) & 0x0000003f ];
+           work   = leftt ^ keys[keysi++];
+           fval  |= SP8[ work         & 0x0000003f ];
+           fval  |= SP6[(work >>>  8) & 0x0000003f ];
+           fval  |= SP4[(work >>> 16) & 0x0000003f ];
+           fval  |= SP2[(work >>> 24) & 0x0000003f ];
+           right ^= fval;
+           }
+
+       right  = (right << 31) | (right >>> 1);
+       work   = (leftt ^ right) & 0xaaaaaaaa;
+       leftt ^= work;
+       right ^= work;
+       leftt  = (leftt << 31) | (leftt >>> 1);
+       work   = ((leftt >>>  8) ^ right) & 0x00ff00ff;
+       right ^= work;
+       leftt ^= (work << 8);
+       work   = ((leftt >>>  2) ^ right) & 0x33333333;
+       right ^= work;
+       leftt ^= (work << 2);
+       work   = ((right >>> 16) ^ leftt) & 0x0000ffff;
+       leftt ^= work;
+       right ^= (work << 16);
+       work   = ((right >>>  4) ^ leftt) & 0x0f0f0f0f;
+       leftt ^= work;
+       right ^= (work << 4);
+       outInts[0] = right;
+       outInts[1] = leftt;
+       }
+
+
+    // Tables, permutations, S-boxes, etc.
+
+    private static byte[] bytebit = {
+       (byte)0x01, (byte)0x02, (byte)0x04, (byte)0x08,
+       (byte)0x10, (byte)0x20, (byte)0x40, (byte)0x80
+       };
+    private static int[] bigbyte = {
+       0x800000, 0x400000, 0x200000, 0x100000,
+       0x080000, 0x040000, 0x020000, 0x010000,
+       0x008000, 0x004000, 0x002000, 0x001000,
+       0x000800, 0x000400, 0x000200, 0x000100,
+       0x000080, 0x000040, 0x000020, 0x000010,
+       0x000008, 0x000004, 0x000002, 0x000001
+       };
+    private static byte[] pc1 = {
+         (byte)56, (byte)48, (byte)40, (byte)32, (byte)24, (byte)16, (byte) 8,
+      (byte) 0, (byte)57, (byte)49, (byte)41, (byte)33, (byte)25, (byte)17,
+        (byte) 9, (byte) 1, (byte)58, (byte)50, (byte)42, (byte)34, (byte)26,
+      (byte)18, (byte)10, (byte) 2, (byte)59, (byte)51, (byte)43, (byte)35,
+        (byte)62, (byte)54, (byte)46, (byte)38, (byte)30, (byte)22, (byte)14,
+      (byte) 6, (byte)61, (byte)53, (byte)45, (byte)37, (byte)29, (byte)21,
+        (byte)13, (byte) 5, (byte)60, (byte)52, (byte)44, (byte)36, (byte)28,
+      (byte)20, (byte)12, (byte) 4, (byte)27, (byte)19, (byte)11, (byte)3
+       };
+    private static int[] totrot = {
+        1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28
+       };
+
+    private static byte[] pc2 = {
+       (byte)13, (byte)16, (byte)10, (byte)23, (byte) 0, (byte) 4,
+                 (byte) 2, (byte)27, (byte)14, (byte) 5, (byte)20, (byte) 9,
+       (byte)22, (byte)18, (byte)11, (byte)3 , (byte)25, (byte) 7,
+                 (byte)15, (byte) 6, (byte)26, (byte)19, (byte)12, (byte) 1,
+       (byte)40, (byte)51, (byte)30, (byte)36, (byte)46, (byte)54,
+                 (byte)29, (byte)39, (byte)50, (byte)44, (byte)32, (byte)47,
+       (byte)43, (byte)48, (byte)38, (byte)55, (byte)33, (byte)52,
+                 (byte)45, (byte)41, (byte)49, (byte)35, (byte)28, (byte)31,
+       };
+
+    private static int[] SP1 = {
+        0x01010400, 0x00000000, 0x00010000, 0x01010404,
+       0x01010004, 0x00010404, 0x00000004, 0x00010000,
+       0x00000400, 0x01010400, 0x01010404, 0x00000400,
+       0x01000404, 0x01010004, 0x01000000, 0x00000004,
+       0x00000404, 0x01000400, 0x01000400, 0x00010400,
+       0x00010400, 0x01010000, 0x01010000, 0x01000404,
+       0x00010004, 0x01000004, 0x01000004, 0x00010004,
+       0x00000000, 0x00000404, 0x00010404, 0x01000000,
+       0x00010000, 0x01010404, 0x00000004, 0x01010000,
+       0x01010400, 0x01000000, 0x01000000, 0x00000400,
+       0x01010004, 0x00010000, 0x00010400, 0x01000004,
+       0x00000400, 0x00000004, 0x01000404, 0x00010404,
+       0x01010404, 0x00010004, 0x01010000, 0x01000404,
+       0x01000004, 0x00000404, 0x00010404, 0x01010400,
+       0x00000404, 0x01000400, 0x01000400, 0x00000000,
+       0x00010004, 0x00010400, 0x00000000, 0x01010004
+       };
+    private static int[] SP2 = {
+       0x80108020, 0x80008000, 0x00008000, 0x00108020,
+       0x00100000, 0x00000020, 0x80100020, 0x80008020,
+       0x80000020, 0x80108020, 0x80108000, 0x80000000,
+       0x80008000, 0x00100000, 0x00000020, 0x80100020,
+       0x00108000, 0x00100020, 0x80008020, 0x00000000,
+       0x80000000, 0x00008000, 0x00108020, 0x80100000,
+       0x00100020, 0x80000020, 0x00000000, 0x00108000,
+       0x00008020, 0x80108000, 0x80100000, 0x00008020,
+       0x00000000, 0x00108020, 0x80100020, 0x00100000,
+       0x80008020, 0x80100000, 0x80108000, 0x00008000,
+       0x80100000, 0x80008000, 0x00000020, 0x80108020,
+       0x00108020, 0x00000020, 0x00008000, 0x80000000,
+       0x00008020, 0x80108000, 0x00100000, 0x80000020,
+       0x00100020, 0x80008020, 0x80000020, 0x00100020,
+       0x00108000, 0x00000000, 0x80008000, 0x00008020,
+       0x80000000, 0x80100020, 0x80108020, 0x00108000
+       };
+    private static int[] SP3 = {
+       0x00000208, 0x08020200, 0x00000000, 0x08020008,
+       0x08000200, 0x00000000, 0x00020208, 0x08000200,
+       0x00020008, 0x08000008, 0x08000008, 0x00020000,
+       0x08020208, 0x00020008, 0x08020000, 0x00000208,
+       0x08000000, 0x00000008, 0x08020200, 0x00000200,
+       0x00020200, 0x08020000, 0x08020008, 0x00020208,
+       0x08000208, 0x00020200, 0x00020000, 0x08000208,
+       0x00000008, 0x08020208, 0x00000200, 0x08000000,
+       0x08020200, 0x08000000, 0x00020008, 0x00000208,
+       0x00020000, 0x08020200, 0x08000200, 0x00000000,
+       0x00000200, 0x00020008, 0x08020208, 0x08000200,
+       0x08000008, 0x00000200, 0x00000000, 0x08020008,
+       0x08000208, 0x00020000, 0x08000000, 0x08020208,
+       0x00000008, 0x00020208, 0x00020200, 0x08000008,
+       0x08020000, 0x08000208, 0x00000208, 0x08020000,
+       0x00020208, 0x00000008, 0x08020008, 0x00020200
+       };
+    private static int[] SP4 = {
+       0x00802001, 0x00002081, 0x00002081, 0x00000080,
+       0x00802080, 0x00800081, 0x00800001, 0x00002001,
+       0x00000000, 0x00802000, 0x00802000, 0x00802081,
+       0x00000081, 0x00000000, 0x00800080, 0x00800001,
+       0x00000001, 0x00002000, 0x00800000, 0x00802001,
+       0x00000080, 0x00800000, 0x00002001, 0x00002080,
+       0x00800081, 0x00000001, 0x00002080, 0x00800080,
+       0x00002000, 0x00802080, 0x00802081, 0x00000081,
+       0x00800080, 0x00800001, 0x00802000, 0x00802081,
+       0x00000081, 0x00000000, 0x00000000, 0x00802000,
+       0x00002080, 0x00800080, 0x00800081, 0x00000001,
+       0x00802001, 0x00002081, 0x00002081, 0x00000080,
+       0x00802081, 0x00000081, 0x00000001, 0x00002000,
+       0x00800001, 0x00002001, 0x00802080, 0x00800081,
+       0x00002001, 0x00002080, 0x00800000, 0x00802001,
+       0x00000080, 0x00800000, 0x00002000, 0x00802080
+       };
+    private static int[] SP5 = {
+       0x00000100, 0x02080100, 0x02080000, 0x42000100,
+       0x00080000, 0x00000100, 0x40000000, 0x02080000,
+       0x40080100, 0x00080000, 0x02000100, 0x40080100,
+       0x42000100, 0x42080000, 0x00080100, 0x40000000,
+       0x02000000, 0x40080000, 0x40080000, 0x00000000,
+       0x40000100, 0x42080100, 0x42080100, 0x02000100,
+       0x42080000, 0x40000100, 0x00000000, 0x42000000,
+       0x02080100, 0x02000000, 0x42000000, 0x00080100,
+       0x00080000, 0x42000100, 0x00000100, 0x02000000,
+       0x40000000, 0x02080000, 0x42000100, 0x40080100,
+       0x02000100, 0x40000000, 0x42080000, 0x02080100,
+       0x40080100, 0x00000100, 0x02000000, 0x42080000,
+       0x42080100, 0x00080100, 0x42000000, 0x42080100,
+       0x02080000, 0x00000000, 0x40080000, 0x42000000,
+       0x00080100, 0x02000100, 0x40000100, 0x00080000,
+       0x00000000, 0x40080000, 0x02080100, 0x40000100
+       };
+    private static int[] SP6 = {
+       0x20000010, 0x20400000, 0x00004000, 0x20404010,
+       0x20400000, 0x00000010, 0x20404010, 0x00400000,
+       0x20004000, 0x00404010, 0x00400000, 0x20000010,
+       0x00400010, 0x20004000, 0x20000000, 0x00004010,
+       0x00000000, 0x00400010, 0x20004010, 0x00004000,
+       0x00404000, 0x20004010, 0x00000010, 0x20400010,
+       0x20400010, 0x00000000, 0x00404010, 0x20404000,
+       0x00004010, 0x00404000, 0x20404000, 0x20000000,
+       0x20004000, 0x00000010, 0x20400010, 0x00404000,
+       0x20404010, 0x00400000, 0x00004010, 0x20000010,
+       0x00400000, 0x20004000, 0x20000000, 0x00004010,
+       0x20000010, 0x20404010, 0x00404000, 0x20400000,
+       0x00404010, 0x20404000, 0x00000000, 0x20400010,
+       0x00000010, 0x00004000, 0x20400000, 0x00404010,
+       0x00004000, 0x00400010, 0x20004010, 0x00000000,
+       0x20404000, 0x20000000, 0x00400010, 0x20004010
+       };
+    private static int[] SP7 = {
+       0x00200000, 0x04200002, 0x04000802, 0x00000000,
+       0x00000800, 0x04000802, 0x00200802, 0x04200800,
+       0x04200802, 0x00200000, 0x00000000, 0x04000002,
+       0x00000002, 0x04000000, 0x04200002, 0x00000802,
+       0x04000800, 0x00200802, 0x00200002, 0x04000800,
+       0x04000002, 0x04200000, 0x04200800, 0x00200002,
+       0x04200000, 0x00000800, 0x00000802, 0x04200802,
+       0x00200800, 0x00000002, 0x04000000, 0x00200800,
+       0x04000000, 0x00200800, 0x00200000, 0x04000802,
+       0x04000802, 0x04200002, 0x04200002, 0x00000002,
+       0x00200002, 0x04000000, 0x04000800, 0x00200000,
+       0x04200800, 0x00000802, 0x00200802, 0x04200800,
+       0x00000802, 0x04000002, 0x04200802, 0x04200000,
+       0x00200800, 0x00000000, 0x00000002, 0x04200802,
+       0x00000000, 0x00200802, 0x04200000, 0x00000800,
+       0x04000002, 0x04000800, 0x00000800, 0x00200002
+       };
+    private static int[] SP8 = {
+       0x10001040, 0x00001000, 0x00040000, 0x10041040,
+       0x10000000, 0x10001040, 0x00000040, 0x10000000,
+       0x00040040, 0x10040000, 0x10041040, 0x00041000,
+       0x10041000, 0x00041040, 0x00001000, 0x00000040,
+       0x10040000, 0x10000040, 0x10001000, 0x00001040,
+       0x00041000, 0x00040040, 0x10040040, 0x10041000,
+       0x00001040, 0x00000000, 0x00000000, 0x10040040,
+       0x10000040, 0x10001000, 0x00041040, 0x00040000,
+       0x00041040, 0x00040000, 0x10041000, 0x00001000,
+       0x00000040, 0x10040040, 0x00001000, 0x00041040,
+       0x10001000, 0x00000040, 0x10000040, 0x10040000,
+       0x10040040, 0x10000000, 0x00040000, 0x10001040,
+       0x00000000, 0x10041040, 0x00040040, 0x10000040,
+       0x10040000, 0x10001000, 0x10001040, 0x00000000,
+       0x10041040, 0x00041000, 0x00041000, 0x00001040,
+       0x00001040, 0x00040040, 0x10000000, 0x10041000
+       };
+
+    // Routines taken from other parts of the Acme utilities.
+
+    /// Squash bytes down to ints.
+    public static void squashBytesToInts( byte[] inBytes, int inOff, int[] outInts, int outOff, int intLen )
+        {
+       for ( int i = 0; i < intLen; ++i )
+           outInts[outOff + i] = 
+               ( ( inBytes[inOff + i * 4    ] & 0xff ) << 24 ) |
+               ( ( inBytes[inOff + i * 4 + 1] & 0xff ) << 16 ) |
+               ( ( inBytes[inOff + i * 4 + 2] & 0xff ) <<  8 ) |
+                 ( inBytes[inOff + i * 4 + 3] & 0xff );
+        }
+
+    /// Spread ints into bytes.
+    public static void spreadIntsToBytes( int[] inInts, int inOff, byte[] outBytes, int outOff, int intLen )
+        {
+       for ( int i = 0; i < intLen; ++i )
+           {
+           outBytes[outOff + i * 4    ] = (byte) ( inInts[inOff + i] >>> 24 );
+           outBytes[outOff + i * 4 + 1] = (byte) ( inInts[inOff + i] >>> 16 );
+           outBytes[outOff + i * 4 + 2] = (byte) ( inInts[inOff + i] >>>  8 );
+           outBytes[outOff + i * 4 + 3] = (byte)   inInts[inOff + i];
+           }
+        }
+    }
diff --git a/java/src/com/tigervnc/vncviewer/HTTPConnectSocket.java b/java/src/com/tigervnc/vncviewer/HTTPConnectSocket.java
new file mode 100644 (file)
index 0000000..c427b06
--- /dev/null
@@ -0,0 +1,61 @@
+//
+//  Copyright (C) 2002 Constantin Kaplinsky, Inc.  All Rights Reserved.
+//
+//  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.
+//
+
+//
+// HTTPConnectSocket.java together with HTTPConnectSocketFactory.java
+// implement an alternate way to connect to VNC servers via one or two
+// HTTP proxies supporting the HTTP CONNECT method.
+//
+
+package com.tightvnc.vncviewer;
+
+import java.net.*;
+import java.io.*;
+
+class HTTPConnectSocket extends Socket {
+
+  public HTTPConnectSocket(String host, int port,
+                          String proxyHost, int proxyPort)
+    throws IOException {
+
+    // Connect to the specified HTTP proxy
+    super(proxyHost, proxyPort);
+
+    // Send the CONNECT request
+    getOutputStream().write(("CONNECT " + host + ":" + port +
+                            " HTTP/1.0\r\n\r\n").getBytes());
+
+    // Read the first line of the response
+    DataInputStream is = new DataInputStream(getInputStream());
+    String str = is.readLine();
+
+    // Check the HTTP error code -- it should be "200" on success
+    if (!str.startsWith("HTTP/1.0 200 ")) {
+      if (str.startsWith("HTTP/1.0 "))
+       str = str.substring(9);
+      throw new IOException("Proxy reports \"" + str + "\"");
+    }
+
+    // Success -- skip remaining HTTP headers
+    do {
+      str = is.readLine();
+    } while (str.length() != 0);
+  }
+}
+
diff --git a/java/src/com/tigervnc/vncviewer/HTTPConnectSocketFactory.java b/java/src/com/tigervnc/vncviewer/HTTPConnectSocketFactory.java
new file mode 100644 (file)
index 0000000..3eae6f9
--- /dev/null
@@ -0,0 +1,88 @@
+//
+//  Copyright (C) 2002 Constantin Kaplinsky, Inc.  All Rights Reserved.
+//
+//  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.
+//
+
+//
+// HTTPConnectSocketFactory.java together with HTTPConnectSocket.java
+// implement an alternate way to connect to VNC servers via one or two
+// HTTP proxies supporting the HTTP CONNECT method.
+//
+
+package com.tightvnc.vncviewer;
+
+import java.applet.*;
+import java.net.*;
+import java.io.*;
+
+class HTTPConnectSocketFactory implements SocketFactory {
+
+  public Socket createSocket(String host, int port, Applet applet)
+    throws IOException {
+
+    return createSocket(host, port,
+                       applet.getParameter("PROXYHOST1"),
+                       applet.getParameter("PROXYPORT1"));
+  }
+
+  public Socket createSocket(String host, int port, String[] args)
+    throws IOException {
+
+    return createSocket(host, port,
+                       readArg(args, "PROXYHOST1"),
+                       readArg(args, "PROXYPORT1"));
+  }
+
+  public Socket createSocket(String host, int port,
+                            String proxyHost, String proxyPortStr)
+    throws IOException {
+
+    int proxyPort = 0;
+    if (proxyPortStr != null) {
+      try {
+       proxyPort = Integer.parseInt(proxyPortStr);
+      } catch (NumberFormatException e) { }
+    }
+
+    if (proxyHost == null || proxyPort == 0) {
+      System.out.println("Incomplete parameter list for HTTPConnectSocket");
+      return new Socket(host, port);
+    }
+
+    System.out.println("HTTP CONNECT via proxy " + proxyHost +
+                      " port " + proxyPort);
+    HTTPConnectSocket s =
+      new HTTPConnectSocket(host, port, proxyHost, proxyPort);
+
+    return (Socket)s;
+  }
+
+  private String readArg(String[] args, String name) {
+
+    for (int i = 0; i < args.length; i += 2) {
+      if (args[i].equalsIgnoreCase(name)) {
+       try {
+         return args[i+1];
+       } catch (Exception e) {
+         return null;
+       }
+      }
+    }
+    return null;
+  }
+}
+
diff --git a/java/src/com/tigervnc/vncviewer/InStream.java b/java/src/com/tigervnc/vncviewer/InStream.java
new file mode 100644 (file)
index 0000000..ecb03d9
--- /dev/null
@@ -0,0 +1,179 @@
+/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
+ * 
+ * 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.
+ */
+
+//
+// rdr::InStream marshalls data from a buffer stored in RDR (RFB Data
+// Representation).
+//
+
+package com.tightvnc.vncviewer;
+
+abstract public class InStream {
+
+  // check() ensures there is buffer data for at least one item of size
+  // itemSize bytes.  Returns the number of items in the buffer (up to a
+  // maximum of nItems).
+
+  public final int check(int itemSize, int nItems) throws Exception {
+    if (ptr + itemSize * nItems > end) {
+      if (ptr + itemSize > end)
+        return overrun(itemSize, nItems);
+
+      nItems = (end - ptr) / itemSize;
+    }
+    return nItems;
+  }
+
+  public final void check(int itemSize) throws Exception {
+    if (ptr + itemSize > end)
+      overrun(itemSize, 1);
+  }
+
+  // readU/SN() methods read unsigned and signed N-bit integers.
+
+  public final int readS8() throws Exception {
+    check(1); return b[ptr++];
+  }
+
+  public final int readS16() throws Exception {
+    check(2); int b0 = b[ptr++];
+    int b1 = b[ptr++] & 0xff; return b0 << 8 | b1;
+  }
+
+  public final int readS32() throws Exception {
+    check(4); int b0 = b[ptr++];
+    int b1 = b[ptr++] & 0xff;
+    int b2 = b[ptr++] & 0xff;
+    int b3 = b[ptr++] & 0xff;
+    return b0 << 24 | b1 << 16 | b2 << 8 | b3;
+  }
+
+  public final int readU8() throws Exception {
+    return readS8() & 0xff;
+  }
+
+  public final int readU16() throws Exception {
+    return readS16() & 0xffff;
+  }
+
+  public final int readU32() throws Exception {
+    return readS32() & 0xffffffff;
+  }
+
+  // readString() reads a string - a U32 length followed by the data.
+
+  public final String readString() throws Exception {
+    int len = readU32();
+    if (len > maxStringLength)
+      throw new Exception("InStream max string length exceeded");
+
+    char[] str = new char[len];
+    int i = 0;
+    while (i < len) {
+      int j = i + check(1, len - i);
+      while (i < j) {
+       str[i++] = (char)b[ptr++];
+      }
+    }
+
+    return new String(str);
+  }
+
+  // maxStringLength protects against allocating a huge buffer.  Set it
+  // higher if you need longer strings.
+
+  public static int maxStringLength = 65535;
+
+  public final void skip(int bytes) throws Exception {
+    while (bytes > 0) {
+      int n = check(1, bytes);
+      ptr += n;
+      bytes -= n;
+    }
+  }
+
+  // readBytes() reads an exact number of bytes into an array at an offset.
+
+  public void readBytes(byte[] data, int offset, int length) throws Exception {
+    int offsetEnd = offset + length;
+    while (offset < offsetEnd) {
+      int n = check(1, offsetEnd - offset);
+      System.arraycopy(b, ptr, data, offset, n);
+      ptr += n;
+      offset += n;
+    }
+  }
+
+  // readOpaqueN() reads a quantity "without byte-swapping".  Because java has
+  // no byte-ordering, we just use big-endian.
+
+  public final int readOpaque8() throws Exception {
+    return readU8();
+  }
+
+  public final int readOpaque16() throws Exception {
+    return readU16();
+  }
+
+  public final int readOpaque32() throws Exception {
+    return readU32();
+  }
+
+  public final int readOpaque24A() throws Exception {
+    check(3); int b0 = b[ptr++];
+    int b1 = b[ptr++]; int b2 = b[ptr++];
+    return b0 << 24 | b1 << 16 | b2 << 8;
+  }
+
+  public final int readOpaque24B() throws Exception {
+    check(3); int b0 = b[ptr++];
+    int b1 = b[ptr++]; int b2 = b[ptr++];
+    return b0 << 16 | b1 << 8 | b2;
+  }
+
+  // pos() returns the position in the stream.
+
+  abstract public int pos();
+
+  // bytesAvailable() returns true if at least one byte can be read from the
+  // stream without blocking.  i.e. if false is returned then readU8() would
+  // block.
+
+  public boolean bytesAvailable() { return end != ptr; }
+
+  // getbuf(), getptr(), getend() and setptr() are "dirty" methods which allow
+  // you to manipulate the buffer directly.  This is useful for a stream which
+  // is a wrapper around an underlying stream.
+
+  public final byte[] getbuf() { return b; }
+  public final int getptr() { return ptr; }
+  public final int getend() { return end; }
+  public final void setptr(int p) { ptr = p; }
+
+  // overrun() is implemented by a derived class to cope with buffer overrun.
+  // It ensures there are at least itemSize bytes of buffer data.  Returns
+  // the number of items in the buffer (up to a maximum of nItems).  itemSize
+  // is supposed to be "small" (a few bytes).
+
+  abstract protected int overrun(int itemSize, int nItems) throws Exception;
+
+  protected InStream() {}
+  protected byte[] b;
+  protected int ptr;
+  protected int end;
+}
diff --git a/java/src/com/tigervnc/vncviewer/LICENCE.TXT b/java/src/com/tigervnc/vncviewer/LICENCE.TXT
new file mode 100644 (file)
index 0000000..ae3b531
--- /dev/null
@@ -0,0 +1,340 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+         Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+        59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+       Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program 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 program 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 program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
+    USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/java/src/com/tigervnc/vncviewer/MANIFEST.MF b/java/src/com/tigervnc/vncviewer/MANIFEST.MF
new file mode 100644 (file)
index 0000000..9ddbfbc
--- /dev/null
@@ -0,0 +1,2 @@
+Manifest-Version: 1.0
+Main-Class: VncViewer
diff --git a/java/src/com/tigervnc/vncviewer/Makefile b/java/src/com/tigervnc/vncviewer/Makefile
new file mode 100644 (file)
index 0000000..f236eae
--- /dev/null
@@ -0,0 +1,47 @@
+#
+# Making the VNC applet.
+#
+
+CP = cp
+JC = javac
+JCFLAGS = -target 1.1
+JAR = jar
+ARCHIVE = VncViewer.jar
+MANIFEST = MANIFEST.MF
+PAGES = index.vnc
+INSTALL_DIR = /usr/local/vnc/classes
+
+CLASSES = VncViewer.class RfbProto.class AuthPanel.class VncCanvas.class \
+         VncCanvas2.class \
+         OptionsFrame.class ClipboardFrame.class ButtonPanel.class \
+         DesCipher.class CapabilityInfo.class CapsContainer.class \
+         RecordingFrame.class SessionRecorder.class \
+         SocketFactory.class HTTPConnectSocketFactory.class \
+         HTTPConnectSocket.class ReloginPanel.class \
+         InStream.class MemInStream.class ZlibInStream.class
+
+SOURCES = VncViewer.java RfbProto.java AuthPanel.java VncCanvas.java \
+         VncCanvas2.java \
+         OptionsFrame.java ClipboardFrame.java ButtonPanel.java \
+         DesCipher.java CapabilityInfo.java CapsContainer.java \
+         RecordingFrame.java SessionRecorder.java \
+         SocketFactory.java HTTPConnectSocketFactory.java \
+         HTTPConnectSocket.java ReloginPanel.java \
+         InStream.java MemInStream.java ZlibInStream.java
+
+all: $(CLASSES) $(ARCHIVE)
+
+$(CLASSES): $(SOURCES)
+       $(JC) $(JCFLAGS) -O $(SOURCES)
+
+$(ARCHIVE): $(CLASSES) $(MANIFEST)
+       $(JAR) cfm $(ARCHIVE) $(MANIFEST) $(CLASSES)
+
+install: $(CLASSES) $(ARCHIVE)
+       $(CP) $(CLASSES) $(ARCHIVE) $(PAGES) $(INSTALL_DIR)
+
+export:: $(CLASSES) $(ARCHIVE) $(PAGES)
+       @$(ExportJavaClasses)
+
+clean::
+       $(RM) *.class *.jar
diff --git a/java/src/com/tigervnc/vncviewer/MemInStream.java b/java/src/com/tigervnc/vncviewer/MemInStream.java
new file mode 100644 (file)
index 0000000..7427a9a
--- /dev/null
@@ -0,0 +1,34 @@
+/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
+ * 
+ * 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.
+ */
+
+package com.tightvnc.vncviewer;
+
+public class MemInStream extends InStream {
+
+  public MemInStream(byte[] data, int offset, int len) {
+    b = data;
+    ptr = offset;
+    end = offset + len;
+  }
+
+  public int pos() { return ptr; }
+
+  protected int overrun(int itemSize, int nItems) throws Exception {
+    throw new Exception("MemInStream overrun: end of stream");
+  }
+}
diff --git a/java/src/com/tigervnc/vncviewer/OptionsFrame.java b/java/src/com/tigervnc/vncviewer/OptionsFrame.java
new file mode 100644 (file)
index 0000000..e1125f4
--- /dev/null
@@ -0,0 +1,478 @@
+//
+//  Copyright (C) 2001 HorizonLive.com, Inc.  All Rights Reserved.
+//  Copyright (C) 2001 Constantin Kaplinsky.  All Rights Reserved.
+//  Copyright (C) 2000 Tridia Corporation.  All Rights Reserved.
+//  Copyright (C) 1999 AT&T Laboratories Cambridge.  All Rights Reserved.
+//
+//  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.
+//
+
+//
+// Options frame.
+//
+// This deals with all the options the user can play with.
+// It sets the encodings array and some booleans.
+//
+
+package com.tightvnc.vncviewer;
+
+import java.awt.*;
+import java.awt.event.*;
+
+class OptionsFrame extends Frame
+  implements WindowListener, ActionListener, ItemListener {
+
+  static String[] names = {
+    "Encoding",
+    "Compression level",
+    "JPEG image quality",
+    "Cursor shape updates",
+    "Use CopyRect",
+    "Continuous updates",
+    "Restricted colors",
+    "Mouse buttons 2 and 3",
+    "View only",
+    "Scaling factor",
+    "Scale remote cursor",
+    "Share desktop"
+  };
+
+  static String[][] values = {
+    { "Auto", "Raw", "RRE", "CoRRE", "Hextile", "Zlib", "Tight", "ZRLE" },
+    { "Default", "1", "2", "3", "4", "5", "6", "7", "8", "9" },
+    { "JPEG off", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" },
+    { "Enable", "Ignore", "Disable" },
+    { "Yes", "No" },
+    { "Yes", "No" },
+    { "Yes", "No" },
+    { "Normal", "Reversed" },
+    { "Yes", "No" },
+    { "Auto", "1%", "5%", "10%", "20%", "25%", "50%", "75%", "100%"},
+    { "No", "50%", "75%", "125%", "150%" },
+    { "Yes", "No" }
+  };
+
+  final int
+    encodingIndex        = 0,
+    compressLevelIndex   = 1,
+    jpegQualityIndex     = 2,
+    cursorUpdatesIndex   = 3,
+    useCopyRectIndex     = 4,
+    contUpdatesIndex     = 5,
+    eightBitColorsIndex  = 6,
+    mouseButtonIndex     = 7,
+    viewOnlyIndex        = 8,
+    scalingFactorIndex   = 9,
+    scaleCursorIndex     = 10,
+    shareDesktopIndex    = 11;
+
+  Label[] labels = new Label[names.length];
+  Choice[] choices = new Choice[names.length];
+  Button closeButton;
+  VncViewer viewer;
+
+
+  //
+  // The actual data which other classes look at:
+  //
+
+  int preferredEncoding;
+  int compressLevel;
+  int jpegQuality;
+  boolean useCopyRect;
+  boolean continuousUpdates;
+  boolean requestCursorUpdates;
+  boolean ignoreCursorUpdates;
+
+  boolean eightBitColors;
+
+  boolean reverseMouseButtons2And3;
+  boolean shareDesktop;
+  boolean viewOnly;
+  int scaleCursor;
+
+  boolean autoScale;
+  int scalingFactor;
+
+  //
+  // Constructor.  Set up the labels and choices from the names and values
+  // arrays.
+  //
+
+  OptionsFrame(VncViewer v) {
+    super("TigerVNC Options");
+
+    viewer = v;
+
+    GridBagLayout gridbag = new GridBagLayout();
+    setLayout(gridbag);
+
+    GridBagConstraints gbc = new GridBagConstraints();
+    gbc.fill = GridBagConstraints.BOTH;
+
+    for (int i = 0; i < names.length; i++) {
+      labels[i] = new Label(names[i]);
+      gbc.gridwidth = 1;
+      gridbag.setConstraints(labels[i],gbc);
+      add(labels[i]);
+
+      choices[i] = new Choice();
+      gbc.gridwidth = GridBagConstraints.REMAINDER;
+      gridbag.setConstraints(choices[i],gbc);
+      add(choices[i]);
+      choices[i].addItemListener(this);
+
+      for (int j = 0; j < values[i].length; j++) {
+       choices[i].addItem(values[i][j]);
+      }
+    }
+
+    closeButton = new Button("Close");
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    gridbag.setConstraints(closeButton, gbc);
+    add(closeButton);
+    closeButton.addActionListener(this);
+
+    pack();
+
+    addWindowListener(this);
+
+    // Set up defaults
+
+    choices[encodingIndex].select("Auto");
+    choices[compressLevelIndex].select("Default");
+    choices[jpegQualityIndex].select("6");
+    choices[cursorUpdatesIndex].select("Enable");
+    choices[useCopyRectIndex].select("Yes");
+    choices[contUpdatesIndex].select("No");
+    choices[eightBitColorsIndex].select("No");
+    choices[mouseButtonIndex].select("Normal");
+    choices[viewOnlyIndex].select("No");
+    choices[scaleCursorIndex].select("No");
+    choices[shareDesktopIndex].select("Yes");
+
+    // But let them be overridden by parameters
+
+    for (int i = 0; i < names.length; i++) {
+      String s = viewer.readParameter(names[i], false);
+      if (s != null) {
+       for (int j = 0; j < values[i].length; j++) {
+         if (s.equalsIgnoreCase(values[i][j])) {
+           choices[i].select(j);
+         }
+       }
+      }
+    }
+
+    // Get scaling factor from parameters and set it
+    // to gui and class member scalingFactor
+    
+    String s = viewer.readParameter("Scaling Factor", false);
+    if (s == null) s = "100%";
+    setScalingFactor(s);
+    if (autoScale) {
+      choices[scalingFactorIndex].select("Auto");
+    } else {
+      choices[scalingFactorIndex].select(s);
+    }
+
+    // Make the booleans and encodings array correspond to the state of the GUI
+
+    setEncodings();
+    setColorFormat();
+    setContinuousUpdates();
+    setOtherOptions();
+  }
+  
+  //
+  // Set scaling factor class member value
+  //
+  
+  void setScalingFactor(int sf) {
+      setScalingFactor(((Integer)sf).toString());
+  }
+  
+  void setScalingFactor(String s) {
+    autoScale = false;
+    scalingFactor = 100;
+    if (s != null) {
+      if (s.equalsIgnoreCase("Auto")) {
+       autoScale = true;
+      } else {
+       // Remove the '%' char at the end of string if present.
+       if (s.charAt(s.length() - 1) == '%') {
+         s = s.substring(0, s.length() - 1);
+       }
+       // Convert to an integer.
+       try {
+         scalingFactor = Integer.parseInt(s);
+       }
+       catch (NumberFormatException e) {
+         scalingFactor = 100;
+       }
+       // Make sure scalingFactor is in the range of [1..1000].
+       if (scalingFactor < 1) {
+         scalingFactor = 1;
+       } else if (scalingFactor > 1000) {
+         scalingFactor = 1000;
+       }
+      }
+    }
+  }
+
+
+  //
+  // Disable the shareDesktop option
+  //
+
+  void disableShareDesktop() {
+    labels[shareDesktopIndex].setEnabled(false);
+    choices[shareDesktopIndex].setEnabled(false);
+  }
+
+
+  //
+  // Disable the "Continuous updates" option. This method is called
+  // when we figure out that the server does not support corresponding
+  // protocol extensions.
+  //
+
+  void disableContUpdates() {
+    labels[contUpdatesIndex].setEnabled(false);
+    choices[contUpdatesIndex].setEnabled(false);
+    choices[contUpdatesIndex].select("No");
+    continuousUpdates = false;
+  }
+
+
+  //
+  // setEncodings looks at the encoding, compression level, JPEG
+  // quality level, cursor shape updates and copyRect choices and sets
+  // corresponding variables properly. Then it calls the VncViewer's
+  // setEncodings method to send a SetEncodings message to the RFB
+  // server.
+  //
+
+  void setEncodings() {
+    useCopyRect = choices[useCopyRectIndex].getSelectedItem().equals("Yes");
+
+    preferredEncoding = RfbProto.EncodingRaw;
+    boolean enableCompressLevel = false;
+    boolean enableQualityLevel = false;
+
+    if (choices[encodingIndex].getSelectedItem().equals("RRE")) {
+      preferredEncoding = RfbProto.EncodingRRE;
+    } else if (choices[encodingIndex].getSelectedItem().equals("CoRRE")) {
+      preferredEncoding = RfbProto.EncodingCoRRE;
+    } else if (choices[encodingIndex].getSelectedItem().equals("Hextile")) {
+      preferredEncoding = RfbProto.EncodingHextile;
+    } else if (choices[encodingIndex].getSelectedItem().equals("ZRLE")) {
+      preferredEncoding = RfbProto.EncodingZRLE;
+    } else if (choices[encodingIndex].getSelectedItem().equals("Zlib")) {
+      preferredEncoding = RfbProto.EncodingZlib;
+      enableCompressLevel = true;
+    } else if (choices[encodingIndex].getSelectedItem().equals("Tight")) {
+      preferredEncoding = RfbProto.EncodingTight;
+      enableCompressLevel = true;
+      enableQualityLevel = !eightBitColors;
+    } else if (choices[encodingIndex].getSelectedItem().equals("Auto")) {
+      preferredEncoding = -1;
+      enableQualityLevel = !eightBitColors;
+    }
+
+    // Handle compression level setting.
+
+    try {
+      compressLevel =
+        Integer.parseInt(choices[compressLevelIndex].getSelectedItem());
+    }
+    catch (NumberFormatException e) {
+      compressLevel = -1;
+    }
+    if (compressLevel < 1 || compressLevel > 9) {
+      compressLevel = -1;
+    }
+    labels[compressLevelIndex].setEnabled(enableCompressLevel);
+    choices[compressLevelIndex].setEnabled(enableCompressLevel);
+
+    // Handle JPEG quality setting.
+
+    try {
+      jpegQuality =
+        Integer.parseInt(choices[jpegQualityIndex].getSelectedItem());
+    }
+    catch (NumberFormatException e) {
+      jpegQuality = -1;
+    }
+    if (jpegQuality < 0 || jpegQuality > 9) {
+      jpegQuality = -1;
+    }
+    labels[jpegQualityIndex].setEnabled(enableQualityLevel);
+    choices[jpegQualityIndex].setEnabled(enableQualityLevel);
+
+    // Request cursor shape updates if necessary.
+
+    requestCursorUpdates =
+      !choices[cursorUpdatesIndex].getSelectedItem().equals("Disable");
+
+    if (requestCursorUpdates) {
+      ignoreCursorUpdates =
+       choices[cursorUpdatesIndex].getSelectedItem().equals("Ignore");
+    }
+
+    viewer.setEncodings();
+  }
+
+  //
+  // setColorFormat sets eightBitColors variable depending on the GUI
+  // setting, causing switches between 8-bit and 24-bit colors mode if
+  // necessary.
+  //
+
+  void setColorFormat() {
+
+    eightBitColors =
+      choices[eightBitColorsIndex].getSelectedItem().equals("Yes");
+
+    boolean enableJPEG = !eightBitColors &&
+      (choices[encodingIndex].getSelectedItem().equals("Tight") ||
+       choices[encodingIndex].getSelectedItem().equals("Auto"));
+
+    labels[jpegQualityIndex].setEnabled(enableJPEG);
+    choices[jpegQualityIndex].setEnabled(enableJPEG);
+  }
+
+  //
+  // setContinuousUpdates sets continuousUpdates variable depending on
+  // the GUI setting. VncViewer monitors the state of this variable and
+  // send corresponding protocol messages to the server when necessary.
+  //
+
+  void setContinuousUpdates() {
+
+    continuousUpdates =
+      choices[contUpdatesIndex].getSelectedItem().equals("Yes");
+  }
+
+  //
+  // setOtherOptions looks at the "other" choices (ones that do not
+  // cause sending any protocol messages) and sets the boolean flags
+  // appropriately.
+  //
+
+  void setOtherOptions() {
+
+    reverseMouseButtons2And3
+      = choices[mouseButtonIndex].getSelectedItem().equals("Reversed");
+
+    viewOnly 
+      = choices[viewOnlyIndex].getSelectedItem().equals("Yes");
+    if (viewer.vc != null)
+      viewer.vc.enableInput(!viewOnly);
+
+    shareDesktop
+      = choices[shareDesktopIndex].getSelectedItem().equals("Yes");
+
+    String scaleString = choices[scaleCursorIndex].getSelectedItem();
+    if (scaleString.endsWith("%"))
+      scaleString = scaleString.substring(0, scaleString.length() - 1);
+    try {
+      scaleCursor = Integer.parseInt(scaleString);
+    }
+    catch (NumberFormatException e) {
+      scaleCursor = 0;
+    }
+    if (scaleCursor < 10 || scaleCursor > 500) {
+      scaleCursor = 0;
+    }
+    if (requestCursorUpdates && !ignoreCursorUpdates && !viewOnly) {
+      labels[scaleCursorIndex].setEnabled(true);
+      choices[scaleCursorIndex].setEnabled(true);
+    } else {
+      labels[scaleCursorIndex].setEnabled(false);
+      choices[scaleCursorIndex].setEnabled(false);
+    }
+    if (viewer.vc != null)
+      viewer.vc.createSoftCursor(); // update cursor scaling
+  }
+
+
+  //
+  // Respond to actions on Choice controls
+  //
+
+  public void itemStateChanged(ItemEvent evt) {
+    Object source = evt.getSource();
+
+    if (source == choices[encodingIndex] ||
+        source == choices[compressLevelIndex] ||
+        source == choices[jpegQualityIndex] ||
+        source == choices[cursorUpdatesIndex] ||
+        source == choices[useCopyRectIndex]) {
+
+      setEncodings();
+
+      if (source == choices[cursorUpdatesIndex]) {
+        setOtherOptions();      // update scaleCursor state
+      }
+
+    } else if (source == choices[eightBitColorsIndex]) {
+
+      setColorFormat();
+
+    } else if (source == choices[contUpdatesIndex]) {
+
+      setContinuousUpdates();
+
+    } else if (source == choices[mouseButtonIndex] ||
+              source == choices[shareDesktopIndex] ||
+              source == choices[viewOnlyIndex] ||
+              source == choices[scaleCursorIndex]) {
+
+      setOtherOptions();
+
+    } else if (source == choices[scalingFactorIndex]){
+        // Tell VNC canvas that scaling factor has changed
+        setScalingFactor(choices[scalingFactorIndex].getSelectedItem());
+        if (viewer.vc != null)
+          viewer.vc.setScalingFactor(scalingFactor);
+    }
+  }
+
+  //
+  // Respond to button press
+  //
+
+  public void actionPerformed(ActionEvent evt) {
+    if (evt.getSource() == closeButton)
+      setVisible(false);
+  }
+
+  //
+  // Respond to window events
+  //
+
+  public void windowClosing(WindowEvent evt) {
+    setVisible(false);
+  }
+
+  public void windowActivated(WindowEvent evt) {}
+  public void windowDeactivated(WindowEvent evt) {}
+  public void windowOpened(WindowEvent evt) {}
+  public void windowClosed(WindowEvent evt) {}
+  public void windowIconified(WindowEvent evt) {}
+  public void windowDeiconified(WindowEvent evt) {}
+}
diff --git a/java/src/com/tigervnc/vncviewer/README b/java/src/com/tigervnc/vncviewer/README
new file mode 100644 (file)
index 0000000..18fd7db
--- /dev/null
@@ -0,0 +1,522 @@
+
+  TigerVNC Java Viewer version 1.3.9
+
+======================================================================
+
+This distribution is based on the standard VNC source and includes new
+TightVNC-specific features and fixes, such as additional low-bandwidth
+optimizations, major GUI improvements, and more.
+
+       Copyright (C) 1999 AT&T Laboratories Cambridge.
+       Copyright (C) 2000 Tridia Corp.
+       Copyright (C) 2002-2003 RealVNC Ltd.
+       Copyright (C) 2001-2004 HorizonLive.com, Inc.
+       Copyright (C) 2000-2007 Constantin Kaplinsky
+       Copyright (C) 2000-2007 TightVNC Group
+       All rights reserved.
+
+This software is distributed under the GNU General Public Licence as
+published by the Free Software Foundation. See the file LICENCE.TXT for the
+conditions under which this software is made available. TigerVNC also
+contains code from other sources. See the Acknowledgements section below, and
+the individual files for details of the conditions under which they are made
+available.
+
+
+Compiling from the sources
+==========================
+
+To compile all the .java files to .class files, simply do:
+
+       % make all
+
+This will also generate a JAR (Java archive) file containing all the classes. 
+Most JVM (Java Virtual Machine) implementations are able to use either a set
+of .class files, or the JAR archive.
+
+
+Installation
+============
+
+There are three basic ways to use TigerVNC Java viewer:
+
+  1. Running applet as part of TigerVNC server installation.
+
+     Both the Unix and Windows versions of TigerVNC servers include small
+     built-in HTTP server which can serve Java viewer to Web clients. This
+     enables easy Web access to the shared desktop without need to install
+     any software on the client computer. Unix and Windows versions of
+     TigerVNC servers are different in the way they store the .class and .jar
+     files: the Unix server (Xvnc) is able to serve any set of files present
+     in a particular directory, while the Windows server (WinVNC) has all the
+     .class and .jar files inside the WinVNC executable file. Therefore, for
+     Xvnc, it's enough to copy the files into a correct directory, but for
+     WinVNC, the server binaries should be rebuild if the built-in Java
+     viewer should be updated.
+
+     To install the Java viewer under Xvnc, copy all the .class files, the
+     .jar file and the .vnc files to an installation directory (e.g.
+     /usr/local/vnc/classes):
+
+         cp *.class *.jar *.vnc /usr/local/vnc/classes
+
+     Also, make sure that the vncserver script is configured to point to the
+     installation directory (see the Xvnc manual page for the description of
+     the -httpd command-line option).
+
+  2. Running applet hosted on a standalone Web server.
+
+     Another possibility to use the Java viewer is to install it under a
+     fully-functional HTTP server such as Apache or IIS. Obviously, this
+     method requires running an HTTP server, and due to the Java security
+     restrictions, it's also required that the server should be installed on
+     the same machine which is running the TigerVNC server. In this case,
+     installation is simply copying the .class and .jar files into a
+     directory that is under control of the HTTP server. Also, an HTML page
+     should be created which will act as a the base document for the viewer
+     applet (see an example named index.html in this distribution).
+
+     NOTE: Provided index.html page is an example only. Before using that
+     file, edit it with a text editor. See more information inside
+     index.html.
+
+  3. Running the viewer as a standalone application.
+
+     Finally, the Java viewer can be executed locally on the client machine,
+     but this method requires installation of either JRE (Java Runtime
+     Environment) or JDK (Java Development Kit). If all the .class files are
+     in the current directory, the Java viewer can be executed like this,
+     from the command line:
+
+         java VncViewer HOST vnchost PORT 5900
+
+     The HOST parameter is required, PORT defaults to 5900 if omitted, and
+     there is a number of other optional parameters, see the Parameters
+     section below.
+
+
+Parameters
+==========
+
+TigerVNC Java viewer supports a number of parameters allowing you to
+customize its behavior. Most parameters directly correspond to the settings
+found in the Options window. However, there are parameters that do not
+correspond to those settings. For such parameters, you can see a note "no GUI
+equivalent", in the documentation below.
+
+Parameters can be specified in one of the two ways, depending on how the Java
+viewer is used:
+
+  1. When the Java viewer is run as an applet (embedded within an HTML
+     document), parameters should be specified in the <PARAM> HTML tags,
+     within the appropriate <APPLET> section. Here is an example:
+
+    <APPLET CODE=VncViewer.class ARCHIVE=VncViewer.jar WIDTH=400 HEIGHT=300>
+      <PARAM NAME="PORT" VALUE=5901>
+      <PARAM NAME="Scaling factor" VALUE=50>
+    </APPLET>
+
+  2. When run as a standalone application, the Java viewer reads parameters
+     from the command line. Command-line arguments should be specified in
+     pairs -- first goes parameter name, then parameter value. Here is a
+     command line example:
+
+     java VncViewer HOST vnchost PORT 5901 "Scaling factor" 50
+
+Both parameter names and their values are case-insensitive. The only
+exception is the "PASSWORD" parameter, as VNC passwords are case-sensitive.
+
+Here is the complete list of parameters supported in TigerVNC Java viewer:
+
+--> "HOST" (no GUI equivalent)
+
+    Value: host name or IP address of the VNC server.
+    Default: in applet mode, the host from which the applet was loaded.
+
+    This parameter tells the viewer which server to connect to. It's not
+    needed in the applet mode, because default Java security policy allow
+    connections from applets to the only one host anyway, and that is the
+    host from which the applet was loaded. However, this parameter is
+    required if the viewer is used as a standalone application.
+
+--> "PORT" (no GUI equivalent)
+
+    Value: TCP port number on the VNC server.
+    Default: 5900.
+
+    This parameter specifies TCP port number for outgoing VNC connection.
+    Note that this port is not the one used for HTTP connection from the
+    browser, it is the port used for VNC/RFB connection. Usually, VNC servers
+    use ports 58xx for HTTP connections, and ports 59xx for RFB connections.
+    Thus, most likely, this parameter should be set to something like 5900,
+    5901 etc.
+
+--> "PASSWORD"
+
+    Value: session password in plain text.
+    Default: none, ask user.
+
+    DO NOT EVER USE THIS PARAMETER, unless you really know what you are
+    doing. It's extremely dangerous from the security point of view. When
+    this parameter is set, the viewer won't ever ask for a password.
+
+--> "ENCPASSWORD"
+
+    Value: encrypted session password in hex-ascii.
+    Default: none, ask user.
+
+    The same as the "PASSWORD" parameter but DES-encrypted using a fixed key.
+    Its value should be represented in hex-ascii e.g. "494015f9a35e8b22".
+    This parameter has higher priority over the "PASSWORD" parameter. DO NOT
+    EVER USE THIS PARAMETER, unless you really know what you are doing. It's
+    extremely dangerous from the security point of view, and encryption does
+    not actually help here since the decryption key is always known.
+
+--> "Encoding"
+
+    Values: "Auto", "Raw", "RRE", "CoRRE", "Hextile", "ZRLE", "Zlib", "Tight".
+    Default: "Auto".
+
+    The preferred encoding. If the value is "Auto", then the viewer will
+    continuously estimate average network throughput and request encodings
+    that are appropriate for current connection speed. "Hextile" is an
+    encoding that was designed for fast networks, while "Tight" is better
+    suited for low-bandwidth connections. From the other side, "Tight"
+    decoder in the TigerVNC Java viewer seems to be more efficient than
+    "Hextile" decoder so it may be ok for fast networks too. "ZRLE" encoding
+    is similar to "Tight", but it does not support JPEG compression and
+    compression levels. Unlike "Tight" encoding, "ZRLE" is supported in
+    recent versions of RealVNC products. Other encodings are not efficient
+    and provided for compatibility reasons.
+
+--> "Compression level"
+
+    Values: "Default", "1", "2", "3", "4", "5", "6", "7", "8", "9".
+    Default: "Default". ;-)
+
+    Use specified compression level for "Tight" and "Zlib" encodings. Level 1
+    uses minimum of CPU time on the server but achieves weak compression
+    ratios. Level 9 offers best compression but may be slow in terms of CPU
+    time consumption on the server side. Use high levels with very slow
+    network connections, and low levels when working over higher-speed
+    networks. The "Default" value means that the server's default compression
+    level should be used.
+
+--> "JPEG image quality"
+
+    Values: "JPEG off", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9".
+    Default: "6".
+
+    Use the specified image quality level in "Tight" encoding. Quality level
+    0 denotes bad image quality but very impressive compression ratios, while
+    level 9 offers very good image quality at lower compression ratios. If
+    the value is "JPEG off", the server will not use lossy JPEG compression
+    in "Tight" encoding.
+
+--> "Cursor shape updates"
+
+    Values: "Enable", "Ignore", "Disable".
+    Default: "Enable".
+
+    Cursor shape updates is a protocol extension used to handle remote cursor
+    movements locally on the client side, saving bandwidth and eliminating
+    delays in mouse pointer movement. Note that current implementation of
+    cursor shape updates does not allow a client to track mouse cursor
+    position at the server side. This means that clients would not see mouse
+    cursor movements if mouse was moved either locally on the server, or by
+    another remote VNC client. Set this parameter to "Disable" if you always
+    want to see real cursor position on the remote side. Setting this option
+    to "Ignore" is similar to "Enable" but the remote cursor will not be
+    visible at all. This can be a reasonable setting if you don't care about
+    cursor shape and don't want to see two mouse cursors, one above another.
+
+--> "Use CopyRect"
+
+    Values: "Yes", "No".
+    Default: "Yes".
+
+    The "CopyRect" encoding saves bandwidth and drawing time when parts of
+    the remote screen are moving around. Most likely, you don't want to
+    change this setting.
+
+--> "Restricted colors"
+
+    Values: "Yes", "No".
+    Default: "No".
+
+    If set to "No", then 24-bit color format is used to represent pixel data. 
+    If set to "Yes", then only 8 bits are used to represent each pixel. 8-bit
+    color format can save bandwidth, but colors may look very inaccurate.
+
+--> "Mouse buttons 2 and 3"
+
+    Values: "Normal", "Reversed".
+    Default: "Normal".
+
+    If set to "Reversed", then right mouse button (button 2) will act as it
+    was middle mouse button (button 3), and vice versa.
+
+--> "View only"
+
+    Values: "Yes", "No".
+    Default: "No".
+
+    If set to "Yes", then all keyboard and mouse events in the desktop window
+    will be silently ignored and will not be passed to the remote side.
+
+--> "Scale remote cursor"
+
+    Values: "No", "50%", "75%", "125%", "150%".
+    Default: "No".
+
+    If a percentage value is specified, the remote cursor is reduced
+    or enlarged accordingly. Scaling takes place only when "View only"
+    is set to "No", and "Cursor shape updates" is set to "Enable".
+
+--> "Share desktop"
+
+    Values: "Yes", "No".
+    Default: "Yes".
+
+    Share the connection with other clients on the same VNC server. The exact
+    behaviour in each case depends on the server configuration.
+
+--> "Open new window" (no GUI equivalent, applicable only in the applet mode)
+
+    Values: "Yes", "No".
+    Default: "No".
+
+    Operate in a separate window. This makes possible resizing the desktop,
+    and adds scroll bars when necessary. If the server supports variable
+    desktop size, the window will resize automatically when remote desktop
+    size changes.
+
+--> "Scaling factor" (no GUI equivalent)
+
+    Value: an integer in the range of [1..1000], or the string "auto".
+    Default: "100".
+
+    Scale local representation of the remote desktop. The value is
+    interpreted as scaling factor in percents. The default value of 100%
+    corresponds to the original framebuffer size. Values below 100 reduce
+    image size, values above 100 enlarge the image proportionally. If the
+    parameter is set to "auto", automatic scaling is performed. Auto-scaling
+    tries to choose scaling factor such way that the whole remote framebuffer
+    will fit on the local screen. Currently, auto-scaling is supported only
+    when the remote desktop is shown in a separate frame (always true in the
+    application mode, and also in the applet mode with "Open new window"
+    parameter set to "yes").
+
+--> "Show controls" (no GUI equivalent)
+
+    Values: "Yes", "No".
+    Default: "Yes".
+
+    Set to "No" if you want to get rid of that button panel at the top.
+
+--> "Offer relogin" (no GUI equivalent, applicable only in the applet mode)
+
+    Values: "Yes", "No".
+    Default: "Yes".
+
+    If set to "No", the buttons "Login again" and "Close window" won't be
+    shown on disconnects or after an error has occured.
+
+--> "Show offline desktop" (no GUI equivalent)
+
+    Values: "Yes", "No".
+    Default: "No".
+
+    If set to "Yes", the viewer would continue to display desktop even
+    if the remote side has closed the connection. In this case, if the
+    button panel is enabled, then the "Disconnect" button would be
+    changed to "Hide desktop" after the connection is lost.
+
+--> "Defer screen updates" (no GUI equivalent)
+
+    Value: time in milliseconds.
+    Default: "20".
+
+    When updating the desktop contents after receiving an update from server,
+    schedule repaint within the specified number of milliseconds. Small delay
+    helps to coalesce several small updates into one drawing operation,
+    improving CPU usage. Set this parameter to 0 to disable deferred updates.
+
+--> "Defer cursor updates" (no GUI equivalent)
+
+    Value: time in milliseconds.
+    Default: "10".
+
+    When updating the desktop after moving the mouse, schedule repaint within
+    the specified number of milliseconds. This setting makes sense only when
+    "Cursor shape updates" parameter is set to "Enable". Small delay helps to
+    coalesce several small updates into one drawing operation, improving CPU
+    usage. Set this parameter to 0 to disable deferred cursor updates.
+
+--> "Defer update requests" (no GUI equivalent)
+
+    Value: time in milliseconds.
+    Default: "0".
+
+    After processing an update received from server, wait for the specified
+    number of milliseconds before requesting next screen update. Such delay
+    will end immediately on every mouse or keyboard event if not in the "view
+    only" mode. Small delay helps the server to coalesce several small
+    updates into one framebuffer update, improving both bandwidth and CPU
+    usage. Increasing the parameter value does not affect responsiveness on
+    mouse and keyboard events, but causes delays in updating the screen when
+    there is no mouse and keyboard activity on the client side.
+
+--> "SocketFactory" (no GUI equivalent)
+
+    Value: name of the class.
+    Default: none.
+
+    This option provides the way to define an alternate I/O implementation.
+    The dynamically referenced class must implement a SocketFactory
+    interface, and create a Socket, as configured by this parameter. See the
+    source in SocketFactory.java.
+
+--> "DEBUG_XU" (no GUI equivalent)
+
+    Value: non-negative integer.
+    Default: 0.
+
+    Debugging option that causes update statistics reset after the specified
+    number of first framebuffer updates. This option was added to measure the
+    performance of a VNC server. First few updates (especially the very first
+    one) may be notably slower than others, and the viewer can exclude such
+    updates from statistics.
+
+--> "DEBUG_CU" (no GUI equivalent)
+
+    Value: non-negative integer.
+    Default: 0.
+
+    Debugging option that causes the viewer disconnect after the specified
+    number of framebuffer updates. When used with the "DEBUG_XU" parameter,
+    the number of updates specified in "DEBUG_XU" is not counted as part of
+    this parameter's value. E.g. if "DEBUG_XU"=2 and "DEBUG_CU"=10, then the
+    viewer will disconnect after 12 framebuffer updates: update statistics
+    will be reset after first two updates, then collected for next 10
+    updates, then the viewer will disconnect automatically. If the value is
+    0, the viewer will not disconnect automatically. This option was added to
+    measure the performance of a VNC server.
+
+
+RECORDING VNC SESSIONS
+======================
+
+Current version of the TigerVNC Java viewer is able to record VNC (RFB)
+sessions in files for later playback. The data format in saved session files
+is compatible with the rfbproxy program written by Tim Waugh. Most important
+thing about session recording is that it's supported only if Java security
+manager allows access to local filesystem. Typically, it would not work for
+unsigned applets. To use this feature, either use TigerVNC Java viewer as a
+standalone application (Java Runtime Environment or Java Development Kit
+should be installed), or as a signed applet. The code checks if it's possible
+to support session recording, and if everything's fine, the new "Record"
+button should appear in the button panel. Pressing this button opens new
+window which controls session recording. The GUI is pretty self-explained.
+
+Other important facts about session recording:
+
+--> All sessions are recorded in the 24-bit color format. If you use
+    restricted colors (8-bit format), it will be temporarly switched to
+    24-bit mode during session recording.
+
+--> All sessions are recorded with cursor shape updates turned off. This is
+    necessary to represent remote cursor movements in recorded sessions.
+
+--> Closing and re-opening the recording control window does not affect the
+    recording. It's not necessary to keep that window open during recording a
+    session.
+
+--> Avoid using Zlib and ZRLE encodings when recording sessions. If you have
+    started recording BEFORE opening a VNC session, then you are ok. But
+    otherwise, all Zlib-encoded updates will be saved Raw-encoded (that is,
+    without compression at all). The case with ZRLE is even worse -- ZRLE
+    updates will not be saved at all, so the resulting session file may be
+    corrupted. Zlib decoding depends on the pixel data received earlier, thus
+    saving the data received from the server at an arbitrary moment is not
+    sufficient to decompress it correctly. And there is no way to tell Zlib
+    or ZRLE decoder to reset decompressor's state -- that's a limitation of
+    these encoders. The viewer could re-compress raw pixel data again before
+    saving Zlib-encoded sessions, but unfortunately Java API does not allow
+    to flush zlib data streams making it impossible to save Zlib-encoded RFB
+    pixel data without using native code.
+
+--> Usually, Tight encoding is the most suitable one for session recording,
+    but some of the issues described above for the Zlib encoding affect the
+    Tight encoding as well. Unlike Zlib sessions, Tight-encoded sessions are
+    always saved Tight-encoded, but the viewer has to re-compress parts of
+    data to synchronize encoder's and decoder's zlib streams. And, due to
+    Java zlib API limitations, zlib streams' states have to be reset on each
+    compressed rectangle, causing compression ratios to be lower than in the
+    original VNC session. If you want to achieve the best possible
+    performance, turn recording on BEFORE connecting to the VNC server,
+    otherwise CPU usage and compression ratios may be notably less efficient.
+
+
+HINTS
+=====
+
+--> To refresh remote desktop in the view-only mode, press "r" or "R"
+    on the keyboard.
+
+
+ACKNOWLEDGEMENTS
+================
+
+This distribution contains Java DES software by Dave Zimmerman
+<dzimm@widget.com> and Jef Poskanzer <jef@acme.com>.  This is:
+
+    Copyright (c) 1996 Widget Workshop, Inc. All Rights Reserved.
+
+    Permission to use, copy, modify, and distribute this software and its
+    documentation for NON-COMMERCIAL or COMMERCIAL purposes and without fee
+    is hereby granted, provided that this copyright notice is kept intact.
+    
+    WIDGET WORKSHOP MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE
+    SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT
+    NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+    PARTICULAR PURPOSE, OR NON-INFRINGEMENT. WIDGET WORKSHOP SHALL NOT BE
+    LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING,
+    MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
+    
+    THIS SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE OR RESALE AS ON-LINE
+    CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE
+    PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT
+    NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT LIFE
+    SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE
+    SOFTWARE COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE
+    PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH RISK ACTIVITIES").  WIDGET
+    WORKSHOP SPECIFICALLY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF
+    FITNESS FOR HIGH RISK ACTIVITIES.
+
+    Copyright (C) 1996 by Jef Poskanzer <jef@acme.com>.  All rights
+    reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions
+    are met:
+    1. Redistributions of source code must retain the above copyright
+       notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+       notice, this list of conditions and the following disclaimer in the
+       documentation and/or other materials provided with the distribution.
+
+    THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+    PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
+    BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+    BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+    WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+    OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+    ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+    Visit the ACME Labs Java page for up-to-date versions of this and other
+    fine Java utilities: http://www.acme.com/java/
diff --git a/java/src/com/tigervnc/vncviewer/RecordOutputStream.java b/java/src/com/tigervnc/vncviewer/RecordOutputStream.java
new file mode 100644 (file)
index 0000000..3978dfc
--- /dev/null
@@ -0,0 +1,60 @@
+package com.tightvnc.vncviewer;
+
+import java.io.DataOutput;
+import java.io.IOException;
+
+public class RecordOutputStream implements DataOutput {
+
+  public RecordOutputStream(RfbProto rfbproto) {
+    rfb = rfbproto;
+  }
+
+  private boolean canWrite() {
+    return ((rfb != null) && (rfb.rec != null));
+  }
+
+  public void write(byte[] b) throws IOException {
+    if (canWrite())
+      rfb.rec.write(b);
+  }
+
+  public void write(byte[] b, int off, int len) throws IOException {
+    if (canWrite())
+      rfb.rec.write(b, off, len);
+  }
+
+  public void write(int b) throws IOException {
+    if (canWrite())
+      rfb.rec.writeIntBE(b);
+  }
+
+  public void writeBoolean(boolean v) { }
+
+  public void writeByte(int v) throws IOException {
+    if (canWrite()) {
+      rfb.rec.writeByte(v);
+    }
+  }
+
+  public void writeBytes(String s) { }
+  public void writeChar(int v) { }
+  public void writeChars(String s) { }
+  public void writeDouble(double v) { }
+  public void writeFloat(float v) { }
+
+  public void writeInt(int v) throws IOException {
+    if (canWrite())
+      rfb.rec.writeIntBE(v);
+  }
+
+  public void writeLong(long v) { }
+
+  public void writeShort(int v) throws IOException {
+    if (canWrite())
+      rfb.rec.writeShortBE(v);
+  }
+
+  public void writeUTF(String str) { }
+
+  private RfbProto rfb = null;
+}
diff --git a/java/src/com/tigervnc/vncviewer/RecordingFrame.java b/java/src/com/tigervnc/vncviewer/RecordingFrame.java
new file mode 100644 (file)
index 0000000..f2e1fae
--- /dev/null
@@ -0,0 +1,313 @@
+//
+//  Copyright (C) 2002 Constantin Kaplinsky.  All Rights Reserved.
+//
+//  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.
+//
+
+//
+// Recording frame. It allows to control recording RFB sessions into
+// FBS (FrameBuffer Stream) files.
+//
+
+package com.tightvnc.vncviewer;
+
+import java.io.*;
+import java.awt.*;
+import java.awt.event.*;
+
+class RecordingFrame extends Frame
+  implements WindowListener, ActionListener {
+
+  boolean recording;
+
+  TextField fnameField;
+  Button browseButton;
+
+  Label statusLabel;
+
+  Button recordButton, nextButton, closeButton;
+  VncViewer viewer;
+
+  //
+  // Check if current security manager allows to create a
+  // RecordingFrame object.
+  //
+
+  public static boolean checkSecurity() {
+    SecurityManager security = System.getSecurityManager();
+    if (security != null) {
+      try {
+       security.checkPropertyAccess("user.dir");
+       security.checkPropertyAccess("file.separator");
+       // Work around (rare) checkPropertyAccess bug
+       System.getProperty("user.dir");
+      } catch (SecurityException e) {
+       System.out.println("SecurityManager restricts session recording.");
+       return false;
+      }
+    }
+    return true;
+  }
+
+  //
+  // Constructor.
+  //
+
+  RecordingFrame(VncViewer v) {
+    super("TigerVNC Session Recording");
+
+    viewer = v;
+
+    // Determine initial filename for next saved session.
+    // FIXME: Check SecurityManager.
+
+    String fname = nextNewFilename(System.getProperty("user.dir") +
+                                  System.getProperty("file.separator") +
+                                  "vncsession.fbs");
+
+    // Construct new panel with file name field and "Browse" button.
+
+    Panel fnamePanel = new Panel();
+    GridBagLayout fnameGridbag = new GridBagLayout();
+    fnamePanel.setLayout(fnameGridbag);
+
+    GridBagConstraints fnameConstraints = new GridBagConstraints();
+    fnameConstraints.gridwidth = GridBagConstraints.RELATIVE;
+    fnameConstraints.fill = GridBagConstraints.BOTH;
+    fnameConstraints.weightx = 4.0;
+
+    fnameField = new TextField(fname, 64);
+    fnameGridbag.setConstraints(fnameField, fnameConstraints);
+    fnamePanel.add(fnameField);
+    fnameField.addActionListener(this);
+
+    fnameConstraints.gridwidth = GridBagConstraints.REMAINDER;
+    fnameConstraints.weightx = 1.0;
+
+    browseButton = new Button("Browse");
+    fnameGridbag.setConstraints(browseButton, fnameConstraints);
+    fnamePanel.add(browseButton);
+    browseButton.addActionListener(this);
+
+    // Construct the frame.
+
+    GridBagLayout gridbag = new GridBagLayout();
+    setLayout(gridbag);
+
+    GridBagConstraints gbc = new GridBagConstraints();
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    gbc.fill = GridBagConstraints.BOTH;
+    gbc.weighty = 1.0;
+    gbc.insets = new Insets(10, 0, 0, 0);
+
+    Label helpLabel =
+      new Label("File name to save next recorded session in:", Label.CENTER);
+    gridbag.setConstraints(helpLabel, gbc);
+    add(helpLabel);
+
+    gbc.fill = GridBagConstraints.HORIZONTAL;
+    gbc.weighty = 0.0;
+    gbc.insets = new Insets(0, 0, 0, 0);
+
+    gridbag.setConstraints(fnamePanel, gbc);
+    add(fnamePanel);
+
+    gbc.fill = GridBagConstraints.BOTH;
+    gbc.weighty = 1.0;
+    gbc.insets = new Insets(10, 0, 10, 0);
+
+    statusLabel = new Label("", Label.CENTER);
+    gridbag.setConstraints(statusLabel, gbc);
+    add(statusLabel);
+
+    gbc.fill = GridBagConstraints.HORIZONTAL;
+    gbc.weightx = 1.0;
+    gbc.weighty = 0.0;
+    gbc.gridwidth = 1;
+    gbc.insets = new Insets(0, 0, 0, 0);
+
+    recordButton = new Button("Record");
+    gridbag.setConstraints(recordButton, gbc);
+    add(recordButton);
+    recordButton.addActionListener(this);
+
+    nextButton = new Button("Next file");
+    gridbag.setConstraints(nextButton, gbc);
+    add(nextButton);
+    nextButton.addActionListener(this);
+
+    closeButton = new Button("Close");
+    gridbag.setConstraints(closeButton, gbc);
+    add(closeButton);
+    closeButton.addActionListener(this);
+
+    // Set correct text, font and color for the statusLabel.
+    stopRecording();
+
+    pack();
+
+    addWindowListener(this);
+  }
+
+  //
+  // If the given string ends with ".NNN" where NNN is a decimal
+  // number, increase this number by one. Otherwise, append ".001"
+  // to the given string.
+  //
+
+  protected String nextFilename(String fname) {
+    int len = fname.length();
+    int suffixPos = len;
+    int suffixNum = 1;
+
+    if (len > 4 && fname.charAt(len - 4) == '.') {
+      try {
+       suffixNum = Integer.parseInt(fname.substring(len - 3, len)) + 1;
+       suffixPos = len - 4;
+      } catch (NumberFormatException e) { }
+    }
+
+    char[] zeroes = {'0', '0', '0'};
+    String suffix = String.valueOf(suffixNum);
+    if (suffix.length() < 3) {
+      suffix = new String(zeroes, 0, 3 - suffix.length()) + suffix;
+    }
+
+    return fname.substring(0, suffixPos) + '.' + suffix;
+  }
+
+  //
+  // Find next name of a file which does not exist yet.
+  //
+
+  protected String nextNewFilename(String fname) {
+    String newName = fname;
+    File f;
+    try {
+      do {
+       newName = nextFilename(newName);
+       f = new File(newName);
+      } while (f.exists());
+    } catch (SecurityException e) { }
+
+    return newName;
+  }
+
+  //
+  // Let the user choose a file name showing a FileDialog.
+  //
+
+  protected boolean browseFile() {
+    File currentFile = new File(fnameField.getText());
+
+    FileDialog fd =
+      new FileDialog(this, "Save next session as...", FileDialog.SAVE);
+    fd.setDirectory(currentFile.getParent());
+    fd.setVisible(true);
+    if (fd.getFile() != null) {
+      String newDir = fd.getDirectory();
+      String sep = System.getProperty("file.separator");
+      if (newDir.length() > 0) {
+       if (!sep.equals(newDir.substring(newDir.length() - sep.length())))
+         newDir += sep;
+      }
+      String newFname = newDir + fd.getFile();
+      if (newFname.equals(fnameField.getText())) {
+       fnameField.setText(newFname);
+       return true;
+      }
+    }
+    return false;
+  }
+
+  //
+  // Start recording.
+  //
+
+  public void startRecording() {
+    statusLabel.setText("Status: Recording...");
+    statusLabel.setFont(new Font("Helvetica", Font.BOLD, 12));
+    statusLabel.setForeground(Color.red);
+    recordButton.setLabel("Stop recording");
+
+    recording = true;
+
+    viewer.setRecordingStatus(fnameField.getText());
+  }
+
+  //
+  // Stop recording.
+  //
+
+  public void stopRecording() {
+    statusLabel.setText("Status: Not recording.");
+    statusLabel.setFont(new Font("Helvetica", Font.PLAIN, 12));
+    statusLabel.setForeground(Color.black);
+    recordButton.setLabel("Record");
+
+    recording = false;
+
+    viewer.setRecordingStatus(null);
+  }
+
+  //
+  // Close our window properly.
+  //
+
+  public void windowClosing(WindowEvent evt) {
+    setVisible(false);
+  }
+
+  //
+  // Ignore window events we're not interested in.
+  //
+
+  public void windowActivated(WindowEvent evt) {}
+  public void windowDeactivated (WindowEvent evt) {}
+  public void windowOpened(WindowEvent evt) {}
+  public void windowClosed(WindowEvent evt) {}
+  public void windowIconified(WindowEvent evt) {}
+  public void windowDeiconified(WindowEvent evt) {}
+
+
+  //
+  // Respond to button presses
+  //
+
+  public void actionPerformed(ActionEvent evt) {
+    if (evt.getSource() == browseButton) {
+      if (browseFile() && recording)
+       startRecording();
+
+    } else if (evt.getSource() == recordButton) {
+      if (!recording) {
+       startRecording();
+      } else {
+       stopRecording();
+        fnameField.setText(nextNewFilename(fnameField.getText()));
+      }
+
+    } else if (evt.getSource() == nextButton) {
+      fnameField.setText(nextNewFilename(fnameField.getText()));
+      if (recording)
+       startRecording();
+
+    } else if (evt.getSource() == closeButton) {
+      setVisible(false);
+
+    }
+  }
+}
diff --git a/java/src/com/tigervnc/vncviewer/ReloginPanel.java b/java/src/com/tigervnc/vncviewer/ReloginPanel.java
new file mode 100644 (file)
index 0000000..4be454d
--- /dev/null
@@ -0,0 +1,66 @@
+//
+//  Copyright (C) 2002 Cendio Systems.  All Rights Reserved.
+//  Copyright (C) 2002 Constantin Kaplinsky.  All Rights Reserved.
+//
+//  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.
+//
+
+//
+// ReloginPanel class implements panel with a button for logging in again,
+// after fatal errors or disconnect
+//
+
+package com.tightvnc.vncviewer;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.applet.*;
+
+//
+// The panel which implements the Relogin button
+//
+
+class ReloginPanel extends Panel implements ActionListener {
+  Button reloginButton;
+  Button closeButton;
+  VncViewer viewer;
+
+  //
+  // Constructor.
+  //
+  public ReloginPanel(VncViewer v) {
+    viewer = v;
+    setLayout(new FlowLayout(FlowLayout.CENTER));
+    reloginButton = new Button("Login again");
+    add(reloginButton);
+    reloginButton.addActionListener(this);
+    if (viewer.inSeparateFrame) {
+      closeButton = new Button("Close window");
+      add(closeButton);
+      closeButton.addActionListener(this);
+    }
+  }
+
+  //
+  // This method is called when a button is pressed.
+  //
+  public synchronized void actionPerformed(ActionEvent evt) {
+    if (viewer.inSeparateFrame)
+      viewer.vncFrame.dispose();
+    if (evt.getSource() == reloginButton)
+      viewer.getAppletContext().showDocument(viewer.getDocumentBase());
+  }
+}
diff --git a/java/src/com/tigervnc/vncviewer/RfbInputStream.java b/java/src/com/tigervnc/vncviewer/RfbInputStream.java
new file mode 100644 (file)
index 0000000..c14b188
--- /dev/null
@@ -0,0 +1,45 @@
+package com.tightvnc.vncviewer;
+
+import java.io.IOException;
+
+//
+// This class is layer between data of private RfbProto class
+// and classes in other packages.
+//
+// For now this class is used by com.tightvnc.decoder.RawDecoder
+//
+public class RfbInputStream {
+  RfbInputStream(RfbProto rfbProto) {
+    rfb = rfbProto;
+  }
+
+  //
+  // Read data methods
+  //
+
+  public void readFully(byte b[]) throws IOException {
+    readFully(b, 0, b.length);
+  }
+
+  public void readFully(byte b[], int off, int len) throws IOException {
+    rfb.readFully(b, off, len);
+  }
+
+  public int readU32() throws IOException  {
+    return rfb.readU32();
+  }
+
+  public int readU8() throws IOException  {
+    return rfb.readU8();
+  }
+
+  public int readCompactLen() throws IOException {
+    return rfb.readCompactLen();
+  }
+
+  public int readU16() throws IOException {
+    return rfb.readU16();
+  }
+
+  private RfbProto rfb = null;
+}
diff --git a/java/src/com/tigervnc/vncviewer/RfbProto.java b/java/src/com/tigervnc/vncviewer/RfbProto.java
new file mode 100644 (file)
index 0000000..d1a9450
--- /dev/null
@@ -0,0 +1,1497 @@
+//
+//  Copyright (C) 2001-2004 HorizonLive.com, Inc.  All Rights Reserved.
+//  Copyright (C) 2001-2006 Constantin Kaplinsky.  All Rights Reserved.
+//  Copyright (C) 2000 Tridia Corporation.  All Rights Reserved.
+//  Copyright (C) 1999 AT&T Laboratories Cambridge.  All Rights Reserved.
+//
+//  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.
+//
+
+//
+// RfbProto.java
+//
+
+package com.tightvnc.vncviewer;
+
+import java.io.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.net.Socket;
+import java.util.zip.*;
+
+class RfbProto {
+
+  final static String
+    versionMsg_3_3 = "RFB 003.003\n",
+    versionMsg_3_7 = "RFB 003.007\n",
+    versionMsg_3_8 = "RFB 003.008\n";
+
+  // Vendor signatures: standard VNC/RealVNC, TridiaVNC, and TightVNC
+  final static String
+    StandardVendor  = "STDV",
+    TridiaVncVendor = "TRDV",
+    TightVncVendor  = "TGHT";
+
+  // Security types
+  final static int
+    SecTypeInvalid = 0,
+    SecTypeNone    = 1,
+    SecTypeVncAuth = 2,
+    SecTypeTight   = 16;
+
+  // Supported tunneling types
+  final static int
+    NoTunneling = 0;
+  final static String
+    SigNoTunneling = "NOTUNNEL";
+
+  // Supported authentication types
+  final static int
+    AuthNone      = 1,
+    AuthVNC       = 2,
+    AuthUnixLogin = 129;
+  final static String
+    SigAuthNone      = "NOAUTH__",
+    SigAuthVNC       = "VNCAUTH_",
+    SigAuthUnixLogin = "ULGNAUTH";
+
+  // VNC authentication results
+  final static int
+    VncAuthOK      = 0,
+    VncAuthFailed  = 1,
+    VncAuthTooMany = 2;
+
+  // Standard server-to-client messages
+  final static int
+    FramebufferUpdate   = 0,
+    SetColourMapEntries = 1,
+    Bell                = 2,
+    ServerCutText       = 3;
+
+  // Non-standard server-to-client messages
+  final static int
+    EndOfContinuousUpdates = 150;
+  final static String
+    SigEndOfContinuousUpdates = "CUS_EOCU";
+
+  // Standard client-to-server messages
+  final static int
+    SetPixelFormat           = 0,
+    FixColourMapEntries      = 1,
+    SetEncodings             = 2,
+    FramebufferUpdateRequest = 3,
+    KeyboardEvent            = 4,
+    PointerEvent             = 5,
+    ClientCutText            = 6;
+
+  // Non-standard client-to-server messages
+  final static int EnableContinuousUpdates = 150;
+  final static int VideoRectangleSelection = 151;
+  final static int VideoFreeze = 152;
+  final static String SigVideoFreeze = "VD_FREEZ";
+  final static String SigEnableContinuousUpdates = "CUC_ENCU";
+  final static String SigVideoRectangleSelection = "VRECTSEL";
+
+  // Supported encodings and pseudo-encodings
+  final static int
+    EncodingRaw            = 0,
+    EncodingCopyRect       = 1,
+    EncodingRRE            = 2,
+    EncodingCoRRE          = 4,
+    EncodingHextile        = 5,
+    EncodingZlib           = 6,
+    EncodingTight          = 7,
+    EncodingZRLE           = 16,
+    EncodingCompressLevel0 = 0xFFFFFF00,
+    EncodingQualityLevel0  = 0xFFFFFFE0,
+    EncodingXCursor        = 0xFFFFFF10,
+    EncodingRichCursor     = 0xFFFFFF11,
+    EncodingPointerPos     = 0xFFFFFF18,
+    EncodingLastRect       = 0xFFFFFF20,
+    EncodingNewFBSize      = 0xFFFFFF21;
+  final static String
+    SigEncodingRaw            = "RAW_____",
+    SigEncodingCopyRect       = "COPYRECT",
+    SigEncodingRRE            = "RRE_____",
+    SigEncodingCoRRE          = "CORRE___",
+    SigEncodingHextile        = "HEXTILE_",
+    SigEncodingZlib           = "ZLIB____",
+    SigEncodingTight          = "TIGHT___",
+    SigEncodingZRLE           = "ZRLE____",
+    SigEncodingCompressLevel0 = "COMPRLVL",
+    SigEncodingQualityLevel0  = "JPEGQLVL",
+    SigEncodingXCursor        = "X11CURSR",
+    SigEncodingRichCursor     = "RCHCURSR",
+    SigEncodingPointerPos     = "POINTPOS",
+    SigEncodingLastRect       = "LASTRECT",
+    SigEncodingNewFBSize      = "NEWFBSIZ";
+
+  final static int MaxNormalEncoding = 255;
+
+  // Contstants used in the Hextile decoder
+  final static int
+    HextileRaw                 = 1,
+    HextileBackgroundSpecified = 2,
+    HextileForegroundSpecified = 4,
+    HextileAnySubrects         = 8,
+    HextileSubrectsColoured    = 16;
+
+  // Contstants used in the Tight decoder
+  final static int TightMinToCompress = 12;
+  final static int
+    TightExplicitFilter = 0x04,
+    TightFill           = 0x08,
+    TightJpeg           = 0x09,
+    TightMaxSubencoding = 0x09,
+    TightFilterCopy     = 0x00,
+    TightFilterPalette  = 0x01,
+    TightFilterGradient = 0x02;
+
+
+  String host;
+  int port;
+  Socket sock;
+  OutputStream os;
+  SessionRecorder rec;
+  boolean inNormalProtocol = false;
+  VncViewer viewer;
+
+  // Input stream is declared private to make sure it can be accessed
+  // only via RfbProto methods. We have to do this because we want to
+  // count how many bytes were read.
+  private DataInputStream is;
+  private long numBytesRead = 0;
+  public long getNumBytesRead() { return numBytesRead; }
+
+  // Java on UNIX does not call keyPressed() on some keys, for example
+  // swedish keys To prevent our workaround to produce duplicate
+  // keypresses on JVMs that actually works, keep track of if
+  // keyPressed() for a "broken" key was called or not.
+  boolean brokenKeyPressed = false;
+
+  // This will be set to true on the first framebuffer update
+  // containing Zlib-, ZRLE- or Tight-encoded data.
+  boolean wereZlibUpdates = false;
+
+  // This fields are needed to show warnings about inefficiently saved
+  // sessions only once per each saved session file.
+  boolean zlibWarningShown;
+  boolean tightWarningShown;
+
+  // Before starting to record each saved session, we set this field
+  // to 0, and increment on each framebuffer update. We don't flush
+  // the SessionRecorder data into the file before the second update.
+  // This allows us to write initial framebuffer update with zero
+  // timestamp, to let the player show initial desktop before
+  // playback.
+  int numUpdatesInSession;
+
+  // Measuring network throughput.
+  boolean timing;
+  long timeWaitedIn100us;
+  long timedKbits;
+
+  // Protocol version and TightVNC-specific protocol options.
+  int serverMajor, serverMinor;
+  int clientMajor, clientMinor;
+  boolean protocolTightVNC;
+  CapsContainer tunnelCaps, authCaps;
+  CapsContainer serverMsgCaps, clientMsgCaps;
+  CapsContainer encodingCaps;
+
+  // "Continuous updates" is a TightVNC-specific feature that allows
+  // receiving framebuffer updates continuously, without sending update
+  // requests. The variables below track the state of this feature.
+  // Initially, continuous updates are disabled. They can be enabled
+  // by calling tryEnableContinuousUpdates() method, and only if this
+  // feature is supported by the server. To disable continuous updates,
+  // tryDisableContinuousUpdates() should be called.
+  private boolean continuousUpdatesActive = false;
+  private boolean continuousUpdatesEnding = false;
+
+  // If true, informs that the RFB socket was closed.
+  private boolean closed;
+
+  //
+  // Constructor. Make TCP connection to RFB server.
+  //
+
+  RfbProto(String h, int p, VncViewer v) throws IOException {
+    viewer = v;
+    host = h;
+    port = p;
+
+    if (viewer.socketFactory == null) {
+      sock = new Socket(host, port);
+      sock.setTcpNoDelay(true);
+    } else {
+      try {
+       Class factoryClass = Class.forName(viewer.socketFactory);
+       SocketFactory factory = (SocketFactory)factoryClass.newInstance();
+       if (viewer.inAnApplet)
+         sock = factory.createSocket(host, port, viewer);
+       else
+         sock = factory.createSocket(host, port, viewer.mainArgs);
+      } catch(Exception e) {
+       e.printStackTrace();
+       throw new IOException(e.getMessage());
+      }
+    }
+    is = new DataInputStream(new BufferedInputStream(sock.getInputStream(),
+                                                    16384));
+    os = sock.getOutputStream();
+
+    timing = false;
+    timeWaitedIn100us = 5;
+    timedKbits = 0;
+  }
+
+
+  synchronized void close() {
+    try {
+      sock.close();
+      closed = true;
+      System.out.println("RFB socket closed");
+      if (rec != null) {
+       rec.close();
+       rec = null;
+      }
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+  }
+
+  synchronized boolean closed() {
+    return closed;
+  }
+
+  //
+  // Read server's protocol version message
+  //
+
+  void readVersionMsg() throws Exception {
+
+    byte[] b = new byte[12];
+
+    readFully(b);
+
+    if ((b[0] != 'R') || (b[1] != 'F') || (b[2] != 'B') || (b[3] != ' ')
+       || (b[4] < '0') || (b[4] > '9') || (b[5] < '0') || (b[5] > '9')
+       || (b[6] < '0') || (b[6] > '9') || (b[7] != '.')
+       || (b[8] < '0') || (b[8] > '9') || (b[9] < '0') || (b[9] > '9')
+       || (b[10] < '0') || (b[10] > '9') || (b[11] != '\n'))
+    {
+      throw new Exception("Host " + host + " port " + port +
+                         " is not an RFB server");
+    }
+
+    serverMajor = (b[4] - '0') * 100 + (b[5] - '0') * 10 + (b[6] - '0');
+    serverMinor = (b[8] - '0') * 100 + (b[9] - '0') * 10 + (b[10] - '0');
+
+    if (serverMajor < 3) {
+      throw new Exception("RFB server does not support protocol version 3");
+    }
+  }
+
+
+  //
+  // Write our protocol version message
+  //
+
+  void writeVersionMsg() throws IOException {
+    clientMajor = 3;
+    if (serverMajor > 3 || serverMinor >= 8) {
+      clientMinor = 8;
+      os.write(versionMsg_3_8.getBytes());
+    } else if (serverMinor >= 7) {
+      clientMinor = 7;
+      os.write(versionMsg_3_7.getBytes());
+    } else {
+      clientMinor = 3;
+      os.write(versionMsg_3_3.getBytes());
+    }
+    protocolTightVNC = false;
+    initCapabilities();
+  }
+
+
+  //
+  // Negotiate the authentication scheme.
+  //
+
+  int negotiateSecurity() throws Exception {
+    return (clientMinor >= 7) ?
+      selectSecurityType() : readSecurityType();
+  }
+
+  //
+  // Read security type from the server (protocol version 3.3).
+  //
+
+  int readSecurityType() throws Exception {
+    int secType = readU32();
+
+    switch (secType) {
+    case SecTypeInvalid:
+      readConnFailedReason();
+      return SecTypeInvalid;   // should never be executed
+    case SecTypeNone:
+    case SecTypeVncAuth:
+      return secType;
+    default:
+      throw new Exception("Unknown security type from RFB server: " + secType);
+    }
+  }
+
+  //
+  // Select security type from the server's list (protocol versions 3.7/3.8).
+  //
+
+  int selectSecurityType() throws Exception {
+    int secType = SecTypeInvalid;
+
+    // Read the list of secutiry types.
+    int nSecTypes = readU8();
+    if (nSecTypes == 0) {
+      readConnFailedReason();
+      return SecTypeInvalid;   // should never be executed
+    }
+    byte[] secTypes = new byte[nSecTypes];
+    readFully(secTypes);
+
+    // Find out if the server supports TightVNC protocol extensions
+    for (int i = 0; i < nSecTypes; i++) {
+      if (secTypes[i] == SecTypeTight) {
+       protocolTightVNC = true;
+       os.write(SecTypeTight);
+       return SecTypeTight;
+      }
+    }
+
+    // Find first supported security type.
+    for (int i = 0; i < nSecTypes; i++) {
+      if (secTypes[i] == SecTypeNone || secTypes[i] == SecTypeVncAuth) {
+       secType = secTypes[i];
+       break;
+      }
+    }
+
+    if (secType == SecTypeInvalid) {
+      throw new Exception("Server did not offer supported security type");
+    } else {
+      os.write(secType);
+    }
+
+    return secType;
+  }
+
+  //
+  // Perform "no authentication".
+  //
+
+  void authenticateNone() throws Exception {
+    if (clientMinor >= 8)
+      readSecurityResult("No authentication");
+  }
+
+  //
+  // Perform standard VNC Authentication.
+  //
+
+  void authenticateVNC(String pw) throws Exception {
+    byte[] challenge = new byte[16];
+    readFully(challenge);
+
+    if (pw.length() > 8)
+      pw = pw.substring(0, 8); // Truncate to 8 chars
+
+    // Truncate password on the first zero byte.
+    int firstZero = pw.indexOf(0);
+    if (firstZero != -1)
+      pw = pw.substring(0, firstZero);
+
+    byte[] key = {0, 0, 0, 0, 0, 0, 0, 0};
+    System.arraycopy(pw.getBytes(), 0, key, 0, pw.length());
+
+    DesCipher des = new DesCipher(key);
+
+    des.encrypt(challenge, 0, challenge, 0);
+    des.encrypt(challenge, 8, challenge, 8);
+
+    os.write(challenge);
+
+    readSecurityResult("VNC authentication");
+  }
+
+  //
+  // Read security result.
+  // Throws an exception on authentication failure.
+  //
+
+  void readSecurityResult(String authType) throws Exception {
+    int securityResult = readU32();
+
+    switch (securityResult) {
+    case VncAuthOK:
+      System.out.println(authType + ": success");
+      break;
+    case VncAuthFailed:
+      if (clientMinor >= 8)
+        readConnFailedReason();
+      throw new Exception(authType + ": failed");
+    case VncAuthTooMany:
+      throw new Exception(authType + ": failed, too many tries");
+    default:
+      throw new Exception(authType + ": unknown result " + securityResult);
+    }
+  }
+
+  //
+  // Read the string describing the reason for a connection failure,
+  // and throw an exception.
+  //
+
+  void readConnFailedReason() throws Exception {
+    int reasonLen = readU32();
+    byte[] reason = new byte[reasonLen];
+    readFully(reason);
+    throw new Exception(new String(reason));
+  }
+
+  //
+  // Initialize capability lists (TightVNC protocol extensions).
+  //
+
+  void initCapabilities() {
+    tunnelCaps    = new CapsContainer();
+    authCaps      = new CapsContainer();
+    serverMsgCaps = new CapsContainer();
+    clientMsgCaps = new CapsContainer();
+    encodingCaps  = new CapsContainer();
+
+    // Supported authentication methods
+    authCaps.add(AuthNone, StandardVendor, SigAuthNone,
+                "No authentication");
+    authCaps.add(AuthVNC, StandardVendor, SigAuthVNC,
+                "Standard VNC password authentication");
+
+    // Supported non-standard server-to-client messages
+    serverMsgCaps.add(EndOfContinuousUpdates, TightVncVendor,
+                      SigEndOfContinuousUpdates,
+                      "End of continuous updates notification");
+
+    // Supported non-standard client-to-server messages
+    clientMsgCaps.add(EnableContinuousUpdates, TightVncVendor,
+                      SigEnableContinuousUpdates,
+                      "Enable/disable continuous updates");
+    clientMsgCaps.add(VideoRectangleSelection, TightVncVendor,
+                      SigVideoRectangleSelection,
+                      "Select a rectangle to be treated as video");
+    clientMsgCaps.add(VideoFreeze, TightVncVendor,
+                      SigVideoFreeze,
+                      "Disable/enable video rectangle");
+
+    // Supported encoding types
+    encodingCaps.add(EncodingCopyRect, StandardVendor,
+                    SigEncodingCopyRect, "Standard CopyRect encoding");
+    encodingCaps.add(EncodingRRE, StandardVendor,
+                    SigEncodingRRE, "Standard RRE encoding");
+    encodingCaps.add(EncodingCoRRE, StandardVendor,
+                    SigEncodingCoRRE, "Standard CoRRE encoding");
+    encodingCaps.add(EncodingHextile, StandardVendor,
+                    SigEncodingHextile, "Standard Hextile encoding");
+    encodingCaps.add(EncodingZRLE, StandardVendor,
+                    SigEncodingZRLE, "Standard ZRLE encoding");
+    encodingCaps.add(EncodingZlib, TridiaVncVendor,
+                    SigEncodingZlib, "Zlib encoding");
+    encodingCaps.add(EncodingTight, TightVncVendor,
+                    SigEncodingTight, "Tight encoding");
+
+    // Supported pseudo-encoding types
+    encodingCaps.add(EncodingCompressLevel0, TightVncVendor,
+                    SigEncodingCompressLevel0, "Compression level");
+    encodingCaps.add(EncodingQualityLevel0, TightVncVendor,
+                    SigEncodingQualityLevel0, "JPEG quality level");
+    encodingCaps.add(EncodingXCursor, TightVncVendor,
+                    SigEncodingXCursor, "X-style cursor shape update");
+    encodingCaps.add(EncodingRichCursor, TightVncVendor,
+                    SigEncodingRichCursor, "Rich-color cursor shape update");
+    encodingCaps.add(EncodingPointerPos, TightVncVendor,
+                    SigEncodingPointerPos, "Pointer position update");
+    encodingCaps.add(EncodingLastRect, TightVncVendor,
+                    SigEncodingLastRect, "LastRect protocol extension");
+    encodingCaps.add(EncodingNewFBSize, TightVncVendor,
+                    SigEncodingNewFBSize, "Framebuffer size change");
+  }
+
+  //
+  // Setup tunneling (TightVNC protocol extensions)
+  //
+
+  void setupTunneling() throws IOException {
+    int nTunnelTypes = readU32();
+    if (nTunnelTypes != 0) {
+      readCapabilityList(tunnelCaps, nTunnelTypes);
+
+      // We don't support tunneling yet.
+      writeInt(NoTunneling);
+    }
+  }
+
+  //
+  // Negotiate authentication scheme (TightVNC protocol extensions)
+  //
+
+  int negotiateAuthenticationTight() throws Exception {
+    int nAuthTypes = readU32();
+    if (nAuthTypes == 0)
+      return AuthNone;
+
+    readCapabilityList(authCaps, nAuthTypes);
+    for (int i = 0; i < authCaps.numEnabled(); i++) {
+      int authType = authCaps.getByOrder(i);
+      if (authType == AuthNone || authType == AuthVNC) {
+       writeInt(authType);
+       return authType;
+      }
+    }
+    throw new Exception("No suitable authentication scheme found");
+  }
+
+  //
+  // Read a capability list (TightVNC protocol extensions)
+  //
+
+  void readCapabilityList(CapsContainer caps, int count) throws IOException {
+    int code;
+    byte[] vendor = new byte[4];
+    byte[] name = new byte[8];
+    for (int i = 0; i < count; i++) {
+      code = readU32();
+      readFully(vendor);
+      readFully(name);
+      caps.enable(new CapabilityInfo(code, vendor, name));
+    }
+  }
+
+  //
+  // Write a 32-bit integer into the output stream.
+  //
+
+  void writeInt(int value) throws IOException {
+    byte[] b = new byte[4];
+    b[0] = (byte) ((value >> 24) & 0xff);
+    b[1] = (byte) ((value >> 16) & 0xff);
+    b[2] = (byte) ((value >> 8) & 0xff);
+    b[3] = (byte) (value & 0xff);
+    os.write(b);
+  }
+
+  //
+  // Write the client initialisation message
+  //
+
+  void writeClientInit() throws IOException {
+    if (viewer.options.shareDesktop) {
+      os.write(1);
+    } else {
+      os.write(0);
+    }
+    viewer.options.disableShareDesktop();
+  }
+
+
+  //
+  // Read the server initialisation message
+  //
+
+  String desktopName;
+  int framebufferWidth, framebufferHeight;
+  int bitsPerPixel, depth;
+  boolean bigEndian, trueColour;
+  int redMax, greenMax, blueMax, redShift, greenShift, blueShift;
+
+  void readServerInit() throws IOException {
+    framebufferWidth = readU16();
+    framebufferHeight = readU16();
+    bitsPerPixel = readU8();
+    depth = readU8();
+    bigEndian = (readU8() != 0);
+    trueColour = (readU8() != 0);
+    redMax = readU16();
+    greenMax = readU16();
+    blueMax = readU16();
+    redShift = readU8();
+    greenShift = readU8();
+    blueShift = readU8();
+    byte[] pad = new byte[3];
+    readFully(pad);
+    int nameLength = readU32();
+    byte[] name = new byte[nameLength];
+    readFully(name);
+    desktopName = new String(name);
+
+    // Read interaction capabilities (TightVNC protocol extensions)
+    if (protocolTightVNC) {
+      int nServerMessageTypes = readU16();
+      int nClientMessageTypes = readU16();
+      int nEncodingTypes = readU16();
+      readU16();
+      readCapabilityList(serverMsgCaps, nServerMessageTypes);
+      readCapabilityList(clientMsgCaps, nClientMessageTypes);
+      readCapabilityList(encodingCaps, nEncodingTypes);
+    }
+
+    if (!clientMsgCaps.isEnabled(EnableContinuousUpdates)) {
+      viewer.options.disableContUpdates();
+    }
+
+    inNormalProtocol = true;
+  }
+
+
+  //
+  // Create session file and write initial protocol messages into it.
+  //
+
+  void startSession(String fname) throws IOException {
+    rec = new SessionRecorder(fname);
+    rec.writeHeader();
+    rec.write(versionMsg_3_3.getBytes());
+    rec.writeIntBE(SecTypeNone);
+    rec.writeShortBE(framebufferWidth);
+    rec.writeShortBE(framebufferHeight);
+    byte[] fbsServerInitMsg =  {
+      32, 24, 0, 1, 0,
+      (byte)0xFF, 0, (byte)0xFF, 0, (byte)0xFF,
+      16, 8, 0, 0, 0, 0
+    };
+    rec.write(fbsServerInitMsg);
+    rec.writeIntBE(desktopName.length());
+    rec.write(desktopName.getBytes());
+    numUpdatesInSession = 0;
+
+    // FIXME: If there were e.g. ZRLE updates only, that should not
+    //        affect recording of Zlib and Tight updates. So, actually
+    //        we should maintain separate flags for Zlib, ZRLE and
+    //        Tight, instead of one ``wereZlibUpdates'' variable.
+    //
+
+    zlibWarningShown = false;
+    tightWarningShown = false;
+  }
+
+  //
+  // Close session file.
+  //
+
+  void closeSession() throws IOException {
+    if (rec != null) {
+      rec.close();
+      rec = null;
+    }
+  }
+
+
+  //
+  // Set new framebuffer size
+  //
+
+  void setFramebufferSize(int width, int height) {
+    framebufferWidth = width;
+    framebufferHeight = height;
+  }
+
+
+  //
+  // Read the server message type
+  //
+
+  int readServerMessageType() throws IOException {
+    int msgType = readU8();
+
+    // If the session is being recorded:
+    if (rec != null) {
+      if (msgType == Bell) {   // Save Bell messages in session files.
+       rec.writeByte(msgType);
+       if (numUpdatesInSession > 0)
+         rec.flush();
+      }
+    }
+
+    return msgType;
+  }
+
+
+  //
+  // Read a FramebufferUpdate message
+  //
+
+  int updateNRects;
+
+  void readFramebufferUpdate() throws IOException {
+    skipBytes(1);
+    updateNRects = readU16();
+
+    // If the session is being recorded:
+    if (rec != null) {
+      rec.writeByte(FramebufferUpdate);
+      rec.writeByte(0);
+      rec.writeShortBE(updateNRects);
+    }
+
+    numUpdatesInSession++;
+  }
+
+  //
+  // Returns true if encoding is not pseudo
+  //
+  // FIXME: Find better way to differ pseudo and real encodings
+  //
+
+  boolean isRealDecoderEncoding(int encoding) {
+    if ((encoding >= 1) && (encoding <= 16)) {
+      return true;
+    }
+    return false;
+  }
+
+  // Read a FramebufferUpdate rectangle header
+
+  int updateRectX, updateRectY, updateRectW, updateRectH, updateRectEncoding;
+
+  void readFramebufferUpdateRectHdr() throws Exception {
+    updateRectX = readU16();
+    updateRectY = readU16();
+    updateRectW = readU16();
+    updateRectH = readU16();
+    updateRectEncoding = readU32();
+
+    if (updateRectEncoding == EncodingZlib ||
+        updateRectEncoding == EncodingZRLE ||
+       updateRectEncoding == EncodingTight)
+      wereZlibUpdates = true;
+
+    // If the session is being recorded:
+    if (rec != null) {
+      if (numUpdatesInSession > 1)
+       rec.flush();            // Flush the output on each rectangle.
+      rec.writeShortBE(updateRectX);
+      rec.writeShortBE(updateRectY);
+      rec.writeShortBE(updateRectW);
+      rec.writeShortBE(updateRectH);
+
+      //
+      // If this is pseudo encoding or CopyRect that write encoding ID
+      // in this place. All real encoding ID will be written to record stream
+      // in decoder classes.
+
+      if (((!isRealDecoderEncoding(updateRectEncoding))) && (rec != null)) {
+        rec.writeIntBE(updateRectEncoding);
+      }
+    }
+
+    if (updateRectEncoding < 0 || updateRectEncoding > MaxNormalEncoding)
+      return;
+
+    if (updateRectX + updateRectW > framebufferWidth ||
+       updateRectY + updateRectH > framebufferHeight) {
+      throw new Exception("Framebuffer update rectangle too large: " +
+                         updateRectW + "x" + updateRectH + " at (" +
+                         updateRectX + "," + updateRectY + ")");
+    }
+  }
+
+  //
+  // Read a ServerCutText message
+  //
+
+  String readServerCutText() throws IOException {
+    skipBytes(3);
+    int len = readU32();
+    byte[] text = new byte[len];
+    readFully(text);
+    return new String(text);
+  }
+
+
+  //
+  // Read an integer in compact representation (1..3 bytes).
+  // Such format is used as a part of the Tight encoding.
+  // Also, this method records data if session recording is active and
+  // the viewer's recordFromBeginning variable is set to true.
+  //
+
+  int readCompactLen() throws IOException {
+    int[] portion = new int[3];
+    portion[0] = readU8();
+    int byteCount = 1;
+    int len = portion[0] & 0x7F;
+    if ((portion[0] & 0x80) != 0) {
+      portion[1] = readU8();
+      byteCount++;
+      len |= (portion[1] & 0x7F) << 7;
+      if ((portion[1] & 0x80) != 0) {
+       portion[2] = readU8();
+       byteCount++;
+       len |= (portion[2] & 0xFF) << 14;
+      }
+    }
+
+    return len;
+  }
+
+
+  //
+  // Write a FramebufferUpdateRequest message
+  //
+
+  void writeFramebufferUpdateRequest(int x, int y, int w, int h,
+                                    boolean incremental)
+       throws IOException
+  {
+    byte[] b = new byte[10];
+
+    b[0] = (byte) FramebufferUpdateRequest;
+    b[1] = (byte) (incremental ? 1 : 0);
+    b[2] = (byte) ((x >> 8) & 0xff);
+    b[3] = (byte) (x & 0xff);
+    b[4] = (byte) ((y >> 8) & 0xff);
+    b[5] = (byte) (y & 0xff);
+    b[6] = (byte) ((w >> 8) & 0xff);
+    b[7] = (byte) (w & 0xff);
+    b[8] = (byte) ((h >> 8) & 0xff);
+    b[9] = (byte) (h & 0xff);
+
+    os.write(b);
+  }
+
+
+  //
+  // Write a SetPixelFormat message
+  //
+
+  void writeSetPixelFormat(int bitsPerPixel, int depth, boolean bigEndian,
+                          boolean trueColour,
+                          int redMax, int greenMax, int blueMax,
+                          int redShift, int greenShift, int blueShift)
+       throws IOException
+  {
+    byte[] b = new byte[20];
+
+    b[0]  = (byte) SetPixelFormat;
+    b[4]  = (byte) bitsPerPixel;
+    b[5]  = (byte) depth;
+    b[6]  = (byte) (bigEndian ? 1 : 0);
+    b[7]  = (byte) (trueColour ? 1 : 0);
+    b[8]  = (byte) ((redMax >> 8) & 0xff);
+    b[9]  = (byte) (redMax & 0xff);
+    b[10] = (byte) ((greenMax >> 8) & 0xff);
+    b[11] = (byte) (greenMax & 0xff);
+    b[12] = (byte) ((blueMax >> 8) & 0xff);
+    b[13] = (byte) (blueMax & 0xff);
+    b[14] = (byte) redShift;
+    b[15] = (byte) greenShift;
+    b[16] = (byte) blueShift;
+
+    os.write(b);
+  }
+
+
+  //
+  // Write a FixColourMapEntries message.  The values in the red, green and
+  // blue arrays are from 0 to 65535.
+  //
+
+  void writeFixColourMapEntries(int firstColour, int nColours,
+                               int[] red, int[] green, int[] blue)
+       throws IOException
+  {
+    byte[] b = new byte[6 + nColours * 6];
+
+    b[0] = (byte) FixColourMapEntries;
+    b[2] = (byte) ((firstColour >> 8) & 0xff);
+    b[3] = (byte) (firstColour & 0xff);
+    b[4] = (byte) ((nColours >> 8) & 0xff);
+    b[5] = (byte) (nColours & 0xff);
+
+    for (int i = 0; i < nColours; i++) {
+      b[6 + i * 6]     = (byte) ((red[i] >> 8) & 0xff);
+      b[6 + i * 6 + 1] = (byte) (red[i] & 0xff);
+      b[6 + i * 6 + 2] = (byte) ((green[i] >> 8) & 0xff);
+      b[6 + i * 6 + 3] = (byte) (green[i] & 0xff);
+      b[6 + i * 6 + 4] = (byte) ((blue[i] >> 8) & 0xff);
+      b[6 + i * 6 + 5] = (byte) (blue[i] & 0xff);
+    }
+
+    os.write(b);
+  }
+
+
+  //
+  // Write a SetEncodings message
+  //
+
+  void writeSetEncodings(int[] encs, int len) throws IOException {
+    byte[] b = new byte[4 + 4 * len];
+
+    b[0] = (byte) SetEncodings;
+    b[2] = (byte) ((len >> 8) & 0xff);
+    b[3] = (byte) (len & 0xff);
+
+    for (int i = 0; i < len; i++) {
+      b[4 + 4 * i] = (byte) ((encs[i] >> 24) & 0xff);
+      b[5 + 4 * i] = (byte) ((encs[i] >> 16) & 0xff);
+      b[6 + 4 * i] = (byte) ((encs[i] >> 8) & 0xff);
+      b[7 + 4 * i] = (byte) (encs[i] & 0xff);
+    }
+
+    os.write(b);
+  }
+
+
+  //
+  // Write a ClientCutText message
+  //
+
+  void writeClientCutText(String text) throws IOException {
+    byte[] b = new byte[8 + text.length()];
+
+    b[0] = (byte) ClientCutText;
+    b[4] = (byte) ((text.length() >> 24) & 0xff);
+    b[5] = (byte) ((text.length() >> 16) & 0xff);
+    b[6] = (byte) ((text.length() >> 8) & 0xff);
+    b[7] = (byte) (text.length() & 0xff);
+
+    System.arraycopy(text.getBytes(), 0, b, 8, text.length());
+
+    os.write(b);
+  }
+
+
+  //
+  // A buffer for putting pointer and keyboard events before being sent.  This
+  // is to ensure that multiple RFB events generated from a single Java Event
+  // will all be sent in a single network packet.  The maximum possible
+  // length is 4 modifier down events, a single key event followed by 4
+  // modifier up events i.e. 9 key events or 72 bytes.
+  //
+
+  byte[] eventBuf = new byte[72];
+  int eventBufLen;
+
+
+  // Useful shortcuts for modifier masks.
+
+  final static int CTRL_MASK  = InputEvent.CTRL_MASK;
+  final static int SHIFT_MASK = InputEvent.SHIFT_MASK;
+  final static int META_MASK  = InputEvent.META_MASK;
+  final static int ALT_MASK   = InputEvent.ALT_MASK;
+
+
+  //
+  // Write a pointer event message.  We may need to send modifier key events
+  // around it to set the correct modifier state.
+  //
+
+  int pointerMask = 0;
+
+  void writePointerEvent(MouseEvent evt) throws IOException {
+    int modifiers = evt.getModifiers();
+
+    int mask2 = 2;
+    int mask3 = 4;
+    if (viewer.options.reverseMouseButtons2And3) {
+      mask2 = 4;
+      mask3 = 2;
+    }
+
+    // Note: For some reason, AWT does not set BUTTON1_MASK on left
+    // button presses. Here we think that it was the left button if
+    // modifiers do not include BUTTON2_MASK or BUTTON3_MASK.
+
+    if (evt.getID() == MouseEvent.MOUSE_PRESSED) {
+      if ((modifiers & InputEvent.BUTTON2_MASK) != 0) {
+        pointerMask = mask2;
+        modifiers &= ~ALT_MASK;
+      } else if ((modifiers & InputEvent.BUTTON3_MASK) != 0) {
+        pointerMask = mask3;
+        modifiers &= ~META_MASK;
+      } else {
+        pointerMask = 1;
+      }
+    } else if (evt.getID() == MouseEvent.MOUSE_RELEASED) {
+      pointerMask = 0;
+      if ((modifiers & InputEvent.BUTTON2_MASK) != 0) {
+        modifiers &= ~ALT_MASK;
+      } else if ((modifiers & InputEvent.BUTTON3_MASK) != 0) {
+        modifiers &= ~META_MASK;
+      }
+    }
+
+    eventBufLen = 0;
+    writeModifierKeyEvents(modifiers);
+
+    int x = evt.getX();
+    int y = evt.getY();
+
+    if (x < 0) x = 0;
+    if (y < 0) y = 0;
+
+    eventBuf[eventBufLen++] = (byte) PointerEvent;
+    eventBuf[eventBufLen++] = (byte) pointerMask;
+    eventBuf[eventBufLen++] = (byte) ((x >> 8) & 0xff);
+    eventBuf[eventBufLen++] = (byte) (x & 0xff);
+    eventBuf[eventBufLen++] = (byte) ((y >> 8) & 0xff);
+    eventBuf[eventBufLen++] = (byte) (y & 0xff);
+
+    //
+    // Always release all modifiers after an "up" event
+    //
+
+    if (pointerMask == 0) {
+      writeModifierKeyEvents(0);
+    }
+
+    os.write(eventBuf, 0, eventBufLen);
+  }
+
+
+  //
+  // Write a key event message.  We may need to send modifier key events
+  // around it to set the correct modifier state.  Also we need to translate
+  // from the Java key values to the X keysym values used by the RFB protocol.
+  //
+
+  void writeKeyEvent(KeyEvent evt) throws IOException {
+
+    int keyChar = evt.getKeyChar();
+
+    //
+    // Ignore event if only modifiers were pressed.
+    //
+
+    // Some JVMs return 0 instead of CHAR_UNDEFINED in getKeyChar().
+    if (keyChar == 0)
+      keyChar = KeyEvent.CHAR_UNDEFINED;
+
+    if (keyChar == KeyEvent.CHAR_UNDEFINED) {
+      int code = evt.getKeyCode();
+      if (code == KeyEvent.VK_CONTROL || code == KeyEvent.VK_SHIFT ||
+          code == KeyEvent.VK_META || code == KeyEvent.VK_ALT)
+        return;
+    }
+
+    //
+    // Key press or key release?
+    //
+
+    boolean down = (evt.getID() == KeyEvent.KEY_PRESSED);
+
+    int key;
+    if (evt.isActionKey()) {
+
+      //
+      // An action key should be one of the following.
+      // If not then just ignore the event.
+      //
+
+      switch(evt.getKeyCode()) {
+      case KeyEvent.VK_HOME:      key = 0xff50; break;
+      case KeyEvent.VK_LEFT:      key = 0xff51; break;
+      case KeyEvent.VK_UP:        key = 0xff52; break;
+      case KeyEvent.VK_RIGHT:     key = 0xff53; break;
+      case KeyEvent.VK_DOWN:      key = 0xff54; break;
+      case KeyEvent.VK_PAGE_UP:   key = 0xff55; break;
+      case KeyEvent.VK_PAGE_DOWN: key = 0xff56; break;
+      case KeyEvent.VK_END:       key = 0xff57; break;
+      case KeyEvent.VK_INSERT:    key = 0xff63; break;
+      case KeyEvent.VK_F1:        key = 0xffbe; break;
+      case KeyEvent.VK_F2:        key = 0xffbf; break;
+      case KeyEvent.VK_F3:        key = 0xffc0; break;
+      case KeyEvent.VK_F4:        key = 0xffc1; break;
+      case KeyEvent.VK_F5:        key = 0xffc2; break;
+      case KeyEvent.VK_F6:        key = 0xffc3; break;
+      case KeyEvent.VK_F7:        key = 0xffc4; break;
+      case KeyEvent.VK_F8:        key = 0xffc5; break;
+      case KeyEvent.VK_F9:        key = 0xffc6; break;
+      case KeyEvent.VK_F10:       key = 0xffc7; break;
+      case KeyEvent.VK_F11:       key = 0xffc8; break;
+      case KeyEvent.VK_F12:       key = 0xffc9; break;
+      default:
+        return;
+      }
+
+    } else {
+
+      //
+      // A "normal" key press.  Ordinary ASCII characters go straight through.
+      // For CTRL-<letter>, CTRL is sent separately so just send <letter>.
+      // Backspace, tab, return, escape and delete have special keysyms.
+      // Anything else we ignore.
+      //
+
+      key = keyChar;
+
+      if (key < 0x20) {
+        if (evt.isControlDown()) {
+          key += 0x60;
+        } else {
+          switch(key) {
+          case KeyEvent.VK_BACK_SPACE: key = 0xff08; break;
+          case KeyEvent.VK_TAB:        key = 0xff09; break;
+          case KeyEvent.VK_ENTER:      key = 0xff0d; break;
+          case KeyEvent.VK_ESCAPE:     key = 0xff1b; break;
+          }
+        }
+      } else if (key == 0x7f) {
+       // Delete
+       key = 0xffff;
+      } else if (key > 0xff) {
+       // JDK1.1 on X incorrectly passes some keysyms straight through,
+       // so we do too.  JDK1.1.4 seems to have fixed this.
+       // The keysyms passed are 0xff00 .. XK_BackSpace .. XK_Delete
+       // Also, we pass through foreign currency keysyms (0x20a0..0x20af).
+       if ((key < 0xff00 || key > 0xffff) &&
+           !(key >= 0x20a0 && key <= 0x20af))
+         return;
+      }
+    }
+
+    // Fake keyPresses for keys that only generates keyRelease events
+    if ((key == 0xe5) || (key == 0xc5) || // XK_aring / XK_Aring
+       (key == 0xe4) || (key == 0xc4) || // XK_adiaeresis / XK_Adiaeresis
+       (key == 0xf6) || (key == 0xd6) || // XK_odiaeresis / XK_Odiaeresis
+       (key == 0xa7) || (key == 0xbd) || // XK_section / XK_onehalf
+       (key == 0xa3)) {                  // XK_sterling
+      // Make sure we do not send keypress events twice on platforms
+      // with correct JVMs (those that actually report KeyPress for all
+      // keys)
+      if (down)
+       brokenKeyPressed = true;
+
+      if (!down && !brokenKeyPressed) {
+       // We've got a release event for this key, but haven't received
+        // a press. Fake it.
+       eventBufLen = 0;
+       writeModifierKeyEvents(evt.getModifiers());
+       writeKeyEvent(key, true);
+       os.write(eventBuf, 0, eventBufLen);
+      }
+
+      if (!down)
+       brokenKeyPressed = false;
+    }
+
+    eventBufLen = 0;
+    writeModifierKeyEvents(evt.getModifiers());
+    writeKeyEvent(key, down);
+
+    // Always release all modifiers after an "up" event
+    if (!down)
+      writeModifierKeyEvents(0);
+
+    os.write(eventBuf, 0, eventBufLen);
+  }
+
+
+  //
+  // Add a raw key event with the given X keysym to eventBuf.
+  //
+
+  void writeKeyEvent(int keysym, boolean down) {
+    eventBuf[eventBufLen++] = (byte) KeyboardEvent;
+    eventBuf[eventBufLen++] = (byte) (down ? 1 : 0);
+    eventBuf[eventBufLen++] = (byte) 0;
+    eventBuf[eventBufLen++] = (byte) 0;
+    eventBuf[eventBufLen++] = (byte) ((keysym >> 24) & 0xff);
+    eventBuf[eventBufLen++] = (byte) ((keysym >> 16) & 0xff);
+    eventBuf[eventBufLen++] = (byte) ((keysym >> 8) & 0xff);
+    eventBuf[eventBufLen++] = (byte) (keysym & 0xff);
+  }
+
+
+  //
+  // Write key events to set the correct modifier state.
+  //
+
+  int oldModifiers = 0;
+
+  void writeModifierKeyEvents(int newModifiers) {
+    if ((newModifiers & CTRL_MASK) != (oldModifiers & CTRL_MASK))
+      writeKeyEvent(0xffe3, (newModifiers & CTRL_MASK) != 0);
+
+    if ((newModifiers & SHIFT_MASK) != (oldModifiers & SHIFT_MASK))
+      writeKeyEvent(0xffe1, (newModifiers & SHIFT_MASK) != 0);
+
+    if ((newModifiers & META_MASK) != (oldModifiers & META_MASK))
+      writeKeyEvent(0xffe7, (newModifiers & META_MASK) != 0);
+
+    if ((newModifiers & ALT_MASK) != (oldModifiers & ALT_MASK))
+      writeKeyEvent(0xffe9, (newModifiers & ALT_MASK) != 0);
+
+    oldModifiers = newModifiers;
+  }
+
+
+  //
+  // Enable continuous updates for the specified area of the screen (but
+  // only if EnableContinuousUpdates message is supported by the server).
+  //
+
+  void tryEnableContinuousUpdates(int x, int y, int w, int h)
+    throws IOException
+  {
+    if (!clientMsgCaps.isEnabled(EnableContinuousUpdates)) {
+      System.out.println("Continuous updates not supported by the server");
+      return;
+    }
+
+    if (continuousUpdatesActive) {
+      System.out.println("Continuous updates already active");
+      return;
+    }
+
+    byte[] b = new byte[10];
+
+    b[0] = (byte) EnableContinuousUpdates;
+    b[1] = (byte) 1; // enable
+    b[2] = (byte) ((x >> 8) & 0xff);
+    b[3] = (byte) (x & 0xff);
+    b[4] = (byte) ((y >> 8) & 0xff);
+    b[5] = (byte) (y & 0xff);
+    b[6] = (byte) ((w >> 8) & 0xff);
+    b[7] = (byte) (w & 0xff);
+    b[8] = (byte) ((h >> 8) & 0xff);
+    b[9] = (byte) (h & 0xff);
+
+    os.write(b);
+
+    continuousUpdatesActive = true;
+    System.out.println("Continuous updates activated");
+  }
+
+
+  //
+  // Disable continuous updates (only if EnableContinuousUpdates message
+  // is supported by the server).
+  //
+
+  void tryDisableContinuousUpdates() throws IOException
+  {
+    if (!clientMsgCaps.isEnabled(EnableContinuousUpdates)) {
+      System.out.println("Continuous updates not supported by the server");
+      return;
+    }
+
+    if (!continuousUpdatesActive) {
+      System.out.println("Continuous updates already disabled");
+      return;
+    }
+
+    if (continuousUpdatesEnding)
+      return;
+
+    byte[] b = { (byte)EnableContinuousUpdates, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+    os.write(b);
+
+    if (!serverMsgCaps.isEnabled(EndOfContinuousUpdates)) {
+      // If the server did not advertise support for the
+      // EndOfContinuousUpdates message (should not normally happen
+      // when EnableContinuousUpdates is supported), then we clear
+      // 'continuousUpdatesActive' variable immediately. Normally,
+      // it will be reset on receiving EndOfContinuousUpdates message
+      // from the server.
+      continuousUpdatesActive = false;
+    } else {
+      // Indicate that we are waiting for EndOfContinuousUpdates.
+      continuousUpdatesEnding = true;
+    }
+  }
+
+
+  //
+  // Process EndOfContinuousUpdates message received from the server.
+  //
+
+  void endOfContinuousUpdates()
+  {
+    continuousUpdatesActive = false;
+    continuousUpdatesEnding = false;
+  }
+
+
+  //
+  // Check if continuous updates are in effect.
+  //
+
+  boolean continuousUpdatesAreActive()
+  {
+    return continuousUpdatesActive;
+  }
+
+  /**
+   * Send a rectangle selection to be treated as video by the server (but
+   * only if VideoRectangleSelection message is supported by the server).
+   * @param rect specifies coordinates and size of the rectangule.
+   * @throws java.io.IOException
+   */
+  void trySendVideoSelection(Rectangle rect) throws IOException
+  {
+    if (!clientMsgCaps.isEnabled(VideoRectangleSelection)) {
+      System.out.println("Video area selection is not supported by the server");
+      return;
+    }
+
+    // Send zero coordinates if the rectangle is empty.
+    if (rect.isEmpty()) {
+      rect = new Rectangle();
+    }
+
+    int x = rect.x;
+    int y = rect.y;
+    int w = rect.width;
+    int h = rect.height;
+
+    byte[] b = new byte[10];
+
+    b[0] = (byte) VideoRectangleSelection;
+    b[1] = (byte) 0; // reserved
+    b[2] = (byte) ((x >> 8) & 0xff);
+    b[3] = (byte) (x & 0xff);
+    b[4] = (byte) ((y >> 8) & 0xff);
+    b[5] = (byte) (y & 0xff);
+    b[6] = (byte) ((w >> 8) & 0xff);
+    b[7] = (byte) (w & 0xff);
+    b[8] = (byte) ((h >> 8) & 0xff);
+    b[9] = (byte) (h & 0xff);
+
+    os.write(b);
+
+    System.out.println("Video rectangle selection message sent");
+  }
+
+  void trySendVideoFreeze(boolean freeze) throws IOException
+  {
+    if (!clientMsgCaps.isEnabled(VideoFreeze)) {
+      System.out.println("Video freeze is not supported by the server");
+      return;
+    }
+
+    byte[] b = new byte[2];
+    byte fb = 0;
+    if (freeze) {
+      fb = 1;
+    }
+
+    b[0] = (byte) VideoFreeze;
+    b[1] = (byte) fb;
+
+    os.write(b);
+
+    System.out.println("Video freeze selection message sent");
+  }
+
+  public void startTiming() {
+    timing = true;
+
+    // Carry over up to 1s worth of previous rate for smoothing.
+
+    if (timeWaitedIn100us > 10000) {
+      timedKbits = timedKbits * 10000 / timeWaitedIn100us;
+      timeWaitedIn100us = 10000;
+    }
+  }
+
+  public void stopTiming() {
+    timing = false;
+    if (timeWaitedIn100us < timedKbits/2)
+      timeWaitedIn100us = timedKbits/2; // upper limit 20Mbit/s
+  }
+
+  public long kbitsPerSecond() {
+    return timedKbits * 10000 / timeWaitedIn100us;
+  }
+
+  public long timeWaited() {
+    return timeWaitedIn100us;
+  }
+
+  //
+  // Methods for reading data via our DataInputStream member variable (is).
+  //
+  // In addition to reading data, the readFully() methods updates variables
+  // used to estimate data throughput.
+  //
+
+  public void readFully(byte b[]) throws IOException {
+    readFully(b, 0, b.length);
+  }
+
+  public void readFully(byte b[], int off, int len) throws IOException {
+    long before = 0;
+    if (timing)
+      before = System.currentTimeMillis();
+
+    is.readFully(b, off, len);
+
+    if (timing) {
+      long after = System.currentTimeMillis();
+      long newTimeWaited = (after - before) * 10;
+      int newKbits = len * 8 / 1000;
+
+      // limit rate to between 10kbit/s and 40Mbit/s
+
+      if (newTimeWaited > newKbits*1000) newTimeWaited = newKbits*1000;
+      if (newTimeWaited < newKbits/4)    newTimeWaited = newKbits/4;
+
+      timeWaitedIn100us += newTimeWaited;
+      timedKbits += newKbits;
+    }
+
+    numBytesRead += len;
+  }
+
+  final int available() throws IOException {
+    return is.available();
+  }
+
+  // FIXME: DataInputStream::skipBytes() is not guaranteed to skip
+  //        exactly n bytes. Probably we don't want to use this method.
+  final int skipBytes(int n) throws IOException {
+    int r = is.skipBytes(n);
+    numBytesRead += r;
+    return r;
+  }
+
+  final int readU8() throws IOException {
+    int r = is.readUnsignedByte();
+    numBytesRead++;
+    return r;
+  }
+
+  final int readU16() throws IOException {
+    int r = is.readUnsignedShort();
+    numBytesRead += 2;
+    return r;
+  }
+
+  final int readU32() throws IOException {
+    int r = is.readInt();
+    numBytesRead += 4;
+    return r;
+  }
+}
diff --git a/java/src/com/tigervnc/vncviewer/SessionRecorder.java b/java/src/com/tigervnc/vncviewer/SessionRecorder.java
new file mode 100644 (file)
index 0000000..9e73531
--- /dev/null
@@ -0,0 +1,195 @@
+//
+//  Copyright (C) 2002 Constantin Kaplinsky.  All Rights Reserved.
+//
+//  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.
+//
+
+//
+// SessionRecorder is a class to write FBS (FrameBuffer Stream) files.
+// FBS files are used to save RFB sessions for later playback.
+//
+
+package com.tightvnc.vncviewer;
+
+import java.io.*;
+
+class SessionRecorder {
+
+  protected FileOutputStream f;
+  protected DataOutputStream df;
+  protected long startTime, lastTimeOffset;
+
+  protected byte[] buffer;
+  protected int bufferSize;
+  protected int bufferBytes;
+
+  public SessionRecorder(String name, int bufsize) throws IOException {
+    f = new FileOutputStream(name);
+    df = new DataOutputStream(f);
+    startTime = System.currentTimeMillis();
+    lastTimeOffset = 0;
+    
+    bufferSize = bufsize;
+    bufferBytes = 0;
+    buffer = new byte[bufferSize];
+  }
+
+  public SessionRecorder(String name) throws IOException {
+    this(name, 65536);
+  }
+
+  //
+  // Close the file, free resources.
+  //
+
+  public void close() throws IOException {
+    try {
+      flush();
+    } catch (IOException e) {
+    }
+
+    df = null;
+    f.close();
+    f = null;
+    buffer = null;
+  }
+
+  //
+  // Write the FBS file header as defined in the rfbproxy utility.
+  //
+
+  public void writeHeader() throws IOException {
+    df.write("FBS 001.000\n".getBytes());
+  }
+
+  //
+  // Write one byte.
+  //
+
+  public void writeByte(int b) throws IOException {
+    prepareWriting();
+    buffer[bufferBytes++] = (byte)b;
+  }
+
+  //
+  // Write 16-bit value, big-endian.
+  //
+
+  public void writeShortBE(int v) throws IOException {
+    prepareWriting();
+    buffer[bufferBytes++] = (byte)(v >> 8);
+    buffer[bufferBytes++] = (byte)v;
+  }
+
+  //
+  // Write 32-bit value, big-endian.
+  //
+
+  public void writeIntBE(int v) throws IOException {
+    prepareWriting();
+    buffer[bufferBytes]     = (byte)(v >> 24);
+    buffer[bufferBytes + 1] = (byte)(v >> 16);
+    buffer[bufferBytes + 2] = (byte)(v >> 8);
+    buffer[bufferBytes + 3] = (byte)v;
+    bufferBytes += 4;
+  }
+
+  //
+  // Write 16-bit value, little-endian.
+  //
+
+  public void writeShortLE(int v) throws IOException {
+    prepareWriting();
+    buffer[bufferBytes++] = (byte)v;
+    buffer[bufferBytes++] = (byte)(v >> 8);
+  }
+
+  //
+  // Write 32-bit value, little-endian.
+  //
+
+  public void writeIntLE(int v) throws IOException {
+    prepareWriting();
+    buffer[bufferBytes]     = (byte)v;
+    buffer[bufferBytes + 1] = (byte)(v >> 8);
+    buffer[bufferBytes + 2] = (byte)(v >> 16);
+    buffer[bufferBytes + 3] = (byte)(v >> 24);
+    bufferBytes += 4;
+  }
+
+  //
+  // Write byte arrays.
+  //
+
+  public void write(byte b[], int off, int len) throws IOException {
+    prepareWriting();
+    while (len > 0) {
+      if (bufferBytes > bufferSize - 4)
+       flush(false);
+
+      int partLen;
+      if (bufferBytes + len > bufferSize) {
+       partLen = bufferSize - bufferBytes;
+      } else {
+       partLen = len;
+      }
+      System.arraycopy(b, off, buffer, bufferBytes, partLen);
+      bufferBytes += partLen;
+      off += partLen;
+      len -= partLen;
+    }
+  }
+
+  public void write(byte b[]) throws IOException {
+    write(b, 0, b.length);
+  }
+
+  //
+  // Flush the output. This method saves buffered data in the
+  // underlying file object adding data sizes and timestamps. If the
+  // updateTimeOffset is set to false, then the current time offset
+  // will not be changed for next write operation.
+  //
+
+  public void flush(boolean updateTimeOffset) throws IOException {
+    if (bufferBytes > 0) {
+      df.writeInt(bufferBytes);
+      df.write(buffer, 0, (bufferBytes + 3) & 0x7FFFFFFC);
+      df.writeInt((int)lastTimeOffset);
+      bufferBytes = 0;
+      if (updateTimeOffset)
+       lastTimeOffset = -1;
+    }
+  }
+
+  public void flush() throws IOException {
+    flush(true);
+  }
+
+  //
+  // Before writing any data, remember time offset and flush the
+  // buffer before it becomes full.
+  //
+
+  protected void prepareWriting() throws IOException {
+    if (lastTimeOffset == -1)
+      lastTimeOffset = System.currentTimeMillis() - startTime;
+    if (bufferBytes > bufferSize - 4)
+      flush(false);
+  }
+
+}
+
diff --git a/java/src/com/tigervnc/vncviewer/SocketFactory.java b/java/src/com/tigervnc/vncviewer/SocketFactory.java
new file mode 100644 (file)
index 0000000..966d1d3
--- /dev/null
@@ -0,0 +1,38 @@
+//
+//  Copyright (C) 2002 HorizonLive.com, Inc.  All Rights Reserved.
+//
+//  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.
+//
+
+//
+// SocketFactory.java describes an interface used to substitute the
+// standard Socket class by its alternative implementations.
+//
+
+package com.tightvnc.vncviewer;
+
+import java.applet.*;
+import java.net.*;
+import java.io.*;
+
+public interface SocketFactory {
+
+  public Socket createSocket(String host, int port, Applet applet)
+    throws IOException;
+
+  public Socket createSocket(String host, int port, String[] args)
+    throws IOException;
+}
diff --git a/java/src/com/tigervnc/vncviewer/VncCanvas.java b/java/src/com/tigervnc/vncviewer/VncCanvas.java
new file mode 100644 (file)
index 0000000..4e5460f
--- /dev/null
@@ -0,0 +1,1315 @@
+//
+//  Copyright (C) 2004 Horizon Wimba.  All Rights Reserved.
+//  Copyright (C) 2001-2003 HorizonLive.com, Inc.  All Rights Reserved.
+//  Copyright (C) 2001,2002 Constantin Kaplinsky.  All Rights Reserved.
+//  Copyright (C) 2000 Tridia Corporation.  All Rights Reserved.
+//  Copyright (C) 1999 AT&T Laboratories Cambridge.  All Rights Reserved.
+//
+//  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.
+//
+
+package com.tightvnc.vncviewer;
+
+import com.tightvnc.decoder.CoRREDecoder;
+import com.tightvnc.decoder.CopyRectDecoder;
+import com.tightvnc.decoder.HextileDecoder;
+import com.tightvnc.decoder.RREDecoder;
+import com.tightvnc.decoder.RawDecoder;
+import com.tightvnc.decoder.TightDecoder;
+import com.tightvnc.decoder.ZRLEDecoder;
+import com.tightvnc.decoder.ZlibDecoder;
+import com.tightvnc.decoder.common.Repaintable;
+import java.awt.*;
+import java.awt.event.*;
+import java.awt.image.*;
+import java.io.*;
+import java.lang.*;
+import java.util.zip.*;
+
+
+//
+// VncCanvas is a subclass of Canvas which draws a VNC desktop on it.
+//
+
+class VncCanvas extends Canvas
+  implements KeyListener, MouseListener, MouseMotionListener, Repaintable, Runnable {
+
+  VncViewer viewer;
+  RfbProto rfb;
+  ColorModel cm8, cm24;
+  int bytesPixel;
+
+  int maxWidth = 0, maxHeight = 0;
+  int scalingFactor;
+  int scaledWidth, scaledHeight;
+
+  Image memImage;
+  Graphics memGraphics;
+
+  //
+  // Decoders
+  //
+
+  RawDecoder rawDecoder;
+  RREDecoder rreDecoder;
+  CoRREDecoder correDecoder;
+  ZlibDecoder zlibDecoder;
+  HextileDecoder hextileDecoder;
+  ZRLEDecoder zrleDecoder;
+  TightDecoder tightDecoder;
+  CopyRectDecoder copyRectDecoder;
+
+  // Base decoder decoders array
+  RawDecoder []decoders = null;
+
+  // Update statistics.
+  long statStartTime;           // time on first framebufferUpdateRequest
+  long statNumUpdates;           // counter for FramebufferUpdate messages
+  long statNumTotalRects;        // rectangles in FramebufferUpdate messages
+  long statNumPixelRects;        // the same, but excluding pseudo-rectangles
+  long statNumRectsTight;        // Tight-encoded rectangles (including JPEG)
+  long statNumRectsTightJPEG;    // JPEG-compressed Tight-encoded rectangles
+  long statNumRectsZRLE;         // ZRLE-encoded rectangles
+  long statNumRectsHextile;      // Hextile-encoded rectangles
+  long statNumRectsRaw;          // Raw-encoded rectangles
+  long statNumRectsCopy;         // CopyRect rectangles
+  long statNumBytesEncoded;      // number of bytes in updates, as received
+  long statNumBytesDecoded;      // number of bytes, as if Raw encoding was used
+
+  // True if we process keyboard and mouse events.
+  boolean inputEnabled;
+
+  // True if was no one auto resize of canvas
+  boolean isFirstSizeAutoUpdate = true;
+
+  // Members for limiting sending mouse events to server
+  long lastMouseEventSendTime = System.currentTimeMillis();
+  long mouseMaxFreq = 20;
+
+  //
+  // The constructors.
+  //
+
+  public VncCanvas(VncViewer v, int maxWidth_, int maxHeight_)
+    throws IOException {
+
+    viewer = v;
+    maxWidth = maxWidth_;
+    maxHeight = maxHeight_;
+
+    rfb = viewer.rfb;
+    scalingFactor = viewer.options.scalingFactor;
+
+    cm8 = new DirectColorModel(8, 7, (7 << 3), (3 << 6));
+    cm24 = new DirectColorModel(24, 0xFF0000, 0x00FF00, 0x0000FF);
+
+    //
+    // Create decoders
+    //
+
+    // Input stream for decoders
+    RfbInputStream rfbis = new RfbInputStream(rfb);
+    // Create output stream for session recording
+    RecordOutputStream ros = new RecordOutputStream(rfb);
+
+    rawDecoder = new RawDecoder(memGraphics, rfbis);
+    rreDecoder = new RREDecoder(memGraphics, rfbis);
+    correDecoder = new CoRREDecoder(memGraphics, rfbis);
+    hextileDecoder = new HextileDecoder(memGraphics, rfbis);
+    tightDecoder = new TightDecoder(memGraphics, rfbis);
+    zlibDecoder = new ZlibDecoder(memGraphics, rfbis);
+    zrleDecoder = new ZRLEDecoder(memGraphics, rfbis);
+    copyRectDecoder = new CopyRectDecoder(memGraphics, rfbis);
+
+    //
+    // Set data for decoders that needs extra parameters
+    //
+
+    hextileDecoder.setRepainableControl(this);
+    tightDecoder.setRepainableControl(this);
+
+    //
+    // Create array that contains our decoders
+    //
+
+    decoders = new RawDecoder[8];
+    decoders[0] = rawDecoder;
+    decoders[1] = rreDecoder;
+    decoders[2] = correDecoder;
+    decoders[3] = hextileDecoder;
+    decoders[4] = zlibDecoder;
+    decoders[5] = tightDecoder;
+    decoders[6] = zrleDecoder;
+    decoders[7] = copyRectDecoder;
+
+    //
+    // Set session recorder for decoders
+    //
+
+    for (int i = 0; i < decoders.length; i++) {
+      decoders[i].setDataOutputStream(ros);
+    }
+
+    setPixelFormat();
+    resetSelection();
+
+    inputEnabled = false;
+    if (!viewer.options.viewOnly)
+      enableInput(true);
+
+    // Enable mouse and keyboard event listeners.
+    addKeyListener(this);
+    addMouseListener(this);
+    addMouseMotionListener(this);
+
+    // Create thread, that will send mouse movement events
+    // to VNC server.
+    Thread mouseThread = new Thread(this);
+    mouseThread.start();
+  }
+
+  public VncCanvas(VncViewer v) throws IOException {
+    this(v, 0, 0);
+  }
+
+  //
+  // Callback methods to determine geometry of our Component.
+  //
+
+  public Dimension getPreferredSize() {
+    return new Dimension(scaledWidth, scaledHeight);
+  }
+
+  public Dimension getMinimumSize() {
+    return new Dimension(scaledWidth, scaledHeight);
+  }
+
+  public Dimension getMaximumSize() {
+    return new Dimension(scaledWidth, scaledHeight);
+  }
+
+  //
+  // All painting is performed here.
+  //
+
+  public void update(Graphics g) {
+    paint(g);
+  }
+
+  public void paint(Graphics g) {
+    synchronized(memImage) {
+      if (rfb.framebufferWidth == scaledWidth) {
+        g.drawImage(memImage, 0, 0, null);
+      } else {
+        paintScaledFrameBuffer(g);
+      }
+    }
+    if (showSoftCursor) {
+      int x0 = cursorX - hotX, y0 = cursorY - hotY;
+      Rectangle r = new Rectangle(x0, y0, cursorWidth, cursorHeight);
+      if (r.intersects(g.getClipBounds())) {
+       g.drawImage(softCursor, x0, y0, null);
+      }
+    }
+    if (isInSelectionMode()) {
+      Rectangle r = getSelection(true);
+      if (r.width > 0 && r.height > 0) {
+        // Don't forget to correct the coordinates for the right and bottom
+        // borders, so that the borders are the part of the selection.
+        r.width -= 1;
+        r.height -= 1;
+        g.setXORMode(Color.yellow);
+        g.drawRect(r.x, r.y, r.width, r.height);
+      }
+    }
+  }
+
+  public void paintScaledFrameBuffer(Graphics g) {
+    g.drawImage(memImage, 0, 0, scaledWidth, scaledHeight, null);
+  }
+
+  //
+  // Start/stop receiving mouse events. Keyboard events are received
+  // even in view-only mode, because we want to map the 'r' key to the
+  // screen refreshing function.
+  //
+
+  public synchronized void enableInput(boolean enable) {
+    if (enable && !inputEnabled) {
+      inputEnabled = true;
+      if (viewer.showControls) {
+       viewer.buttonPanel.enableRemoteAccessControls(true);
+      }
+      createSoftCursor();      // scaled cursor
+    } else if (!enable && inputEnabled) {
+      inputEnabled = false;
+      if (viewer.showControls) {
+       viewer.buttonPanel.enableRemoteAccessControls(false);
+      }
+      createSoftCursor();      // non-scaled cursor
+    }
+  }
+
+  public void setPixelFormat() throws IOException {
+    if (viewer.options.eightBitColors) {
+      rfb.writeSetPixelFormat(8, 8, false, true, 7, 7, 3, 0, 3, 6);
+      bytesPixel = 1;
+    } else {
+      rfb.writeSetPixelFormat(32, 24, false, true, 255, 255, 255, 16, 8, 0);
+      bytesPixel = 4;
+    }
+    updateFramebufferSize();
+  }
+
+  void setScalingFactor(int sf) {
+    scalingFactor = sf;
+    updateFramebufferSize();
+    invalidate();
+  }
+
+  void updateFramebufferSize() {
+
+    // Useful shortcuts.
+    int fbWidth = rfb.framebufferWidth;
+    int fbHeight = rfb.framebufferHeight;
+
+    // FIXME: This part of code must be in VncViewer i think
+    if (viewer.options.autoScale) {
+      if (viewer.inAnApplet) {
+        maxWidth = viewer.getWidth();
+        maxHeight = viewer.getHeight();
+      } else {
+        if (viewer.vncFrame != null) {
+          if (isFirstSizeAutoUpdate) {
+            isFirstSizeAutoUpdate = false;
+            Dimension screenSize = viewer.vncFrame.getToolkit().getScreenSize();
+            maxWidth = (int)screenSize.getWidth() - 100;
+            maxHeight = (int)screenSize.getHeight() - 100;
+            viewer.vncFrame.setSize(maxWidth, maxHeight);
+          } else {
+            viewer.desktopScrollPane.doLayout();
+            maxWidth = viewer.desktopScrollPane.getWidth();
+            maxHeight = viewer.desktopScrollPane.getHeight();
+          }
+        } else {
+          maxWidth = fbWidth;
+          maxHeight = fbHeight;
+        }
+      }
+      int f1 = maxWidth * 100 / fbWidth;
+      int f2 = maxHeight * 100 / fbHeight;
+      scalingFactor = Math.min(f1, f2);
+      if (scalingFactor > 100)
+       scalingFactor = 100;
+      System.out.println("Scaling desktop at " + scalingFactor + "%");
+    }
+
+    // Update scaled framebuffer geometry.
+    scaledWidth = (fbWidth * scalingFactor + 50) / 100;
+    scaledHeight = (fbHeight * scalingFactor + 50) / 100;
+
+    // Create new off-screen image either if it does not exist, or if
+    // its geometry should be changed. It's not necessary to replace
+    // existing image if only pixel format should be changed.
+    if (memImage == null) {
+      memImage = viewer.vncContainer.createImage(fbWidth, fbHeight);
+      memGraphics = memImage.getGraphics();
+    } else if (memImage.getWidth(null) != fbWidth ||
+              memImage.getHeight(null) != fbHeight) {
+      synchronized(memImage) {
+       memImage = viewer.vncContainer.createImage(fbWidth, fbHeight);
+       memGraphics = memImage.getGraphics();
+      }
+    }
+
+    //
+    // Update decoders
+    //
+
+    //
+    // FIXME: Why decoders can be null here?
+    //
+
+    if (decoders != null) {
+      for (int i = 0; i < decoders.length; i++) {
+        //
+        // Set changes to every decoder that we can use
+        //
+
+        decoders[i].setBPP(bytesPixel);
+        decoders[i].setFrameBufferSize(fbWidth, fbHeight);
+        decoders[i].setGraphics(memGraphics);
+
+        //
+        // Update decoder
+        //
+
+        decoders[i].update();
+      }
+    }
+
+    // FIXME: This part of code must be in VncViewer i think
+    // Update the size of desktop containers.
+    if (viewer.inSeparateFrame) {
+      if (viewer.desktopScrollPane != null) {
+        if (!viewer.options.autoScale) {
+          resizeDesktopFrame();
+        } else {
+          setSize(scaledWidth, scaledHeight);
+          viewer.desktopScrollPane.setSize(maxWidth + 200,
+                                           maxHeight + 200);
+        }
+      }
+    } else {
+      setSize(scaledWidth, scaledHeight);
+    }
+    viewer.moveFocusToDesktop();
+  }
+
+  void resizeDesktopFrame() {
+    setSize(scaledWidth, scaledHeight);
+
+    // FIXME: Find a better way to determine correct size of a
+    // ScrollPane.  -- const
+    Insets insets = viewer.desktopScrollPane.getInsets();
+    viewer.desktopScrollPane.setSize(scaledWidth +
+                                    2 * Math.min(insets.left, insets.right),
+                                    scaledHeight +
+                                    2 * Math.min(insets.top, insets.bottom));
+
+    viewer.vncFrame.pack();
+
+    // Try to limit the frame size to the screen size.
+
+    Dimension screenSize = viewer.vncFrame.getToolkit().getScreenSize();
+    Dimension frameSize = viewer.vncFrame.getSize();
+    Dimension newSize = frameSize;
+
+    // Reduce Screen Size by 30 pixels in each direction;
+    // This is a (poor) attempt to account for
+    //     1) Menu bar on Macintosh (should really also account for
+    //        Dock on OSX).  Usually 22px on top of screen.
+    //     2) Taxkbar on Windows (usually about 28 px on bottom)
+    //     3) Other obstructions.
+
+    screenSize.height -= 30;
+    screenSize.width  -= 30;
+
+    boolean needToResizeFrame = false;
+    if (frameSize.height > screenSize.height) {
+      newSize.height = screenSize.height;
+      needToResizeFrame = true;
+    }
+    if (frameSize.width > screenSize.width) {
+      newSize.width = screenSize.width;
+      needToResizeFrame = true;
+    }
+    if (needToResizeFrame) {
+      viewer.vncFrame.setSize(newSize);
+    }
+
+    viewer.desktopScrollPane.doLayout();
+  }
+
+  //
+  // processNormalProtocol() - executed by the rfbThread to deal with the
+  // RFB socket.
+  //
+
+  public void processNormalProtocol() throws Exception {
+
+    // Start/stop session recording if necessary.
+    viewer.checkRecordingStatus();
+
+    rfb.writeFramebufferUpdateRequest(0, 0, rfb.framebufferWidth,
+                                     rfb.framebufferHeight, false);
+
+    if (viewer.options.continuousUpdates) {
+      rfb.tryEnableContinuousUpdates(0, 0, rfb.framebufferWidth,
+                                     rfb.framebufferHeight);
+    }
+
+    resetStats();
+    boolean statsRestarted = false;
+
+    //
+    // main dispatch loop
+    //
+
+    while (true) {
+
+      // Read message type from the server.
+      int msgType = rfb.readServerMessageType();
+
+      // Process the message depending on its type.
+      switch (msgType) {
+      case RfbProto.FramebufferUpdate:
+
+        if (statNumUpdates == viewer.debugStatsExcludeUpdates &&
+            !statsRestarted) {
+          resetStats();
+          statsRestarted = true;
+        } else if (statNumUpdates == viewer.debugStatsMeasureUpdates &&
+                   statsRestarted) {
+          viewer.disconnect();
+        }
+
+       rfb.readFramebufferUpdate();
+       statNumUpdates++;
+
+       boolean cursorPosReceived = false;
+
+       for (int i = 0; i < rfb.updateNRects; i++) {
+
+         rfb.readFramebufferUpdateRectHdr();
+         statNumTotalRects++;
+         int rx = rfb.updateRectX, ry = rfb.updateRectY;
+         int rw = rfb.updateRectW, rh = rfb.updateRectH;
+
+         if (rfb.updateRectEncoding == rfb.EncodingLastRect)
+           break;
+
+         if (rfb.updateRectEncoding == rfb.EncodingNewFBSize) {
+           rfb.setFramebufferSize(rw, rh);
+           updateFramebufferSize();
+           break;
+         }
+
+         if (rfb.updateRectEncoding == rfb.EncodingXCursor ||
+             rfb.updateRectEncoding == rfb.EncodingRichCursor) {
+           handleCursorShapeUpdate(rfb.updateRectEncoding, rx, ry, rw, rh);
+           continue;
+         }
+
+         if (rfb.updateRectEncoding == rfb.EncodingPointerPos) {
+           softCursorMove(rx, ry);
+           cursorPosReceived = true;
+           continue;
+         }
+
+          long numBytesReadBefore = rfb.getNumBytesRead();
+
+          rfb.startTiming();
+
+         switch (rfb.updateRectEncoding) {
+         case RfbProto.EncodingRaw:
+           statNumRectsRaw++;
+           handleRawRect(rx, ry, rw, rh);
+           break;
+         case RfbProto.EncodingCopyRect:
+           statNumRectsCopy++;
+           handleCopyRect(rx, ry, rw, rh);
+           break;
+         case RfbProto.EncodingRRE:
+           handleRRERect(rx, ry, rw, rh);
+           break;
+         case RfbProto.EncodingCoRRE:
+           handleCoRRERect(rx, ry, rw, rh);
+           break;
+         case RfbProto.EncodingHextile:
+           statNumRectsHextile++;
+           handleHextileRect(rx, ry, rw, rh);
+           break;
+         case RfbProto.EncodingZRLE:
+           statNumRectsZRLE++;
+           handleZRLERect(rx, ry, rw, rh);
+           break;
+         case RfbProto.EncodingZlib:
+            handleZlibRect(rx, ry, rw, rh);
+           break;
+         case RfbProto.EncodingTight:
+            if (tightDecoder != null) {
+             statNumRectsTightJPEG = tightDecoder.getNumJPEGRects();
+              //statNumRectsTight = tightDecoder.getNumTightRects();
+            }
+            statNumRectsTight++;
+           handleTightRect(rx, ry, rw, rh);
+           break;
+         default:
+           throw new Exception("Unknown RFB rectangle encoding " +
+                               rfb.updateRectEncoding);
+         }
+
+          rfb.stopTiming();
+
+          statNumPixelRects++;
+          statNumBytesDecoded += rw * rh * bytesPixel;
+          statNumBytesEncoded +=
+            (int)(rfb.getNumBytesRead() - numBytesReadBefore);
+       }
+
+       boolean fullUpdateNeeded = false;
+
+       // Start/stop session recording if necessary. Request full
+       // update if a new session file was opened.
+       if (viewer.checkRecordingStatus())
+         fullUpdateNeeded = true;
+
+       // Defer framebuffer update request if necessary. But wake up
+       // immediately on keyboard or mouse event. Also, don't sleep
+       // if there is some data to receive, or if the last update
+       // included a PointerPos message.
+       if (viewer.deferUpdateRequests > 0 &&
+           rfb.available() == 0 && !cursorPosReceived) {
+         synchronized(rfb) {
+           try {
+             rfb.wait(viewer.deferUpdateRequests);
+           } catch (InterruptedException e) {
+           }
+         }
+       }
+
+        viewer.autoSelectEncodings();
+
+       // Before requesting framebuffer update, check if the pixel
+       // format should be changed.
+       if (viewer.options.eightBitColors != (bytesPixel == 1)) {
+          // Pixel format should be changed.
+          if (!rfb.continuousUpdatesAreActive()) {
+            // Continuous updates are not used. In this case, we just
+            // set new pixel format and request full update.
+            setPixelFormat();
+            fullUpdateNeeded = true;
+          } else {
+            // Otherwise, disable continuous updates first. Pixel
+            // format will be set later when we are sure that there
+            // will be no unsolicited framebuffer updates.
+            rfb.tryDisableContinuousUpdates();
+            break; // skip the code below
+          }
+       }
+
+        // Enable/disable continuous updates to reflect the GUI setting.
+        boolean enable = viewer.options.continuousUpdates;
+        if (enable != rfb.continuousUpdatesAreActive()) {
+          if (enable) {
+            rfb.tryEnableContinuousUpdates(0, 0, rfb.framebufferWidth,
+                                           rfb.framebufferHeight);
+          } else {
+            rfb.tryDisableContinuousUpdates();
+          }
+        }
+
+        // Finally, request framebuffer update if needed.
+        if (fullUpdateNeeded) {
+          rfb.writeFramebufferUpdateRequest(0, 0, rfb.framebufferWidth,
+                                            rfb.framebufferHeight, false);
+        } else if (!rfb.continuousUpdatesAreActive()) {
+          rfb.writeFramebufferUpdateRequest(0, 0, rfb.framebufferWidth,
+                                            rfb.framebufferHeight, true);
+        }
+
+       break;
+
+      case RfbProto.SetColourMapEntries:
+       throw new Exception("Can't handle SetColourMapEntries message");
+
+      case RfbProto.Bell:
+        Toolkit.getDefaultToolkit().beep();
+       break;
+
+      case RfbProto.ServerCutText:
+       String s = rfb.readServerCutText();
+       viewer.clipboard.setCutText(s);
+       break;
+
+      case RfbProto.EndOfContinuousUpdates:
+        if (rfb.continuousUpdatesAreActive()) {
+          rfb.endOfContinuousUpdates();
+
+          // Change pixel format if such change was pending. Note that we
+          // could not change pixel format while continuous updates were
+          // in effect.
+          boolean incremental = true;
+          if (viewer.options.eightBitColors != (bytesPixel == 1)) {
+            setPixelFormat();
+            incremental = false;
+          }
+          // From this point, we ask for updates explicitly.
+          rfb.writeFramebufferUpdateRequest(0, 0, rfb.framebufferWidth,
+                                            rfb.framebufferHeight,
+                                            incremental);
+        }
+        break;
+
+      default:
+       throw new Exception("Unknown RFB message type " + msgType);
+      }
+    }
+  }
+
+  //
+  // Handle a raw rectangle. The second form with paint==false is used
+  // by the Hextile decoder for raw-encoded tiles.
+  //
+
+  void handleRawRect(int x, int y, int w, int h) throws IOException, Exception {
+    handleRawRect(x, y, w, h, true);
+  }
+
+  void handleRawRect(int x, int y, int w, int h, boolean paint)
+    throws IOException , Exception{
+    rawDecoder.handleRect(x, y, w, h);
+    if (paint)
+      scheduleRepaint(x, y, w, h);
+  }
+
+  //
+  // Handle a CopyRect rectangle.
+  //
+
+  void handleCopyRect(int x, int y, int w, int h) throws IOException {
+    copyRectDecoder.handleRect(x, y, w, h);
+    scheduleRepaint(x, y, w, h);
+  }
+
+  //
+  // Handle an RRE-encoded rectangle.
+  //
+
+  void handleRRERect(int x, int y, int w, int h) throws IOException {
+    rreDecoder.handleRect(x, y, w, h);
+    scheduleRepaint(x, y, w, h);
+  }
+
+  //
+  // Handle a CoRRE-encoded rectangle.
+  //
+
+  void handleCoRRERect(int x, int y, int w, int h) throws IOException {
+    correDecoder.handleRect(x, y, w, h);
+    scheduleRepaint(x, y, w, h);
+  }
+
+  //
+  // Handle a Hextile-encoded rectangle.
+  //
+
+  void handleHextileRect(int x, int y, int w, int h) throws IOException,
+                                                            Exception {
+    hextileDecoder.handleRect(x, y, w, h);
+  }
+
+  //
+  // Handle a ZRLE-encoded rectangle.
+  //
+  // FIXME: Currently, session recording is not fully supported for ZRLE.
+  //
+
+  void handleZRLERect(int x, int y, int w, int h) throws Exception {
+    zrleDecoder.handleRect(x, y, w, h);
+    scheduleRepaint(x, y, w, h);
+  }
+
+  //
+  // Handle a Zlib-encoded rectangle.
+  //
+
+  void handleZlibRect(int x, int y, int w, int h) throws Exception {
+    zlibDecoder.handleRect(x, y, w, h);
+    scheduleRepaint(x, y, w, h);
+  }
+
+  //
+  // Handle a Tight-encoded rectangle.
+  //
+
+  void handleTightRect(int x, int y, int w, int h) throws Exception {
+    tightDecoder.handleRect(x, y, w, h);
+    scheduleRepaint(x, y, w, h);
+  }
+
+  //
+  // Tell JVM to repaint specified desktop area.
+  //
+
+  public void scheduleRepaint(int x, int y, int w, int h) {
+    // Request repaint, deferred if necessary.
+    if (rfb.framebufferWidth == scaledWidth) {
+      repaint(viewer.deferScreenUpdates, x, y, w, h);
+    } else {
+      int sx = x * scalingFactor / 100;
+      int sy = y * scalingFactor / 100;
+      int sw = ((x + w) * scalingFactor + 49) / 100 - sx + 1;
+      int sh = ((y + h) * scalingFactor + 49) / 100 - sy + 1;
+      repaint(viewer.deferScreenUpdates, sx, sy, sw, sh);
+    }
+  }
+
+  //
+  // Handle events.
+  //
+
+  public void keyPressed(KeyEvent evt) {
+    processLocalKeyEvent(evt);
+  }
+  public void keyReleased(KeyEvent evt) {
+    processLocalKeyEvent(evt);
+  }
+  public void keyTyped(KeyEvent evt) {
+    evt.consume();
+  }
+
+  public void mousePressed(MouseEvent evt) {
+    processLocalMouseEvent(evt, false);
+  }
+  public void mouseReleased(MouseEvent evt) {
+    processLocalMouseEvent(evt, false);
+  }
+  public void mouseMoved(MouseEvent evt) {
+    processLocalMouseEvent(evt, true);
+  }
+  public void mouseDragged(MouseEvent evt) {
+    processLocalMouseEvent(evt, true);
+  }
+
+  private synchronized void trySendPointerEvent() {
+    if ((needToSendMouseEvent) && (mouseEvent!=null)) {
+      sendMouseEvent(mouseEvent, false);
+      needToSendMouseEvent = false;
+      lastMouseEventSendTime = System.currentTimeMillis();
+    }
+  }
+
+  public void run() {
+    while (true) {
+      // Send mouse movement if we have it
+      trySendPointerEvent();
+      // Sleep for some time
+      try {
+        Thread.sleep(1000 / mouseMaxFreq);
+      } catch (InterruptedException ex) {
+      }
+    }
+  }
+
+  //
+  // Ignored events.
+  //
+
+  public void mouseClicked(MouseEvent evt) {}
+  public void mouseEntered(MouseEvent evt) {}
+  public void mouseExited(MouseEvent evt) {}
+
+  //
+  // Actual event processing.
+  //
+
+  private void processLocalKeyEvent(KeyEvent evt) {
+    if (viewer.rfb != null && rfb.inNormalProtocol) {
+      if (!inputEnabled) {
+       if ((evt.getKeyChar() == 'r' || evt.getKeyChar() == 'R') &&
+           evt.getID() == KeyEvent.KEY_PRESSED ) {
+         // Request screen update.
+         try {
+           rfb.writeFramebufferUpdateRequest(0, 0, rfb.framebufferWidth,
+                                             rfb.framebufferHeight, false);
+         } catch (IOException e) {
+           e.printStackTrace();
+         }
+       }
+      } else {
+       // Input enabled.
+       synchronized(rfb) {
+         try {
+           rfb.writeKeyEvent(evt);
+         } catch (Exception e) {
+           e.printStackTrace();
+         }
+         rfb.notify();
+       }
+      }
+    }
+    // Don't ever pass keyboard events to AWT for default processing.
+    // Otherwise, pressing Tab would switch focus to ButtonPanel etc.
+    evt.consume();
+  }
+
+  private void processLocalMouseEvent(MouseEvent evt, boolean moved) {
+    if (viewer.rfb != null && rfb.inNormalProtocol) {
+      if (!inSelectionMode) {
+        if (inputEnabled) {
+          // If mouse not moved, but it's click event then
+          // send it to server immideanlty.
+          // Else, it's mouse movement - we can send it in
+          // our thread later.
+          if (!moved) {
+            sendMouseEvent(evt, moved);
+          } else {
+            mouseEvent = evt;
+            needToSendMouseEvent = true;
+          }
+        }
+      } else {
+        handleSelectionMouseEvent(evt);
+      }
+    }
+  }
+
+  private void sendMouseEvent(MouseEvent evt, boolean moved) {
+    if (moved) {
+      softCursorMove(evt.getX(), evt.getY());
+    }
+    if (rfb.framebufferWidth != scaledWidth) {
+      int sx = (evt.getX() * 100 + scalingFactor/2) / scalingFactor;
+      int sy = (evt.getY() * 100 + scalingFactor/2) / scalingFactor;
+      evt.translatePoint(sx - evt.getX(), sy - evt.getY());
+    }
+    synchronized(rfb) {
+      try {
+        rfb.writePointerEvent(evt);
+      } catch (Exception e) {
+        e.printStackTrace();
+      }
+      rfb.notify();
+      lastMouseEventSendTime = System.currentTimeMillis();
+    }
+  }
+
+  //
+  // Reset update statistics.
+  //
+
+  void resetStats() {
+    statStartTime = System.currentTimeMillis();
+    statNumUpdates = 0;
+    statNumTotalRects = 0;
+    statNumPixelRects = 0;
+    statNumRectsTight = 0;
+    statNumRectsTightJPEG = 0;
+    statNumRectsZRLE = 0;
+    statNumRectsHextile = 0;
+    statNumRectsRaw = 0;
+    statNumRectsCopy = 0;
+    statNumBytesEncoded = 0;
+    statNumBytesDecoded = 0;
+    if (tightDecoder != null) {
+      tightDecoder.setNumJPEGRects(0);
+      tightDecoder.setNumTightRects(0);
+    }
+  }
+
+  //////////////////////////////////////////////////////////////////
+  //
+  // Handle cursor shape updates (XCursor and RichCursor encodings).
+  //
+
+  boolean showSoftCursor = false;
+
+  MemoryImageSource softCursorSource;
+  Image softCursor;
+  MouseEvent mouseEvent = null;
+  boolean needToSendMouseEvent = false;
+  int cursorX = 0, cursorY = 0;
+  int cursorWidth, cursorHeight;
+  int origCursorWidth, origCursorHeight;
+  int hotX, hotY;
+  int origHotX, origHotY;
+
+  //
+  // Handle cursor shape update (XCursor and RichCursor encodings).
+  //
+
+  synchronized void
+    handleCursorShapeUpdate(int encodingType,
+                           int xhot, int yhot, int width, int height)
+    throws IOException {
+
+    softCursorFree();
+
+    if (width * height == 0)
+      return;
+
+    // Ignore cursor shape data if requested by user.
+    if (viewer.options.ignoreCursorUpdates) {
+      int bytesPerRow = (width + 7) / 8;
+      int bytesMaskData = bytesPerRow * height;
+
+      if (encodingType == rfb.EncodingXCursor) {
+       rfb.skipBytes(6 + bytesMaskData * 2);
+      } else {
+       // rfb.EncodingRichCursor
+       rfb.skipBytes(width * height + bytesMaskData);
+      }
+      return;
+    }
+
+    // Decode cursor pixel data.
+    softCursorSource = decodeCursorShape(encodingType, width, height);
+
+    // Set original (non-scaled) cursor dimensions.
+    origCursorWidth = width;
+    origCursorHeight = height;
+    origHotX = xhot;
+    origHotY = yhot;
+
+    // Create off-screen cursor image.
+    createSoftCursor();
+
+    // Show the cursor.
+    showSoftCursor = true;
+    repaint(viewer.deferCursorUpdates,
+           cursorX - hotX, cursorY - hotY, cursorWidth, cursorHeight);
+  }
+
+  //
+  // decodeCursorShape(). Decode cursor pixel data and return
+  // corresponding MemoryImageSource instance.
+  //
+
+  synchronized MemoryImageSource
+    decodeCursorShape(int encodingType, int width, int height)
+    throws IOException {
+
+    int bytesPerRow = (width + 7) / 8;
+    int bytesMaskData = bytesPerRow * height;
+
+    int[] softCursorPixels = new int[width * height];
+
+    if (encodingType == rfb.EncodingXCursor) {
+
+      // Read foreground and background colors of the cursor.
+      byte[] rgb = new byte[6];
+      rfb.readFully(rgb);
+      int[] colors = { (0xFF000000 | (rgb[3] & 0xFF) << 16 |
+                       (rgb[4] & 0xFF) << 8 | (rgb[5] & 0xFF)),
+                      (0xFF000000 | (rgb[0] & 0xFF) << 16 |
+                       (rgb[1] & 0xFF) << 8 | (rgb[2] & 0xFF)) };
+
+      // Read pixel and mask data.
+      byte[] pixBuf = new byte[bytesMaskData];
+      rfb.readFully(pixBuf);
+      byte[] maskBuf = new byte[bytesMaskData];
+      rfb.readFully(maskBuf);
+
+      // Decode pixel data into softCursorPixels[].
+      byte pixByte, maskByte;
+      int x, y, n, result;
+      int i = 0;
+      for (y = 0; y < height; y++) {
+       for (x = 0; x < width / 8; x++) {
+         pixByte = pixBuf[y * bytesPerRow + x];
+         maskByte = maskBuf[y * bytesPerRow + x];
+         for (n = 7; n >= 0; n--) {
+           if ((maskByte >> n & 1) != 0) {
+             result = colors[pixByte >> n & 1];
+           } else {
+             result = 0;       // Transparent pixel
+           }
+           softCursorPixels[i++] = result;
+         }
+       }
+       for (n = 7; n >= 8 - width % 8; n--) {
+         if ((maskBuf[y * bytesPerRow + x] >> n & 1) != 0) {
+           result = colors[pixBuf[y * bytesPerRow + x] >> n & 1];
+         } else {
+           result = 0;         // Transparent pixel
+         }
+         softCursorPixels[i++] = result;
+       }
+      }
+
+    } else {
+      // encodingType == rfb.EncodingRichCursor
+
+      // Read pixel and mask data.
+      byte[] pixBuf = new byte[width * height * bytesPixel];
+      rfb.readFully(pixBuf);
+      byte[] maskBuf = new byte[bytesMaskData];
+      rfb.readFully(maskBuf);
+
+      // Decode pixel data into softCursorPixels[].
+      byte pixByte, maskByte;
+      int x, y, n, result;
+      int i = 0;
+      for (y = 0; y < height; y++) {
+       for (x = 0; x < width / 8; x++) {
+         maskByte = maskBuf[y * bytesPerRow + x];
+         for (n = 7; n >= 0; n--) {
+           if ((maskByte >> n & 1) != 0) {
+             if (bytesPixel == 1) {
+               result = cm8.getRGB(pixBuf[i]);
+             } else {
+               result = 0xFF000000 |
+                 (pixBuf[i * 4 + 2] & 0xFF) << 16 |
+                 (pixBuf[i * 4 + 1] & 0xFF) << 8 |
+                 (pixBuf[i * 4] & 0xFF);
+             }
+           } else {
+             result = 0;       // Transparent pixel
+           }
+           softCursorPixels[i++] = result;
+         }
+       }
+       for (n = 7; n >= 8 - width % 8; n--) {
+         if ((maskBuf[y * bytesPerRow + x] >> n & 1) != 0) {
+           if (bytesPixel == 1) {
+             result = cm8.getRGB(pixBuf[i]);
+           } else {
+             result = 0xFF000000 |
+               (pixBuf[i * 4 + 2] & 0xFF) << 16 |
+               (pixBuf[i * 4 + 1] & 0xFF) << 8 |
+               (pixBuf[i * 4] & 0xFF);
+           }
+         } else {
+           result = 0;         // Transparent pixel
+         }
+         softCursorPixels[i++] = result;
+       }
+      }
+
+    }
+
+    return new MemoryImageSource(width, height, softCursorPixels, 0, width);
+  }
+
+  //
+  // createSoftCursor(). Assign softCursor new Image (scaled if necessary).
+  // Uses softCursorSource as a source for new cursor image.
+  //
+
+  synchronized void
+    createSoftCursor() {
+
+    if (softCursorSource == null)
+      return;
+
+    int scaleCursor = viewer.options.scaleCursor;
+    if (scaleCursor == 0 || !inputEnabled)
+      scaleCursor = 100;
+
+    // Save original cursor coordinates.
+    int x = cursorX - hotX;
+    int y = cursorY - hotY;
+    int w = cursorWidth;
+    int h = cursorHeight;
+
+    cursorWidth = (origCursorWidth * scaleCursor + 50) / 100;
+    cursorHeight = (origCursorHeight * scaleCursor + 50) / 100;
+    hotX = (origHotX * scaleCursor + 50) / 100;
+    hotY = (origHotY * scaleCursor + 50) / 100;
+    softCursor = Toolkit.getDefaultToolkit().createImage(softCursorSource);
+
+    if (scaleCursor != 100) {
+      softCursor = softCursor.getScaledInstance(cursorWidth, cursorHeight,
+                                               Image.SCALE_SMOOTH);
+    }
+
+    if (showSoftCursor) {
+      // Compute screen area to update.
+      x = Math.min(x, cursorX - hotX);
+      y = Math.min(y, cursorY - hotY);
+      w = Math.max(w, cursorWidth);
+      h = Math.max(h, cursorHeight);
+
+      repaint(viewer.deferCursorUpdates, x, y, w, h);
+    }
+  }
+
+  //
+  // softCursorMove(). Moves soft cursor into a particular location.
+  //
+
+  synchronized void softCursorMove(int x, int y) {
+    int oldX = cursorX;
+    int oldY = cursorY;
+    cursorX = x;
+    cursorY = y;
+    if (showSoftCursor) {
+      repaint(viewer.deferCursorUpdates,
+             oldX - hotX, oldY - hotY, cursorWidth, cursorHeight);
+      repaint(viewer.deferCursorUpdates,
+             cursorX - hotX, cursorY - hotY, cursorWidth, cursorHeight);
+    }
+  }
+
+  //
+  // softCursorFree(). Remove soft cursor, dispose resources.
+  //
+
+  synchronized void softCursorFree() {
+    if (showSoftCursor) {
+      showSoftCursor = false;
+      softCursor = null;
+      softCursorSource = null;
+
+      repaint(viewer.deferCursorUpdates,
+             cursorX - hotX, cursorY - hotY, cursorWidth, cursorHeight);
+    }
+  }
+
+  //////////////////////////////////////////////////////////////////
+  //
+  // Support for selecting a rectangular video area.
+  //
+
+  /** This flag is false in normal operation, and true in the selection mode. */
+  private boolean inSelectionMode;
+
+  /** The point where the selection was started. */
+  private Point selectionStart;
+
+  /** The second point of the selection. */
+  private Point selectionEnd;
+
+  /**
+   * We change cursor when enabling the selection mode. In this variable, we
+   * save the original cursor so we can restore it on returning to the normal
+   * mode.
+   */
+  private Cursor savedCursor;
+
+  /**
+   * Initialize selection-related varibles.
+   */
+  private synchronized void resetSelection() {
+    inSelectionMode = false;
+    selectionStart = new Point(0, 0);
+    selectionEnd = new Point(0, 0);
+
+    savedCursor = getCursor();
+  }
+
+  /**
+   * Check current state of the selection mode.
+   * @return true in the selection mode, false otherwise.
+   */
+  public boolean isInSelectionMode() {
+    return inSelectionMode;
+  }
+
+  /**
+   * Get current selection.
+   * @param useScreenCoords use screen coordinates if true, or framebuffer
+   * coordinates if false. This makes difference when scaling factor is not 100.
+   * @return The selection as a {@link Rectangle}.
+   */
+  private synchronized Rectangle getSelection(boolean useScreenCoords) {
+    int x0 = selectionStart.x;
+    int x1 = selectionEnd.x;
+    int y0 = selectionStart.y;
+    int y1 = selectionEnd.y;
+    // Make x and y point to the upper left corner of the selection.
+    if (x1 < x0) {
+      int t = x0; x0 = x1; x1 = t;
+    }
+    if (y1 < y0) {
+      int t = y0; y0 = y1; y1 = t;
+    }
+    // Include the borders in the selection (unless it's empty).
+    if (x0 != x1 && y0 != y1) {
+      x1 += 1;
+      y1 += 1;
+    }
+    // Translate from screen coordinates to framebuffer coordinates.
+    if (rfb.framebufferWidth != scaledWidth) {
+      x0 = (x0 * 100 + scalingFactor/2) / scalingFactor;
+      y0 = (y0 * 100 + scalingFactor/2) / scalingFactor;
+      x1 = (x1 * 100 + scalingFactor/2) / scalingFactor;
+      y1 = (y1 * 100 + scalingFactor/2) / scalingFactor;
+    }
+    // Clip the selection to framebuffer.
+    if (x0 < 0)
+      x0 = 0;
+    if (y0 < 0)
+      y0 = 0;
+    if (x1 > rfb.framebufferWidth)
+      x1 = rfb.framebufferWidth;
+    if (y1 > rfb.framebufferHeight)
+      y1 = rfb.framebufferHeight;
+    // Make width a multiple of 16.
+    int widthBlocks = (x1 - x0 + 8) / 16;
+    if (selectionStart.x <= selectionEnd.x) {
+      x1 = x0 + widthBlocks * 16;
+      if (x1 > rfb.framebufferWidth) {
+        x1 -= 16;
+      }
+    } else {
+      x0 = x1 - widthBlocks * 16;
+      if (x0 < 0) {
+        x0 += 16;
+      }
+    }
+    // Make height a multiple of 8.
+    int heightBlocks = (y1 - y0 + 4) / 8;
+    if (selectionStart.y <= selectionEnd.y) {
+      y1 = y0 + heightBlocks * 8;
+      if (y1 > rfb.framebufferHeight) {
+        y1 -= 8;
+      }
+    } else {
+      y0 = y1 - heightBlocks * 8;
+      if (y0 < 0) {
+        y0 += 8;
+      }
+    }
+    // Translate the selection back to screen coordinates if requested.
+    if (useScreenCoords && rfb.framebufferWidth != scaledWidth) {
+      x0 = (x0 * scalingFactor + 50) / 100;
+      y0 = (y0 * scalingFactor + 50) / 100;
+      x1 = (x1 * scalingFactor + 50) / 100;
+      y1 = (y1 * scalingFactor + 50) / 100;
+    }
+    // Construct and return the result.
+    return new Rectangle(x0, y0, x1 - x0, y1 - y0);
+  }
+
+  /**
+   * Enable or disable the selection mode.
+   * @param enable enables the selection mode if true, disables if fasle.
+   */
+  public synchronized void enableSelection(boolean enable) {
+    if (enable && !inSelectionMode) {
+      // Enter the selection mode.
+      inSelectionMode = true;
+      savedCursor = getCursor();
+      setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
+      repaint();
+    } else if (!enable && inSelectionMode) {
+      // Leave the selection mode.
+      inSelectionMode = false;
+      setCursor(savedCursor);
+      repaint();
+    }
+  }
+
+  /**
+   * Process mouse events in the selection mode.
+   *
+   * @param evt mouse event that was originally passed to
+   *   {@link MouseListener} or {@link MouseMotionListener}.
+   */
+  private synchronized void handleSelectionMouseEvent(MouseEvent evt) {
+    int id = evt.getID();
+    boolean button1 = (evt.getModifiers() & InputEvent.BUTTON1_MASK) != 0;
+
+    if (id == MouseEvent.MOUSE_PRESSED && button1) {
+      selectionStart = selectionEnd = evt.getPoint();
+      repaint();
+    }
+    if (id == MouseEvent.MOUSE_DRAGGED && button1) {
+      selectionEnd = evt.getPoint();
+      repaint();
+    }
+    if (id == MouseEvent.MOUSE_RELEASED && button1) {
+      try {
+        rfb.trySendVideoSelection(getSelection(false));
+      } catch (IOException e) {
+        e.printStackTrace();
+      }
+    }
+  }
+}
diff --git a/java/src/com/tigervnc/vncviewer/VncCanvas2.java b/java/src/com/tigervnc/vncviewer/VncCanvas2.java
new file mode 100644 (file)
index 0000000..502d26f
--- /dev/null
@@ -0,0 +1,65 @@
+//
+//  Copyright (C) 2006 Constantin Kaplinsky.  All Rights Reserved.
+//
+//  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.
+//
+
+package com.tightvnc.vncviewer;
+
+import java.awt.*;
+import java.io.*;
+
+//
+// VncCanvas2 is a special version of VncCanvas which may use Java 2 API.
+//
+
+class VncCanvas2 extends VncCanvas {
+
+  public VncCanvas2(VncViewer v) throws IOException {
+    super(v);
+    disableFocusTraversalKeys();
+  }
+
+  public VncCanvas2(VncViewer v, int maxWidth_, int maxHeight_)
+    throws IOException {
+
+    super(v, maxWidth_, maxHeight_);
+    disableFocusTraversalKeys();
+  }
+
+  public void paintScaledFrameBuffer(Graphics g) {
+    Graphics2D g2d = (Graphics2D)g;
+    g2d.setRenderingHint(RenderingHints.KEY_RENDERING,
+                         RenderingHints.VALUE_RENDER_QUALITY);
+    g2d.drawImage(memImage, 0, 0, scaledWidth, scaledHeight, null);
+  }
+
+  //
+  // Try to disable focus traversal keys (JVMs 1.4 and higher).
+  //
+
+  private void disableFocusTraversalKeys() {
+    try {
+      Class[] argClasses = { Boolean.TYPE };
+      java.lang.reflect.Method method =
+        getClass().getMethod("setFocusTraversalKeysEnabled", argClasses);
+      Object[] argObjects = { new Boolean(false) };
+      method.invoke(this, argObjects);
+    } catch (Exception e) {}
+  }
+
+}
+
diff --git a/java/src/com/tigervnc/vncviewer/VncViewer.java b/java/src/com/tigervnc/vncviewer/VncViewer.java
new file mode 100644 (file)
index 0000000..bdaee68
--- /dev/null
@@ -0,0 +1,1049 @@
+//
+//  Copyright (C) 2001-2004 HorizonLive.com, Inc.  All Rights Reserved.
+//  Copyright (C) 2002 Constantin Kaplinsky.  All Rights Reserved.
+//  Copyright (C) 1999 AT&T Laboratories Cambridge.  All Rights Reserved.
+//
+//  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.
+//
+
+//
+// VncViewer.java - the VNC viewer applet.  This class mainly just sets up the
+// user interface, leaving it to the VncCanvas to do the actual rendering of
+// a VNC desktop.
+//
+
+package com.tightvnc.vncviewer;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import java.net.*;
+
+public class VncViewer extends java.applet.Applet
+  implements java.lang.Runnable, WindowListener, ComponentListener {
+
+  boolean inAnApplet = true;
+  boolean inSeparateFrame = false;
+
+  //
+  // main() is called when run as a java program from the command line.
+  // It simply runs the applet inside a newly-created frame.
+  //
+
+  public static void main(String[] argv) {
+    VncViewer v = new VncViewer();
+    v.mainArgs = argv;
+    v.inAnApplet = false;
+    v.inSeparateFrame = true;
+
+    v.init();
+    v.start();
+  }
+
+  String[] mainArgs;
+
+  RfbProto rfb;
+  Thread rfbThread;
+
+  Frame vncFrame;
+  Container vncContainer;
+  ScrollPane desktopScrollPane;
+  GridBagLayout gridbag;
+  ButtonPanel buttonPanel;
+  Label connStatusLabel;
+  VncCanvas vc;
+  OptionsFrame options;
+  ClipboardFrame clipboard;
+  RecordingFrame rec;
+
+  // Control session recording.
+  Object recordingSync;
+  String sessionFileName;
+  boolean recordingActive;
+  boolean recordingStatusChanged;
+  String cursorUpdatesDef;
+  String eightBitColorsDef;
+
+  // Variables read from parameter values.
+  String socketFactory;
+  String host;
+  int port;
+  String passwordParam;
+  boolean showControls;
+  boolean offerRelogin;
+  boolean showOfflineDesktop;
+  int deferScreenUpdates;
+  int deferCursorUpdates;
+  int deferUpdateRequests;
+  int debugStatsExcludeUpdates;
+  int debugStatsMeasureUpdates;
+
+  // Reference to this applet for inter-applet communication.
+  public static java.applet.Applet refApplet;
+
+  //
+  // init()
+  //
+
+  public void init() {
+
+    readParameters();
+
+    refApplet = this;
+
+    if (inSeparateFrame) {
+      vncFrame = new Frame("TigerVNC");
+      if (!inAnApplet) {
+       vncFrame.add("Center", this);
+      }
+      vncContainer = vncFrame;
+    } else {
+      vncContainer = this;
+    }
+
+    recordingSync = new Object();
+
+    options = new OptionsFrame(this);
+    clipboard = new ClipboardFrame(this);
+    if (RecordingFrame.checkSecurity())
+      rec = new RecordingFrame(this);
+
+    sessionFileName = null;
+    recordingActive = false;
+    recordingStatusChanged = false;
+    cursorUpdatesDef = null;
+    eightBitColorsDef = null;
+
+    if (inSeparateFrame) {
+      vncFrame.addWindowListener(this);
+      vncFrame.addComponentListener(this);
+    }
+
+    rfbThread = new Thread(this);
+    rfbThread.start();
+  }
+
+  public void update(Graphics g) {
+  }
+
+  //
+  // run() - executed by the rfbThread to deal with the RFB socket.
+  //
+
+  public void run() {
+
+    gridbag = new GridBagLayout();
+    vncContainer.setLayout(gridbag);
+
+    GridBagConstraints gbc = new GridBagConstraints();
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    gbc.anchor = GridBagConstraints.NORTHWEST;
+
+    if (showControls) {
+      buttonPanel = new ButtonPanel(this);
+      gridbag.setConstraints(buttonPanel, gbc);
+      vncContainer.add(buttonPanel);
+    }
+
+    try {
+      connectAndAuthenticate();
+      doProtocolInitialisation();
+
+      if (showControls &&
+          rfb.clientMsgCaps.isEnabled(RfbProto.VideoRectangleSelection)) {
+        buttonPanel.addSelectButton();
+      }
+
+      if (showControls &&
+          rfb.clientMsgCaps.isEnabled(RfbProto.VideoFreeze)) {
+        buttonPanel.addVideoFreezeButton();
+      }
+
+      // FIXME: Use auto-scaling not only in a separate frame.
+      if (options.autoScale && inSeparateFrame) {
+       Dimension screenSize;
+       try {
+         screenSize = vncContainer.getToolkit().getScreenSize();
+       } catch (Exception e) {
+         screenSize = new Dimension(0, 0);
+       }
+       createCanvas(screenSize.width - 32, screenSize.height - 32);
+      } else {
+       createCanvas(0, 0);
+      }
+
+      gbc.weightx = 1.0;
+      gbc.weighty = 1.0;
+
+      if (inSeparateFrame) {
+
+       // Create a panel which itself is resizeable and can hold
+       // non-resizeable VncCanvas component at the top left corner.
+       Panel canvasPanel = new Panel();
+       canvasPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
+       canvasPanel.add(vc);
+
+       // Create a ScrollPane which will hold a panel with VncCanvas
+       // inside.
+       desktopScrollPane = new ScrollPane(ScrollPane.SCROLLBARS_AS_NEEDED);
+       gbc.fill = GridBagConstraints.BOTH;
+       gridbag.setConstraints(desktopScrollPane, gbc);
+       desktopScrollPane.add(canvasPanel);
+        // If auto scale is not enabled we don't need to set first frame
+        // size to fullscreen
+        if (!options.autoScale) {
+          vc.isFirstSizeAutoUpdate = false;
+        }
+
+       // Finally, add our ScrollPane to the Frame window.
+       vncFrame.add(desktopScrollPane);
+       vncFrame.setTitle(rfb.desktopName);
+       vncFrame.pack();
+       vc.resizeDesktopFrame();
+
+      } else {
+       // Just add the VncCanvas component to the Applet.
+       gridbag.setConstraints(vc, gbc);
+       add(vc);
+       validate();
+      }
+
+      if (showControls) {
+        buttonPanel.enableButtons();
+      }
+
+      moveFocusToDesktop();
+      processNormalProtocol();
+
+    } catch (NoRouteToHostException e) {
+      fatalError("Network error: no route to server: " + host, e);
+    } catch (UnknownHostException e) {
+      fatalError("Network error: server name unknown: " + host, e);
+    } catch (ConnectException e) {
+      fatalError("Network error: could not connect to server: " +
+                host + ":" + port, e);
+    } catch (EOFException e) {
+      if (showOfflineDesktop) {
+       e.printStackTrace();
+       System.out.println("Network error: remote side closed connection");
+       if (vc != null) {
+         vc.enableInput(false);
+       }
+       if (inSeparateFrame) {
+         vncFrame.setTitle(rfb.desktopName + " [disconnected]");
+       }
+       if (rfb != null && !rfb.closed())
+         rfb.close();
+       if (showControls && buttonPanel != null) {
+         buttonPanel.disableButtonsOnDisconnect();
+         if (inSeparateFrame) {
+           vncFrame.pack();
+         } else {
+           validate();
+         }
+       }
+      } else {
+       fatalError("Network error: remote side closed connection", e);
+      }
+    } catch (IOException e) {
+      String str = e.getMessage();
+      if (str != null && str.length() != 0) {
+       fatalError("Network Error: " + str, e);
+      } else {
+       fatalError(e.toString(), e);
+      }
+    } catch (Exception e) {
+      String str = e.getMessage();
+      if (str != null && str.length() != 0) {
+       fatalError("Error: " + str, e);
+      } else {
+       fatalError(e.toString(), e);
+      }
+    }
+    
+  }
+
+  //
+  // Create a VncCanvas instance.
+  //
+
+  void createCanvas(int maxWidth, int maxHeight) throws IOException {
+    // Determine if Java 2D API is available and use a special
+    // version of VncCanvas if it is present.
+    vc = null;
+    try {
+      // This throws ClassNotFoundException if there is no Java 2D API.
+      Class cl = Class.forName("java.awt.Graphics2D");
+      // If we could load Graphics2D class, then we can use VncCanvas2D.
+      cl = Class.forName("com.tightvnc.vncviewer.VncCanvas2");
+      Class[] argClasses = { this.getClass(), Integer.TYPE, Integer.TYPE };
+      java.lang.reflect.Constructor cstr = cl.getConstructor(argClasses);
+      Object[] argObjects =
+        { this, new Integer(maxWidth), new Integer(maxHeight) };
+      vc = (VncCanvas)cstr.newInstance(argObjects);
+    } catch (Exception e) {
+      System.out.println("Warning: Java 2D API is not available");
+    }
+
+    // If we failed to create VncCanvas2D, use old VncCanvas.
+    if (vc == null)
+      vc = new VncCanvas(this, maxWidth, maxHeight);
+  }
+
+
+  //
+  // Process RFB socket messages.
+  // If the rfbThread is being stopped, ignore any exceptions,
+  // otherwise rethrow the exception so it can be handled.
+  //
+  void processNormalProtocol() throws Exception {
+    try {
+      vc.processNormalProtocol();
+    } catch (Exception e) {
+      if (rfbThread == null) {
+       System.out.println("Ignoring RFB socket exceptions" +
+                          " because applet is stopping");
+      } else {
+       throw e;
+      }
+    }
+  }
+
+
+  //
+  // Connect to the RFB server and authenticate the user.
+  //
+
+  void connectAndAuthenticate() throws Exception
+  {
+    showConnectionStatus("Initializing...");
+    if (inSeparateFrame) {
+      vncFrame.pack();
+      vncFrame.show();
+    } else {
+      validate();
+    }
+
+    showConnectionStatus("Connecting to " + host + ", port " + port + "...");
+
+    rfb = new RfbProto(host, port, this);
+    showConnectionStatus("Connected to server");
+
+    rfb.readVersionMsg();
+    showConnectionStatus("RFB server supports protocol version " +
+                        rfb.serverMajor + "." + rfb.serverMinor);
+
+    rfb.writeVersionMsg();
+    showConnectionStatus("Using RFB protocol version " +
+                        rfb.clientMajor + "." + rfb.clientMinor);
+
+    int secType = rfb.negotiateSecurity();
+    int authType;
+    if (secType == RfbProto.SecTypeTight) {
+      showConnectionStatus("Enabling TightVNC protocol extensions");
+      rfb.setupTunneling();
+      authType = rfb.negotiateAuthenticationTight();
+    } else {
+      authType = secType;
+    }
+
+    switch (authType) {
+    case RfbProto.AuthNone:
+      showConnectionStatus("No authentication needed");
+      rfb.authenticateNone();
+      break;
+    case RfbProto.AuthVNC:
+      showConnectionStatus("Performing standard VNC authentication");
+      if (passwordParam != null) {
+        rfb.authenticateVNC(passwordParam);
+      } else {
+        String pw = askPassword();
+        rfb.authenticateVNC(pw);
+      }
+      break;
+    default:
+      throw new Exception("Unknown authentication scheme " + authType);
+    }
+  }
+
+
+  //
+  // Show a message describing the connection status.
+  // To hide the connection status label, use (msg == null).
+  //
+
+  void showConnectionStatus(String msg)
+  {
+    if (msg == null) {
+      if (vncContainer.isAncestorOf(connStatusLabel)) {
+       vncContainer.remove(connStatusLabel);
+      }
+      return;
+    }
+
+    System.out.println(msg);
+
+    if (connStatusLabel == null) {
+      connStatusLabel = new Label("Status: " + msg);
+      connStatusLabel.setFont(new Font("Helvetica", Font.PLAIN, 12));
+    } else {
+      connStatusLabel.setText("Status: " + msg);
+    }
+
+    if (!vncContainer.isAncestorOf(connStatusLabel)) {
+      GridBagConstraints gbc = new GridBagConstraints();
+      gbc.gridwidth = GridBagConstraints.REMAINDER;
+      gbc.fill = GridBagConstraints.HORIZONTAL;
+      gbc.anchor = GridBagConstraints.NORTHWEST;
+      gbc.weightx = 1.0;
+      gbc.weighty = 1.0;
+      gbc.insets = new Insets(20, 30, 20, 30);
+      gridbag.setConstraints(connStatusLabel, gbc);
+      vncContainer.add(connStatusLabel);
+    }
+
+    if (inSeparateFrame) {
+      vncFrame.pack();
+    } else {
+      validate();
+    }
+  }
+
+
+  //
+  // Show an authentication panel.
+  //
+
+  String askPassword() throws Exception
+  {
+    showConnectionStatus(null);
+
+    AuthPanel authPanel = new AuthPanel(this);
+
+    GridBagConstraints gbc = new GridBagConstraints();
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    gbc.anchor = GridBagConstraints.NORTHWEST;
+    gbc.weightx = 1.0;
+    gbc.weighty = 1.0;
+    gbc.ipadx = 100;
+    gbc.ipady = 50;
+    gridbag.setConstraints(authPanel, gbc);
+    vncContainer.add(authPanel);
+
+    if (inSeparateFrame) {
+      vncFrame.pack();
+    } else {
+      validate();
+    }
+
+    authPanel.moveFocusToDefaultField();
+    String pw = authPanel.getPassword();
+    vncContainer.remove(authPanel);
+
+    return pw;
+  }
+
+
+  //
+  // Do the rest of the protocol initialisation.
+  //
+
+  void doProtocolInitialisation() throws IOException
+  {
+    rfb.writeClientInit();
+    rfb.readServerInit();
+
+    System.out.println("Desktop name is " + rfb.desktopName);
+    System.out.println("Desktop size is " + rfb.framebufferWidth + " x " +
+                      rfb.framebufferHeight);
+
+    setEncodings();
+
+    showConnectionStatus(null);
+  }
+
+
+  //
+  // Send current encoding list to the RFB server.
+  //
+
+  int[] encodingsSaved;
+  int nEncodingsSaved;
+
+  void setEncodings()        { setEncodings(false); }
+  void autoSelectEncodings() { setEncodings(true); }
+
+  void setEncodings(boolean autoSelectOnly) {
+    if (options == null || rfb == null || !rfb.inNormalProtocol)
+      return;
+
+    int preferredEncoding = options.preferredEncoding;
+    if (preferredEncoding == -1) {
+      long kbitsPerSecond = rfb.kbitsPerSecond();
+      if (nEncodingsSaved < 1) {
+        // Choose Tight or ZRLE encoding for the very first update.
+        System.out.println("Using Tight/ZRLE encodings");
+        preferredEncoding = RfbProto.EncodingTight;
+      } else if (kbitsPerSecond > 2000 &&
+                 encodingsSaved[0] != RfbProto.EncodingHextile) {
+        // Switch to Hextile if the connection speed is above 2Mbps.
+        System.out.println("Throughput " + kbitsPerSecond +
+                           " kbit/s - changing to Hextile encoding");
+        preferredEncoding = RfbProto.EncodingHextile;
+      } else if (kbitsPerSecond < 1000 &&
+                 encodingsSaved[0] != RfbProto.EncodingTight) {
+        // Switch to Tight/ZRLE if the connection speed is below 1Mbps.
+        System.out.println("Throughput " + kbitsPerSecond +
+                           " kbit/s - changing to Tight/ZRLE encodings");
+        preferredEncoding = RfbProto.EncodingTight;
+      } else {
+        // Don't change the encoder.
+        if (autoSelectOnly)
+          return;
+        preferredEncoding = encodingsSaved[0];
+      }
+    } else {
+      // Auto encoder selection is not enabled.
+      if (autoSelectOnly)
+        return;
+    }
+
+    int[] encodings = new int[20];
+    int nEncodings = 0;
+
+    encodings[nEncodings++] = preferredEncoding;
+    if (options.useCopyRect) {
+      encodings[nEncodings++] = RfbProto.EncodingCopyRect;
+    }
+
+    if (preferredEncoding != RfbProto.EncodingTight) {
+      encodings[nEncodings++] = RfbProto.EncodingTight;
+    }
+    if (preferredEncoding != RfbProto.EncodingZRLE) {
+      encodings[nEncodings++] = RfbProto.EncodingZRLE;
+    }
+    if (preferredEncoding != RfbProto.EncodingHextile) {
+      encodings[nEncodings++] = RfbProto.EncodingHextile;
+    }
+    if (preferredEncoding != RfbProto.EncodingZlib) {
+      encodings[nEncodings++] = RfbProto.EncodingZlib;
+    }
+    if (preferredEncoding != RfbProto.EncodingCoRRE) {
+      encodings[nEncodings++] = RfbProto.EncodingCoRRE;
+    }
+    if (preferredEncoding != RfbProto.EncodingRRE) {
+      encodings[nEncodings++] = RfbProto.EncodingRRE;
+    }
+
+    if (options.compressLevel >= 0 && options.compressLevel <= 9) {
+      encodings[nEncodings++] =
+        RfbProto.EncodingCompressLevel0 + options.compressLevel;
+    }
+    if (options.jpegQuality >= 0 && options.jpegQuality <= 9) {
+      encodings[nEncodings++] =
+        RfbProto.EncodingQualityLevel0 + options.jpegQuality;
+    }
+
+    if (options.requestCursorUpdates) {
+      encodings[nEncodings++] = RfbProto.EncodingXCursor;
+      encodings[nEncodings++] = RfbProto.EncodingRichCursor;
+      if (!options.ignoreCursorUpdates)
+       encodings[nEncodings++] = RfbProto.EncodingPointerPos;
+    }
+
+    encodings[nEncodings++] = RfbProto.EncodingLastRect;
+    encodings[nEncodings++] = RfbProto.EncodingNewFBSize;
+
+    boolean encodingsWereChanged = false;
+    if (nEncodings != nEncodingsSaved) {
+      encodingsWereChanged = true;
+    } else {
+      for (int i = 0; i < nEncodings; i++) {
+        if (encodings[i] != encodingsSaved[i]) {
+          encodingsWereChanged = true;
+          break;
+        }
+      }
+    }
+
+    if (encodingsWereChanged) {
+      try {
+        rfb.writeSetEncodings(encodings, nEncodings);
+        if (vc != null) {
+          vc.softCursorFree();
+        }
+      } catch (Exception e) {
+        e.printStackTrace();
+      }
+      encodingsSaved = encodings;
+      nEncodingsSaved = nEncodings;
+    }
+  }
+
+
+  //
+  // setCutText() - send the given cut text to the RFB server.
+  //
+
+  void setCutText(String text) {
+    try {
+      if (rfb != null && rfb.inNormalProtocol) {
+       rfb.writeClientCutText(text);
+      }
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+  }
+
+
+  //
+  // Order change in session recording status. To stop recording, pass
+  // null in place of the fname argument.
+  //
+
+  void setRecordingStatus(String fname) {
+    synchronized(recordingSync) {
+      sessionFileName = fname;
+      recordingStatusChanged = true;
+    }
+  }
+
+  //
+  // Start or stop session recording. Returns true if this method call
+  // causes recording of a new session.
+  //
+
+  boolean checkRecordingStatus() throws IOException {
+    synchronized(recordingSync) {
+      if (recordingStatusChanged) {
+       recordingStatusChanged = false;
+       if (sessionFileName != null) {
+         startRecording();
+         return true;
+       } else {
+         stopRecording();
+       }
+      }
+    }
+    return false;
+  }
+
+  //
+  // Start session recording.
+  //
+
+  protected void startRecording() throws IOException {
+    synchronized(recordingSync) {
+      if (!recordingActive) {
+       // Save settings to restore them after recording the session.
+       cursorUpdatesDef =
+         options.choices[options.cursorUpdatesIndex].getSelectedItem();
+       eightBitColorsDef =
+         options.choices[options.eightBitColorsIndex].getSelectedItem();
+       // Set options to values suitable for recording.
+       options.choices[options.cursorUpdatesIndex].select("Disable");
+       options.choices[options.cursorUpdatesIndex].setEnabled(false);
+       options.setEncodings();
+       options.choices[options.eightBitColorsIndex].select("No");
+       options.choices[options.eightBitColorsIndex].setEnabled(false);
+       options.setColorFormat();
+      } else {
+       rfb.closeSession();
+      }
+
+      System.out.println("Recording the session in " + sessionFileName);
+      rfb.startSession(sessionFileName);
+      recordingActive = true;
+    }
+  }
+
+  //
+  // Stop session recording.
+  //
+
+  protected void stopRecording() throws IOException {
+    synchronized(recordingSync) {
+      if (recordingActive) {
+       // Restore options.
+       options.choices[options.cursorUpdatesIndex].select(cursorUpdatesDef);
+       options.choices[options.cursorUpdatesIndex].setEnabled(true);
+       options.setEncodings();
+       options.choices[options.eightBitColorsIndex].select(eightBitColorsDef);
+       options.choices[options.eightBitColorsIndex].setEnabled(true);
+       options.setColorFormat();
+
+       rfb.closeSession();
+       System.out.println("Session recording stopped.");
+      }
+      sessionFileName = null;
+      recordingActive = false;
+    }
+  }
+
+
+  //
+  // readParameters() - read parameters from the html source or from the
+  // command line.  On the command line, the arguments are just a sequence of
+  // param_name/param_value pairs where the names and values correspond to
+  // those expected in the html applet tag source.
+  //
+
+  void readParameters() {
+    host = readParameter("HOST", !inAnApplet);
+    if (host == null) {
+      host = getCodeBase().getHost();
+      if (host.equals("")) {
+       fatalError("HOST parameter not specified");
+      }
+    }
+
+    port = readIntParameter("PORT", 5900);
+
+    // Read "ENCPASSWORD" or "PASSWORD" parameter if specified.
+    readPasswordParameters();
+
+    String str;
+    if (inAnApplet) {
+      str = readParameter("Open New Window", false);
+      if (str != null && str.equalsIgnoreCase("Yes"))
+       inSeparateFrame = true;
+    }
+
+    // "Show Controls" set to "No" disables button panel.
+    showControls = true;
+    str = readParameter("Show Controls", false);
+    if (str != null && str.equalsIgnoreCase("No"))
+      showControls = false;
+
+    // "Offer Relogin" set to "No" disables "Login again" and "Close
+    // window" buttons under error messages in applet mode.
+    offerRelogin = true;
+    str = readParameter("Offer Relogin", false);
+    if (str != null && str.equalsIgnoreCase("No"))
+      offerRelogin = false;
+
+    // Do we continue showing desktop on remote disconnect?
+    showOfflineDesktop = false;
+    str = readParameter("Show Offline Desktop", false);
+    if (str != null && str.equalsIgnoreCase("Yes"))
+      showOfflineDesktop = true;
+
+    // Fine tuning options.
+    deferScreenUpdates = readIntParameter("Defer screen updates", 20);
+    deferCursorUpdates = readIntParameter("Defer cursor updates", 10);
+    deferUpdateRequests = readIntParameter("Defer update requests", 0);
+
+    // Debugging options.
+    debugStatsExcludeUpdates = readIntParameter("DEBUG_XU", 0);
+    debugStatsMeasureUpdates = readIntParameter("DEBUG_CU", 0);
+
+    // SocketFactory.
+    socketFactory = readParameter("SocketFactory", false);
+  }
+
+  //
+  // Read password parameters. If an "ENCPASSWORD" parameter is set,
+  // then decrypt the password into the passwordParam string. Otherwise,
+  // try to read the "PASSWORD" parameter directly to passwordParam.
+  //
+
+  private void readPasswordParameters() {
+    String encPasswordParam = readParameter("ENCPASSWORD", false);
+    if (encPasswordParam == null) {
+      passwordParam = readParameter("PASSWORD", false);
+    } else {
+      // ENCPASSWORD is hexascii-encoded. Decode.
+      byte[] pw = {0, 0, 0, 0, 0, 0, 0, 0};
+      int len = encPasswordParam.length() / 2;
+      if (len > 8)
+        len = 8;
+      for (int i = 0; i < len; i++) {
+        String hex = encPasswordParam.substring(i*2, i*2+2);
+        Integer x = new Integer(Integer.parseInt(hex, 16));
+        pw[i] = x.byteValue();
+      }
+      // Decrypt the password.
+      byte[] key = {23, 82, 107, 6, 35, 78, 88, 7};
+      DesCipher des = new DesCipher(key);
+      des.decrypt(pw, 0, pw, 0);
+      passwordParam = new String(pw);
+    }
+  }
+
+  public String readParameter(String name, boolean required) {
+    if (inAnApplet) {
+      String s = getParameter(name);
+      if ((s == null) && required) {
+       fatalError(name + " parameter not specified");
+      }
+      return s;
+    }
+
+    for (int i = 0; i < mainArgs.length; i += 2) {
+      if (mainArgs[i].equalsIgnoreCase(name)) {
+       try {
+         return mainArgs[i+1];
+       } catch (Exception e) {
+         if (required) {
+           fatalError(name + " parameter not specified");
+         }
+         return null;
+       }
+      }
+    }
+    if (required) {
+      fatalError(name + " parameter not specified");
+    }
+    return null;
+  }
+
+  int readIntParameter(String name, int defaultValue) {
+    String str = readParameter(name, false);
+    int result = defaultValue;
+    if (str != null) {
+      try {
+       result = Integer.parseInt(str);
+      } catch (NumberFormatException e) { }
+    }
+    return result;
+  }
+
+  //
+  // moveFocusToDesktop() - move keyboard focus either to VncCanvas.
+  //
+
+  void moveFocusToDesktop() {
+    if (vncContainer != null) {
+      if (vc != null && vncContainer.isAncestorOf(vc))
+       vc.requestFocus();
+    }
+  }
+
+  //
+  // disconnect() - close connection to server.
+  //
+
+  synchronized public void disconnect() {
+    System.out.println("Disconnecting");
+
+    if (vc != null) {
+      double sec = (System.currentTimeMillis() - vc.statStartTime) / 1000.0;
+      double rate = Math.round(vc.statNumUpdates / sec * 100) / 100.0;
+      long nRealRects = vc.statNumPixelRects;
+      long nPseudoRects = vc.statNumTotalRects - vc.statNumPixelRects;
+      System.out.println("Updates received: " + vc.statNumUpdates + " (" +
+                         nRealRects + " rectangles + " + nPseudoRects +
+                         " pseudo), " + rate + " updates/sec");
+      long numRectsOther = nRealRects - vc.statNumRectsTight
+        - vc.statNumRectsZRLE - vc.statNumRectsHextile
+        - vc.statNumRectsRaw - vc.statNumRectsCopy;
+      System.out.println("Rectangles:" +
+                         " Tight=" + vc.statNumRectsTight +
+                         "(JPEG=" + vc.statNumRectsTightJPEG +
+                         ") ZRLE=" + vc.statNumRectsZRLE +
+                         " Hextile=" + vc.statNumRectsHextile +
+                         " Raw=" + vc.statNumRectsRaw +
+                         " CopyRect=" + vc.statNumRectsCopy +
+                         " other=" + numRectsOther);
+
+      long raw = vc.statNumBytesDecoded;
+      long compressed = vc.statNumBytesEncoded;
+      if (compressed > 0) {
+          double ratio = Math.round((double)raw / compressed * 1000) / 1000.0;
+          System.out.println("Pixel data: " + vc.statNumBytesDecoded +
+                             " bytes, " + vc.statNumBytesEncoded +
+                             " compressed, ratio " + ratio);
+      }
+    }
+
+    if (rfb != null && !rfb.closed())
+      rfb.close();
+    options.dispose();
+    clipboard.dispose();
+    if (rec != null)
+      rec.dispose();
+
+    if (inAnApplet) {
+      showMessage("Disconnected");
+    } else {
+      System.exit(0);
+    }
+  }
+
+  //
+  // fatalError() - print out a fatal error message.
+  // FIXME: Do we really need two versions of the fatalError() method?
+  //
+
+  synchronized public void fatalError(String str) {
+    System.out.println(str);
+
+    if (inAnApplet) {
+      // vncContainer null, applet not inited,
+      // can not present the error to the user.
+      Thread.currentThread().stop();
+    } else {
+      System.exit(1);
+    }
+  }
+
+  synchronized public void fatalError(String str, Exception e) {
+    if (rfb != null && rfb.closed()) {
+      // Not necessary to show error message if the error was caused
+      // by I/O problems after the rfb.close() method call.
+      System.out.println("RFB thread finished");
+      return;
+    }
+
+    System.out.println(str);
+    e.printStackTrace();
+
+    if (rfb != null)
+      rfb.close();
+
+    if (inAnApplet) {
+      showMessage(str);
+    } else {
+      System.exit(1);
+    }
+  }
+
+  //
+  // Show message text and optionally "Relogin" and "Close" buttons.
+  //
+
+  void showMessage(String msg) {
+    vncContainer.removeAll();
+
+    Label errLabel = new Label(msg, Label.CENTER);
+    errLabel.setFont(new Font("Helvetica", Font.PLAIN, 12));
+
+    if (offerRelogin) {
+
+      Panel gridPanel = new Panel(new GridLayout(0, 1));
+      Panel outerPanel = new Panel(new FlowLayout(FlowLayout.LEFT));
+      outerPanel.add(gridPanel);
+      vncContainer.setLayout(new FlowLayout(FlowLayout.LEFT, 30, 16));
+      vncContainer.add(outerPanel);
+      Panel textPanel = new Panel(new FlowLayout(FlowLayout.CENTER));
+      textPanel.add(errLabel);
+      gridPanel.add(textPanel);
+      gridPanel.add(new ReloginPanel(this));
+
+    } else {
+
+      vncContainer.setLayout(new FlowLayout(FlowLayout.LEFT, 30, 30));
+      vncContainer.add(errLabel);
+
+    }
+
+    if (inSeparateFrame) {
+      vncFrame.pack();
+    } else {
+      validate();
+    }
+  }
+
+  //
+  // Stop the applet.
+  // Main applet thread will terminate on first exception
+  // after seeing that rfbThread has been set to null.
+  //
+
+  public void stop() {
+    System.out.println("Stopping applet");
+    rfbThread = null;
+  }
+
+  //
+  // This method is called before the applet is destroyed.
+  //
+
+  public void destroy() {
+    System.out.println("Destroying applet");
+
+    vncContainer.removeAll();
+    options.dispose();
+    clipboard.dispose();
+    if (rec != null)
+      rec.dispose();
+    if (rfb != null && !rfb.closed())
+      rfb.close();
+    if (inSeparateFrame)
+      vncFrame.dispose();
+  }
+
+  //
+  // Start/stop receiving mouse events.
+  //
+
+  public void enableInput(boolean enable) {
+    vc.enableInput(enable);
+  }
+  
+  //
+  // Resize framebuffer if autoScale is enabled.
+  //
+  
+  public void componentResized(ComponentEvent e) {
+    if (e.getComponent() == vncFrame) {
+      if (options.autoScale) {
+        if (vc != null) {
+          if (!vc.isFirstSizeAutoUpdate) {
+            vc.updateFramebufferSize();
+          }
+        }
+      }
+    }
+  }
+  
+  //
+  // Ignore component events we're not interested in.
+  //
+  
+  public void componentShown(ComponentEvent e) { }
+  public void componentMoved(ComponentEvent e) { }
+  public void componentHidden(ComponentEvent e) { }
+
+  //
+  // Close application properly on window close event.
+  //
+
+  public void windowClosing(WindowEvent evt) {
+    System.out.println("Closing window");
+    if (rfb != null)
+      disconnect();
+
+    vncContainer.hide();
+
+    if (!inAnApplet) {
+      System.exit(0);
+    }
+  }
+
+  //
+  // Ignore window events we're not interested in.
+  //
+
+  public void windowActivated(WindowEvent evt) {}
+  public void windowDeactivated (WindowEvent evt) {}
+  public void windowOpened(WindowEvent evt) {}
+  public void windowClosed(WindowEvent evt) {}
+  public void windowIconified(WindowEvent evt) {}
+  public void windowDeiconified(WindowEvent evt) {}
+}
diff --git a/java/src/com/tigervnc/vncviewer/ZlibInStream.java b/java/src/com/tigervnc/vncviewer/ZlibInStream.java
new file mode 100644 (file)
index 0000000..636fb54
--- /dev/null
@@ -0,0 +1,113 @@
+/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
+ * 
+ * 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.
+ */
+
+//
+// A ZlibInStream reads from a zlib.io.InputStream
+//
+
+package com.tightvnc.vncviewer;
+
+public class ZlibInStream extends InStream {
+
+  static final int defaultBufSize = 16384;
+
+  public ZlibInStream(int bufSize_) {
+    bufSize = bufSize_;
+    b = new byte[bufSize];
+    ptr = end = ptrOffset = 0;
+    inflater = new java.util.zip.Inflater();
+  }
+
+  public ZlibInStream() { this(defaultBufSize); }
+
+  public void setUnderlying(InStream is, int bytesIn_) {
+    underlying = is;
+    bytesIn = bytesIn_;
+    ptr = end = 0;
+  }
+
+  public void reset() throws Exception {
+    ptr = end = 0;
+    if (underlying == null) return;
+
+    while (bytesIn > 0) {
+      decompress();
+      end = 0; // throw away any data
+    }
+    underlying = null;
+  }
+
+  public int pos() { return ptrOffset + ptr; }
+
+  protected int overrun(int itemSize, int nItems) throws Exception {
+    if (itemSize > bufSize)
+      throw new Exception("ZlibInStream overrun: max itemSize exceeded");
+    if (underlying == null)
+      throw new Exception("ZlibInStream overrun: no underlying stream");
+
+    if (end - ptr != 0)
+      System.arraycopy(b, ptr, b, 0, end - ptr);
+
+    ptrOffset += ptr;
+    end -= ptr;
+    ptr = 0;
+
+    while (end < itemSize) {
+      decompress();
+    }
+
+    if (itemSize * nItems > end)
+      nItems = end / itemSize;
+
+    return nItems;
+  }
+
+  // decompress() calls the decompressor once.  Note that this won't
+  // necessarily generate any output data - it may just consume some input
+  // data.  Returns false if wait is false and we would block on the underlying
+  // stream.
+
+  private void decompress() throws Exception {
+    try {
+      underlying.check(1);
+      int avail_in = underlying.getend() - underlying.getptr();
+      if (avail_in > bytesIn)
+        avail_in = bytesIn;
+
+      if (inflater.needsInput()) {
+        inflater.setInput(underlying.getbuf(), underlying.getptr(), avail_in);
+      }
+
+      int n = inflater.inflate(b, end, bufSize - end); 
+
+      end += n;
+      if (inflater.needsInput()) {
+        bytesIn -= avail_in;
+        underlying.setptr(underlying.getptr() + avail_in);
+      }
+    } catch (java.util.zip.DataFormatException e) {
+      throw new Exception("ZlibInStream: inflate failed");
+    }
+  }
+
+  private InStream underlying;
+  private int bufSize;
+  private int ptrOffset;
+  private java.util.zip.Inflater inflater;
+  private int bytesIn;
+}
diff --git a/java/src/com/tigervnc/vncviewer/index.html b/java/src/com/tigervnc/vncviewer/index.html
new file mode 100644 (file)
index 0000000..96805dc
--- /dev/null
@@ -0,0 +1,29 @@
+<!-- 
+     index.html - an example HTML page for TigerVNC Java viewer applet, to be
+     used with a standalone Web server running on the same machine where the
+     TigerVNC server is running. Before using this example, please MAKE SURE
+     to check the following:
+
+     * the value of the PORT parameter should be set correctly (normally, the
+       port number is 5900 + display number);
+
+     * the CODE and ARCHIVE attributes of the <APPLET> tag should point to
+       the correct directory (this example assumes that this page is in the
+       same directory with .jar and .class files);
+
+     * the WIDTH and HEIGHT attributes of the <APPLET> tag correspond to the
+       actual desktop size on the server (height should be increased to leave
+       enough space for the button panel).
+-->
+
+<HTML>
+<TITLE>
+TigerVNC desktop
+</TITLE>
+<APPLET CODE="VncViewer.class" ARCHIVE="VncViewer.jar"
+        WIDTH="800" HEIGHT="632">
+<PARAM NAME="PORT" VALUE="5901">
+</APPLET>
+<BR>
+<A href="http://www.tigervnc.org/">TigerVNC site</A>
+</HTML>
diff --git a/java/src/com/tigervnc/vncviewer/index.vnc b/java/src/com/tigervnc/vncviewer/index.vnc
new file mode 100644 (file)
index 0000000..f24df7c
--- /dev/null
@@ -0,0 +1,25 @@
+<!-- 
+     index.vnc - default HTML page for TigerVNC Java viewer applet, to be
+     used with Xvnc. On any file ending in .vnc, the HTTP server embedded in
+     Xvnc will substitute the following variables when preceded by a dollar:
+     USER, DESKTOP, DISPLAY, APPLETWIDTH, APPLETHEIGHT, WIDTH, HEIGHT, PORT,
+     PARAMS. Use two dollar signs ($$) to get a dollar sign in the generated
+     HTML page.
+
+     NOTE: the $PARAMS variable is not supported by the standard VNC, so
+     make sure you have TigerVNC on the server side, if you're using this
+     variable.
+-->
+
+<HTML>
+<TITLE>
+$USER's $DESKTOP desktop ($DISPLAY)
+</TITLE>
+<APPLET CODE=VncViewer.class ARCHIVE=VncViewer.jar
+        WIDTH=$APPLETWIDTH HEIGHT=$APPLETHEIGHT>
+<param name=PORT value=$PORT>
+$PARAMS
+</APPLET>
+<BR>
+<A href="http://www.tigervnc.org/">TigerVNC site</A>
+</HTML>
diff --git a/java/src/com/tightvnc/decoder/CoRREDecoder.java b/java/src/com/tightvnc/decoder/CoRREDecoder.java
deleted file mode 100644 (file)
index bc08668..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-package com.tightvnc.decoder;
-
-import com.tightvnc.vncviewer.RfbInputStream;
-import java.awt.Graphics;
-import java.awt.Color;
-import java.io.IOException;
-
-//
-// Class that used for decoding CoRRE encoded data.
-//
-
-public class CoRREDecoder extends RawDecoder {
-
-  final static int EncodingCoRRE = 4;
-
-  public CoRREDecoder(Graphics g, RfbInputStream is) {
-    super(g, is);
-  }
-
-  public CoRREDecoder(Graphics g, RfbInputStream is, int frameBufferW,
-                      int frameBufferH) {
-    super(g, is, frameBufferW, frameBufferH);
-  }
-
-  //
-  // Override handleRect method to decode CoRRE encoded data insted of
-  // raw pixel data.
-  //
-
-  public void handleRect(int x, int y, int w, int h) throws IOException {
-
-    //
-    // Write encoding ID to record output stream
-    //
-
-    if (dos != null) {
-      dos.writeInt(CoRREDecoder.EncodingCoRRE);
-    }
-
-    int nSubrects = rfbis.readU32();
-
-    byte[] bg_buf = new byte[bytesPerPixel];
-    rfbis.readFully(bg_buf);
-    Color pixel;
-    if (bytesPerPixel == 1) {
-      pixel = getColor256()[bg_buf[0] & 0xFF];
-    } else {
-      pixel = new Color(bg_buf[2] & 0xFF, bg_buf[1] & 0xFF, bg_buf[0] & 0xFF);
-    }
-    graphics.setColor(pixel);
-    graphics.fillRect(x, y, w, h);
-
-    byte[] buf = new byte[nSubrects * (bytesPerPixel + 4)];
-    rfbis.readFully(buf);
-
-    //
-    // Save decoded data to data output stream
-    //
-
-    if (dos != null) {
-      dos.writeInt(nSubrects);
-      dos.write(bg_buf);
-      dos.write(buf);
-    }
-
-    int sx, sy, sw, sh;
-    int i = 0;
-
-    for (int j = 0; j < nSubrects; j++) {
-      if (bytesPerPixel == 1) {
-        pixel = getColor256()[buf[i++] & 0xFF];
-      } else {
-        pixel = new Color(buf[i+2] & 0xFF, buf[i+1] & 0xFF, buf[i] & 0xFF);
-        i += 4;
-      }
-      sx = x + (buf[i++] & 0xFF);
-      sy = y + (buf[i++] & 0xFF);
-      sw = buf[i++] & 0xFF;
-      sh = buf[i++] & 0xFF;
-
-      graphics.setColor(pixel);
-      graphics.fillRect(sx, sy, sw, sh);
-    }
-  }
-}
diff --git a/java/src/com/tightvnc/decoder/CopyRectDecoder.java b/java/src/com/tightvnc/decoder/CopyRectDecoder.java
deleted file mode 100644 (file)
index 07a14bd..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-package com.tightvnc.decoder;
-
-import com.tightvnc.vncviewer.RfbInputStream;
-import java.awt.Graphics;
-import java.io.IOException;
-
-//
-// Class that used for decoding CopyRect encoded data.
-//
-
-public class CopyRectDecoder extends RawDecoder {
-
-  final static int EncodingCopyRect = 1;
-
-  public CopyRectDecoder(Graphics g, RfbInputStream is) {
-    super(g, is);
-  }
-
-  public CopyRectDecoder(Graphics g, RfbInputStream is, int frameBufferW,
-                         int frameBufferH) {
-    super(g, is, frameBufferW, frameBufferH);
-  }
-
-  //
-  // Override handleRect method handle CopyRect
-  //
-
-  public void handleRect(int x, int y, int w, int h) throws IOException {
-
-    //
-    // Write encoding ID to record output stream
-    //
-
-    if (dos != null) {
-      dos.writeInt(CopyRectDecoder.EncodingCopyRect);
-    }
-
-    int copyRectSrcX = rfbis.readU16();
-    int copyRectSrcY = rfbis.readU16();
-
-    // If the session is being recorded:
-    if (dos != null) {
-      dos.writeShort(copyRectSrcX);
-      dos.writeShort(copyRectSrcY);
-    }
-
-    graphics.copyArea(copyRectSrcX, copyRectSrcY, w, h,
-                      x - copyRectSrcX, y - copyRectSrcY);
-  }
-}
diff --git a/java/src/com/tightvnc/decoder/HextileDecoder.java b/java/src/com/tightvnc/decoder/HextileDecoder.java
deleted file mode 100644 (file)
index da7e778..0000000
+++ /dev/null
@@ -1,228 +0,0 @@
-package com.tightvnc.decoder;
-
-import com.tightvnc.decoder.common.Repaintable;
-import com.tightvnc.vncviewer.RfbInputStream;
-import java.awt.Color;
-import java.awt.Graphics;
-import java.io.IOException;
-
-//
-// Class that used for decoding hextile encoded data.
-//
-
-public class HextileDecoder extends RawDecoder {
-
-  final static int EncodingHextile = 5;
-
-  // Contstants used in the Hextile decoder
-  final static int
-    HextileRaw                 = 1,
-    HextileBackgroundSpecified = 2,
-    HextileForegroundSpecified = 4,
-    HextileAnySubrects         = 8,
-    HextileSubrectsColoured    = 16;
-
-  public HextileDecoder(Graphics g, RfbInputStream is) {
-    super(g, is);
-  }
-
-  public HextileDecoder(Graphics g, RfbInputStream is, int frameBufferW,
-                        int frameBufferH) {
-    super(g, is, frameBufferW, frameBufferH);
-  }
-
-  //
-  // Set private members methods
-  //
-
-  public void setRepainableControl(Repaintable r) {
-    repainableControl = r;
-  }
-
-  //
-  // Override handleRect method to decode Hextile encoded data insted of
-  // raw pixel data.
-  //
-
-  public void handleRect(int x, int y, int w, int h) throws IOException,
-                                                            Exception {
-
-    //
-    // Write encoding ID to record output stream
-    //
-
-    if (dos != null) {
-      dos.writeInt(HextileDecoder.EncodingHextile);
-    }
-
-    hextile_bg = new Color(0);
-    hextile_fg = new Color(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);
-      }
-      if (repainableControl != null)
-        repainableControl.scheduleRepaint(x, y, w, h);
-    }
-    if (repainableControl != null)
-      repainableControl.scheduleRepaint(x, y, w, h);
-  }
-
-  //
-  // Handle one tile in the Hextile-encoded data.
-  //
-
-  private void handleHextileSubrect(int tx, int ty, int tw, int th)
-    throws IOException, Exception {
-
-    int subencoding = rfbis.readU8();
-
-    //
-    // Save decoded data to data output stream
-    //
-
-    if (dos != null) {
-      dos.writeByte((byte)subencoding);
-    }
-
-    // Is it a raw-encoded sub-rectangle?
-    if ((subencoding & HextileRaw) != 0) {
-      //
-      // Disable encoding id writting to record stream
-      // in super (RawDecoder) class, cause we write subencoding ID
-      // in this class (see code above).
-      //
-
-      super.enableEncodingRecordWritting(false);
-      super.handleRect(tx, ty, tw, th);
-      super.handleUpdatedPixels(tx, ty, tw, th);
-      super.enableEncodingRecordWritting(true);
-      return;
-    }
-
-    // Read and draw the background if specified.
-    byte[] cbuf = new byte[bytesPerPixel];
-    if ((subencoding & HextileBackgroundSpecified) != 0) {
-      rfbis.readFully(cbuf);
-      if (bytesPerPixel == 1) {
-        hextile_bg = getColor256()[cbuf[0] & 0xFF];
-      } else {
-        hextile_bg = new Color(cbuf[2] & 0xFF, cbuf[1] & 0xFF, cbuf[0] & 0xFF);
-      }
-
-      //
-      // Save decoded data to data output stream
-      //
-
-      if (dos != null) {
-        dos.write(cbuf);
-      }
-    }
-    graphics.setColor(hextile_bg);
-    graphics.fillRect(tx, ty, tw, th);
-
-    // Read the foreground color if specified.
-    if ((subencoding & HextileForegroundSpecified) != 0) {
-      rfbis.readFully(cbuf);
-      if (bytesPerPixel == 1) {
-        hextile_fg = getColor256()[cbuf[0] & 0xFF];
-      } else {
-        hextile_fg = new Color(cbuf[2] & 0xFF, cbuf[1] & 0xFF, cbuf[0] & 0xFF);
-      }
-
-      //
-      // Save decoded data to data output stream
-      //
-
-      if (dos != null) {
-        dos.write(cbuf);
-      }
-    }
-
-    // Done with this tile if there is no sub-rectangles.
-    if ((subencoding & HextileAnySubrects) == 0)
-      return;
-
-    int nSubrects = rfbis.readU8();
-    int bufsize = nSubrects * 2;
-    if ((subencoding & HextileSubrectsColoured) != 0) {
-      bufsize += nSubrects * bytesPerPixel;
-    }
-    byte[] buf = new byte[bufsize];
-    rfbis.readFully(buf);
-
-    //
-    // Save decoded data to data output stream
-    //
-
-    if (dos != null) {
-      dos.writeByte((byte)nSubrects);
-      dos.write(buf);
-    }
-
-    int b1, b2, sx, sy, sw, sh;
-    int i = 0;
-
-    if ((subencoding & HextileSubrectsColoured) == 0) {
-
-      // Sub-rectangles are all of the same color.
-      graphics.setColor(hextile_fg);
-      for (int j = 0; j < nSubrects; j++) {
-        b1 = buf[i++] & 0xFF;
-        b2 = buf[i++] & 0xFF;
-        sx = tx + (b1 >> 4);
-        sy = ty + (b1 & 0xf);
-        sw = (b2 >> 4) + 1;
-        sh = (b2 & 0xf) + 1;
-        graphics.fillRect(sx, sy, sw, sh);
-      }
-    } else if (bytesPerPixel == 1) {
-
-      // BGR233 (8-bit color) version for colored sub-rectangles.
-      for (int j = 0; j < nSubrects; j++) {
-        hextile_fg = getColor256()[buf[i++] & 0xFF];
-        b1 = buf[i++] & 0xFF;
-        b2 = buf[i++] & 0xFF;
-        sx = tx + (b1 >> 4);
-        sy = ty + (b1 & 0xf);
-        sw = (b2 >> 4) + 1;
-        sh = (b2 & 0xf) + 1;
-        graphics.setColor(hextile_fg);
-        graphics.fillRect(sx, sy, sw, sh);
-      }
-
-    } else {
-
-      // Full-color (24-bit) version for colored sub-rectangles.
-      for (int j = 0; j < nSubrects; j++) {
-        hextile_fg = new Color(buf[i+2] & 0xFF,
-                               buf[i+1] & 0xFF,
-                               buf[i] & 0xFF);
-        i += 4;
-        b1 = buf[i++] & 0xFF;
-        b2 = buf[i++] & 0xFF;
-        sx = tx + (b1 >> 4);
-        sy = ty + (b1 & 0xf);
-        sw = (b2 >> 4) + 1;
-        sh = (b2 & 0xf) + 1;
-        graphics.setColor(hextile_fg);
-        graphics.fillRect(sx, sy, sw, sh);
-      }
-
-    }
-  }
-
-  // These colors should be kept between handleHextileSubrect() calls.
-  private Color hextile_bg, hextile_fg;
-  // Repaitable object
-  private Repaintable repainableControl = null;
-}
diff --git a/java/src/com/tightvnc/decoder/RREDecoder.java b/java/src/com/tightvnc/decoder/RREDecoder.java
deleted file mode 100644 (file)
index 02eb513..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-package com.tightvnc.decoder;
-
-import com.tightvnc.vncviewer.RfbInputStream;
-import java.awt.Graphics;
-import java.awt.Color;
-import java.io.ByteArrayInputStream;
-import java.io.DataInputStream;
-import java.io.IOException;
-
-//
-// Class that used for decoding RRE encoded data.
-//
-
-public class RREDecoder extends RawDecoder {
-
-  final static int EncodingRRE = 2;
-
-  public RREDecoder(Graphics g, RfbInputStream is) {
-    super(g, is);
-  }
-
-  public RREDecoder(Graphics g, RfbInputStream is, int frameBufferW,
-                    int frameBufferH) {
-    super(g, is, frameBufferW, frameBufferH);
-  }
-
-  //
-  // Override handleRect method to decode RRE encoded data insted of
-  // raw pixel data.
-  //
-
-  public void handleRect(int x, int y, int w, int h) throws IOException {
-
-    //
-    // Write encoding ID to record output stream
-    //
-
-    if (dos != null) {
-      dos.writeInt(RREDecoder.EncodingRRE);
-    }
-
-    int nSubrects = rfbis.readU32();
-    byte[] bg_buf = new byte[bytesPerPixel];
-    rfbis.readFully(bg_buf);
-    Color pixel;
-    if (bytesPerPixel == 1) {
-      pixel = getColor256()[bg_buf[0] & 0xFF];
-    } else {
-      pixel = new Color(bg_buf[2] & 0xFF, bg_buf[1] & 0xFF, bg_buf[0] & 0xFF);
-    }
-    graphics.setColor(pixel);
-    graphics.fillRect(x, y, w, h);
-    byte[] buf = new byte[nSubrects * (bytesPerPixel + 8)];
-    rfbis.readFully(buf);
-    DataInputStream ds = new DataInputStream(new ByteArrayInputStream(buf));
-
-    //
-    // Save decoded data to data output stream
-    //
-    if (dos != null) {
-      dos.writeInt(nSubrects);
-      dos.write(bg_buf);
-      dos.write(buf);
-    }
-
-    int sx, sy, sw, sh;
-    for (int j = 0; j < nSubrects; j++) {
-      if (bytesPerPixel == 1) {
-        pixel = getColor256()[ds.readUnsignedByte()];
-      } else {
-        ds.skip(4);
-        pixel = new Color(buf[j*12+2] & 0xFF,
-                          buf[j*12+1] & 0xFF,
-                          buf[j*12]   & 0xFF);
-      }
-      sx = x + ds.readUnsignedShort();
-      sy = y + ds.readUnsignedShort();
-      sw = ds.readUnsignedShort();
-      sh = ds.readUnsignedShort();
-
-      graphics.setColor(pixel);
-      graphics.fillRect(sx, sy, sw, sh);
-    }
-  }
-}
diff --git a/java/src/com/tightvnc/decoder/RawDecoder.java b/java/src/com/tightvnc/decoder/RawDecoder.java
deleted file mode 100644 (file)
index 9ef167a..0000000
+++ /dev/null
@@ -1,223 +0,0 @@
-package com.tightvnc.decoder;
-
-import com.tightvnc.vncviewer.RfbInputStream;
-import java.io.IOException;
-import java.io.DataOutput;
-import java.awt.Graphics;
-import java.awt.Image;
-import java.awt.image.ColorModel;
-import java.awt.image.DirectColorModel;
-import java.awt.image.MemoryImageSource;
-import java.awt.Color;
-import java.awt.Toolkit;
-
-//
-// This is base decoder class.
-// Other classes will be childs of RawDecoder.
-//
-
-public class RawDecoder {
-  final static int EncodingRaw = 0;
-
-  public RawDecoder(Graphics g, RfbInputStream is) {
-    setGraphics(g);
-    setRfbInputStream(is);
-  }
-
-  public RawDecoder(Graphics g, RfbInputStream is, int frameBufferW,
-                    int frameBufferH) {
-    setGraphics(g);
-    setRfbInputStream(is);
-    setFrameBufferSize(frameBufferW, frameBufferH);
-    // FIXME: cm24 created in getColorModel24.
-    // Remove if no bugs
-    cm24 = new DirectColorModel(24, 0xFF0000, 0x00FF00, 0x0000FF);
-  }
-
-  //
-  // Set methods to set value of non-static protected members of class
-  //
-
-  public void setRfbInputStream(RfbInputStream is) {
-    rfbis = is;
-  }
-
-  public void setGraphics(Graphics g) {
-    graphics = g;
-  }
-
-  public void setBPP(int bpp) {
-    bytesPerPixel = bpp;
-  }
-
-  public void setFrameBufferSize(int w, int h) {
-    framebufferWidth = w;
-    framebufferHeight = h;
-  }
-
-  //
-  // FIXME: Rename this method after we don't need RecordInterface
-  // in RawDecoder class to record session
-  //
-
-  public void setDataOutputStream(DataOutput os) {
-    dos = os;
-  }
-
-  //
-  // Decodes Raw Pixels data and draw it into graphics
-  //
-
-  public void handleRect(int x, int y, int w, int h) throws IOException, Exception {
-
-    //
-    // Write encoding ID to record output stream
-    //
-
-    if ((dos != null) && (enableEncodingRecordWritting)) {
-      dos.writeInt(RawDecoder.EncodingRaw);
-    }
-
-    if (bytesPerPixel == 1) {
-      for (int dy = y; dy < y + h; dy++) {
-        if (pixels8 != null) {
-          rfbis.readFully(pixels8, dy * framebufferWidth + x, w);
-        }
-        //
-        // Save decoded data to record output stream
-        //
-        if (dos != null) {
-          dos.write(pixels8, dy * framebufferWidth + x, w);
-        }
-      }
-    } else {
-      byte[] buf = new byte[w * 4];
-      int i, offset;
-      for (int dy = y; dy < y + h; dy++) {
-        rfbis.readFully(buf);
-        //
-        // Save decoded data to record output stream
-        //
-        if (dos != null) {
-          dos.write(buf);
-        }
-        offset = dy * framebufferWidth + x;
-        if (pixels24 != null) {
-          for (i = 0; i < w; i++) {
-            pixels24[offset + i] =
-              (buf[i * 4 + 2] & 0xFF) << 16 |
-              (buf[i * 4 + 1] & 0xFF) << 8 |
-              (buf[i * 4] & 0xFF);
-          } //for
-        } // if
-      } // for
-    } // else
-    handleUpdatedPixels(x, y, w, h);
-  } // void
-
-  //
-  // Display newly updated area of pixels.
-  //
-
-  protected void handleUpdatedPixels(int x, int y, int w, int h) {
-    // Draw updated pixels of the off-screen image.
-    pixelsSource.newPixels(x, y, w, h);
-    graphics.setClip(x, y, w, h);
-    graphics.drawImage(rawPixelsImage, 0, 0, null);
-    graphics.setClip(0, 0, framebufferWidth, framebufferHeight);
-  }
-
-  //
-  // Updates pixels data.
-  // This method must be called when framebuffer is resized
-  // or BPP is changed.
-  //
-
-  public void update() {
-    // Images with raw pixels should be re-allocated on every change
-    // of geometry or pixel format.
-    int fbWidth = framebufferWidth;
-    int fbHeight = framebufferHeight;
-
-    if (bytesPerPixel == 1) {
-      pixels24 = null;
-      pixels8 = new byte[fbWidth * fbHeight];
-      pixelsSource = new MemoryImageSource(fbWidth, fbHeight, getColorModel8(),
-                                           pixels8, 0, fbWidth);
-    } else {
-      pixels8 = null;
-      pixels24 = new int[fbWidth * fbHeight];
-      pixelsSource =
-        new MemoryImageSource(fbWidth, fbHeight, cm24, pixels24, 0, fbWidth);
-    }
-    pixelsSource.setAnimated(true);
-    rawPixelsImage = Toolkit.getDefaultToolkit().createImage(pixelsSource);
-  }
-
-  //
-  // Private static members access methods
-  //
-
-  protected ColorModel getColorModel8() {
-    if (cm8 == null) {
-      cm8 = cm8 = new DirectColorModel(8, 7, (7 << 3), (3 << 6));
-    }
-    return cm8;
-  }
-
-  protected ColorModel getColorModel24() {
-    if (cm24 == null) {
-      cm24 = new DirectColorModel(24, 0xFF0000, 0x00FF00, 0x0000FF);
-    }
-    return cm24;
-  }
-
-  protected Color[]getColor256() {
-    if (color256 == null) {
-      color256 = new Color[256];
-      for (int i = 0; i < 256; i++)
-        color256[i] = new Color(cm8.getRGB(i));
-    }
-    return color256;
-  }
-
-  //
-  // This method will be used by HextileDecoder to disable
-  // double writting encoding id to record stream.
-  //
-  // FIXME: Try to find better solution than this.
-  //
-
-  protected void enableEncodingRecordWritting(boolean enable) {
-    enableEncodingRecordWritting = enable;
-  }
-
-  //
-  // Unique data for every decoder (? maybe not ?)
-  //
-
-  protected int bytesPerPixel = 4;
-  protected int framebufferWidth = 0;
-  protected int framebufferHeight = 0;
-  protected RfbInputStream rfbis = null;
-  protected Graphics graphics = null;
-  protected DataOutput dos = null;
-  protected boolean enableEncodingRecordWritting = true;
-
-  //
-  // This data must be shared between decoders
-  //
-
-  protected static byte []pixels8 = null;
-  protected static int []pixels24 = null;
-  protected static MemoryImageSource pixelsSource = null;
-  protected static Image rawPixelsImage = null;
-
-  //
-  // Access to this static members only though protected methods
-  //
-
-  private static ColorModel cm8 = null;
-  private static ColorModel cm24 = null;
-  private static Color []color256 = null;
-}
diff --git a/java/src/com/tightvnc/decoder/TightDecoder.java b/java/src/com/tightvnc/decoder/TightDecoder.java
deleted file mode 100644 (file)
index 015f73c..0000000
+++ /dev/null
@@ -1,525 +0,0 @@
-package com.tightvnc.decoder;
-
-import com.tightvnc.decoder.common.Repaintable;
-import com.tightvnc.vncviewer.RfbInputStream;
-import java.awt.Graphics;
-import java.awt.Color;
-import java.awt.Image;
-import java.awt.Rectangle;
-import java.awt.Toolkit;
-import java.awt.image.ImageObserver;
-import java.io.IOException;
-import java.util.zip.Deflater;
-import java.util.zip.Inflater;
-
-//
-// Class that used for decoding Tight encoded data.
-//
-
-public class TightDecoder extends RawDecoder implements ImageObserver {
-
-  final static int EncodingTight = 7;
-
-  //
-  // Tight decoder constants
-  //
-
-  final static int TightExplicitFilter = 0x04;
-  final static int TightFill = 0x08;
-  final static int TightJpeg = 0x09;
-  final static int TightMaxSubencoding = 0x09;
-  final static int TightFilterCopy = 0x00;
-  final static int TightFilterPalette = 0x01;
-  final static int TightFilterGradient = 0x02;
-  final static int TightMinToCompress = 12;
-
-  // Tight encoder's data.
-  final static int tightZlibBufferSize = 512;
-
-  public TightDecoder(Graphics g, RfbInputStream is) {
-    super(g, is);
-    tightInflaters = new Inflater[4];
-  }
-
-  public TightDecoder(Graphics g, RfbInputStream is, int frameBufferW,
-                      int frameBufferH) {
-    super(g, is, frameBufferW, frameBufferH);
-    tightInflaters = new Inflater[4];
-  }
-
-  //
-  // Set and get methods for private TightDecoder
-  //
-
-  public void setRepainableControl(Repaintable r) {
-    repainatableControl = r;
-  }
-
-  //
-  // JPEG processing statistic methods
-  //
-
-  public long getNumJPEGRects() {
-    return statNumRectsTightJPEG;
-  }
-
-  public void setNumJPEGRects(int v) {
-    statNumRectsTightJPEG = v;
-  }
-
-  //
-  // Tight processing statistic methods
-  //
-
-  public long getNumTightRects() {
-    return statNumRectsTight;
-  }
-
-  public void setNumTightRects(int v) {
-    statNumRectsTight = v;
-  }
-
-  //
-  // Handle a Tight-encoded rectangle.
-  //
-
-  public void handleRect(int x, int y, int w, int h) throws Exception {
-
-    //
-    // Write encoding ID to record output stream
-    //
-
-    if (dos != null) {
-      dos.writeInt(TightDecoder.EncodingTight);
-    }
-
-    int comp_ctl = rfbis.readU8();
-
-    if (dos != null) {
-      // Tell the decoder to flush each of the four zlib streams.
-      dos.writeByte(comp_ctl | 0x0F);
-    }
-
-    // Flush zlib streams if we are told by the server to do so.
-    for (int stream_id = 0; stream_id < 4; stream_id++) {
-      if ((comp_ctl & 1) != 0 && tightInflaters[stream_id] != null) {
-        tightInflaters[stream_id] = null;
-      }
-      comp_ctl >>= 1;
-    }
-
-    // Check correctness of subencoding value.
-    if (comp_ctl > TightDecoder.TightMaxSubencoding) {
-      throw new Exception("Incorrect tight subencoding: " + comp_ctl);
-    }
-
-    // Handle solid-color rectangles.
-    if (comp_ctl == TightDecoder.TightFill) {
-
-      if (bytesPerPixel == 1) {
-        int idx = rfbis.readU8();
-        graphics.setColor(getColor256()[idx]);
-        if (dos != null) {
-          dos.writeByte(idx);
-        }
-      } else {
-        byte[] buf = new byte[3];
-        rfbis.readFully(buf);
-        if (dos != null) {
-          dos.write(buf);
-        }
-        Color bg = new Color(0xFF000000 | (buf[0] & 0xFF) << 16 |
-                            (buf[1] & 0xFF) << 8 | (buf[2] & 0xFF));
-        graphics.setColor(bg);
-      }
-      graphics.fillRect(x, y, w, h);
-      repainatableControl.scheduleRepaint(x, y, w, h);
-      return;
-
-    }
-
-    if (comp_ctl == TightDecoder.TightJpeg) {
-
-      statNumRectsTightJPEG++;
-
-      // Read JPEG data.
-      byte[] jpegData = new byte[rfbis.readCompactLen()];
-      rfbis.readFully(jpegData);
-      if (dos != null) {
-        recordCompactLen(jpegData.length);
-        dos.write(jpegData);
-      }
-
-      // Create an Image object from the JPEG data.
-      Image jpegImage = Toolkit.getDefaultToolkit().createImage(jpegData);
-
-      // Remember the rectangle where the image should be drawn.
-      jpegRect = new Rectangle(x, y, w, h);
-
-      // Let the imageUpdate() method do the actual drawing, here just
-      // wait until the image is fully loaded and drawn.
-      synchronized(jpegRect) {
-        Toolkit.getDefaultToolkit().prepareImage(jpegImage, -1, -1, this);
-        try {
-          // Wait no longer than three seconds.
-          jpegRect.wait(3000);
-        } catch (InterruptedException e) {
-          throw new Exception("Interrupted while decoding JPEG image");
-        }
-      }
-
-      // Done, jpegRect is not needed any more.
-      jpegRect = null;
-      return;
-
-    } else {
-      statNumRectsTight++;
-    }
-
-    // Read filter id and parameters.
-    int numColors = 0, rowSize = w;
-    byte[] palette8 = new byte[2];
-    int[] palette24 = new int[256];
-    boolean useGradient = false;
-    if ((comp_ctl & TightDecoder.TightExplicitFilter) != 0) {
-      int filter_id = rfbis.readU8();
-      if (dos != null) {
-        dos.writeByte(filter_id);
-      }
-      if (filter_id == TightDecoder.TightFilterPalette) {
-        numColors = rfbis.readU8() + 1;
-        if (dos != null) {
-          dos.writeByte((numColors - 1));
-        }
-        if (bytesPerPixel == 1) {
-          if (numColors != 2) {
-            throw new Exception("Incorrect tight palette size: " + numColors);
-          }
-          rfbis.readFully(palette8);
-          if (dos != null) {
-            dos.write(palette8);
-          }
-        } else {
-          byte[] buf = new byte[numColors * 3];
-          rfbis.readFully(buf);
-          if (dos != null) {
-            dos.write(buf);
-          }
-          for (int i = 0; i < numColors; i++) {
-           palette24[i] = ((buf[i * 3] & 0xFF) << 16 |
-                           (buf[i * 3 + 1] & 0xFF) << 8 |
-                           (buf[i * 3 + 2] & 0xFF));
-          }
-        }
-        if (numColors == 2) {
-          rowSize = (w + 7) / 8;
-        }
-      } else if (filter_id == TightDecoder.TightFilterGradient) {
-        useGradient = true;
-      } else if (filter_id != TightDecoder.TightFilterCopy) {
-        throw new Exception("Incorrect tight filter id: " + filter_id);
-      }
-    }
-    if (numColors == 0 && bytesPerPixel == 4)
-      rowSize *= 3;
-
-    // Read, optionally uncompress and decode data.
-    int dataSize = h * rowSize;
-    if (dataSize < TightDecoder.TightMinToCompress) {
-      // Data size is small - not compressed with zlib.
-      if (numColors != 0) {
-        // Indexed colors.
-        byte[] indexedData = new byte[dataSize];
-        rfbis.readFully(indexedData);
-        if (dos != null) {
-          dos.write(indexedData);
-        }
-        if (numColors == 2) {
-          // Two colors.
-          if (bytesPerPixel == 1) {
-            decodeMonoData(x, y, w, h, indexedData, palette8);
-          } else {
-            decodeMonoData(x, y, w, h, indexedData, palette24);
-          }
-        } else {
-          // 3..255 colors (assuming bytesPixel == 4).
-          int i = 0;
-          for (int dy = y; dy < y + h; dy++) {
-            for (int dx = x; dx < x + w; dx++) {
-              pixels24[dy * framebufferWidth + dx] =
-                palette24[indexedData[i++] & 0xFF];
-            }
-          }
-        }
-      } else if (useGradient) {
-        // "Gradient"-processed data
-        byte[] buf = new byte[w * h * 3];
-        rfbis.readFully(buf);
-        if (dos != null) {
-          dos.write(buf);
-        }
-        decodeGradientData(x, y, w, h, buf);
-      } else {
-        // Raw truecolor data.
-        if (bytesPerPixel == 1) {
-          for (int dy = y; dy < y + h; dy++) {
-            rfbis.readFully(pixels8, dy * framebufferWidth + x, w);
-            if (dos != null) {
-              dos.write(pixels8, dy * framebufferWidth + x, w);
-            }
-          }
-        } else {
-          byte[] buf = new byte[w * 3];
-          int i, offset;
-          for (int dy = y; dy < y + h; dy++) {
-            rfbis.readFully(buf);
-            if (dos != null) {
-              dos.write(buf);
-            }
-            offset = dy * framebufferWidth + x;
-            for (i = 0; i < w; i++) {
-              pixels24[offset + i] =
-                (buf[i * 3] & 0xFF) << 16 |
-                (buf[i * 3 + 1] & 0xFF) << 8 |
-                (buf[i * 3 + 2] & 0xFF);
-            }
-          }
-        }
-      }
-    } else {
-      // Data was compressed with zlib.
-      int zlibDataLen = rfbis.readCompactLen();
-      byte[] zlibData = new byte[zlibDataLen];
-      rfbis.readFully(zlibData);
-      int stream_id = comp_ctl & 0x03;
-      if (tightInflaters[stream_id] == null) {
-        tightInflaters[stream_id] = new Inflater();
-      }
-      Inflater myInflater = tightInflaters[stream_id];
-      myInflater.setInput(zlibData);
-      byte[] buf = new byte[dataSize];
-      myInflater.inflate(buf);
-      if (dos != null) {
-        recordCompressedData(buf);
-      }
-
-      if (numColors != 0) {
-        // Indexed colors.
-        if (numColors == 2) {
-          // Two colors.
-          if (bytesPerPixel == 1) {
-            decodeMonoData(x, y, w, h, buf, palette8);
-          } else {
-            decodeMonoData(x, y, w, h, buf, palette24);
-          }
-        } else {
-          // More than two colors (assuming bytesPixel == 4).
-          int i = 0;
-          for (int dy = y; dy < y + h; dy++) {
-            for (int dx = x; dx < x + w; dx++) {
-              pixels24[dy * framebufferWidth + dx] =
-                palette24[buf[i++] & 0xFF];
-            }
-          }
-        }
-      } else if (useGradient) {
-        // Compressed "Gradient"-filtered data (assuming bytesPixel == 4).
-        decodeGradientData(x, y, w, h, buf);
-      } else {
-        // Compressed truecolor data.
-        if (bytesPerPixel == 1) {
-          int destOffset = y * framebufferWidth + x;
-          for (int dy = 0; dy < h; dy++) {
-            System.arraycopy(buf, dy * w, pixels8, destOffset, w);
-            destOffset += framebufferWidth;
-          }
-        } else {
-          int srcOffset = 0;
-          int destOffset, i;
-          for (int dy = 0; dy < h; dy++) {
-            myInflater.inflate(buf);
-            destOffset = (y + dy) * framebufferWidth + x;
-            for (i = 0; i < w; i++) {
-              RawDecoder.pixels24[destOffset + i] =
-                (buf[srcOffset] & 0xFF) << 16 |
-                (buf[srcOffset + 1] & 0xFF) << 8 |
-                (buf[srcOffset + 2] & 0xFF);
-              srcOffset += 3;
-            }
-          }
-        }
-      }
-    }
-    handleUpdatedPixels(x, y, w, h);
-  }
-
-  //
-  // Decode 1bpp-encoded bi-color rectangle (8-bit and 24-bit versions).
-  //
-
-  private void decodeMonoData(int x, int y, int w, int h, byte[] src, byte[] palette) {
-
-    int dx, dy, n;
-    int i = y * framebufferWidth + x;
-    int rowBytes = (w + 7) / 8;
-    byte b;
-
-    for (dy = 0; dy < h; dy++) {
-      for (dx = 0; dx < w / 8; dx++) {
-        b = src[dy*rowBytes+dx];
-        for (n = 7; n >= 0; n--)
-          pixels8[i++] = palette[b >> n & 1];
-      }
-      for (n = 7; n >= 8 - w % 8; n--) {
-        pixels8[i++] = palette[src[dy*rowBytes+dx] >> n & 1];
-      }
-      i += (framebufferWidth - w);
-    }
-  }
-
-  private void decodeMonoData(int x, int y, int w, int h, byte[] src, int[] palette) {
-
-    int dx, dy, n;
-    int i = y * framebufferWidth + x;
-    int rowBytes = (w + 7) / 8;
-    byte b;
-
-    for (dy = 0; dy < h; dy++) {
-      for (dx = 0; dx < w / 8; dx++) {
-        b = src[dy*rowBytes+dx];
-        for (n = 7; n >= 0; n--)
-          pixels24[i++] = palette[b >> n & 1];
-      }
-      for (n = 7; n >= 8 - w % 8; n--) {
-        pixels24[i++] = palette[src[dy*rowBytes+dx] >> n & 1];
-      }
-      i += (framebufferWidth - w);
-    }
-  }
-
-  //
-  // Decode data processed with the "Gradient" filter.
-  //
-
-  private void decodeGradientData (int x, int y, int w, int h, byte[] buf) {
-
-    int dx, dy, c;
-    byte[] prevRow = new byte[w * 3];
-    byte[] thisRow = new byte[w * 3];
-    byte[] pix = new byte[3];
-    int[] est = new int[3];
-
-    int offset = y * framebufferWidth + x;
-
-    for (dy = 0; dy < h; dy++) {
-
-      /* First pixel in a row */
-      for (c = 0; c < 3; c++) {
-        pix[c] = (byte)(prevRow[c] + buf[dy * w * 3 + c]);
-        thisRow[c] = pix[c];
-      }
-      pixels24[offset++] =
-         (pix[0] & 0xFF) << 16 | (pix[1] & 0xFF) << 8 | (pix[2] & 0xFF);
-
-      /* Remaining pixels of a row */
-      for (dx = 1; dx < w; dx++) {
-        for (c = 0; c < 3; c++) {
-          est[c] = ((prevRow[dx * 3 + c] & 0xFF) + (pix[c] & 0xFF) -
-                    (prevRow[(dx-1) * 3 + c] & 0xFF));
-          if (est[c] > 0xFF) {
-            est[c] = 0xFF;
-          } else if (est[c] < 0x00) {
-            est[c] = 0x00;
-          }
-          pix[c] = (byte)(est[c] + buf[(dy * w + dx) * 3 + c]);
-          thisRow[dx * 3 + c] = pix[c];
-        }
-        pixels24[offset++] =
-          (pix[0] & 0xFF) << 16 | (pix[1] & 0xFF) << 8 | (pix[2] & 0xFF);
-      }
-
-      System.arraycopy(thisRow, 0, prevRow, 0, w * 3);
-      offset += (framebufferWidth - w);
-    }
-  }
-
-  //
-  // Override the ImageObserver interface method to handle drawing of
-  // JPEG-encoded data.
-  //
-
-  public boolean imageUpdate(Image img, int infoflags,
-                             int x, int y, int width, int height) {
-    if ((infoflags & (ALLBITS | ABORT)) == 0) {
-      return true; // We need more image data.
-    } else {
-      // If the whole image is available, draw it now.
-      if ((infoflags & ALLBITS) != 0) {
-        if (jpegRect != null) {
-          synchronized(jpegRect) {
-            graphics.drawImage(img, jpegRect.x, jpegRect.y, null);
-            repainatableControl.scheduleRepaint(jpegRect.x, jpegRect.y,
-                                                jpegRect.width, jpegRect.height);
-            jpegRect.notify();
-          }
-        }
-      }
-      return false; // All image data was processed.
-    }
-  }
-
-  //
-  // Write an integer in compact representation (1..3 bytes) into the
-  // recorded session file.
-  //
-
-  void recordCompactLen(int len) throws IOException {
-    byte[] buf = new byte[3];
-    int bytes = 0;
-    buf[bytes++] = (byte)(len & 0x7F);
-    if (len > 0x7F) {
-      buf[bytes-1] |= 0x80;
-      buf[bytes++] = (byte)(len >> 7 & 0x7F);
-      if (len > 0x3FFF) {
-       buf[bytes-1] |= 0x80;
-       buf[bytes++] = (byte)(len >> 14 & 0xFF);
-      }
-    }
-    if (dos != null) dos.write(buf, 0, bytes);
-  }
-
-  //
-  // Compress and write the data into the recorded session file.
-  //
-
-  void recordCompressedData(byte[] data, int off, int len) throws IOException {
-    Deflater deflater = new Deflater();
-    deflater.setInput(data, off, len);
-    int bufSize = len + len / 100 + 12;
-    byte[] buf = new byte[bufSize];
-    deflater.finish();
-    int compressedSize = deflater.deflate(buf);
-    recordCompactLen(compressedSize);
-    if (dos != null) dos.write(buf, 0, compressedSize);
-  }
-
-  void recordCompressedData(byte[] data) throws IOException {
-    recordCompressedData(data, 0, data.length);
-  }
-
-  //
-  // Private members
-  //
-
-  private Inflater[] tightInflaters;
-  // Since JPEG images are loaded asynchronously, we have to remember
-  // their position in the framebuffer. Also, this jpegRect object is
-  // used for synchronization between the rfbThread and a JVM's thread
-  // which decodes and loads JPEG images.
-  private Rectangle jpegRect;
-  private Repaintable repainatableControl = null;
-  // Jpeg decoding statistics
-  private long statNumRectsTightJPEG = 0;
-  // Tight decoding statistics
-  private long statNumRectsTight = 0;
-}
diff --git a/java/src/com/tightvnc/decoder/ZRLEDecoder.java b/java/src/com/tightvnc/decoder/ZRLEDecoder.java
deleted file mode 100644 (file)
index a22da90..0000000
+++ /dev/null
@@ -1,310 +0,0 @@
-package com.tightvnc.decoder;
-
-import com.tightvnc.vncviewer.InStream;
-import com.tightvnc.vncviewer.RfbInputStream;
-import com.tightvnc.vncviewer.ZlibInStream;
-import java.awt.Graphics;
-import com.tightvnc.vncviewer.MemInStream;
-import java.awt.Color;
-import java.awt.Toolkit;
-import java.awt.image.MemoryImageSource;
-import java.io.IOException;
-
-//
-// Class that used for decoding ZRLE encoded data.
-//
-
-public class ZRLEDecoder extends RawDecoder {
-
-  final static int EncodingZRLE = 16;
-
-  public ZRLEDecoder(Graphics g, RfbInputStream is) {
-    super(g, is);
-  }
-
-  public ZRLEDecoder(Graphics g, RfbInputStream is, int frameBufferW,
-                     int frameBufferH) {
-    super(g, is, frameBufferW, frameBufferH);
-  }
-
-  //
-  // Handle a ZRLE-encoded rectangle.
-  //
-  // FIXME: Currently, session recording is not fully supported for ZRLE.
-  //
-
-  public void handleRect(int x, int y, int w, int h) throws IOException, Exception {
-
-    //
-    // Write encoding ID to record output stream
-    //
-
-    if (dos != null) {
-      dos.writeInt(ZRLEDecoder.EncodingZRLE);
-    }
-
-    if (zrleInStream == null)
-      zrleInStream = new ZlibInStream();
-
-    int nBytes = rfbis.readU32();
-    if (nBytes > 64 * 1024 * 1024)
-      throw new Exception("ZRLE decoder: illegal compressed data size");
-
-    if (zrleBuf == null || zrleBufLen < nBytes) {
-      zrleBufLen = nBytes + 4096;
-      zrleBuf = new byte[zrleBufLen];
-    }
-
-    // FIXME: Do not wait for all the data before decompression.
-    rfbis.readFully(zrleBuf, 0, nBytes);
-
-    //
-    // Override handleRect method to decode RRE encoded data insted of
-    // raw pixel data.
-    //
-
-    if (dos != null) {
-      if (!zrleRecWarningShown) {
-        System.out.println("Warning: ZRLE session can be recorded" +
-                           " only from the beginning");
-        System.out.println("Warning: Recorded file may be corrupted");
-        zrleRecWarningShown = true;
-      }
-    }
-
-    zrleInStream.setUnderlying(new MemInStream(zrleBuf, 0, nBytes), nBytes);
-
-    for (int ty = y; ty < y+h; ty += 64) {
-
-      int th = Math.min(y+h-ty, 64);
-
-      for (int tx = x; tx < x+w; tx += 64) {
-
-        int tw = Math.min(x+w-tx, 64);
-
-        int mode = zrleInStream.readU8();
-        boolean rle = (mode & 128) != 0;
-        int palSize = mode & 127;
-        int[] palette = new int[128];
-
-        readZrlePalette(palette, palSize);
-
-        if (palSize == 1) {
-          int pix = palette[0];
-          Color c = (bytesPerPixel == 1) ?
-            getColor256()[pix] : new Color(0xFF000000 | pix);
-          graphics.setColor(c);
-          graphics.fillRect(tx, ty, tw, th);
-          continue;
-        }
-
-        if (!rle) {
-          if (palSize == 0) {
-            readZrleRawPixels(tw, th);
-          } else {
-            readZrlePackedPixels(tw, th, palette, palSize);
-          }
-        } else {
-          if (palSize == 0) {
-            readZrlePlainRLEPixels(tw, th);
-          } else {
-            readZrlePackedRLEPixels(tw, th, palette);
-          }
-        }
-        handleUpdatedZrleTile(tx, ty, tw, th);
-      }
-    }
-    zrleInStream.reset();
-  }
-
-  //
-  // Override update() method cause we have own data that
-  // must be updated when framebuffer is resized or BPP is changed
-  //
-
-  public void update() {
-    // Images with raw pixels should be re-allocated on every change
-    // of geometry or pixel format.
-    int fbWidth = framebufferWidth;
-    int fbHeight = framebufferHeight;
-
-    if (bytesPerPixel == 1) {
-      RawDecoder.pixels24 = null;
-      RawDecoder.pixels8 = new byte[fbWidth * fbHeight];
-      RawDecoder.pixelsSource = new MemoryImageSource(fbWidth, fbHeight, getColorModel8(), pixels8, 0, fbWidth);
-      zrleTilePixels24 = null;
-      zrleTilePixels8 = new byte[64 * 64];
-    } else {
-      RawDecoder.pixels8 = null;
-      RawDecoder.pixels24 = new int[fbWidth * fbHeight];
-      RawDecoder.pixelsSource =
-        new MemoryImageSource(fbWidth, fbHeight, getColorModel24(), pixels24, 0, fbWidth);
-      zrleTilePixels8 = null;
-      zrleTilePixels24 = new int[64 * 64];
-    }
-    RawDecoder.pixelsSource.setAnimated(true);
-    RawDecoder.rawPixelsImage = Toolkit.getDefaultToolkit().createImage(pixelsSource);
-  }
-
-  //
-  // Copy pixels from zrleTilePixels8 or zrleTilePixels24, then update.
-  //
-
-  private void handleUpdatedZrleTile(int x, int y, int w, int h) {
-    Object src, dst;
-    if (bytesPerPixel == 1) {
-      src = zrleTilePixels8; dst = pixels8;
-    } else {
-      src = zrleTilePixels24; dst = pixels24;
-    }
-    int offsetSrc = 0;
-    int offsetDst = (y * framebufferWidth + x);
-    for (int j = 0; j < h; j++) {
-      System.arraycopy(src, offsetSrc, dst, offsetDst, w);
-      offsetSrc += w;
-      offsetDst += framebufferWidth;
-    }
-    handleUpdatedPixels(x, y, w, h);
-  }
-
-  //
-  // Private methods for reading ZRLE data
-  //
-
-  private int readPixel(InStream is) throws Exception {
-    int pix;
-    if (bytesPerPixel == 1) {
-      pix = is.readU8();
-    } else {
-      int p1 = is.readU8();
-      int p2 = is.readU8();
-      int p3 = is.readU8();
-      pix = (p3 & 0xFF) << 16 | (p2 & 0xFF) << 8 | (p1 & 0xFF);
-    }
-    return pix;
-  }
-
-  private void readPixels(InStream is, int[] dst, int count) throws Exception {
-    if (bytesPerPixel == 1) {
-      byte[] buf = new byte[count];
-      is.readBytes(buf, 0, count);
-      for (int i = 0; i < count; i++) {
-        dst[i] = (int)buf[i] & 0xFF;
-      }
-    } else {
-      byte[] buf = new byte[count * 3];
-      is.readBytes(buf, 0, count * 3);
-      for (int i = 0; i < count; i++) {
-        dst[i] = ((buf[i*3+2] & 0xFF) << 16 |
-                  (buf[i*3+1] & 0xFF) << 8 |
-                  (buf[i*3] & 0xFF));
-      }
-    }
-  }
-
-  private void readZrlePalette(int[] palette, int palSize) throws Exception {
-    readPixels(zrleInStream, palette, palSize);
-  }
-
-  private void readZrleRawPixels(int tw, int th) throws Exception {
-    if (bytesPerPixel == 1) {
-      zrleInStream.readBytes(zrleTilePixels8, 0, tw * th);
-    } else {
-      readPixels(zrleInStream, zrleTilePixels24, tw * th); ///
-    }
-  }
-
-  private void readZrlePackedPixels(int tw, int th, int[] palette, int palSize)
-    throws Exception {
-
-    int bppp = ((palSize > 16) ? 8 :
-                ((palSize > 4) ? 4 : ((palSize > 2) ? 2 : 1)));
-    int ptr = 0;
-
-    for (int i = 0; i < th; i++) {
-      int eol = ptr + tw;
-      int b = 0;
-      int nbits = 0;
-
-      while (ptr < eol) {
-        if (nbits == 0) {
-          b = zrleInStream.readU8();
-          nbits = 8;
-        }
-        nbits -= bppp;
-        int index = (b >> nbits) & ((1 << bppp) - 1) & 127;
-        if (bytesPerPixel == 1) {
-          zrleTilePixels8[ptr++] = (byte)palette[index];
-        } else {
-          zrleTilePixels24[ptr++] = palette[index];
-        }
-      }
-    }
-  }
-
-  private void readZrlePlainRLEPixels(int tw, int th) throws Exception {
-    int ptr = 0;
-    int end = ptr + tw * th;
-    while (ptr < end) {
-      int pix = readPixel(zrleInStream);
-      int len = 1;
-      int b;
-      do {
-        b = zrleInStream.readU8();
-        len += b;
-      } while (b == 255);
-
-      if (!(len <= end - ptr))
-        throw new Exception("ZRLE decoder: assertion failed" +
-                            " (len <= end-ptr)");
-
-      if (bytesPerPixel == 1) {
-        while (len-- > 0) zrleTilePixels8[ptr++] = (byte)pix;
-      } else {
-        while (len-- > 0) zrleTilePixels24[ptr++] = pix;
-      }
-    }
-  }
-
-  private void readZrlePackedRLEPixels(int tw, int th, int[] palette)
-    throws Exception {
-
-    int ptr = 0;
-    int end = ptr + tw * th;
-    while (ptr < end) {
-      int index = zrleInStream.readU8();
-      int len = 1;
-      if ((index & 128) != 0) {
-        int b;
-        do {
-          b = zrleInStream.readU8();
-          len += b;
-        } while (b == 255);
-
-        if (!(len <= end - ptr))
-          throw new Exception("ZRLE decoder: assertion failed" +
-                              " (len <= end - ptr)");
-      }
-
-      index &= 127;
-      int pix = palette[index];
-
-      if (bytesPerPixel == 1) {
-        while (len-- > 0) zrleTilePixels8[ptr++] = (byte)pix;
-      } else {
-        while (len-- > 0) zrleTilePixels24[ptr++] = pix;
-      }
-    }
-  }
-
-  //
-  // ZRLE encoder's data.
-  //
-
-  private byte[] zrleBuf;
-  private int zrleBufLen = 0;
-  private byte[] zrleTilePixels8;
-  private int[] zrleTilePixels24;
-  private ZlibInStream zrleInStream;
-  private boolean zrleRecWarningShown = false;
-}
diff --git a/java/src/com/tightvnc/decoder/ZlibDecoder.java b/java/src/com/tightvnc/decoder/ZlibDecoder.java
deleted file mode 100644 (file)
index 1370da1..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-package com.tightvnc.decoder;
-
-import com.tightvnc.vncviewer.RfbInputStream;
-import java.awt.Graphics;
-import java.io.IOException;
-import java.util.zip.DataFormatException;
-import java.util.zip.Inflater;
-
-//
-// Class that used for decoding ZLib encoded data.
-//
-
-public class ZlibDecoder extends RawDecoder {
-
-  final static int EncodingZlib = 6;
-
-  public ZlibDecoder(Graphics g, RfbInputStream is) {
-    super(g, is);
-  }
-
-  public ZlibDecoder(Graphics g, RfbInputStream is, int frameBufferW,
-                     int frameBufferH) {
-    super(g, is, frameBufferW, frameBufferH);
-  }
-
-  //
-  // Override handleRect method to decode ZLib encoded data insted of
-  // raw pixel data.
-  //
-
-  public void handleRect(int x, int y, int w, int h) throws IOException  {
-
-    //
-    // Write encoding ID to record output stream.
-    // Remark: we forced changed encoding from zlib to raw
-    // cause at this moment we cannot save data in zlib encoding.
-    //
-
-    if (dos != null) {
-      dos.writeInt(RawDecoder.EncodingRaw);
-    }
-
-    int nBytes = rfbis.readU32();
-
-    if (zlibBuf == null || zlibBufLen < nBytes) {
-      zlibBufLen = nBytes * 2;
-      zlibBuf = new byte[zlibBufLen];
-    }
-
-    rfbis.readFully(zlibBuf, 0, nBytes);
-
-    if (zlibInflater == null) {
-      zlibInflater = new Inflater();
-    }
-    zlibInflater.setInput(zlibBuf, 0, nBytes);
-
-    try {
-      if (bytesPerPixel == 1) {
-        for (int dy = y; dy < y + h; dy++) {
-          zlibInflater.inflate(pixels8, dy * framebufferWidth + x, w);
-
-          //
-          // Save decoded raw data to data output stream
-          //
-
-          if (dos != null)
-            dos.write(pixels8, dy * framebufferWidth + x, w);
-        }
-      } else {
-        byte[] buf = new byte[w * 4];
-        int i, offset;
-        for (int dy = y; dy < y + h; dy++) {
-          zlibInflater.inflate(buf);
-          offset = dy * framebufferWidth + x;
-          for (i = 0; i < w; i++) {
-            RawDecoder.pixels24[offset + i] =
-              (buf[i * 4 + 2] & 0xFF) << 16 |
-              (buf[i * 4 + 1] & 0xFF) << 8 |
-              (buf[i * 4] & 0xFF);
-          }
-
-          //
-          // Save decoded raw data to data output stream
-          //
-
-          if (dos != null)
-            dos.write(buf);
-        }
-      }
-    } catch (DataFormatException ex) {
-      ex.printStackTrace();
-    }
-    handleUpdatedPixels(x, y, w, h);
-  }
-
-  //
-  // Zlib encoder's data.
-  //
-
-  protected byte[] zlibBuf;
-  protected int zlibBufLen = 0;
-  protected Inflater zlibInflater;
-}
diff --git a/java/src/com/tightvnc/decoder/common/Repaintable.java b/java/src/com/tightvnc/decoder/common/Repaintable.java
deleted file mode 100644 (file)
index de11f4c..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.tightvnc.decoder.common;
-
-public interface Repaintable {
-
-  public void scheduleRepaint(int x, int y, int w, int h);
-
-}
diff --git a/java/src/com/tightvnc/vncviewer/AuthPanel.java b/java/src/com/tightvnc/vncviewer/AuthPanel.java
deleted file mode 100644 (file)
index 28be721..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-//
-//  Copyright (C) 1999 AT&T Laboratories Cambridge.  All Rights Reserved.
-//  Copyright (C) 2002-2006 Constantin Kaplinsky.  All Rights Reserved.
-//
-//  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.
-//
-
-package com.tightvnc.vncviewer;
-
-import java.awt.*;
-import java.awt.event.*;
-
-//
-// The panel which implements the user authentication scheme
-//
-
-class AuthPanel extends Panel implements ActionListener {
-
-  TextField passwordField;
-  Button okButton;
-
-  //
-  // Constructor.
-  //
-
-  public AuthPanel(VncViewer viewer)
-  {
-    Label titleLabel = new Label("VNC Authentication", Label.CENTER);
-    titleLabel.setFont(new Font("Helvetica", Font.BOLD, 18));
-
-    Label promptLabel = new Label("Password:", Label.CENTER);
-
-    passwordField = new TextField(10);
-    passwordField.setForeground(Color.black);
-    passwordField.setBackground(Color.white);
-    passwordField.setEchoChar('*');
-
-    okButton = new Button("OK");
-
-    GridBagLayout gridbag = new GridBagLayout();
-    GridBagConstraints gbc = new GridBagConstraints();
-
-    setLayout(gridbag);
-
-    gbc.gridwidth = GridBagConstraints.REMAINDER;
-    gbc.insets = new Insets(0,0,20,0);
-    gridbag.setConstraints(titleLabel,gbc);
-    add(titleLabel);
-
-    gbc.fill = GridBagConstraints.NONE;
-    gbc.gridwidth = 1;
-    gbc.insets = new Insets(0,0,0,0);
-    gridbag.setConstraints(promptLabel,gbc);
-    add(promptLabel);
-
-    gridbag.setConstraints(passwordField,gbc);
-    add(passwordField);
-    passwordField.addActionListener(this);
-
-    // gbc.ipady = 10;
-    gbc.gridwidth = GridBagConstraints.REMAINDER;
-    gbc.fill = GridBagConstraints.BOTH;
-    gbc.insets = new Insets(0,20,0,0);
-    gbc.ipadx = 30;
-    gridbag.setConstraints(okButton,gbc);
-    add(okButton);
-    okButton.addActionListener(this);
-  }
-
-  //
-  // Move keyboard focus to the default object, that is, the password
-  // text field.
-  //
-
-  public void moveFocusToDefaultField()
-  {
-    passwordField.requestFocus();
-  }
-
-  //
-  // This method is called when a button is pressed or return is
-  // pressed in the password text field.
-  //
-
-  public synchronized void actionPerformed(ActionEvent evt)
-  {
-    if (evt.getSource() == passwordField || evt.getSource() == okButton) {
-      passwordField.setEnabled(false);
-      notify();
-    }
-  }
-
-  //
-  // Wait for user entering a password, and return it as String.
-  //
-
-  public synchronized String getPassword() throws Exception
-  {
-    try {
-      wait();
-    } catch (InterruptedException e) { }
-    return passwordField.getText();
-  }
-
-}
diff --git a/java/src/com/tightvnc/vncviewer/ButtonPanel.java b/java/src/com/tightvnc/vncviewer/ButtonPanel.java
deleted file mode 100644 (file)
index 985a9c2..0000000
+++ /dev/null
@@ -1,222 +0,0 @@
-//
-//  Copyright (C) 2001,2002 HorizonLive.com, Inc.  All Rights Reserved.
-//  Copyright (C) 1999 AT&T Laboratories Cambridge.  All Rights Reserved.
-//
-//  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.
-//
-
-//
-// ButtonPanel class implements panel with four buttons in the
-// VNCViewer desktop window.
-//
-
-package com.tightvnc.vncviewer;
-
-import java.awt.*;
-import java.awt.event.*;
-import java.io.*;
-
-class ButtonPanel extends Panel implements ActionListener {
-
-  VncViewer viewer;
-  Button disconnectButton;
-  Button optionsButton;
-  Button recordButton;
-  Button clipboardButton;
-  Button ctrlAltDelButton;
-  Button refreshButton;
-  Button selectButton;
-  Button videoFreezeButton;
-
-  final String enableVideoFreezeLabel = "Ignore Video";
-  final String disableVideoFreezeLabel = "Enable Video";
-  final String selectEnterLabel = "Select Video Area";
-  final String selectLeaveLabel = "Hide Selection";
-
-  ButtonPanel(VncViewer v) {
-    viewer = v;
-
-    setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
-    disconnectButton = new Button("Disconnect");
-    disconnectButton.setEnabled(false);
-    add(disconnectButton);
-    disconnectButton.addActionListener(this);
-    optionsButton = new Button("Options");
-    add(optionsButton);
-    optionsButton.addActionListener(this);
-    clipboardButton = new Button("Clipboard");
-    clipboardButton.setEnabled(false);
-    add(clipboardButton);
-    clipboardButton.addActionListener(this);
-    if (viewer.rec != null) {
-      recordButton = new Button("Record");
-      add(recordButton);
-      recordButton.addActionListener(this);
-    }
-    ctrlAltDelButton = new Button("Send Ctrl-Alt-Del");
-    ctrlAltDelButton.setEnabled(false);
-    add(ctrlAltDelButton);
-    ctrlAltDelButton.addActionListener(this);
-    refreshButton = new Button("Refresh");
-    refreshButton.setEnabled(false);
-    add(refreshButton);
-    refreshButton.addActionListener(this);
-  }
-
-  /**
-   * Add video selection button to the ButtonPanel.
-   */
-  public void addSelectButton() {
-    selectButton = new Button(selectEnterLabel);
-    selectButton.setEnabled(false);
-    add(selectButton);
-    selectButton.addActionListener(this);
-  }
-
-  /**
-   * Add video ignore button to the ButtonPanel.
-   */
-  public void addVideoFreezeButton() {
-    videoFreezeButton = new Button(enableVideoFreezeLabel);
-    add(videoFreezeButton);
-    videoFreezeButton.addActionListener(this);
-  }
-
-  //
-  // Enable buttons on successful connection.
-  //
-
-  public void enableButtons() {
-    disconnectButton.setEnabled(true);
-    clipboardButton.setEnabled(true);
-    refreshButton.setEnabled(true);
-    if (selectButton != null) {
-      selectButton.setEnabled(true);
-    }
-  }
-
-  //
-  // Disable all buttons on disconnect.
-  //
-
-  public void disableButtonsOnDisconnect() {
-    remove(disconnectButton);
-    disconnectButton = new Button("Hide desktop");
-    disconnectButton.setEnabled(true);
-    add(disconnectButton, 0);
-    disconnectButton.addActionListener(this);
-
-    optionsButton.setEnabled(false);
-    clipboardButton.setEnabled(false);
-    ctrlAltDelButton.setEnabled(false);
-    refreshButton.setEnabled(false);
-    if (selectButton != null) {
-      selectButton.setEnabled(false);
-    }
-  }
-
-  //
-  // Enable/disable controls that should not be available in view-only
-  // mode.
-  //
-
-  public void enableRemoteAccessControls(boolean enable) {
-    ctrlAltDelButton.setEnabled(enable);
-  }
-
-  //
-  // Event processing.
-  //
-
-  public void actionPerformed(ActionEvent evt) {
-
-    viewer.moveFocusToDesktop();
-
-    if (evt.getSource() == disconnectButton) {
-      viewer.disconnect();
-
-    } else if (evt.getSource() == optionsButton) {
-      viewer.options.setVisible(!viewer.options.isVisible());
-
-    } else if (evt.getSource() == recordButton) {
-      viewer.rec.setVisible(!viewer.rec.isVisible());
-
-    } else if (evt.getSource() == clipboardButton) {
-      viewer.clipboard.setVisible(!viewer.clipboard.isVisible());
-    } else if (evt.getSource() == videoFreezeButton) {
-
-      //
-      // Send video freeze message to server and change caption of button
-      //
-
-      //
-      // TODO: Move this code to another place.
-      //
-
-      boolean sendOk = true;
-      boolean currentFreezeState =
-              videoFreezeButton.getLabel().equals(disableVideoFreezeLabel);
-      try {
-        viewer.rfb.trySendVideoFreeze(!currentFreezeState);
-      } catch (IOException ex) {
-        sendOk = false;
-        ex.printStackTrace();
-      }
-      if (sendOk) {
-        if (!currentFreezeState) {
-            videoFreezeButton.setLabel(disableVideoFreezeLabel);
-        } else {
-            videoFreezeButton.setLabel(enableVideoFreezeLabel);
-        }
-      }
-    } else if (evt.getSource() == ctrlAltDelButton) {
-      try {
-        final int modifiers = InputEvent.CTRL_MASK | InputEvent.ALT_MASK;
-
-        KeyEvent ctrlAltDelEvent =
-          new KeyEvent(this, KeyEvent.KEY_PRESSED, 0, modifiers, 127);
-        viewer.rfb.writeKeyEvent(ctrlAltDelEvent);
-
-        ctrlAltDelEvent =
-          new KeyEvent(this, KeyEvent.KEY_RELEASED, 0, modifiers, 127);
-        viewer.rfb.writeKeyEvent(ctrlAltDelEvent);
-
-      } catch (IOException e) {
-        e.printStackTrace();
-      }
-    } else if (evt.getSource() == refreshButton) {
-      try {
-       RfbProto rfb = viewer.rfb;
-       rfb.writeFramebufferUpdateRequest(0, 0, rfb.framebufferWidth,
-                                         rfb.framebufferHeight, false);
-      } catch (IOException e) {
-        e.printStackTrace();
-      }
-    } else if (selectButton != null && evt.getSource() == selectButton) {
-      if (viewer.vc != null) {
-        boolean isSelecting = viewer.vc.isInSelectionMode();
-        if (!isSelecting) {
-          selectButton.setLabel(selectLeaveLabel);
-          viewer.vc.enableSelection(true);
-        } else {
-          selectButton.setLabel(selectEnterLabel);
-          viewer.vc.enableSelection(false);
-        }
-      }
-    }
-  }
-}
-
diff --git a/java/src/com/tightvnc/vncviewer/CapabilityInfo.java b/java/src/com/tightvnc/vncviewer/CapabilityInfo.java
deleted file mode 100644 (file)
index 092f53e..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-//
-//  Copyright (C) 2003 Constantin Kaplinsky.  All Rights Reserved.
-//
-//  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.
-//
-
-//
-// CapabilityInfo.java - A class to hold information about a
-// particular capability as used in the RFB protocol 3.130.
-//
-
-package com.tightvnc.vncviewer;
-
-class CapabilityInfo {
-
-  // Public methods
-
-  public CapabilityInfo(int code,
-                       String vendorSignature,
-                       String nameSignature,
-                       String description) {
-    this.code = code;
-    this.vendorSignature = vendorSignature;
-    this.nameSignature = nameSignature;
-    this.description = description;
-    enabled = false;
-  }
-
-  public CapabilityInfo(int code,
-                       byte[] vendorSignature,
-                       byte[] nameSignature) {
-    this.code = code;
-    this.vendorSignature = new String(vendorSignature);
-    this.nameSignature = new String(nameSignature);
-    this.description = null;
-    enabled = false;
-  }
-
-  public int getCode() {
-    return code;
-  }
-
-  public String getDescription() {
-    return description;
-  }
-
-  public boolean isEnabled() {
-    return enabled;
-  }
-
-  public void enable() {
-    enabled = true;
-  }
-
-  public boolean equals(CapabilityInfo other) {
-    return (other != null && this.code == other.code &&
-           this.vendorSignature.equals(other.vendorSignature) &&
-           this.nameSignature.equals(other.nameSignature));
-  }
-
-  public boolean enableIfEquals(CapabilityInfo other) {
-    if (this.equals(other))
-      enable();
-
-    return isEnabled();
-  }
-
-  // Protected data
-
-  protected int code;
-  protected String vendorSignature;
-  protected String nameSignature;
-
-  protected String description;
-  protected boolean enabled;
-}
diff --git a/java/src/com/tightvnc/vncviewer/CapsContainer.java b/java/src/com/tightvnc/vncviewer/CapsContainer.java
deleted file mode 100644 (file)
index b9acbf4..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-//
-//  Copyright (C) 2003 Constantin Kaplinsky.  All Rights Reserved.
-//
-//  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.
-//
-
-//
-// CapsContainer.java - A container of capabilities as used in the RFB
-// protocol 3.130
-//
-
-package com.tightvnc.vncviewer;
-
-import java.util.Vector;
-import java.util.Hashtable;
-
-class CapsContainer {
-
-  // Public methods
-
-  public CapsContainer() {
-    infoMap = new Hashtable(64, (float)0.25);
-    orderedList = new Vector(32, 8);
-  }
-
-  public void add(CapabilityInfo capinfo) {
-    Integer key = new Integer(capinfo.getCode());
-    infoMap.put(key, capinfo);
-  }
-
-  public void add(int code, String vendor, String name, String desc) {
-    Integer key = new Integer(code);
-    infoMap.put(key, new CapabilityInfo(code, vendor, name, desc));
-  }
-
-  public boolean isKnown(int code) {
-    return infoMap.containsKey(new Integer(code));
-  }
-
-  public CapabilityInfo getInfo(int code) {
-    return (CapabilityInfo)infoMap.get(new Integer(code));
-  }
-
-  public String getDescription(int code) {
-    CapabilityInfo capinfo = (CapabilityInfo)infoMap.get(new Integer(code));
-    if (capinfo == null)
-      return null;
-
-    return capinfo.getDescription();
-  }
-
-  public boolean enable(CapabilityInfo other) {
-    Integer key = new Integer(other.getCode());
-    CapabilityInfo capinfo = (CapabilityInfo)infoMap.get(key);
-    if (capinfo == null)
-      return false;
-
-    boolean enabled = capinfo.enableIfEquals(other);
-    if (enabled)
-      orderedList.addElement(key);
-
-    return enabled;
-  }
-
-  public boolean isEnabled(int code) {
-    CapabilityInfo capinfo = (CapabilityInfo)infoMap.get(new Integer(code));
-    if (capinfo == null)
-      return false;
-
-    return capinfo.isEnabled();
-  }
-
-  public int numEnabled() {
-    return orderedList.size();
-  }
-
-  public int getByOrder(int idx) {
-    int code;
-    try {
-      code = ((Integer)orderedList.elementAt(idx)).intValue();
-    } catch (ArrayIndexOutOfBoundsException e) {
-      code = 0;
-    }
-    return code;
-  }
-
-  // Protected data
-
-  protected Hashtable infoMap;
-  protected Vector orderedList;
-}
-
diff --git a/java/src/com/tightvnc/vncviewer/ClipboardFrame.java b/java/src/com/tightvnc/vncviewer/ClipboardFrame.java
deleted file mode 100644 (file)
index 2b11eb8..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-//
-//  Copyright (C) 2001 HorizonLive.com, Inc.  All Rights Reserved.
-//  Copyright (C) 1999 AT&T Laboratories Cambridge.  All Rights Reserved.
-//
-//  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.
-//
-
-//
-// Clipboard frame.
-//
-
-package com.tightvnc.vncviewer;
-
-import java.awt.*;
-import java.awt.event.*;
-
-class ClipboardFrame extends Frame
-  implements WindowListener, ActionListener {
-
-  TextArea textArea;
-  Button clearButton, closeButton;
-  String selection;
-  VncViewer viewer;
-
-  //
-  // Constructor.
-  //
-
-  ClipboardFrame(VncViewer v) {
-    super("TigerVNC Clipboard");
-
-    viewer = v;
-
-    GridBagLayout gridbag = new GridBagLayout();
-    setLayout(gridbag);
-
-    GridBagConstraints gbc = new GridBagConstraints();
-    gbc.gridwidth = GridBagConstraints.REMAINDER;
-    gbc.fill = GridBagConstraints.BOTH;
-    gbc.weighty = 1.0;
-
-    textArea = new TextArea(5, 40);
-    gridbag.setConstraints(textArea, gbc);
-    add(textArea);
-
-    gbc.fill = GridBagConstraints.HORIZONTAL;
-    gbc.weightx = 1.0;
-    gbc.weighty = 0.0;
-    gbc.gridwidth = 1;
-
-    clearButton = new Button("Clear");
-    gridbag.setConstraints(clearButton, gbc);
-    add(clearButton);
-    clearButton.addActionListener(this);
-
-    closeButton = new Button("Close");
-    gridbag.setConstraints(closeButton, gbc);
-    add(closeButton);
-    closeButton.addActionListener(this);
-
-    pack();
-
-    addWindowListener(this);
-  }
-
-
-  //
-  // Set the cut text from the RFB server.
-  //
-
-  void setCutText(String text) {
-    selection = text;
-    textArea.setText(text);
-    if (isVisible()) {
-      textArea.selectAll();
-    }
-  }
-
-
-  //
-  // When the focus leaves the window, see if we have new cut text and
-  // if so send it to the RFB server.
-  //
-
-  public void windowDeactivated (WindowEvent evt) {
-    if (selection != null && !selection.equals(textArea.getText())) {
-      selection = textArea.getText();
-      viewer.setCutText(selection);
-    }
-  }
-
-  //
-  // Close our window properly.
-  //
-
-  public void windowClosing(WindowEvent evt) {
-    setVisible(false);
-  }
-
-  //
-  // Ignore window events we're not interested in.
-  //
-
-  public void windowActivated(WindowEvent evt) {}
-  public void windowOpened(WindowEvent evt) {}
-  public void windowClosed(WindowEvent evt) {}
-  public void windowIconified(WindowEvent evt) {}
-  public void windowDeiconified(WindowEvent evt) {}
-
-
-  //
-  // Respond to button presses
-  //
-
-  public void actionPerformed(ActionEvent evt) {
-    if (evt.getSource() == clearButton) {
-      textArea.setText("");
-    } else if (evt.getSource() == closeButton) {
-      setVisible(false);
-    }
-  }
-}
diff --git a/java/src/com/tightvnc/vncviewer/DesCipher.java b/java/src/com/tightvnc/vncviewer/DesCipher.java
deleted file mode 100644 (file)
index 9ebeaa8..0000000
+++ /dev/null
@@ -1,498 +0,0 @@
-//
-// This DES class has been extracted from package Acme.Crypto for use in VNC.
-// The bytebit[] array has been reversed so that the most significant bit
-// in each byte of the key is ignored, not the least significant.  Also the
-// unnecessary odd parity code has been removed.
-//
-// These changes are:
-//  Copyright (C) 1999 AT&T Laboratories Cambridge.  All Rights Reserved.
-//
-// 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.
-//
-
-// DesCipher - the DES encryption method
-//
-// The meat of this code is by Dave Zimmerman <dzimm@widget.com>, and is:
-//
-// Copyright (c) 1996 Widget Workshop, Inc. All Rights Reserved.
-//
-// Permission to use, copy, modify, and distribute this software
-// and its documentation for NON-COMMERCIAL or COMMERCIAL purposes and
-// without fee is hereby granted, provided that this copyright notice is kept 
-// intact. 
-// 
-// WIDGET WORKSHOP MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY
-// OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
-// TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
-// PARTICULAR PURPOSE, OR NON-INFRINGEMENT. WIDGET WORKSHOP SHALL NOT BE LIABLE
-// FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
-// DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
-// 
-// THIS SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE OR RESALE AS ON-LINE
-// CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE
-// PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT
-// NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT LIFE
-// SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE
-// SOFTWARE COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE
-// PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH RISK ACTIVITIES").  WIDGET WORKSHOP
-// SPECIFICALLY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR
-// HIGH RISK ACTIVITIES.
-//
-//
-// The rest is:
-//
-// Copyright (C) 1996 by Jef Poskanzer <jef@acme.com>.  All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions
-// are met:
-// 1. Redistributions of source code must retain the above copyright
-//    notice, this list of conditions and the following disclaimer.
-// 2. Redistributions in binary form must reproduce the above copyright
-//    notice, this list of conditions and the following disclaimer in the
-//    documentation and/or other materials provided with the distribution.
-//
-// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-// ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-// SUCH DAMAGE.
-//
-// Visit the ACME Labs Java page for up-to-date versions of this and other
-// fine Java utilities: http://www.acme.com/java/
-
-
-package com.tightvnc.vncviewer;
-
-import java.io.*;
-
-/// The DES encryption method.
-// <P>
-// This is surprisingly fast, for pure Java.  On a SPARC 20, wrapped
-// in Acme.Crypto.EncryptedOutputStream or Acme.Crypto.EncryptedInputStream,
-// it does around 7000 bytes/second.
-// <P>
-// Most of this code is by Dave Zimmerman <dzimm@widget.com>, and is
-// Copyright (c) 1996 Widget Workshop, Inc.  See the source file for details.
-// <P>
-// <A HREF="/resources/classes/Acme/Crypto/DesCipher.java">Fetch the software.</A><BR>
-// <A HREF="/resources/classes/Acme.tar.Z">Fetch the entire Acme package.</A>
-// <P>
-// @see Des3Cipher
-// @see EncryptedOutputStream
-// @see EncryptedInputStream
-
-public class DesCipher
-    {
-
-    // Constructor, byte-array key.
-    public DesCipher( byte[] key )
-       {
-       setKey( key );
-       }
-
-    // Key routines.
-
-    private int[] encryptKeys = new int[32];
-    private int[] decryptKeys = new int[32];
-
-    /// Set the key.
-    public void setKey( byte[] key )
-       {
-       deskey( key, true, encryptKeys );
-       deskey( key, false, decryptKeys );
-       }
-
-    // Turn an 8-byte key into internal keys.
-    private void deskey( byte[] keyBlock, boolean encrypting, int[] KnL )
-       {
-       int i, j, l, m, n;
-       int[] pc1m = new int[56];
-       int[] pcr = new int[56];
-       int[] kn = new int[32];
-
-       for ( j = 0; j < 56; ++j )
-           {
-           l = pc1[j];
-           m = l & 07;
-           pc1m[j] = ( (keyBlock[l >>> 3] & bytebit[m]) != 0 )? 1: 0;
-           }
-
-       for ( i = 0; i < 16; ++i )
-           {
-           if ( encrypting )
-               m = i << 1;
-           else
-               m = (15-i) << 1;
-           n = m+1;
-           kn[m] = kn[n] = 0;
-           for ( j = 0; j < 28; ++j )
-               {
-               l = j+totrot[i];
-               if ( l < 28 )
-                   pcr[j] = pc1m[l];
-               else
-                   pcr[j] = pc1m[l-28];
-               }
-           for ( j=28; j < 56; ++j )
-               {
-               l = j+totrot[i];
-               if ( l < 56 )
-                   pcr[j] = pc1m[l];
-               else
-                   pcr[j] = pc1m[l-28];
-               }
-           for ( j = 0; j < 24; ++j )
-               {
-               if ( pcr[pc2[j]] != 0 )
-                   kn[m] |= bigbyte[j];
-               if ( pcr[pc2[j+24]] != 0 )
-                   kn[n] |= bigbyte[j];
-               }
-           }
-       cookey( kn, KnL );
-       }
-
-    private void cookey( int[] raw, int KnL[] )
-       {
-       int raw0, raw1;
-       int rawi, KnLi;
-       int i;
-
-       for ( i = 0, rawi = 0, KnLi = 0; i < 16; ++i )
-           {
-           raw0 = raw[rawi++];
-           raw1 = raw[rawi++];
-           KnL[KnLi]  = (raw0 & 0x00fc0000) <<   6;
-           KnL[KnLi] |= (raw0 & 0x00000fc0) <<  10;
-           KnL[KnLi] |= (raw1 & 0x00fc0000) >>> 10;
-           KnL[KnLi] |= (raw1 & 0x00000fc0) >>>  6;
-           ++KnLi;
-           KnL[KnLi]  = (raw0 & 0x0003f000) <<  12;
-           KnL[KnLi] |= (raw0 & 0x0000003f) <<  16;
-           KnL[KnLi] |= (raw1 & 0x0003f000) >>>  4;
-           KnL[KnLi] |= (raw1 & 0x0000003f);
-           ++KnLi;
-           }
-       }
-
-
-    // Block encryption routines.
-
-    private int[] tempInts = new int[2];
-
-    /// Encrypt a block of eight bytes.
-    public void encrypt( byte[] clearText, int clearOff, byte[] cipherText, int cipherOff )
-       {
-       squashBytesToInts( clearText, clearOff, tempInts, 0, 2 );
-       des( tempInts, tempInts, encryptKeys );
-       spreadIntsToBytes( tempInts, 0, cipherText, cipherOff, 2 );
-       }
-
-    /// Decrypt a block of eight bytes.
-    public void decrypt( byte[] cipherText, int cipherOff, byte[] clearText, int clearOff )
-       {
-       squashBytesToInts( cipherText, cipherOff, tempInts, 0, 2 );
-       des( tempInts, tempInts, decryptKeys );
-       spreadIntsToBytes( tempInts, 0, clearText, clearOff, 2 );
-       }
-
-    // The DES function.
-    private void des( int[] inInts, int[] outInts, int[] keys )
-       {
-       int fval, work, right, leftt;
-       int round;
-       int keysi = 0;
-
-       leftt = inInts[0];
-       right = inInts[1];
-
-       work   = ((leftt >>>  4) ^ right) & 0x0f0f0f0f;
-       right ^= work;
-       leftt ^= (work << 4);
-
-       work   = ((leftt >>> 16) ^ right) & 0x0000ffff;
-       right ^= work;
-       leftt ^= (work << 16);
-
-       work   = ((right >>>  2) ^ leftt) & 0x33333333;
-       leftt ^= work;
-       right ^= (work << 2);
-
-       work   = ((right >>>  8) ^ leftt) & 0x00ff00ff;
-       leftt ^= work;
-       right ^= (work << 8);
-       right  = (right << 1) | ((right >>> 31) & 1);
-
-       work   = (leftt ^ right) & 0xaaaaaaaa;
-       leftt ^= work;
-       right ^= work;
-       leftt  = (leftt << 1) | ((leftt >>> 31) & 1);
-
-       for ( round = 0; round < 8; ++round )
-           {
-           work   = (right << 28) | (right >>> 4);
-           work  ^= keys[keysi++];
-           fval   = SP7[ work         & 0x0000003f ];
-           fval  |= SP5[(work >>>  8) & 0x0000003f ];
-           fval  |= SP3[(work >>> 16) & 0x0000003f ];
-           fval  |= SP1[(work >>> 24) & 0x0000003f ];
-           work   = right ^ keys[keysi++];
-           fval  |= SP8[ work         & 0x0000003f ];
-           fval  |= SP6[(work >>>  8) & 0x0000003f ];
-           fval  |= SP4[(work >>> 16) & 0x0000003f ];
-           fval  |= SP2[(work >>> 24) & 0x0000003f ];
-           leftt ^= fval;
-           work   = (leftt << 28) | (leftt >>> 4);
-           work  ^= keys[keysi++];
-           fval   = SP7[ work         & 0x0000003f ];
-           fval  |= SP5[(work >>>  8) & 0x0000003f ];
-           fval  |= SP3[(work >>> 16) & 0x0000003f ];
-           fval  |= SP1[(work >>> 24) & 0x0000003f ];
-           work   = leftt ^ keys[keysi++];
-           fval  |= SP8[ work         & 0x0000003f ];
-           fval  |= SP6[(work >>>  8) & 0x0000003f ];
-           fval  |= SP4[(work >>> 16) & 0x0000003f ];
-           fval  |= SP2[(work >>> 24) & 0x0000003f ];
-           right ^= fval;
-           }
-
-       right  = (right << 31) | (right >>> 1);
-       work   = (leftt ^ right) & 0xaaaaaaaa;
-       leftt ^= work;
-       right ^= work;
-       leftt  = (leftt << 31) | (leftt >>> 1);
-       work   = ((leftt >>>  8) ^ right) & 0x00ff00ff;
-       right ^= work;
-       leftt ^= (work << 8);
-       work   = ((leftt >>>  2) ^ right) & 0x33333333;
-       right ^= work;
-       leftt ^= (work << 2);
-       work   = ((right >>> 16) ^ leftt) & 0x0000ffff;
-       leftt ^= work;
-       right ^= (work << 16);
-       work   = ((right >>>  4) ^ leftt) & 0x0f0f0f0f;
-       leftt ^= work;
-       right ^= (work << 4);
-       outInts[0] = right;
-       outInts[1] = leftt;
-       }
-
-
-    // Tables, permutations, S-boxes, etc.
-
-    private static byte[] bytebit = {
-       (byte)0x01, (byte)0x02, (byte)0x04, (byte)0x08,
-       (byte)0x10, (byte)0x20, (byte)0x40, (byte)0x80
-       };
-    private static int[] bigbyte = {
-       0x800000, 0x400000, 0x200000, 0x100000,
-       0x080000, 0x040000, 0x020000, 0x010000,
-       0x008000, 0x004000, 0x002000, 0x001000,
-       0x000800, 0x000400, 0x000200, 0x000100,
-       0x000080, 0x000040, 0x000020, 0x000010,
-       0x000008, 0x000004, 0x000002, 0x000001
-       };
-    private static byte[] pc1 = {
-         (byte)56, (byte)48, (byte)40, (byte)32, (byte)24, (byte)16, (byte) 8,
-      (byte) 0, (byte)57, (byte)49, (byte)41, (byte)33, (byte)25, (byte)17,
-        (byte) 9, (byte) 1, (byte)58, (byte)50, (byte)42, (byte)34, (byte)26,
-      (byte)18, (byte)10, (byte) 2, (byte)59, (byte)51, (byte)43, (byte)35,
-        (byte)62, (byte)54, (byte)46, (byte)38, (byte)30, (byte)22, (byte)14,
-      (byte) 6, (byte)61, (byte)53, (byte)45, (byte)37, (byte)29, (byte)21,
-        (byte)13, (byte) 5, (byte)60, (byte)52, (byte)44, (byte)36, (byte)28,
-      (byte)20, (byte)12, (byte) 4, (byte)27, (byte)19, (byte)11, (byte)3
-       };
-    private static int[] totrot = {
-        1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28
-       };
-
-    private static byte[] pc2 = {
-       (byte)13, (byte)16, (byte)10, (byte)23, (byte) 0, (byte) 4,
-                 (byte) 2, (byte)27, (byte)14, (byte) 5, (byte)20, (byte) 9,
-       (byte)22, (byte)18, (byte)11, (byte)3 , (byte)25, (byte) 7,
-                 (byte)15, (byte) 6, (byte)26, (byte)19, (byte)12, (byte) 1,
-       (byte)40, (byte)51, (byte)30, (byte)36, (byte)46, (byte)54,
-                 (byte)29, (byte)39, (byte)50, (byte)44, (byte)32, (byte)47,
-       (byte)43, (byte)48, (byte)38, (byte)55, (byte)33, (byte)52,
-                 (byte)45, (byte)41, (byte)49, (byte)35, (byte)28, (byte)31,
-       };
-
-    private static int[] SP1 = {
-        0x01010400, 0x00000000, 0x00010000, 0x01010404,
-       0x01010004, 0x00010404, 0x00000004, 0x00010000,
-       0x00000400, 0x01010400, 0x01010404, 0x00000400,
-       0x01000404, 0x01010004, 0x01000000, 0x00000004,
-       0x00000404, 0x01000400, 0x01000400, 0x00010400,
-       0x00010400, 0x01010000, 0x01010000, 0x01000404,
-       0x00010004, 0x01000004, 0x01000004, 0x00010004,
-       0x00000000, 0x00000404, 0x00010404, 0x01000000,
-       0x00010000, 0x01010404, 0x00000004, 0x01010000,
-       0x01010400, 0x01000000, 0x01000000, 0x00000400,
-       0x01010004, 0x00010000, 0x00010400, 0x01000004,
-       0x00000400, 0x00000004, 0x01000404, 0x00010404,
-       0x01010404, 0x00010004, 0x01010000, 0x01000404,
-       0x01000004, 0x00000404, 0x00010404, 0x01010400,
-       0x00000404, 0x01000400, 0x01000400, 0x00000000,
-       0x00010004, 0x00010400, 0x00000000, 0x01010004
-       };
-    private static int[] SP2 = {
-       0x80108020, 0x80008000, 0x00008000, 0x00108020,
-       0x00100000, 0x00000020, 0x80100020, 0x80008020,
-       0x80000020, 0x80108020, 0x80108000, 0x80000000,
-       0x80008000, 0x00100000, 0x00000020, 0x80100020,
-       0x00108000, 0x00100020, 0x80008020, 0x00000000,
-       0x80000000, 0x00008000, 0x00108020, 0x80100000,
-       0x00100020, 0x80000020, 0x00000000, 0x00108000,
-       0x00008020, 0x80108000, 0x80100000, 0x00008020,
-       0x00000000, 0x00108020, 0x80100020, 0x00100000,
-       0x80008020, 0x80100000, 0x80108000, 0x00008000,
-       0x80100000, 0x80008000, 0x00000020, 0x80108020,
-       0x00108020, 0x00000020, 0x00008000, 0x80000000,
-       0x00008020, 0x80108000, 0x00100000, 0x80000020,
-       0x00100020, 0x80008020, 0x80000020, 0x00100020,
-       0x00108000, 0x00000000, 0x80008000, 0x00008020,
-       0x80000000, 0x80100020, 0x80108020, 0x00108000
-       };
-    private static int[] SP3 = {
-       0x00000208, 0x08020200, 0x00000000, 0x08020008,
-       0x08000200, 0x00000000, 0x00020208, 0x08000200,
-       0x00020008, 0x08000008, 0x08000008, 0x00020000,
-       0x08020208, 0x00020008, 0x08020000, 0x00000208,
-       0x08000000, 0x00000008, 0x08020200, 0x00000200,
-       0x00020200, 0x08020000, 0x08020008, 0x00020208,
-       0x08000208, 0x00020200, 0x00020000, 0x08000208,
-       0x00000008, 0x08020208, 0x00000200, 0x08000000,
-       0x08020200, 0x08000000, 0x00020008, 0x00000208,
-       0x00020000, 0x08020200, 0x08000200, 0x00000000,
-       0x00000200, 0x00020008, 0x08020208, 0x08000200,
-       0x08000008, 0x00000200, 0x00000000, 0x08020008,
-       0x08000208, 0x00020000, 0x08000000, 0x08020208,
-       0x00000008, 0x00020208, 0x00020200, 0x08000008,
-       0x08020000, 0x08000208, 0x00000208, 0x08020000,
-       0x00020208, 0x00000008, 0x08020008, 0x00020200
-       };
-    private static int[] SP4 = {
-       0x00802001, 0x00002081, 0x00002081, 0x00000080,
-       0x00802080, 0x00800081, 0x00800001, 0x00002001,
-       0x00000000, 0x00802000, 0x00802000, 0x00802081,
-       0x00000081, 0x00000000, 0x00800080, 0x00800001,
-       0x00000001, 0x00002000, 0x00800000, 0x00802001,
-       0x00000080, 0x00800000, 0x00002001, 0x00002080,
-       0x00800081, 0x00000001, 0x00002080, 0x00800080,
-       0x00002000, 0x00802080, 0x00802081, 0x00000081,
-       0x00800080, 0x00800001, 0x00802000, 0x00802081,
-       0x00000081, 0x00000000, 0x00000000, 0x00802000,
-       0x00002080, 0x00800080, 0x00800081, 0x00000001,
-       0x00802001, 0x00002081, 0x00002081, 0x00000080,
-       0x00802081, 0x00000081, 0x00000001, 0x00002000,
-       0x00800001, 0x00002001, 0x00802080, 0x00800081,
-       0x00002001, 0x00002080, 0x00800000, 0x00802001,
-       0x00000080, 0x00800000, 0x00002000, 0x00802080
-       };
-    private static int[] SP5 = {
-       0x00000100, 0x02080100, 0x02080000, 0x42000100,
-       0x00080000, 0x00000100, 0x40000000, 0x02080000,
-       0x40080100, 0x00080000, 0x02000100, 0x40080100,
-       0x42000100, 0x42080000, 0x00080100, 0x40000000,
-       0x02000000, 0x40080000, 0x40080000, 0x00000000,
-       0x40000100, 0x42080100, 0x42080100, 0x02000100,
-       0x42080000, 0x40000100, 0x00000000, 0x42000000,
-       0x02080100, 0x02000000, 0x42000000, 0x00080100,
-       0x00080000, 0x42000100, 0x00000100, 0x02000000,
-       0x40000000, 0x02080000, 0x42000100, 0x40080100,
-       0x02000100, 0x40000000, 0x42080000, 0x02080100,
-       0x40080100, 0x00000100, 0x02000000, 0x42080000,
-       0x42080100, 0x00080100, 0x42000000, 0x42080100,
-       0x02080000, 0x00000000, 0x40080000, 0x42000000,
-       0x00080100, 0x02000100, 0x40000100, 0x00080000,
-       0x00000000, 0x40080000, 0x02080100, 0x40000100
-       };
-    private static int[] SP6 = {
-       0x20000010, 0x20400000, 0x00004000, 0x20404010,
-       0x20400000, 0x00000010, 0x20404010, 0x00400000,
-       0x20004000, 0x00404010, 0x00400000, 0x20000010,
-       0x00400010, 0x20004000, 0x20000000, 0x00004010,
-       0x00000000, 0x00400010, 0x20004010, 0x00004000,
-       0x00404000, 0x20004010, 0x00000010, 0x20400010,
-       0x20400010, 0x00000000, 0x00404010, 0x20404000,
-       0x00004010, 0x00404000, 0x20404000, 0x20000000,
-       0x20004000, 0x00000010, 0x20400010, 0x00404000,
-       0x20404010, 0x00400000, 0x00004010, 0x20000010,
-       0x00400000, 0x20004000, 0x20000000, 0x00004010,
-       0x20000010, 0x20404010, 0x00404000, 0x20400000,
-       0x00404010, 0x20404000, 0x00000000, 0x20400010,
-       0x00000010, 0x00004000, 0x20400000, 0x00404010,
-       0x00004000, 0x00400010, 0x20004010, 0x00000000,
-       0x20404000, 0x20000000, 0x00400010, 0x20004010
-       };
-    private static int[] SP7 = {
-       0x00200000, 0x04200002, 0x04000802, 0x00000000,
-       0x00000800, 0x04000802, 0x00200802, 0x04200800,
-       0x04200802, 0x00200000, 0x00000000, 0x04000002,
-       0x00000002, 0x04000000, 0x04200002, 0x00000802,
-       0x04000800, 0x00200802, 0x00200002, 0x04000800,
-       0x04000002, 0x04200000, 0x04200800, 0x00200002,
-       0x04200000, 0x00000800, 0x00000802, 0x04200802,
-       0x00200800, 0x00000002, 0x04000000, 0x00200800,
-       0x04000000, 0x00200800, 0x00200000, 0x04000802,
-       0x04000802, 0x04200002, 0x04200002, 0x00000002,
-       0x00200002, 0x04000000, 0x04000800, 0x00200000,
-       0x04200800, 0x00000802, 0x00200802, 0x04200800,
-       0x00000802, 0x04000002, 0x04200802, 0x04200000,
-       0x00200800, 0x00000000, 0x00000002, 0x04200802,
-       0x00000000, 0x00200802, 0x04200000, 0x00000800,
-       0x04000002, 0x04000800, 0x00000800, 0x00200002
-       };
-    private static int[] SP8 = {
-       0x10001040, 0x00001000, 0x00040000, 0x10041040,
-       0x10000000, 0x10001040, 0x00000040, 0x10000000,
-       0x00040040, 0x10040000, 0x10041040, 0x00041000,
-       0x10041000, 0x00041040, 0x00001000, 0x00000040,
-       0x10040000, 0x10000040, 0x10001000, 0x00001040,
-       0x00041000, 0x00040040, 0x10040040, 0x10041000,
-       0x00001040, 0x00000000, 0x00000000, 0x10040040,
-       0x10000040, 0x10001000, 0x00041040, 0x00040000,
-       0x00041040, 0x00040000, 0x10041000, 0x00001000,
-       0x00000040, 0x10040040, 0x00001000, 0x00041040,
-       0x10001000, 0x00000040, 0x10000040, 0x10040000,
-       0x10040040, 0x10000000, 0x00040000, 0x10001040,
-       0x00000000, 0x10041040, 0x00040040, 0x10000040,
-       0x10040000, 0x10001000, 0x10001040, 0x00000000,
-       0x10041040, 0x00041000, 0x00041000, 0x00001040,
-       0x00001040, 0x00040040, 0x10000000, 0x10041000
-       };
-
-    // Routines taken from other parts of the Acme utilities.
-
-    /// Squash bytes down to ints.
-    public static void squashBytesToInts( byte[] inBytes, int inOff, int[] outInts, int outOff, int intLen )
-        {
-       for ( int i = 0; i < intLen; ++i )
-           outInts[outOff + i] = 
-               ( ( inBytes[inOff + i * 4    ] & 0xff ) << 24 ) |
-               ( ( inBytes[inOff + i * 4 + 1] & 0xff ) << 16 ) |
-               ( ( inBytes[inOff + i * 4 + 2] & 0xff ) <<  8 ) |
-                 ( inBytes[inOff + i * 4 + 3] & 0xff );
-        }
-
-    /// Spread ints into bytes.
-    public static void spreadIntsToBytes( int[] inInts, int inOff, byte[] outBytes, int outOff, int intLen )
-        {
-       for ( int i = 0; i < intLen; ++i )
-           {
-           outBytes[outOff + i * 4    ] = (byte) ( inInts[inOff + i] >>> 24 );
-           outBytes[outOff + i * 4 + 1] = (byte) ( inInts[inOff + i] >>> 16 );
-           outBytes[outOff + i * 4 + 2] = (byte) ( inInts[inOff + i] >>>  8 );
-           outBytes[outOff + i * 4 + 3] = (byte)   inInts[inOff + i];
-           }
-        }
-    }
diff --git a/java/src/com/tightvnc/vncviewer/HTTPConnectSocket.java b/java/src/com/tightvnc/vncviewer/HTTPConnectSocket.java
deleted file mode 100644 (file)
index c427b06..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-//
-//  Copyright (C) 2002 Constantin Kaplinsky, Inc.  All Rights Reserved.
-//
-//  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.
-//
-
-//
-// HTTPConnectSocket.java together with HTTPConnectSocketFactory.java
-// implement an alternate way to connect to VNC servers via one or two
-// HTTP proxies supporting the HTTP CONNECT method.
-//
-
-package com.tightvnc.vncviewer;
-
-import java.net.*;
-import java.io.*;
-
-class HTTPConnectSocket extends Socket {
-
-  public HTTPConnectSocket(String host, int port,
-                          String proxyHost, int proxyPort)
-    throws IOException {
-
-    // Connect to the specified HTTP proxy
-    super(proxyHost, proxyPort);
-
-    // Send the CONNECT request
-    getOutputStream().write(("CONNECT " + host + ":" + port +
-                            " HTTP/1.0\r\n\r\n").getBytes());
-
-    // Read the first line of the response
-    DataInputStream is = new DataInputStream(getInputStream());
-    String str = is.readLine();
-
-    // Check the HTTP error code -- it should be "200" on success
-    if (!str.startsWith("HTTP/1.0 200 ")) {
-      if (str.startsWith("HTTP/1.0 "))
-       str = str.substring(9);
-      throw new IOException("Proxy reports \"" + str + "\"");
-    }
-
-    // Success -- skip remaining HTTP headers
-    do {
-      str = is.readLine();
-    } while (str.length() != 0);
-  }
-}
-
diff --git a/java/src/com/tightvnc/vncviewer/HTTPConnectSocketFactory.java b/java/src/com/tightvnc/vncviewer/HTTPConnectSocketFactory.java
deleted file mode 100644 (file)
index 3eae6f9..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-//
-//  Copyright (C) 2002 Constantin Kaplinsky, Inc.  All Rights Reserved.
-//
-//  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.
-//
-
-//
-// HTTPConnectSocketFactory.java together with HTTPConnectSocket.java
-// implement an alternate way to connect to VNC servers via one or two
-// HTTP proxies supporting the HTTP CONNECT method.
-//
-
-package com.tightvnc.vncviewer;
-
-import java.applet.*;
-import java.net.*;
-import java.io.*;
-
-class HTTPConnectSocketFactory implements SocketFactory {
-
-  public Socket createSocket(String host, int port, Applet applet)
-    throws IOException {
-
-    return createSocket(host, port,
-                       applet.getParameter("PROXYHOST1"),
-                       applet.getParameter("PROXYPORT1"));
-  }
-
-  public Socket createSocket(String host, int port, String[] args)
-    throws IOException {
-
-    return createSocket(host, port,
-                       readArg(args, "PROXYHOST1"),
-                       readArg(args, "PROXYPORT1"));
-  }
-
-  public Socket createSocket(String host, int port,
-                            String proxyHost, String proxyPortStr)
-    throws IOException {
-
-    int proxyPort = 0;
-    if (proxyPortStr != null) {
-      try {
-       proxyPort = Integer.parseInt(proxyPortStr);
-      } catch (NumberFormatException e) { }
-    }
-
-    if (proxyHost == null || proxyPort == 0) {
-      System.out.println("Incomplete parameter list for HTTPConnectSocket");
-      return new Socket(host, port);
-    }
-
-    System.out.println("HTTP CONNECT via proxy " + proxyHost +
-                      " port " + proxyPort);
-    HTTPConnectSocket s =
-      new HTTPConnectSocket(host, port, proxyHost, proxyPort);
-
-    return (Socket)s;
-  }
-
-  private String readArg(String[] args, String name) {
-
-    for (int i = 0; i < args.length; i += 2) {
-      if (args[i].equalsIgnoreCase(name)) {
-       try {
-         return args[i+1];
-       } catch (Exception e) {
-         return null;
-       }
-      }
-    }
-    return null;
-  }
-}
-
diff --git a/java/src/com/tightvnc/vncviewer/InStream.java b/java/src/com/tightvnc/vncviewer/InStream.java
deleted file mode 100644 (file)
index ecb03d9..0000000
+++ /dev/null
@@ -1,179 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
- * 
- * 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.
- */
-
-//
-// rdr::InStream marshalls data from a buffer stored in RDR (RFB Data
-// Representation).
-//
-
-package com.tightvnc.vncviewer;
-
-abstract public class InStream {
-
-  // check() ensures there is buffer data for at least one item of size
-  // itemSize bytes.  Returns the number of items in the buffer (up to a
-  // maximum of nItems).
-
-  public final int check(int itemSize, int nItems) throws Exception {
-    if (ptr + itemSize * nItems > end) {
-      if (ptr + itemSize > end)
-        return overrun(itemSize, nItems);
-
-      nItems = (end - ptr) / itemSize;
-    }
-    return nItems;
-  }
-
-  public final void check(int itemSize) throws Exception {
-    if (ptr + itemSize > end)
-      overrun(itemSize, 1);
-  }
-
-  // readU/SN() methods read unsigned and signed N-bit integers.
-
-  public final int readS8() throws Exception {
-    check(1); return b[ptr++];
-  }
-
-  public final int readS16() throws Exception {
-    check(2); int b0 = b[ptr++];
-    int b1 = b[ptr++] & 0xff; return b0 << 8 | b1;
-  }
-
-  public final int readS32() throws Exception {
-    check(4); int b0 = b[ptr++];
-    int b1 = b[ptr++] & 0xff;
-    int b2 = b[ptr++] & 0xff;
-    int b3 = b[ptr++] & 0xff;
-    return b0 << 24 | b1 << 16 | b2 << 8 | b3;
-  }
-
-  public final int readU8() throws Exception {
-    return readS8() & 0xff;
-  }
-
-  public final int readU16() throws Exception {
-    return readS16() & 0xffff;
-  }
-
-  public final int readU32() throws Exception {
-    return readS32() & 0xffffffff;
-  }
-
-  // readString() reads a string - a U32 length followed by the data.
-
-  public final String readString() throws Exception {
-    int len = readU32();
-    if (len > maxStringLength)
-      throw new Exception("InStream max string length exceeded");
-
-    char[] str = new char[len];
-    int i = 0;
-    while (i < len) {
-      int j = i + check(1, len - i);
-      while (i < j) {
-       str[i++] = (char)b[ptr++];
-      }
-    }
-
-    return new String(str);
-  }
-
-  // maxStringLength protects against allocating a huge buffer.  Set it
-  // higher if you need longer strings.
-
-  public static int maxStringLength = 65535;
-
-  public final void skip(int bytes) throws Exception {
-    while (bytes > 0) {
-      int n = check(1, bytes);
-      ptr += n;
-      bytes -= n;
-    }
-  }
-
-  // readBytes() reads an exact number of bytes into an array at an offset.
-
-  public void readBytes(byte[] data, int offset, int length) throws Exception {
-    int offsetEnd = offset + length;
-    while (offset < offsetEnd) {
-      int n = check(1, offsetEnd - offset);
-      System.arraycopy(b, ptr, data, offset, n);
-      ptr += n;
-      offset += n;
-    }
-  }
-
-  // readOpaqueN() reads a quantity "without byte-swapping".  Because java has
-  // no byte-ordering, we just use big-endian.
-
-  public final int readOpaque8() throws Exception {
-    return readU8();
-  }
-
-  public final int readOpaque16() throws Exception {
-    return readU16();
-  }
-
-  public final int readOpaque32() throws Exception {
-    return readU32();
-  }
-
-  public final int readOpaque24A() throws Exception {
-    check(3); int b0 = b[ptr++];
-    int b1 = b[ptr++]; int b2 = b[ptr++];
-    return b0 << 24 | b1 << 16 | b2 << 8;
-  }
-
-  public final int readOpaque24B() throws Exception {
-    check(3); int b0 = b[ptr++];
-    int b1 = b[ptr++]; int b2 = b[ptr++];
-    return b0 << 16 | b1 << 8 | b2;
-  }
-
-  // pos() returns the position in the stream.
-
-  abstract public int pos();
-
-  // bytesAvailable() returns true if at least one byte can be read from the
-  // stream without blocking.  i.e. if false is returned then readU8() would
-  // block.
-
-  public boolean bytesAvailable() { return end != ptr; }
-
-  // getbuf(), getptr(), getend() and setptr() are "dirty" methods which allow
-  // you to manipulate the buffer directly.  This is useful for a stream which
-  // is a wrapper around an underlying stream.
-
-  public final byte[] getbuf() { return b; }
-  public final int getptr() { return ptr; }
-  public final int getend() { return end; }
-  public final void setptr(int p) { ptr = p; }
-
-  // overrun() is implemented by a derived class to cope with buffer overrun.
-  // It ensures there are at least itemSize bytes of buffer data.  Returns
-  // the number of items in the buffer (up to a maximum of nItems).  itemSize
-  // is supposed to be "small" (a few bytes).
-
-  abstract protected int overrun(int itemSize, int nItems) throws Exception;
-
-  protected InStream() {}
-  protected byte[] b;
-  protected int ptr;
-  protected int end;
-}
diff --git a/java/src/com/tightvnc/vncviewer/LICENCE.TXT b/java/src/com/tightvnc/vncviewer/LICENCE.TXT
deleted file mode 100644 (file)
index ae3b531..0000000
+++ /dev/null
@@ -1,340 +0,0 @@
-                   GNU GENERAL PUBLIC LICENSE
-                      Version 2, June 1991
-
-         Copyright (C) 1989, 1991 Free Software Foundation, Inc.
-        59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-                           Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users.  This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it.  (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.)  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have.  You must make sure that they, too, receive or can get the
-source code.  And you must show them these terms so they know their
-rights.
-
-  We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
-  Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software.  If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary.  To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-\f
-                   GNU GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License.  The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language.  (Hereinafter, translation is included without limitation in
-the term "modification".)  Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
-  1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
-  2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) You must cause the modified files to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    b) You must cause any work that you distribute or publish, that in
-    whole or in part contains or is derived from the Program or any
-    part thereof, to be licensed as a whole at no charge to all third
-    parties under the terms of this License.
-
-    c) If the modified program normally reads commands interactively
-    when run, you must cause it, when started running for such
-    interactive use in the most ordinary way, to print or display an
-    announcement including an appropriate copyright notice and a
-    notice that there is no warranty (or else, saying that you provide
-    a warranty) and that users may redistribute the program under
-    these conditions, and telling the user how to view a copy of this
-    License.  (Exception: if the Program itself is interactive but
-    does not normally print such an announcement, your work based on
-    the Program is not required to print an announcement.)
-\f
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
-    a) Accompany it with the complete corresponding machine-readable
-    source code, which must be distributed under the terms of Sections
-    1 and 2 above on a medium customarily used for software interchange; or,
-
-    b) Accompany it with a written offer, valid for at least three
-    years, to give any third party, for a charge no more than your
-    cost of physically performing source distribution, a complete
-    machine-readable copy of the corresponding source code, to be
-    distributed under the terms of Sections 1 and 2 above on a medium
-    customarily used for software interchange; or,
-
-    c) Accompany it with the information you received as to the offer
-    to distribute corresponding source code.  (This alternative is
-    allowed only for noncommercial distribution and only if you
-    received the program in object code or executable form with such
-    an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it.  For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable.  However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-\f
-  4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License.  Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
-  5. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Program or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
-  6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-  7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-\f
-  8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded.  In such case, this License incorporates
-the limitation as if written in the body of this License.
-
-  9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation.  If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
-  10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission.  For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this.  Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
-                           NO WARRANTY
-
-  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
-  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
-                    END OF TERMS AND CONDITIONS
-\f
-       Appendix: How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) 19yy  <name of author>
-
-    This program 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 program 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 program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
-    USA.
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
-    Gnomovision version 69, Copyright (C) 19yy name of author
-    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-    This is free software, and you are welcome to redistribute it
-    under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
-  `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
-  <signature of Ty Coon>, 1 April 1989
-  Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs.  If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library.  If this is what you want to do, use the GNU Library General
-Public License instead of this License.
diff --git a/java/src/com/tightvnc/vncviewer/MANIFEST.MF b/java/src/com/tightvnc/vncviewer/MANIFEST.MF
deleted file mode 100644 (file)
index 9ddbfbc..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-Manifest-Version: 1.0
-Main-Class: VncViewer
diff --git a/java/src/com/tightvnc/vncviewer/Makefile b/java/src/com/tightvnc/vncviewer/Makefile
deleted file mode 100644 (file)
index f236eae..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-#
-# Making the VNC applet.
-#
-
-CP = cp
-JC = javac
-JCFLAGS = -target 1.1
-JAR = jar
-ARCHIVE = VncViewer.jar
-MANIFEST = MANIFEST.MF
-PAGES = index.vnc
-INSTALL_DIR = /usr/local/vnc/classes
-
-CLASSES = VncViewer.class RfbProto.class AuthPanel.class VncCanvas.class \
-         VncCanvas2.class \
-         OptionsFrame.class ClipboardFrame.class ButtonPanel.class \
-         DesCipher.class CapabilityInfo.class CapsContainer.class \
-         RecordingFrame.class SessionRecorder.class \
-         SocketFactory.class HTTPConnectSocketFactory.class \
-         HTTPConnectSocket.class ReloginPanel.class \
-         InStream.class MemInStream.class ZlibInStream.class
-
-SOURCES = VncViewer.java RfbProto.java AuthPanel.java VncCanvas.java \
-         VncCanvas2.java \
-         OptionsFrame.java ClipboardFrame.java ButtonPanel.java \
-         DesCipher.java CapabilityInfo.java CapsContainer.java \
-         RecordingFrame.java SessionRecorder.java \
-         SocketFactory.java HTTPConnectSocketFactory.java \
-         HTTPConnectSocket.java ReloginPanel.java \
-         InStream.java MemInStream.java ZlibInStream.java
-
-all: $(CLASSES) $(ARCHIVE)
-
-$(CLASSES): $(SOURCES)
-       $(JC) $(JCFLAGS) -O $(SOURCES)
-
-$(ARCHIVE): $(CLASSES) $(MANIFEST)
-       $(JAR) cfm $(ARCHIVE) $(MANIFEST) $(CLASSES)
-
-install: $(CLASSES) $(ARCHIVE)
-       $(CP) $(CLASSES) $(ARCHIVE) $(PAGES) $(INSTALL_DIR)
-
-export:: $(CLASSES) $(ARCHIVE) $(PAGES)
-       @$(ExportJavaClasses)
-
-clean::
-       $(RM) *.class *.jar
diff --git a/java/src/com/tightvnc/vncviewer/MemInStream.java b/java/src/com/tightvnc/vncviewer/MemInStream.java
deleted file mode 100644 (file)
index 7427a9a..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
- * 
- * 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.
- */
-
-package com.tightvnc.vncviewer;
-
-public class MemInStream extends InStream {
-
-  public MemInStream(byte[] data, int offset, int len) {
-    b = data;
-    ptr = offset;
-    end = offset + len;
-  }
-
-  public int pos() { return ptr; }
-
-  protected int overrun(int itemSize, int nItems) throws Exception {
-    throw new Exception("MemInStream overrun: end of stream");
-  }
-}
diff --git a/java/src/com/tightvnc/vncviewer/OptionsFrame.java b/java/src/com/tightvnc/vncviewer/OptionsFrame.java
deleted file mode 100644 (file)
index e1125f4..0000000
+++ /dev/null
@@ -1,478 +0,0 @@
-//
-//  Copyright (C) 2001 HorizonLive.com, Inc.  All Rights Reserved.
-//  Copyright (C) 2001 Constantin Kaplinsky.  All Rights Reserved.
-//  Copyright (C) 2000 Tridia Corporation.  All Rights Reserved.
-//  Copyright (C) 1999 AT&T Laboratories Cambridge.  All Rights Reserved.
-//
-//  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.
-//
-
-//
-// Options frame.
-//
-// This deals with all the options the user can play with.
-// It sets the encodings array and some booleans.
-//
-
-package com.tightvnc.vncviewer;
-
-import java.awt.*;
-import java.awt.event.*;
-
-class OptionsFrame extends Frame
-  implements WindowListener, ActionListener, ItemListener {
-
-  static String[] names = {
-    "Encoding",
-    "Compression level",
-    "JPEG image quality",
-    "Cursor shape updates",
-    "Use CopyRect",
-    "Continuous updates",
-    "Restricted colors",
-    "Mouse buttons 2 and 3",
-    "View only",
-    "Scaling factor",
-    "Scale remote cursor",
-    "Share desktop"
-  };
-
-  static String[][] values = {
-    { "Auto", "Raw", "RRE", "CoRRE", "Hextile", "Zlib", "Tight", "ZRLE" },
-    { "Default", "1", "2", "3", "4", "5", "6", "7", "8", "9" },
-    { "JPEG off", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" },
-    { "Enable", "Ignore", "Disable" },
-    { "Yes", "No" },
-    { "Yes", "No" },
-    { "Yes", "No" },
-    { "Normal", "Reversed" },
-    { "Yes", "No" },
-    { "Auto", "1%", "5%", "10%", "20%", "25%", "50%", "75%", "100%"},
-    { "No", "50%", "75%", "125%", "150%" },
-    { "Yes", "No" }
-  };
-
-  final int
-    encodingIndex        = 0,
-    compressLevelIndex   = 1,
-    jpegQualityIndex     = 2,
-    cursorUpdatesIndex   = 3,
-    useCopyRectIndex     = 4,
-    contUpdatesIndex     = 5,
-    eightBitColorsIndex  = 6,
-    mouseButtonIndex     = 7,
-    viewOnlyIndex        = 8,
-    scalingFactorIndex   = 9,
-    scaleCursorIndex     = 10,
-    shareDesktopIndex    = 11;
-
-  Label[] labels = new Label[names.length];
-  Choice[] choices = new Choice[names.length];
-  Button closeButton;
-  VncViewer viewer;
-
-
-  //
-  // The actual data which other classes look at:
-  //
-
-  int preferredEncoding;
-  int compressLevel;
-  int jpegQuality;
-  boolean useCopyRect;
-  boolean continuousUpdates;
-  boolean requestCursorUpdates;
-  boolean ignoreCursorUpdates;
-
-  boolean eightBitColors;
-
-  boolean reverseMouseButtons2And3;
-  boolean shareDesktop;
-  boolean viewOnly;
-  int scaleCursor;
-
-  boolean autoScale;
-  int scalingFactor;
-
-  //
-  // Constructor.  Set up the labels and choices from the names and values
-  // arrays.
-  //
-
-  OptionsFrame(VncViewer v) {
-    super("TigerVNC Options");
-
-    viewer = v;
-
-    GridBagLayout gridbag = new GridBagLayout();
-    setLayout(gridbag);
-
-    GridBagConstraints gbc = new GridBagConstraints();
-    gbc.fill = GridBagConstraints.BOTH;
-
-    for (int i = 0; i < names.length; i++) {
-      labels[i] = new Label(names[i]);
-      gbc.gridwidth = 1;
-      gridbag.setConstraints(labels[i],gbc);
-      add(labels[i]);
-
-      choices[i] = new Choice();
-      gbc.gridwidth = GridBagConstraints.REMAINDER;
-      gridbag.setConstraints(choices[i],gbc);
-      add(choices[i]);
-      choices[i].addItemListener(this);
-
-      for (int j = 0; j < values[i].length; j++) {
-       choices[i].addItem(values[i][j]);
-      }
-    }
-
-    closeButton = new Button("Close");
-    gbc.gridwidth = GridBagConstraints.REMAINDER;
-    gridbag.setConstraints(closeButton, gbc);
-    add(closeButton);
-    closeButton.addActionListener(this);
-
-    pack();
-
-    addWindowListener(this);
-
-    // Set up defaults
-
-    choices[encodingIndex].select("Auto");
-    choices[compressLevelIndex].select("Default");
-    choices[jpegQualityIndex].select("6");
-    choices[cursorUpdatesIndex].select("Enable");
-    choices[useCopyRectIndex].select("Yes");
-    choices[contUpdatesIndex].select("No");
-    choices[eightBitColorsIndex].select("No");
-    choices[mouseButtonIndex].select("Normal");
-    choices[viewOnlyIndex].select("No");
-    choices[scaleCursorIndex].select("No");
-    choices[shareDesktopIndex].select("Yes");
-
-    // But let them be overridden by parameters
-
-    for (int i = 0; i < names.length; i++) {
-      String s = viewer.readParameter(names[i], false);
-      if (s != null) {
-       for (int j = 0; j < values[i].length; j++) {
-         if (s.equalsIgnoreCase(values[i][j])) {
-           choices[i].select(j);
-         }
-       }
-      }
-    }
-
-    // Get scaling factor from parameters and set it
-    // to gui and class member scalingFactor
-    
-    String s = viewer.readParameter("Scaling Factor", false);
-    if (s == null) s = "100%";
-    setScalingFactor(s);
-    if (autoScale) {
-      choices[scalingFactorIndex].select("Auto");
-    } else {
-      choices[scalingFactorIndex].select(s);
-    }
-
-    // Make the booleans and encodings array correspond to the state of the GUI
-
-    setEncodings();
-    setColorFormat();
-    setContinuousUpdates();
-    setOtherOptions();
-  }
-  
-  //
-  // Set scaling factor class member value
-  //
-  
-  void setScalingFactor(int sf) {
-      setScalingFactor(((Integer)sf).toString());
-  }
-  
-  void setScalingFactor(String s) {
-    autoScale = false;
-    scalingFactor = 100;
-    if (s != null) {
-      if (s.equalsIgnoreCase("Auto")) {
-       autoScale = true;
-      } else {
-       // Remove the '%' char at the end of string if present.
-       if (s.charAt(s.length() - 1) == '%') {
-         s = s.substring(0, s.length() - 1);
-       }
-       // Convert to an integer.
-       try {
-         scalingFactor = Integer.parseInt(s);
-       }
-       catch (NumberFormatException e) {
-         scalingFactor = 100;
-       }
-       // Make sure scalingFactor is in the range of [1..1000].
-       if (scalingFactor < 1) {
-         scalingFactor = 1;
-       } else if (scalingFactor > 1000) {
-         scalingFactor = 1000;
-       }
-      }
-    }
-  }
-
-
-  //
-  // Disable the shareDesktop option
-  //
-
-  void disableShareDesktop() {
-    labels[shareDesktopIndex].setEnabled(false);
-    choices[shareDesktopIndex].setEnabled(false);
-  }
-
-
-  //
-  // Disable the "Continuous updates" option. This method is called
-  // when we figure out that the server does not support corresponding
-  // protocol extensions.
-  //
-
-  void disableContUpdates() {
-    labels[contUpdatesIndex].setEnabled(false);
-    choices[contUpdatesIndex].setEnabled(false);
-    choices[contUpdatesIndex].select("No");
-    continuousUpdates = false;
-  }
-
-
-  //
-  // setEncodings looks at the encoding, compression level, JPEG
-  // quality level, cursor shape updates and copyRect choices and sets
-  // corresponding variables properly. Then it calls the VncViewer's
-  // setEncodings method to send a SetEncodings message to the RFB
-  // server.
-  //
-
-  void setEncodings() {
-    useCopyRect = choices[useCopyRectIndex].getSelectedItem().equals("Yes");
-
-    preferredEncoding = RfbProto.EncodingRaw;
-    boolean enableCompressLevel = false;
-    boolean enableQualityLevel = false;
-
-    if (choices[encodingIndex].getSelectedItem().equals("RRE")) {
-      preferredEncoding = RfbProto.EncodingRRE;
-    } else if (choices[encodingIndex].getSelectedItem().equals("CoRRE")) {
-      preferredEncoding = RfbProto.EncodingCoRRE;
-    } else if (choices[encodingIndex].getSelectedItem().equals("Hextile")) {
-      preferredEncoding = RfbProto.EncodingHextile;
-    } else if (choices[encodingIndex].getSelectedItem().equals("ZRLE")) {
-      preferredEncoding = RfbProto.EncodingZRLE;
-    } else if (choices[encodingIndex].getSelectedItem().equals("Zlib")) {
-      preferredEncoding = RfbProto.EncodingZlib;
-      enableCompressLevel = true;
-    } else if (choices[encodingIndex].getSelectedItem().equals("Tight")) {
-      preferredEncoding = RfbProto.EncodingTight;
-      enableCompressLevel = true;
-      enableQualityLevel = !eightBitColors;
-    } else if (choices[encodingIndex].getSelectedItem().equals("Auto")) {
-      preferredEncoding = -1;
-      enableQualityLevel = !eightBitColors;
-    }
-
-    // Handle compression level setting.
-
-    try {
-      compressLevel =
-        Integer.parseInt(choices[compressLevelIndex].getSelectedItem());
-    }
-    catch (NumberFormatException e) {
-      compressLevel = -1;
-    }
-    if (compressLevel < 1 || compressLevel > 9) {
-      compressLevel = -1;
-    }
-    labels[compressLevelIndex].setEnabled(enableCompressLevel);
-    choices[compressLevelIndex].setEnabled(enableCompressLevel);
-
-    // Handle JPEG quality setting.
-
-    try {
-      jpegQuality =
-        Integer.parseInt(choices[jpegQualityIndex].getSelectedItem());
-    }
-    catch (NumberFormatException e) {
-      jpegQuality = -1;
-    }
-    if (jpegQuality < 0 || jpegQuality > 9) {
-      jpegQuality = -1;
-    }
-    labels[jpegQualityIndex].setEnabled(enableQualityLevel);
-    choices[jpegQualityIndex].setEnabled(enableQualityLevel);
-
-    // Request cursor shape updates if necessary.
-
-    requestCursorUpdates =
-      !choices[cursorUpdatesIndex].getSelectedItem().equals("Disable");
-
-    if (requestCursorUpdates) {
-      ignoreCursorUpdates =
-       choices[cursorUpdatesIndex].getSelectedItem().equals("Ignore");
-    }
-
-    viewer.setEncodings();
-  }
-
-  //
-  // setColorFormat sets eightBitColors variable depending on the GUI
-  // setting, causing switches between 8-bit and 24-bit colors mode if
-  // necessary.
-  //
-
-  void setColorFormat() {
-
-    eightBitColors =
-      choices[eightBitColorsIndex].getSelectedItem().equals("Yes");
-
-    boolean enableJPEG = !eightBitColors &&
-      (choices[encodingIndex].getSelectedItem().equals("Tight") ||
-       choices[encodingIndex].getSelectedItem().equals("Auto"));
-
-    labels[jpegQualityIndex].setEnabled(enableJPEG);
-    choices[jpegQualityIndex].setEnabled(enableJPEG);
-  }
-
-  //
-  // setContinuousUpdates sets continuousUpdates variable depending on
-  // the GUI setting. VncViewer monitors the state of this variable and
-  // send corresponding protocol messages to the server when necessary.
-  //
-
-  void setContinuousUpdates() {
-
-    continuousUpdates =
-      choices[contUpdatesIndex].getSelectedItem().equals("Yes");
-  }
-
-  //
-  // setOtherOptions looks at the "other" choices (ones that do not
-  // cause sending any protocol messages) and sets the boolean flags
-  // appropriately.
-  //
-
-  void setOtherOptions() {
-
-    reverseMouseButtons2And3
-      = choices[mouseButtonIndex].getSelectedItem().equals("Reversed");
-
-    viewOnly 
-      = choices[viewOnlyIndex].getSelectedItem().equals("Yes");
-    if (viewer.vc != null)
-      viewer.vc.enableInput(!viewOnly);
-
-    shareDesktop
-      = choices[shareDesktopIndex].getSelectedItem().equals("Yes");
-
-    String scaleString = choices[scaleCursorIndex].getSelectedItem();
-    if (scaleString.endsWith("%"))
-      scaleString = scaleString.substring(0, scaleString.length() - 1);
-    try {
-      scaleCursor = Integer.parseInt(scaleString);
-    }
-    catch (NumberFormatException e) {
-      scaleCursor = 0;
-    }
-    if (scaleCursor < 10 || scaleCursor > 500) {
-      scaleCursor = 0;
-    }
-    if (requestCursorUpdates && !ignoreCursorUpdates && !viewOnly) {
-      labels[scaleCursorIndex].setEnabled(true);
-      choices[scaleCursorIndex].setEnabled(true);
-    } else {
-      labels[scaleCursorIndex].setEnabled(false);
-      choices[scaleCursorIndex].setEnabled(false);
-    }
-    if (viewer.vc != null)
-      viewer.vc.createSoftCursor(); // update cursor scaling
-  }
-
-
-  //
-  // Respond to actions on Choice controls
-  //
-
-  public void itemStateChanged(ItemEvent evt) {
-    Object source = evt.getSource();
-
-    if (source == choices[encodingIndex] ||
-        source == choices[compressLevelIndex] ||
-        source == choices[jpegQualityIndex] ||
-        source == choices[cursorUpdatesIndex] ||
-        source == choices[useCopyRectIndex]) {
-
-      setEncodings();
-
-      if (source == choices[cursorUpdatesIndex]) {
-        setOtherOptions();      // update scaleCursor state
-      }
-
-    } else if (source == choices[eightBitColorsIndex]) {
-
-      setColorFormat();
-
-    } else if (source == choices[contUpdatesIndex]) {
-
-      setContinuousUpdates();
-
-    } else if (source == choices[mouseButtonIndex] ||
-              source == choices[shareDesktopIndex] ||
-              source == choices[viewOnlyIndex] ||
-              source == choices[scaleCursorIndex]) {
-
-      setOtherOptions();
-
-    } else if (source == choices[scalingFactorIndex]){
-        // Tell VNC canvas that scaling factor has changed
-        setScalingFactor(choices[scalingFactorIndex].getSelectedItem());
-        if (viewer.vc != null)
-          viewer.vc.setScalingFactor(scalingFactor);
-    }
-  }
-
-  //
-  // Respond to button press
-  //
-
-  public void actionPerformed(ActionEvent evt) {
-    if (evt.getSource() == closeButton)
-      setVisible(false);
-  }
-
-  //
-  // Respond to window events
-  //
-
-  public void windowClosing(WindowEvent evt) {
-    setVisible(false);
-  }
-
-  public void windowActivated(WindowEvent evt) {}
-  public void windowDeactivated(WindowEvent evt) {}
-  public void windowOpened(WindowEvent evt) {}
-  public void windowClosed(WindowEvent evt) {}
-  public void windowIconified(WindowEvent evt) {}
-  public void windowDeiconified(WindowEvent evt) {}
-}
diff --git a/java/src/com/tightvnc/vncviewer/README b/java/src/com/tightvnc/vncviewer/README
deleted file mode 100644 (file)
index 18fd7db..0000000
+++ /dev/null
@@ -1,522 +0,0 @@
-
-  TigerVNC Java Viewer version 1.3.9
-
-======================================================================
-
-This distribution is based on the standard VNC source and includes new
-TightVNC-specific features and fixes, such as additional low-bandwidth
-optimizations, major GUI improvements, and more.
-
-       Copyright (C) 1999 AT&T Laboratories Cambridge.
-       Copyright (C) 2000 Tridia Corp.
-       Copyright (C) 2002-2003 RealVNC Ltd.
-       Copyright (C) 2001-2004 HorizonLive.com, Inc.
-       Copyright (C) 2000-2007 Constantin Kaplinsky
-       Copyright (C) 2000-2007 TightVNC Group
-       All rights reserved.
-
-This software is distributed under the GNU General Public Licence as
-published by the Free Software Foundation. See the file LICENCE.TXT for the
-conditions under which this software is made available. TigerVNC also
-contains code from other sources. See the Acknowledgements section below, and
-the individual files for details of the conditions under which they are made
-available.
-
-
-Compiling from the sources
-==========================
-
-To compile all the .java files to .class files, simply do:
-
-       % make all
-
-This will also generate a JAR (Java archive) file containing all the classes. 
-Most JVM (Java Virtual Machine) implementations are able to use either a set
-of .class files, or the JAR archive.
-
-
-Installation
-============
-
-There are three basic ways to use TigerVNC Java viewer:
-
-  1. Running applet as part of TigerVNC server installation.
-
-     Both the Unix and Windows versions of TigerVNC servers include small
-     built-in HTTP server which can serve Java viewer to Web clients. This
-     enables easy Web access to the shared desktop without need to install
-     any software on the client computer. Unix and Windows versions of
-     TigerVNC servers are different in the way they store the .class and .jar
-     files: the Unix server (Xvnc) is able to serve any set of files present
-     in a particular directory, while the Windows server (WinVNC) has all the
-     .class and .jar files inside the WinVNC executable file. Therefore, for
-     Xvnc, it's enough to copy the files into a correct directory, but for
-     WinVNC, the server binaries should be rebuild if the built-in Java
-     viewer should be updated.
-
-     To install the Java viewer under Xvnc, copy all the .class files, the
-     .jar file and the .vnc files to an installation directory (e.g.
-     /usr/local/vnc/classes):
-
-         cp *.class *.jar *.vnc /usr/local/vnc/classes
-
-     Also, make sure that the vncserver script is configured to point to the
-     installation directory (see the Xvnc manual page for the description of
-     the -httpd command-line option).
-
-  2. Running applet hosted on a standalone Web server.
-
-     Another possibility to use the Java viewer is to install it under a
-     fully-functional HTTP server such as Apache or IIS. Obviously, this
-     method requires running an HTTP server, and due to the Java security
-     restrictions, it's also required that the server should be installed on
-     the same machine which is running the TigerVNC server. In this case,
-     installation is simply copying the .class and .jar files into a
-     directory that is under control of the HTTP server. Also, an HTML page
-     should be created which will act as a the base document for the viewer
-     applet (see an example named index.html in this distribution).
-
-     NOTE: Provided index.html page is an example only. Before using that
-     file, edit it with a text editor. See more information inside
-     index.html.
-
-  3. Running the viewer as a standalone application.
-
-     Finally, the Java viewer can be executed locally on the client machine,
-     but this method requires installation of either JRE (Java Runtime
-     Environment) or JDK (Java Development Kit). If all the .class files are
-     in the current directory, the Java viewer can be executed like this,
-     from the command line:
-
-         java VncViewer HOST vnchost PORT 5900
-
-     The HOST parameter is required, PORT defaults to 5900 if omitted, and
-     there is a number of other optional parameters, see the Parameters
-     section below.
-
-
-Parameters
-==========
-
-TigerVNC Java viewer supports a number of parameters allowing you to
-customize its behavior. Most parameters directly correspond to the settings
-found in the Options window. However, there are parameters that do not
-correspond to those settings. For such parameters, you can see a note "no GUI
-equivalent", in the documentation below.
-
-Parameters can be specified in one of the two ways, depending on how the Java
-viewer is used:
-
-  1. When the Java viewer is run as an applet (embedded within an HTML
-     document), parameters should be specified in the <PARAM> HTML tags,
-     within the appropriate <APPLET> section. Here is an example:
-
-    <APPLET CODE=VncViewer.class ARCHIVE=VncViewer.jar WIDTH=400 HEIGHT=300>
-      <PARAM NAME="PORT" VALUE=5901>
-      <PARAM NAME="Scaling factor" VALUE=50>
-    </APPLET>
-
-  2. When run as a standalone application, the Java viewer reads parameters
-     from the command line. Command-line arguments should be specified in
-     pairs -- first goes parameter name, then parameter value. Here is a
-     command line example:
-
-     java VncViewer HOST vnchost PORT 5901 "Scaling factor" 50
-
-Both parameter names and their values are case-insensitive. The only
-exception is the "PASSWORD" parameter, as VNC passwords are case-sensitive.
-
-Here is the complete list of parameters supported in TigerVNC Java viewer:
-
---> "HOST" (no GUI equivalent)
-
-    Value: host name or IP address of the VNC server.
-    Default: in applet mode, the host from which the applet was loaded.
-
-    This parameter tells the viewer which server to connect to. It's not
-    needed in the applet mode, because default Java security policy allow
-    connections from applets to the only one host anyway, and that is the
-    host from which the applet was loaded. However, this parameter is
-    required if the viewer is used as a standalone application.
-
---> "PORT" (no GUI equivalent)
-
-    Value: TCP port number on the VNC server.
-    Default: 5900.
-
-    This parameter specifies TCP port number for outgoing VNC connection.
-    Note that this port is not the one used for HTTP connection from the
-    browser, it is the port used for VNC/RFB connection. Usually, VNC servers
-    use ports 58xx for HTTP connections, and ports 59xx for RFB connections.
-    Thus, most likely, this parameter should be set to something like 5900,
-    5901 etc.
-
---> "PASSWORD"
-
-    Value: session password in plain text.
-    Default: none, ask user.
-
-    DO NOT EVER USE THIS PARAMETER, unless you really know what you are
-    doing. It's extremely dangerous from the security point of view. When
-    this parameter is set, the viewer won't ever ask for a password.
-
---> "ENCPASSWORD"
-
-    Value: encrypted session password in hex-ascii.
-    Default: none, ask user.
-
-    The same as the "PASSWORD" parameter but DES-encrypted using a fixed key.
-    Its value should be represented in hex-ascii e.g. "494015f9a35e8b22".
-    This parameter has higher priority over the "PASSWORD" parameter. DO NOT
-    EVER USE THIS PARAMETER, unless you really know what you are doing. It's
-    extremely dangerous from the security point of view, and encryption does
-    not actually help here since the decryption key is always known.
-
---> "Encoding"
-
-    Values: "Auto", "Raw", "RRE", "CoRRE", "Hextile", "ZRLE", "Zlib", "Tight".
-    Default: "Auto".
-
-    The preferred encoding. If the value is "Auto", then the viewer will
-    continuously estimate average network throughput and request encodings
-    that are appropriate for current connection speed. "Hextile" is an
-    encoding that was designed for fast networks, while "Tight" is better
-    suited for low-bandwidth connections. From the other side, "Tight"
-    decoder in the TigerVNC Java viewer seems to be more efficient than
-    "Hextile" decoder so it may be ok for fast networks too. "ZRLE" encoding
-    is similar to "Tight", but it does not support JPEG compression and
-    compression levels. Unlike "Tight" encoding, "ZRLE" is supported in
-    recent versions of RealVNC products. Other encodings are not efficient
-    and provided for compatibility reasons.
-
---> "Compression level"
-
-    Values: "Default", "1", "2", "3", "4", "5", "6", "7", "8", "9".
-    Default: "Default". ;-)
-
-    Use specified compression level for "Tight" and "Zlib" encodings. Level 1
-    uses minimum of CPU time on the server but achieves weak compression
-    ratios. Level 9 offers best compression but may be slow in terms of CPU
-    time consumption on the server side. Use high levels with very slow
-    network connections, and low levels when working over higher-speed
-    networks. The "Default" value means that the server's default compression
-    level should be used.
-
---> "JPEG image quality"
-
-    Values: "JPEG off", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9".
-    Default: "6".
-
-    Use the specified image quality level in "Tight" encoding. Quality level
-    0 denotes bad image quality but very impressive compression ratios, while
-    level 9 offers very good image quality at lower compression ratios. If
-    the value is "JPEG off", the server will not use lossy JPEG compression
-    in "Tight" encoding.
-
---> "Cursor shape updates"
-
-    Values: "Enable", "Ignore", "Disable".
-    Default: "Enable".
-
-    Cursor shape updates is a protocol extension used to handle remote cursor
-    movements locally on the client side, saving bandwidth and eliminating
-    delays in mouse pointer movement. Note that current implementation of
-    cursor shape updates does not allow a client to track mouse cursor
-    position at the server side. This means that clients would not see mouse
-    cursor movements if mouse was moved either locally on the server, or by
-    another remote VNC client. Set this parameter to "Disable" if you always
-    want to see real cursor position on the remote side. Setting this option
-    to "Ignore" is similar to "Enable" but the remote cursor will not be
-    visible at all. This can be a reasonable setting if you don't care about
-    cursor shape and don't want to see two mouse cursors, one above another.
-
---> "Use CopyRect"
-
-    Values: "Yes", "No".
-    Default: "Yes".
-
-    The "CopyRect" encoding saves bandwidth and drawing time when parts of
-    the remote screen are moving around. Most likely, you don't want to
-    change this setting.
-
---> "Restricted colors"
-
-    Values: "Yes", "No".
-    Default: "No".
-
-    If set to "No", then 24-bit color format is used to represent pixel data. 
-    If set to "Yes", then only 8 bits are used to represent each pixel. 8-bit
-    color format can save bandwidth, but colors may look very inaccurate.
-
---> "Mouse buttons 2 and 3"
-
-    Values: "Normal", "Reversed".
-    Default: "Normal".
-
-    If set to "Reversed", then right mouse button (button 2) will act as it
-    was middle mouse button (button 3), and vice versa.
-
---> "View only"
-
-    Values: "Yes", "No".
-    Default: "No".
-
-    If set to "Yes", then all keyboard and mouse events in the desktop window
-    will be silently ignored and will not be passed to the remote side.
-
---> "Scale remote cursor"
-
-    Values: "No", "50%", "75%", "125%", "150%".
-    Default: "No".
-
-    If a percentage value is specified, the remote cursor is reduced
-    or enlarged accordingly. Scaling takes place only when "View only"
-    is set to "No", and "Cursor shape updates" is set to "Enable".
-
---> "Share desktop"
-
-    Values: "Yes", "No".
-    Default: "Yes".
-
-    Share the connection with other clients on the same VNC server. The exact
-    behaviour in each case depends on the server configuration.
-
---> "Open new window" (no GUI equivalent, applicable only in the applet mode)
-
-    Values: "Yes", "No".
-    Default: "No".
-
-    Operate in a separate window. This makes possible resizing the desktop,
-    and adds scroll bars when necessary. If the server supports variable
-    desktop size, the window will resize automatically when remote desktop
-    size changes.
-
---> "Scaling factor" (no GUI equivalent)
-
-    Value: an integer in the range of [1..1000], or the string "auto".
-    Default: "100".
-
-    Scale local representation of the remote desktop. The value is
-    interpreted as scaling factor in percents. The default value of 100%
-    corresponds to the original framebuffer size. Values below 100 reduce
-    image size, values above 100 enlarge the image proportionally. If the
-    parameter is set to "auto", automatic scaling is performed. Auto-scaling
-    tries to choose scaling factor such way that the whole remote framebuffer
-    will fit on the local screen. Currently, auto-scaling is supported only
-    when the remote desktop is shown in a separate frame (always true in the
-    application mode, and also in the applet mode with "Open new window"
-    parameter set to "yes").
-
---> "Show controls" (no GUI equivalent)
-
-    Values: "Yes", "No".
-    Default: "Yes".
-
-    Set to "No" if you want to get rid of that button panel at the top.
-
---> "Offer relogin" (no GUI equivalent, applicable only in the applet mode)
-
-    Values: "Yes", "No".
-    Default: "Yes".
-
-    If set to "No", the buttons "Login again" and "Close window" won't be
-    shown on disconnects or after an error has occured.
-
---> "Show offline desktop" (no GUI equivalent)
-
-    Values: "Yes", "No".
-    Default: "No".
-
-    If set to "Yes", the viewer would continue to display desktop even
-    if the remote side has closed the connection. In this case, if the
-    button panel is enabled, then the "Disconnect" button would be
-    changed to "Hide desktop" after the connection is lost.
-
---> "Defer screen updates" (no GUI equivalent)
-
-    Value: time in milliseconds.
-    Default: "20".
-
-    When updating the desktop contents after receiving an update from server,
-    schedule repaint within the specified number of milliseconds. Small delay
-    helps to coalesce several small updates into one drawing operation,
-    improving CPU usage. Set this parameter to 0 to disable deferred updates.
-
---> "Defer cursor updates" (no GUI equivalent)
-
-    Value: time in milliseconds.
-    Default: "10".
-
-    When updating the desktop after moving the mouse, schedule repaint within
-    the specified number of milliseconds. This setting makes sense only when
-    "Cursor shape updates" parameter is set to "Enable". Small delay helps to
-    coalesce several small updates into one drawing operation, improving CPU
-    usage. Set this parameter to 0 to disable deferred cursor updates.
-
---> "Defer update requests" (no GUI equivalent)
-
-    Value: time in milliseconds.
-    Default: "0".
-
-    After processing an update received from server, wait for the specified
-    number of milliseconds before requesting next screen update. Such delay
-    will end immediately on every mouse or keyboard event if not in the "view
-    only" mode. Small delay helps the server to coalesce several small
-    updates into one framebuffer update, improving both bandwidth and CPU
-    usage. Increasing the parameter value does not affect responsiveness on
-    mouse and keyboard events, but causes delays in updating the screen when
-    there is no mouse and keyboard activity on the client side.
-
---> "SocketFactory" (no GUI equivalent)
-
-    Value: name of the class.
-    Default: none.
-
-    This option provides the way to define an alternate I/O implementation.
-    The dynamically referenced class must implement a SocketFactory
-    interface, and create a Socket, as configured by this parameter. See the
-    source in SocketFactory.java.
-
---> "DEBUG_XU" (no GUI equivalent)
-
-    Value: non-negative integer.
-    Default: 0.
-
-    Debugging option that causes update statistics reset after the specified
-    number of first framebuffer updates. This option was added to measure the
-    performance of a VNC server. First few updates (especially the very first
-    one) may be notably slower than others, and the viewer can exclude such
-    updates from statistics.
-
---> "DEBUG_CU" (no GUI equivalent)
-
-    Value: non-negative integer.
-    Default: 0.
-
-    Debugging option that causes the viewer disconnect after the specified
-    number of framebuffer updates. When used with the "DEBUG_XU" parameter,
-    the number of updates specified in "DEBUG_XU" is not counted as part of
-    this parameter's value. E.g. if "DEBUG_XU"=2 and "DEBUG_CU"=10, then the
-    viewer will disconnect after 12 framebuffer updates: update statistics
-    will be reset after first two updates, then collected for next 10
-    updates, then the viewer will disconnect automatically. If the value is
-    0, the viewer will not disconnect automatically. This option was added to
-    measure the performance of a VNC server.
-
-
-RECORDING VNC SESSIONS
-======================
-
-Current version of the TigerVNC Java viewer is able to record VNC (RFB)
-sessions in files for later playback. The data format in saved session files
-is compatible with the rfbproxy program written by Tim Waugh. Most important
-thing about session recording is that it's supported only if Java security
-manager allows access to local filesystem. Typically, it would not work for
-unsigned applets. To use this feature, either use TigerVNC Java viewer as a
-standalone application (Java Runtime Environment or Java Development Kit
-should be installed), or as a signed applet. The code checks if it's possible
-to support session recording, and if everything's fine, the new "Record"
-button should appear in the button panel. Pressing this button opens new
-window which controls session recording. The GUI is pretty self-explained.
-
-Other important facts about session recording:
-
---> All sessions are recorded in the 24-bit color format. If you use
-    restricted colors (8-bit format), it will be temporarly switched to
-    24-bit mode during session recording.
-
---> All sessions are recorded with cursor shape updates turned off. This is
-    necessary to represent remote cursor movements in recorded sessions.
-
---> Closing and re-opening the recording control window does not affect the
-    recording. It's not necessary to keep that window open during recording a
-    session.
-
---> Avoid using Zlib and ZRLE encodings when recording sessions. If you have
-    started recording BEFORE opening a VNC session, then you are ok. But
-    otherwise, all Zlib-encoded updates will be saved Raw-encoded (that is,
-    without compression at all). The case with ZRLE is even worse -- ZRLE
-    updates will not be saved at all, so the resulting session file may be
-    corrupted. Zlib decoding depends on the pixel data received earlier, thus
-    saving the data received from the server at an arbitrary moment is not
-    sufficient to decompress it correctly. And there is no way to tell Zlib
-    or ZRLE decoder to reset decompressor's state -- that's a limitation of
-    these encoders. The viewer could re-compress raw pixel data again before
-    saving Zlib-encoded sessions, but unfortunately Java API does not allow
-    to flush zlib data streams making it impossible to save Zlib-encoded RFB
-    pixel data without using native code.
-
---> Usually, Tight encoding is the most suitable one for session recording,
-    but some of the issues described above for the Zlib encoding affect the
-    Tight encoding as well. Unlike Zlib sessions, Tight-encoded sessions are
-    always saved Tight-encoded, but the viewer has to re-compress parts of
-    data to synchronize encoder's and decoder's zlib streams. And, due to
-    Java zlib API limitations, zlib streams' states have to be reset on each
-    compressed rectangle, causing compression ratios to be lower than in the
-    original VNC session. If you want to achieve the best possible
-    performance, turn recording on BEFORE connecting to the VNC server,
-    otherwise CPU usage and compression ratios may be notably less efficient.
-
-
-HINTS
-=====
-
---> To refresh remote desktop in the view-only mode, press "r" or "R"
-    on the keyboard.
-
-
-ACKNOWLEDGEMENTS
-================
-
-This distribution contains Java DES software by Dave Zimmerman
-<dzimm@widget.com> and Jef Poskanzer <jef@acme.com>.  This is:
-
-    Copyright (c) 1996 Widget Workshop, Inc. All Rights Reserved.
-
-    Permission to use, copy, modify, and distribute this software and its
-    documentation for NON-COMMERCIAL or COMMERCIAL purposes and without fee
-    is hereby granted, provided that this copyright notice is kept intact.
-    
-    WIDGET WORKSHOP MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE
-    SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT
-    NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
-    PARTICULAR PURPOSE, OR NON-INFRINGEMENT. WIDGET WORKSHOP SHALL NOT BE
-    LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING,
-    MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
-    
-    THIS SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE OR RESALE AS ON-LINE
-    CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE
-    PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT
-    NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT LIFE
-    SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE
-    SOFTWARE COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE
-    PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH RISK ACTIVITIES").  WIDGET
-    WORKSHOP SPECIFICALLY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF
-    FITNESS FOR HIGH RISK ACTIVITIES.
-
-    Copyright (C) 1996 by Jef Poskanzer <jef@acme.com>.  All rights
-    reserved.
-
-    Redistribution and use in source and binary forms, with or without
-    modification, are permitted provided that the following conditions
-    are met:
-    1. Redistributions of source code must retain the above copyright
-       notice, this list of conditions and the following disclaimer.
-    2. Redistributions in binary form must reproduce the above copyright
-       notice, this list of conditions and the following disclaimer in the
-       documentation and/or other materials provided with the distribution.
-
-    THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-    PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
-    BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-    BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-    WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-    OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-    ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-    Visit the ACME Labs Java page for up-to-date versions of this and other
-    fine Java utilities: http://www.acme.com/java/
diff --git a/java/src/com/tightvnc/vncviewer/RecordOutputStream.java b/java/src/com/tightvnc/vncviewer/RecordOutputStream.java
deleted file mode 100644 (file)
index 3978dfc..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-package com.tightvnc.vncviewer;
-
-import java.io.DataOutput;
-import java.io.IOException;
-
-public class RecordOutputStream implements DataOutput {
-
-  public RecordOutputStream(RfbProto rfbproto) {
-    rfb = rfbproto;
-  }
-
-  private boolean canWrite() {
-    return ((rfb != null) && (rfb.rec != null));
-  }
-
-  public void write(byte[] b) throws IOException {
-    if (canWrite())
-      rfb.rec.write(b);
-  }
-
-  public void write(byte[] b, int off, int len) throws IOException {
-    if (canWrite())
-      rfb.rec.write(b, off, len);
-  }
-
-  public void write(int b) throws IOException {
-    if (canWrite())
-      rfb.rec.writeIntBE(b);
-  }
-
-  public void writeBoolean(boolean v) { }
-
-  public void writeByte(int v) throws IOException {
-    if (canWrite()) {
-      rfb.rec.writeByte(v);
-    }
-  }
-
-  public void writeBytes(String s) { }
-  public void writeChar(int v) { }
-  public void writeChars(String s) { }
-  public void writeDouble(double v) { }
-  public void writeFloat(float v) { }
-
-  public void writeInt(int v) throws IOException {
-    if (canWrite())
-      rfb.rec.writeIntBE(v);
-  }
-
-  public void writeLong(long v) { }
-
-  public void writeShort(int v) throws IOException {
-    if (canWrite())
-      rfb.rec.writeShortBE(v);
-  }
-
-  public void writeUTF(String str) { }
-
-  private RfbProto rfb = null;
-}
diff --git a/java/src/com/tightvnc/vncviewer/RecordingFrame.java b/java/src/com/tightvnc/vncviewer/RecordingFrame.java
deleted file mode 100644 (file)
index f2e1fae..0000000
+++ /dev/null
@@ -1,313 +0,0 @@
-//
-//  Copyright (C) 2002 Constantin Kaplinsky.  All Rights Reserved.
-//
-//  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.
-//
-
-//
-// Recording frame. It allows to control recording RFB sessions into
-// FBS (FrameBuffer Stream) files.
-//
-
-package com.tightvnc.vncviewer;
-
-import java.io.*;
-import java.awt.*;
-import java.awt.event.*;
-
-class RecordingFrame extends Frame
-  implements WindowListener, ActionListener {
-
-  boolean recording;
-
-  TextField fnameField;
-  Button browseButton;
-
-  Label statusLabel;
-
-  Button recordButton, nextButton, closeButton;
-  VncViewer viewer;
-
-  //
-  // Check if current security manager allows to create a
-  // RecordingFrame object.
-  //
-
-  public static boolean checkSecurity() {
-    SecurityManager security = System.getSecurityManager();
-    if (security != null) {
-      try {
-       security.checkPropertyAccess("user.dir");
-       security.checkPropertyAccess("file.separator");
-       // Work around (rare) checkPropertyAccess bug
-       System.getProperty("user.dir");
-      } catch (SecurityException e) {
-       System.out.println("SecurityManager restricts session recording.");
-       return false;
-      }
-    }
-    return true;
-  }
-
-  //
-  // Constructor.
-  //
-
-  RecordingFrame(VncViewer v) {
-    super("TigerVNC Session Recording");
-
-    viewer = v;
-
-    // Determine initial filename for next saved session.
-    // FIXME: Check SecurityManager.
-
-    String fname = nextNewFilename(System.getProperty("user.dir") +
-                                  System.getProperty("file.separator") +
-                                  "vncsession.fbs");
-
-    // Construct new panel with file name field and "Browse" button.
-
-    Panel fnamePanel = new Panel();
-    GridBagLayout fnameGridbag = new GridBagLayout();
-    fnamePanel.setLayout(fnameGridbag);
-
-    GridBagConstraints fnameConstraints = new GridBagConstraints();
-    fnameConstraints.gridwidth = GridBagConstraints.RELATIVE;
-    fnameConstraints.fill = GridBagConstraints.BOTH;
-    fnameConstraints.weightx = 4.0;
-
-    fnameField = new TextField(fname, 64);
-    fnameGridbag.setConstraints(fnameField, fnameConstraints);
-    fnamePanel.add(fnameField);
-    fnameField.addActionListener(this);
-
-    fnameConstraints.gridwidth = GridBagConstraints.REMAINDER;
-    fnameConstraints.weightx = 1.0;
-
-    browseButton = new Button("Browse");
-    fnameGridbag.setConstraints(browseButton, fnameConstraints);
-    fnamePanel.add(browseButton);
-    browseButton.addActionListener(this);
-
-    // Construct the frame.
-
-    GridBagLayout gridbag = new GridBagLayout();
-    setLayout(gridbag);
-
-    GridBagConstraints gbc = new GridBagConstraints();
-    gbc.gridwidth = GridBagConstraints.REMAINDER;
-    gbc.fill = GridBagConstraints.BOTH;
-    gbc.weighty = 1.0;
-    gbc.insets = new Insets(10, 0, 0, 0);
-
-    Label helpLabel =
-      new Label("File name to save next recorded session in:", Label.CENTER);
-    gridbag.setConstraints(helpLabel, gbc);
-    add(helpLabel);
-
-    gbc.fill = GridBagConstraints.HORIZONTAL;
-    gbc.weighty = 0.0;
-    gbc.insets = new Insets(0, 0, 0, 0);
-
-    gridbag.setConstraints(fnamePanel, gbc);
-    add(fnamePanel);
-
-    gbc.fill = GridBagConstraints.BOTH;
-    gbc.weighty = 1.0;
-    gbc.insets = new Insets(10, 0, 10, 0);
-
-    statusLabel = new Label("", Label.CENTER);
-    gridbag.setConstraints(statusLabel, gbc);
-    add(statusLabel);
-
-    gbc.fill = GridBagConstraints.HORIZONTAL;
-    gbc.weightx = 1.0;
-    gbc.weighty = 0.0;
-    gbc.gridwidth = 1;
-    gbc.insets = new Insets(0, 0, 0, 0);
-
-    recordButton = new Button("Record");
-    gridbag.setConstraints(recordButton, gbc);
-    add(recordButton);
-    recordButton.addActionListener(this);
-
-    nextButton = new Button("Next file");
-    gridbag.setConstraints(nextButton, gbc);
-    add(nextButton);
-    nextButton.addActionListener(this);
-
-    closeButton = new Button("Close");
-    gridbag.setConstraints(closeButton, gbc);
-    add(closeButton);
-    closeButton.addActionListener(this);
-
-    // Set correct text, font and color for the statusLabel.
-    stopRecording();
-
-    pack();
-
-    addWindowListener(this);
-  }
-
-  //
-  // If the given string ends with ".NNN" where NNN is a decimal
-  // number, increase this number by one. Otherwise, append ".001"
-  // to the given string.
-  //
-
-  protected String nextFilename(String fname) {
-    int len = fname.length();
-    int suffixPos = len;
-    int suffixNum = 1;
-
-    if (len > 4 && fname.charAt(len - 4) == '.') {
-      try {
-       suffixNum = Integer.parseInt(fname.substring(len - 3, len)) + 1;
-       suffixPos = len - 4;
-      } catch (NumberFormatException e) { }
-    }
-
-    char[] zeroes = {'0', '0', '0'};
-    String suffix = String.valueOf(suffixNum);
-    if (suffix.length() < 3) {
-      suffix = new String(zeroes, 0, 3 - suffix.length()) + suffix;
-    }
-
-    return fname.substring(0, suffixPos) + '.' + suffix;
-  }
-
-  //
-  // Find next name of a file which does not exist yet.
-  //
-
-  protected String nextNewFilename(String fname) {
-    String newName = fname;
-    File f;
-    try {
-      do {
-       newName = nextFilename(newName);
-       f = new File(newName);
-      } while (f.exists());
-    } catch (SecurityException e) { }
-
-    return newName;
-  }
-
-  //
-  // Let the user choose a file name showing a FileDialog.
-  //
-
-  protected boolean browseFile() {
-    File currentFile = new File(fnameField.getText());
-
-    FileDialog fd =
-      new FileDialog(this, "Save next session as...", FileDialog.SAVE);
-    fd.setDirectory(currentFile.getParent());
-    fd.setVisible(true);
-    if (fd.getFile() != null) {
-      String newDir = fd.getDirectory();
-      String sep = System.getProperty("file.separator");
-      if (newDir.length() > 0) {
-       if (!sep.equals(newDir.substring(newDir.length() - sep.length())))
-         newDir += sep;
-      }
-      String newFname = newDir + fd.getFile();
-      if (newFname.equals(fnameField.getText())) {
-       fnameField.setText(newFname);
-       return true;
-      }
-    }
-    return false;
-  }
-
-  //
-  // Start recording.
-  //
-
-  public void startRecording() {
-    statusLabel.setText("Status: Recording...");
-    statusLabel.setFont(new Font("Helvetica", Font.BOLD, 12));
-    statusLabel.setForeground(Color.red);
-    recordButton.setLabel("Stop recording");
-
-    recording = true;
-
-    viewer.setRecordingStatus(fnameField.getText());
-  }
-
-  //
-  // Stop recording.
-  //
-
-  public void stopRecording() {
-    statusLabel.setText("Status: Not recording.");
-    statusLabel.setFont(new Font("Helvetica", Font.PLAIN, 12));
-    statusLabel.setForeground(Color.black);
-    recordButton.setLabel("Record");
-
-    recording = false;
-
-    viewer.setRecordingStatus(null);
-  }
-
-  //
-  // Close our window properly.
-  //
-
-  public void windowClosing(WindowEvent evt) {
-    setVisible(false);
-  }
-
-  //
-  // Ignore window events we're not interested in.
-  //
-
-  public void windowActivated(WindowEvent evt) {}
-  public void windowDeactivated (WindowEvent evt) {}
-  public void windowOpened(WindowEvent evt) {}
-  public void windowClosed(WindowEvent evt) {}
-  public void windowIconified(WindowEvent evt) {}
-  public void windowDeiconified(WindowEvent evt) {}
-
-
-  //
-  // Respond to button presses
-  //
-
-  public void actionPerformed(ActionEvent evt) {
-    if (evt.getSource() == browseButton) {
-      if (browseFile() && recording)
-       startRecording();
-
-    } else if (evt.getSource() == recordButton) {
-      if (!recording) {
-       startRecording();
-      } else {
-       stopRecording();
-        fnameField.setText(nextNewFilename(fnameField.getText()));
-      }
-
-    } else if (evt.getSource() == nextButton) {
-      fnameField.setText(nextNewFilename(fnameField.getText()));
-      if (recording)
-       startRecording();
-
-    } else if (evt.getSource() == closeButton) {
-      setVisible(false);
-
-    }
-  }
-}
diff --git a/java/src/com/tightvnc/vncviewer/ReloginPanel.java b/java/src/com/tightvnc/vncviewer/ReloginPanel.java
deleted file mode 100644 (file)
index 4be454d..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-//
-//  Copyright (C) 2002 Cendio Systems.  All Rights Reserved.
-//  Copyright (C) 2002 Constantin Kaplinsky.  All Rights Reserved.
-//
-//  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.
-//
-
-//
-// ReloginPanel class implements panel with a button for logging in again,
-// after fatal errors or disconnect
-//
-
-package com.tightvnc.vncviewer;
-
-import java.awt.*;
-import java.awt.event.*;
-import java.applet.*;
-
-//
-// The panel which implements the Relogin button
-//
-
-class ReloginPanel extends Panel implements ActionListener {
-  Button reloginButton;
-  Button closeButton;
-  VncViewer viewer;
-
-  //
-  // Constructor.
-  //
-  public ReloginPanel(VncViewer v) {
-    viewer = v;
-    setLayout(new FlowLayout(FlowLayout.CENTER));
-    reloginButton = new Button("Login again");
-    add(reloginButton);
-    reloginButton.addActionListener(this);
-    if (viewer.inSeparateFrame) {
-      closeButton = new Button("Close window");
-      add(closeButton);
-      closeButton.addActionListener(this);
-    }
-  }
-
-  //
-  // This method is called when a button is pressed.
-  //
-  public synchronized void actionPerformed(ActionEvent evt) {
-    if (viewer.inSeparateFrame)
-      viewer.vncFrame.dispose();
-    if (evt.getSource() == reloginButton)
-      viewer.getAppletContext().showDocument(viewer.getDocumentBase());
-  }
-}
diff --git a/java/src/com/tightvnc/vncviewer/RfbInputStream.java b/java/src/com/tightvnc/vncviewer/RfbInputStream.java
deleted file mode 100644 (file)
index c14b188..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-package com.tightvnc.vncviewer;
-
-import java.io.IOException;
-
-//
-// This class is layer between data of private RfbProto class
-// and classes in other packages.
-//
-// For now this class is used by com.tightvnc.decoder.RawDecoder
-//
-public class RfbInputStream {
-  RfbInputStream(RfbProto rfbProto) {
-    rfb = rfbProto;
-  }
-
-  //
-  // Read data methods
-  //
-
-  public void readFully(byte b[]) throws IOException {
-    readFully(b, 0, b.length);
-  }
-
-  public void readFully(byte b[], int off, int len) throws IOException {
-    rfb.readFully(b, off, len);
-  }
-
-  public int readU32() throws IOException  {
-    return rfb.readU32();
-  }
-
-  public int readU8() throws IOException  {
-    return rfb.readU8();
-  }
-
-  public int readCompactLen() throws IOException {
-    return rfb.readCompactLen();
-  }
-
-  public int readU16() throws IOException {
-    return rfb.readU16();
-  }
-
-  private RfbProto rfb = null;
-}
diff --git a/java/src/com/tightvnc/vncviewer/RfbProto.java b/java/src/com/tightvnc/vncviewer/RfbProto.java
deleted file mode 100644 (file)
index d1a9450..0000000
+++ /dev/null
@@ -1,1497 +0,0 @@
-//
-//  Copyright (C) 2001-2004 HorizonLive.com, Inc.  All Rights Reserved.
-//  Copyright (C) 2001-2006 Constantin Kaplinsky.  All Rights Reserved.
-//  Copyright (C) 2000 Tridia Corporation.  All Rights Reserved.
-//  Copyright (C) 1999 AT&T Laboratories Cambridge.  All Rights Reserved.
-//
-//  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.
-//
-
-//
-// RfbProto.java
-//
-
-package com.tightvnc.vncviewer;
-
-import java.io.*;
-import java.awt.*;
-import java.awt.event.*;
-import java.net.Socket;
-import java.util.zip.*;
-
-class RfbProto {
-
-  final static String
-    versionMsg_3_3 = "RFB 003.003\n",
-    versionMsg_3_7 = "RFB 003.007\n",
-    versionMsg_3_8 = "RFB 003.008\n";
-
-  // Vendor signatures: standard VNC/RealVNC, TridiaVNC, and TightVNC
-  final static String
-    StandardVendor  = "STDV",
-    TridiaVncVendor = "TRDV",
-    TightVncVendor  = "TGHT";
-
-  // Security types
-  final static int
-    SecTypeInvalid = 0,
-    SecTypeNone    = 1,
-    SecTypeVncAuth = 2,
-    SecTypeTight   = 16;
-
-  // Supported tunneling types
-  final static int
-    NoTunneling = 0;
-  final static String
-    SigNoTunneling = "NOTUNNEL";
-
-  // Supported authentication types
-  final static int
-    AuthNone      = 1,
-    AuthVNC       = 2,
-    AuthUnixLogin = 129;
-  final static String
-    SigAuthNone      = "NOAUTH__",
-    SigAuthVNC       = "VNCAUTH_",
-    SigAuthUnixLogin = "ULGNAUTH";
-
-  // VNC authentication results
-  final static int
-    VncAuthOK      = 0,
-    VncAuthFailed  = 1,
-    VncAuthTooMany = 2;
-
-  // Standard server-to-client messages
-  final static int
-    FramebufferUpdate   = 0,
-    SetColourMapEntries = 1,
-    Bell                = 2,
-    ServerCutText       = 3;
-
-  // Non-standard server-to-client messages
-  final static int
-    EndOfContinuousUpdates = 150;
-  final static String
-    SigEndOfContinuousUpdates = "CUS_EOCU";
-
-  // Standard client-to-server messages
-  final static int
-    SetPixelFormat           = 0,
-    FixColourMapEntries      = 1,
-    SetEncodings             = 2,
-    FramebufferUpdateRequest = 3,
-    KeyboardEvent            = 4,
-    PointerEvent             = 5,
-    ClientCutText            = 6;
-
-  // Non-standard client-to-server messages
-  final static int EnableContinuousUpdates = 150;
-  final static int VideoRectangleSelection = 151;
-  final static int VideoFreeze = 152;
-  final static String SigVideoFreeze = "VD_FREEZ";
-  final static String SigEnableContinuousUpdates = "CUC_ENCU";
-  final static String SigVideoRectangleSelection = "VRECTSEL";
-
-  // Supported encodings and pseudo-encodings
-  final static int
-    EncodingRaw            = 0,
-    EncodingCopyRect       = 1,
-    EncodingRRE            = 2,
-    EncodingCoRRE          = 4,
-    EncodingHextile        = 5,
-    EncodingZlib           = 6,
-    EncodingTight          = 7,
-    EncodingZRLE           = 16,
-    EncodingCompressLevel0 = 0xFFFFFF00,
-    EncodingQualityLevel0  = 0xFFFFFFE0,
-    EncodingXCursor        = 0xFFFFFF10,
-    EncodingRichCursor     = 0xFFFFFF11,
-    EncodingPointerPos     = 0xFFFFFF18,
-    EncodingLastRect       = 0xFFFFFF20,
-    EncodingNewFBSize      = 0xFFFFFF21;
-  final static String
-    SigEncodingRaw            = "RAW_____",
-    SigEncodingCopyRect       = "COPYRECT",
-    SigEncodingRRE            = "RRE_____",
-    SigEncodingCoRRE          = "CORRE___",
-    SigEncodingHextile        = "HEXTILE_",
-    SigEncodingZlib           = "ZLIB____",
-    SigEncodingTight          = "TIGHT___",
-    SigEncodingZRLE           = "ZRLE____",
-    SigEncodingCompressLevel0 = "COMPRLVL",
-    SigEncodingQualityLevel0  = "JPEGQLVL",
-    SigEncodingXCursor        = "X11CURSR",
-    SigEncodingRichCursor     = "RCHCURSR",
-    SigEncodingPointerPos     = "POINTPOS",
-    SigEncodingLastRect       = "LASTRECT",
-    SigEncodingNewFBSize      = "NEWFBSIZ";
-
-  final static int MaxNormalEncoding = 255;
-
-  // Contstants used in the Hextile decoder
-  final static int
-    HextileRaw                 = 1,
-    HextileBackgroundSpecified = 2,
-    HextileForegroundSpecified = 4,
-    HextileAnySubrects         = 8,
-    HextileSubrectsColoured    = 16;
-
-  // Contstants used in the Tight decoder
-  final static int TightMinToCompress = 12;
-  final static int
-    TightExplicitFilter = 0x04,
-    TightFill           = 0x08,
-    TightJpeg           = 0x09,
-    TightMaxSubencoding = 0x09,
-    TightFilterCopy     = 0x00,
-    TightFilterPalette  = 0x01,
-    TightFilterGradient = 0x02;
-
-
-  String host;
-  int port;
-  Socket sock;
-  OutputStream os;
-  SessionRecorder rec;
-  boolean inNormalProtocol = false;
-  VncViewer viewer;
-
-  // Input stream is declared private to make sure it can be accessed
-  // only via RfbProto methods. We have to do this because we want to
-  // count how many bytes were read.
-  private DataInputStream is;
-  private long numBytesRead = 0;
-  public long getNumBytesRead() { return numBytesRead; }
-
-  // Java on UNIX does not call keyPressed() on some keys, for example
-  // swedish keys To prevent our workaround to produce duplicate
-  // keypresses on JVMs that actually works, keep track of if
-  // keyPressed() for a "broken" key was called or not.
-  boolean brokenKeyPressed = false;
-
-  // This will be set to true on the first framebuffer update
-  // containing Zlib-, ZRLE- or Tight-encoded data.
-  boolean wereZlibUpdates = false;
-
-  // This fields are needed to show warnings about inefficiently saved
-  // sessions only once per each saved session file.
-  boolean zlibWarningShown;
-  boolean tightWarningShown;
-
-  // Before starting to record each saved session, we set this field
-  // to 0, and increment on each framebuffer update. We don't flush
-  // the SessionRecorder data into the file before the second update.
-  // This allows us to write initial framebuffer update with zero
-  // timestamp, to let the player show initial desktop before
-  // playback.
-  int numUpdatesInSession;
-
-  // Measuring network throughput.
-  boolean timing;
-  long timeWaitedIn100us;
-  long timedKbits;
-
-  // Protocol version and TightVNC-specific protocol options.
-  int serverMajor, serverMinor;
-  int clientMajor, clientMinor;
-  boolean protocolTightVNC;
-  CapsContainer tunnelCaps, authCaps;
-  CapsContainer serverMsgCaps, clientMsgCaps;
-  CapsContainer encodingCaps;
-
-  // "Continuous updates" is a TightVNC-specific feature that allows
-  // receiving framebuffer updates continuously, without sending update
-  // requests. The variables below track the state of this feature.
-  // Initially, continuous updates are disabled. They can be enabled
-  // by calling tryEnableContinuousUpdates() method, and only if this
-  // feature is supported by the server. To disable continuous updates,
-  // tryDisableContinuousUpdates() should be called.
-  private boolean continuousUpdatesActive = false;
-  private boolean continuousUpdatesEnding = false;
-
-  // If true, informs that the RFB socket was closed.
-  private boolean closed;
-
-  //
-  // Constructor. Make TCP connection to RFB server.
-  //
-
-  RfbProto(String h, int p, VncViewer v) throws IOException {
-    viewer = v;
-    host = h;
-    port = p;
-
-    if (viewer.socketFactory == null) {
-      sock = new Socket(host, port);
-      sock.setTcpNoDelay(true);
-    } else {
-      try {
-       Class factoryClass = Class.forName(viewer.socketFactory);
-       SocketFactory factory = (SocketFactory)factoryClass.newInstance();
-       if (viewer.inAnApplet)
-         sock = factory.createSocket(host, port, viewer);
-       else
-         sock = factory.createSocket(host, port, viewer.mainArgs);
-      } catch(Exception e) {
-       e.printStackTrace();
-       throw new IOException(e.getMessage());
-      }
-    }
-    is = new DataInputStream(new BufferedInputStream(sock.getInputStream(),
-                                                    16384));
-    os = sock.getOutputStream();
-
-    timing = false;
-    timeWaitedIn100us = 5;
-    timedKbits = 0;
-  }
-
-
-  synchronized void close() {
-    try {
-      sock.close();
-      closed = true;
-      System.out.println("RFB socket closed");
-      if (rec != null) {
-       rec.close();
-       rec = null;
-      }
-    } catch (Exception e) {
-      e.printStackTrace();
-    }
-  }
-
-  synchronized boolean closed() {
-    return closed;
-  }
-
-  //
-  // Read server's protocol version message
-  //
-
-  void readVersionMsg() throws Exception {
-
-    byte[] b = new byte[12];
-
-    readFully(b);
-
-    if ((b[0] != 'R') || (b[1] != 'F') || (b[2] != 'B') || (b[3] != ' ')
-       || (b[4] < '0') || (b[4] > '9') || (b[5] < '0') || (b[5] > '9')
-       || (b[6] < '0') || (b[6] > '9') || (b[7] != '.')
-       || (b[8] < '0') || (b[8] > '9') || (b[9] < '0') || (b[9] > '9')
-       || (b[10] < '0') || (b[10] > '9') || (b[11] != '\n'))
-    {
-      throw new Exception("Host " + host + " port " + port +
-                         " is not an RFB server");
-    }
-
-    serverMajor = (b[4] - '0') * 100 + (b[5] - '0') * 10 + (b[6] - '0');
-    serverMinor = (b[8] - '0') * 100 + (b[9] - '0') * 10 + (b[10] - '0');
-
-    if (serverMajor < 3) {
-      throw new Exception("RFB server does not support protocol version 3");
-    }
-  }
-
-
-  //
-  // Write our protocol version message
-  //
-
-  void writeVersionMsg() throws IOException {
-    clientMajor = 3;
-    if (serverMajor > 3 || serverMinor >= 8) {
-      clientMinor = 8;
-      os.write(versionMsg_3_8.getBytes());
-    } else if (serverMinor >= 7) {
-      clientMinor = 7;
-      os.write(versionMsg_3_7.getBytes());
-    } else {
-      clientMinor = 3;
-      os.write(versionMsg_3_3.getBytes());
-    }
-    protocolTightVNC = false;
-    initCapabilities();
-  }
-
-
-  //
-  // Negotiate the authentication scheme.
-  //
-
-  int negotiateSecurity() throws Exception {
-    return (clientMinor >= 7) ?
-      selectSecurityType() : readSecurityType();
-  }
-
-  //
-  // Read security type from the server (protocol version 3.3).
-  //
-
-  int readSecurityType() throws Exception {
-    int secType = readU32();
-
-    switch (secType) {
-    case SecTypeInvalid:
-      readConnFailedReason();
-      return SecTypeInvalid;   // should never be executed
-    case SecTypeNone:
-    case SecTypeVncAuth:
-      return secType;
-    default:
-      throw new Exception("Unknown security type from RFB server: " + secType);
-    }
-  }
-
-  //
-  // Select security type from the server's list (protocol versions 3.7/3.8).
-  //
-
-  int selectSecurityType() throws Exception {
-    int secType = SecTypeInvalid;
-
-    // Read the list of secutiry types.
-    int nSecTypes = readU8();
-    if (nSecTypes == 0) {
-      readConnFailedReason();
-      return SecTypeInvalid;   // should never be executed
-    }
-    byte[] secTypes = new byte[nSecTypes];
-    readFully(secTypes);
-
-    // Find out if the server supports TightVNC protocol extensions
-    for (int i = 0; i < nSecTypes; i++) {
-      if (secTypes[i] == SecTypeTight) {
-       protocolTightVNC = true;
-       os.write(SecTypeTight);
-       return SecTypeTight;
-      }
-    }
-
-    // Find first supported security type.
-    for (int i = 0; i < nSecTypes; i++) {
-      if (secTypes[i] == SecTypeNone || secTypes[i] == SecTypeVncAuth) {
-       secType = secTypes[i];
-       break;
-      }
-    }
-
-    if (secType == SecTypeInvalid) {
-      throw new Exception("Server did not offer supported security type");
-    } else {
-      os.write(secType);
-    }
-
-    return secType;
-  }
-
-  //
-  // Perform "no authentication".
-  //
-
-  void authenticateNone() throws Exception {
-    if (clientMinor >= 8)
-      readSecurityResult("No authentication");
-  }
-
-  //
-  // Perform standard VNC Authentication.
-  //
-
-  void authenticateVNC(String pw) throws Exception {
-    byte[] challenge = new byte[16];
-    readFully(challenge);
-
-    if (pw.length() > 8)
-      pw = pw.substring(0, 8); // Truncate to 8 chars
-
-    // Truncate password on the first zero byte.
-    int firstZero = pw.indexOf(0);
-    if (firstZero != -1)
-      pw = pw.substring(0, firstZero);
-
-    byte[] key = {0, 0, 0, 0, 0, 0, 0, 0};
-    System.arraycopy(pw.getBytes(), 0, key, 0, pw.length());
-
-    DesCipher des = new DesCipher(key);
-
-    des.encrypt(challenge, 0, challenge, 0);
-    des.encrypt(challenge, 8, challenge, 8);
-
-    os.write(challenge);
-
-    readSecurityResult("VNC authentication");
-  }
-
-  //
-  // Read security result.
-  // Throws an exception on authentication failure.
-  //
-
-  void readSecurityResult(String authType) throws Exception {
-    int securityResult = readU32();
-
-    switch (securityResult) {
-    case VncAuthOK:
-      System.out.println(authType + ": success");
-      break;
-    case VncAuthFailed:
-      if (clientMinor >= 8)
-        readConnFailedReason();
-      throw new Exception(authType + ": failed");
-    case VncAuthTooMany:
-      throw new Exception(authType + ": failed, too many tries");
-    default:
-      throw new Exception(authType + ": unknown result " + securityResult);
-    }
-  }
-
-  //
-  // Read the string describing the reason for a connection failure,
-  // and throw an exception.
-  //
-
-  void readConnFailedReason() throws Exception {
-    int reasonLen = readU32();
-    byte[] reason = new byte[reasonLen];
-    readFully(reason);
-    throw new Exception(new String(reason));
-  }
-
-  //
-  // Initialize capability lists (TightVNC protocol extensions).
-  //
-
-  void initCapabilities() {
-    tunnelCaps    = new CapsContainer();
-    authCaps      = new CapsContainer();
-    serverMsgCaps = new CapsContainer();
-    clientMsgCaps = new CapsContainer();
-    encodingCaps  = new CapsContainer();
-
-    // Supported authentication methods
-    authCaps.add(AuthNone, StandardVendor, SigAuthNone,
-                "No authentication");
-    authCaps.add(AuthVNC, StandardVendor, SigAuthVNC,
-                "Standard VNC password authentication");
-
-    // Supported non-standard server-to-client messages
-    serverMsgCaps.add(EndOfContinuousUpdates, TightVncVendor,
-                      SigEndOfContinuousUpdates,
-                      "End of continuous updates notification");
-
-    // Supported non-standard client-to-server messages
-    clientMsgCaps.add(EnableContinuousUpdates, TightVncVendor,
-                      SigEnableContinuousUpdates,
-                      "Enable/disable continuous updates");
-    clientMsgCaps.add(VideoRectangleSelection, TightVncVendor,
-                      SigVideoRectangleSelection,
-                      "Select a rectangle to be treated as video");
-    clientMsgCaps.add(VideoFreeze, TightVncVendor,
-                      SigVideoFreeze,
-                      "Disable/enable video rectangle");
-
-    // Supported encoding types
-    encodingCaps.add(EncodingCopyRect, StandardVendor,
-                    SigEncodingCopyRect, "Standard CopyRect encoding");
-    encodingCaps.add(EncodingRRE, StandardVendor,
-                    SigEncodingRRE, "Standard RRE encoding");
-    encodingCaps.add(EncodingCoRRE, StandardVendor,
-                    SigEncodingCoRRE, "Standard CoRRE encoding");
-    encodingCaps.add(EncodingHextile, StandardVendor,
-                    SigEncodingHextile, "Standard Hextile encoding");
-    encodingCaps.add(EncodingZRLE, StandardVendor,
-                    SigEncodingZRLE, "Standard ZRLE encoding");
-    encodingCaps.add(EncodingZlib, TridiaVncVendor,
-                    SigEncodingZlib, "Zlib encoding");
-    encodingCaps.add(EncodingTight, TightVncVendor,
-                    SigEncodingTight, "Tight encoding");
-
-    // Supported pseudo-encoding types
-    encodingCaps.add(EncodingCompressLevel0, TightVncVendor,
-                    SigEncodingCompressLevel0, "Compression level");
-    encodingCaps.add(EncodingQualityLevel0, TightVncVendor,
-                    SigEncodingQualityLevel0, "JPEG quality level");
-    encodingCaps.add(EncodingXCursor, TightVncVendor,
-                    SigEncodingXCursor, "X-style cursor shape update");
-    encodingCaps.add(EncodingRichCursor, TightVncVendor,
-                    SigEncodingRichCursor, "Rich-color cursor shape update");
-    encodingCaps.add(EncodingPointerPos, TightVncVendor,
-                    SigEncodingPointerPos, "Pointer position update");
-    encodingCaps.add(EncodingLastRect, TightVncVendor,
-                    SigEncodingLastRect, "LastRect protocol extension");
-    encodingCaps.add(EncodingNewFBSize, TightVncVendor,
-                    SigEncodingNewFBSize, "Framebuffer size change");
-  }
-
-  //
-  // Setup tunneling (TightVNC protocol extensions)
-  //
-
-  void setupTunneling() throws IOException {
-    int nTunnelTypes = readU32();
-    if (nTunnelTypes != 0) {
-      readCapabilityList(tunnelCaps, nTunnelTypes);
-
-      // We don't support tunneling yet.
-      writeInt(NoTunneling);
-    }
-  }
-
-  //
-  // Negotiate authentication scheme (TightVNC protocol extensions)
-  //
-
-  int negotiateAuthenticationTight() throws Exception {
-    int nAuthTypes = readU32();
-    if (nAuthTypes == 0)
-      return AuthNone;
-
-    readCapabilityList(authCaps, nAuthTypes);
-    for (int i = 0; i < authCaps.numEnabled(); i++) {
-      int authType = authCaps.getByOrder(i);
-      if (authType == AuthNone || authType == AuthVNC) {
-       writeInt(authType);
-       return authType;
-      }
-    }
-    throw new Exception("No suitable authentication scheme found");
-  }
-
-  //
-  // Read a capability list (TightVNC protocol extensions)
-  //
-
-  void readCapabilityList(CapsContainer caps, int count) throws IOException {
-    int code;
-    byte[] vendor = new byte[4];
-    byte[] name = new byte[8];
-    for (int i = 0; i < count; i++) {
-      code = readU32();
-      readFully(vendor);
-      readFully(name);
-      caps.enable(new CapabilityInfo(code, vendor, name));
-    }
-  }
-
-  //
-  // Write a 32-bit integer into the output stream.
-  //
-
-  void writeInt(int value) throws IOException {
-    byte[] b = new byte[4];
-    b[0] = (byte) ((value >> 24) & 0xff);
-    b[1] = (byte) ((value >> 16) & 0xff);
-    b[2] = (byte) ((value >> 8) & 0xff);
-    b[3] = (byte) (value & 0xff);
-    os.write(b);
-  }
-
-  //
-  // Write the client initialisation message
-  //
-
-  void writeClientInit() throws IOException {
-    if (viewer.options.shareDesktop) {
-      os.write(1);
-    } else {
-      os.write(0);
-    }
-    viewer.options.disableShareDesktop();
-  }
-
-
-  //
-  // Read the server initialisation message
-  //
-
-  String desktopName;
-  int framebufferWidth, framebufferHeight;
-  int bitsPerPixel, depth;
-  boolean bigEndian, trueColour;
-  int redMax, greenMax, blueMax, redShift, greenShift, blueShift;
-
-  void readServerInit() throws IOException {
-    framebufferWidth = readU16();
-    framebufferHeight = readU16();
-    bitsPerPixel = readU8();
-    depth = readU8();
-    bigEndian = (readU8() != 0);
-    trueColour = (readU8() != 0);
-    redMax = readU16();
-    greenMax = readU16();
-    blueMax = readU16();
-    redShift = readU8();
-    greenShift = readU8();
-    blueShift = readU8();
-    byte[] pad = new byte[3];
-    readFully(pad);
-    int nameLength = readU32();
-    byte[] name = new byte[nameLength];
-    readFully(name);
-    desktopName = new String(name);
-
-    // Read interaction capabilities (TightVNC protocol extensions)
-    if (protocolTightVNC) {
-      int nServerMessageTypes = readU16();
-      int nClientMessageTypes = readU16();
-      int nEncodingTypes = readU16();
-      readU16();
-      readCapabilityList(serverMsgCaps, nServerMessageTypes);
-      readCapabilityList(clientMsgCaps, nClientMessageTypes);
-      readCapabilityList(encodingCaps, nEncodingTypes);
-    }
-
-    if (!clientMsgCaps.isEnabled(EnableContinuousUpdates)) {
-      viewer.options.disableContUpdates();
-    }
-
-    inNormalProtocol = true;
-  }
-
-
-  //
-  // Create session file and write initial protocol messages into it.
-  //
-
-  void startSession(String fname) throws IOException {
-    rec = new SessionRecorder(fname);
-    rec.writeHeader();
-    rec.write(versionMsg_3_3.getBytes());
-    rec.writeIntBE(SecTypeNone);
-    rec.writeShortBE(framebufferWidth);
-    rec.writeShortBE(framebufferHeight);
-    byte[] fbsServerInitMsg =  {
-      32, 24, 0, 1, 0,
-      (byte)0xFF, 0, (byte)0xFF, 0, (byte)0xFF,
-      16, 8, 0, 0, 0, 0
-    };
-    rec.write(fbsServerInitMsg);
-    rec.writeIntBE(desktopName.length());
-    rec.write(desktopName.getBytes());
-    numUpdatesInSession = 0;
-
-    // FIXME: If there were e.g. ZRLE updates only, that should not
-    //        affect recording of Zlib and Tight updates. So, actually
-    //        we should maintain separate flags for Zlib, ZRLE and
-    //        Tight, instead of one ``wereZlibUpdates'' variable.
-    //
-
-    zlibWarningShown = false;
-    tightWarningShown = false;
-  }
-
-  //
-  // Close session file.
-  //
-
-  void closeSession() throws IOException {
-    if (rec != null) {
-      rec.close();
-      rec = null;
-    }
-  }
-
-
-  //
-  // Set new framebuffer size
-  //
-
-  void setFramebufferSize(int width, int height) {
-    framebufferWidth = width;
-    framebufferHeight = height;
-  }
-
-
-  //
-  // Read the server message type
-  //
-
-  int readServerMessageType() throws IOException {
-    int msgType = readU8();
-
-    // If the session is being recorded:
-    if (rec != null) {
-      if (msgType == Bell) {   // Save Bell messages in session files.
-       rec.writeByte(msgType);
-       if (numUpdatesInSession > 0)
-         rec.flush();
-      }
-    }
-
-    return msgType;
-  }
-
-
-  //
-  // Read a FramebufferUpdate message
-  //
-
-  int updateNRects;
-
-  void readFramebufferUpdate() throws IOException {
-    skipBytes(1);
-    updateNRects = readU16();
-
-    // If the session is being recorded:
-    if (rec != null) {
-      rec.writeByte(FramebufferUpdate);
-      rec.writeByte(0);
-      rec.writeShortBE(updateNRects);
-    }
-
-    numUpdatesInSession++;
-  }
-
-  //
-  // Returns true if encoding is not pseudo
-  //
-  // FIXME: Find better way to differ pseudo and real encodings
-  //
-
-  boolean isRealDecoderEncoding(int encoding) {
-    if ((encoding >= 1) && (encoding <= 16)) {
-      return true;
-    }
-    return false;
-  }
-
-  // Read a FramebufferUpdate rectangle header
-
-  int updateRectX, updateRectY, updateRectW, updateRectH, updateRectEncoding;
-
-  void readFramebufferUpdateRectHdr() throws Exception {
-    updateRectX = readU16();
-    updateRectY = readU16();
-    updateRectW = readU16();
-    updateRectH = readU16();
-    updateRectEncoding = readU32();
-
-    if (updateRectEncoding == EncodingZlib ||
-        updateRectEncoding == EncodingZRLE ||
-       updateRectEncoding == EncodingTight)
-      wereZlibUpdates = true;
-
-    // If the session is being recorded:
-    if (rec != null) {
-      if (numUpdatesInSession > 1)
-       rec.flush();            // Flush the output on each rectangle.
-      rec.writeShortBE(updateRectX);
-      rec.writeShortBE(updateRectY);
-      rec.writeShortBE(updateRectW);
-      rec.writeShortBE(updateRectH);
-
-      //
-      // If this is pseudo encoding or CopyRect that write encoding ID
-      // in this place. All real encoding ID will be written to record stream
-      // in decoder classes.
-
-      if (((!isRealDecoderEncoding(updateRectEncoding))) && (rec != null)) {
-        rec.writeIntBE(updateRectEncoding);
-      }
-    }
-
-    if (updateRectEncoding < 0 || updateRectEncoding > MaxNormalEncoding)
-      return;
-
-    if (updateRectX + updateRectW > framebufferWidth ||
-       updateRectY + updateRectH > framebufferHeight) {
-      throw new Exception("Framebuffer update rectangle too large: " +
-                         updateRectW + "x" + updateRectH + " at (" +
-                         updateRectX + "," + updateRectY + ")");
-    }
-  }
-
-  //
-  // Read a ServerCutText message
-  //
-
-  String readServerCutText() throws IOException {
-    skipBytes(3);
-    int len = readU32();
-    byte[] text = new byte[len];
-    readFully(text);
-    return new String(text);
-  }
-
-
-  //
-  // Read an integer in compact representation (1..3 bytes).
-  // Such format is used as a part of the Tight encoding.
-  // Also, this method records data if session recording is active and
-  // the viewer's recordFromBeginning variable is set to true.
-  //
-
-  int readCompactLen() throws IOException {
-    int[] portion = new int[3];
-    portion[0] = readU8();
-    int byteCount = 1;
-    int len = portion[0] & 0x7F;
-    if ((portion[0] & 0x80) != 0) {
-      portion[1] = readU8();
-      byteCount++;
-      len |= (portion[1] & 0x7F) << 7;
-      if ((portion[1] & 0x80) != 0) {
-       portion[2] = readU8();
-       byteCount++;
-       len |= (portion[2] & 0xFF) << 14;
-      }
-    }
-
-    return len;
-  }
-
-
-  //
-  // Write a FramebufferUpdateRequest message
-  //
-
-  void writeFramebufferUpdateRequest(int x, int y, int w, int h,
-                                    boolean incremental)
-       throws IOException
-  {
-    byte[] b = new byte[10];
-
-    b[0] = (byte) FramebufferUpdateRequest;
-    b[1] = (byte) (incremental ? 1 : 0);
-    b[2] = (byte) ((x >> 8) & 0xff);
-    b[3] = (byte) (x & 0xff);
-    b[4] = (byte) ((y >> 8) & 0xff);
-    b[5] = (byte) (y & 0xff);
-    b[6] = (byte) ((w >> 8) & 0xff);
-    b[7] = (byte) (w & 0xff);
-    b[8] = (byte) ((h >> 8) & 0xff);
-    b[9] = (byte) (h & 0xff);
-
-    os.write(b);
-  }
-
-
-  //
-  // Write a SetPixelFormat message
-  //
-
-  void writeSetPixelFormat(int bitsPerPixel, int depth, boolean bigEndian,
-                          boolean trueColour,
-                          int redMax, int greenMax, int blueMax,
-                          int redShift, int greenShift, int blueShift)
-       throws IOException
-  {
-    byte[] b = new byte[20];
-
-    b[0]  = (byte) SetPixelFormat;
-    b[4]  = (byte) bitsPerPixel;
-    b[5]  = (byte) depth;
-    b[6]  = (byte) (bigEndian ? 1 : 0);
-    b[7]  = (byte) (trueColour ? 1 : 0);
-    b[8]  = (byte) ((redMax >> 8) & 0xff);
-    b[9]  = (byte) (redMax & 0xff);
-    b[10] = (byte) ((greenMax >> 8) & 0xff);
-    b[11] = (byte) (greenMax & 0xff);
-    b[12] = (byte) ((blueMax >> 8) & 0xff);
-    b[13] = (byte) (blueMax & 0xff);
-    b[14] = (byte) redShift;
-    b[15] = (byte) greenShift;
-    b[16] = (byte) blueShift;
-
-    os.write(b);
-  }
-
-
-  //
-  // Write a FixColourMapEntries message.  The values in the red, green and
-  // blue arrays are from 0 to 65535.
-  //
-
-  void writeFixColourMapEntries(int firstColour, int nColours,
-                               int[] red, int[] green, int[] blue)
-       throws IOException
-  {
-    byte[] b = new byte[6 + nColours * 6];
-
-    b[0] = (byte) FixColourMapEntries;
-    b[2] = (byte) ((firstColour >> 8) & 0xff);
-    b[3] = (byte) (firstColour & 0xff);
-    b[4] = (byte) ((nColours >> 8) & 0xff);
-    b[5] = (byte) (nColours & 0xff);
-
-    for (int i = 0; i < nColours; i++) {
-      b[6 + i * 6]     = (byte) ((red[i] >> 8) & 0xff);
-      b[6 + i * 6 + 1] = (byte) (red[i] & 0xff);
-      b[6 + i * 6 + 2] = (byte) ((green[i] >> 8) & 0xff);
-      b[6 + i * 6 + 3] = (byte) (green[i] & 0xff);
-      b[6 + i * 6 + 4] = (byte) ((blue[i] >> 8) & 0xff);
-      b[6 + i * 6 + 5] = (byte) (blue[i] & 0xff);
-    }
-
-    os.write(b);
-  }
-
-
-  //
-  // Write a SetEncodings message
-  //
-
-  void writeSetEncodings(int[] encs, int len) throws IOException {
-    byte[] b = new byte[4 + 4 * len];
-
-    b[0] = (byte) SetEncodings;
-    b[2] = (byte) ((len >> 8) & 0xff);
-    b[3] = (byte) (len & 0xff);
-
-    for (int i = 0; i < len; i++) {
-      b[4 + 4 * i] = (byte) ((encs[i] >> 24) & 0xff);
-      b[5 + 4 * i] = (byte) ((encs[i] >> 16) & 0xff);
-      b[6 + 4 * i] = (byte) ((encs[i] >> 8) & 0xff);
-      b[7 + 4 * i] = (byte) (encs[i] & 0xff);
-    }
-
-    os.write(b);
-  }
-
-
-  //
-  // Write a ClientCutText message
-  //
-
-  void writeClientCutText(String text) throws IOException {
-    byte[] b = new byte[8 + text.length()];
-
-    b[0] = (byte) ClientCutText;
-    b[4] = (byte) ((text.length() >> 24) & 0xff);
-    b[5] = (byte) ((text.length() >> 16) & 0xff);
-    b[6] = (byte) ((text.length() >> 8) & 0xff);
-    b[7] = (byte) (text.length() & 0xff);
-
-    System.arraycopy(text.getBytes(), 0, b, 8, text.length());
-
-    os.write(b);
-  }
-
-
-  //
-  // A buffer for putting pointer and keyboard events before being sent.  This
-  // is to ensure that multiple RFB events generated from a single Java Event
-  // will all be sent in a single network packet.  The maximum possible
-  // length is 4 modifier down events, a single key event followed by 4
-  // modifier up events i.e. 9 key events or 72 bytes.
-  //
-
-  byte[] eventBuf = new byte[72];
-  int eventBufLen;
-
-
-  // Useful shortcuts for modifier masks.
-
-  final static int CTRL_MASK  = InputEvent.CTRL_MASK;
-  final static int SHIFT_MASK = InputEvent.SHIFT_MASK;
-  final static int META_MASK  = InputEvent.META_MASK;
-  final static int ALT_MASK   = InputEvent.ALT_MASK;
-
-
-  //
-  // Write a pointer event message.  We may need to send modifier key events
-  // around it to set the correct modifier state.
-  //
-
-  int pointerMask = 0;
-
-  void writePointerEvent(MouseEvent evt) throws IOException {
-    int modifiers = evt.getModifiers();
-
-    int mask2 = 2;
-    int mask3 = 4;
-    if (viewer.options.reverseMouseButtons2And3) {
-      mask2 = 4;
-      mask3 = 2;
-    }
-
-    // Note: For some reason, AWT does not set BUTTON1_MASK on left
-    // button presses. Here we think that it was the left button if
-    // modifiers do not include BUTTON2_MASK or BUTTON3_MASK.
-
-    if (evt.getID() == MouseEvent.MOUSE_PRESSED) {
-      if ((modifiers & InputEvent.BUTTON2_MASK) != 0) {
-        pointerMask = mask2;
-        modifiers &= ~ALT_MASK;
-      } else if ((modifiers & InputEvent.BUTTON3_MASK) != 0) {
-        pointerMask = mask3;
-        modifiers &= ~META_MASK;
-      } else {
-        pointerMask = 1;
-      }
-    } else if (evt.getID() == MouseEvent.MOUSE_RELEASED) {
-      pointerMask = 0;
-      if ((modifiers & InputEvent.BUTTON2_MASK) != 0) {
-        modifiers &= ~ALT_MASK;
-      } else if ((modifiers & InputEvent.BUTTON3_MASK) != 0) {
-        modifiers &= ~META_MASK;
-      }
-    }
-
-    eventBufLen = 0;
-    writeModifierKeyEvents(modifiers);
-
-    int x = evt.getX();
-    int y = evt.getY();
-
-    if (x < 0) x = 0;
-    if (y < 0) y = 0;
-
-    eventBuf[eventBufLen++] = (byte) PointerEvent;
-    eventBuf[eventBufLen++] = (byte) pointerMask;
-    eventBuf[eventBufLen++] = (byte) ((x >> 8) & 0xff);
-    eventBuf[eventBufLen++] = (byte) (x & 0xff);
-    eventBuf[eventBufLen++] = (byte) ((y >> 8) & 0xff);
-    eventBuf[eventBufLen++] = (byte) (y & 0xff);
-
-    //
-    // Always release all modifiers after an "up" event
-    //
-
-    if (pointerMask == 0) {
-      writeModifierKeyEvents(0);
-    }
-
-    os.write(eventBuf, 0, eventBufLen);
-  }
-
-
-  //
-  // Write a key event message.  We may need to send modifier key events
-  // around it to set the correct modifier state.  Also we need to translate
-  // from the Java key values to the X keysym values used by the RFB protocol.
-  //
-
-  void writeKeyEvent(KeyEvent evt) throws IOException {
-
-    int keyChar = evt.getKeyChar();
-
-    //
-    // Ignore event if only modifiers were pressed.
-    //
-
-    // Some JVMs return 0 instead of CHAR_UNDEFINED in getKeyChar().
-    if (keyChar == 0)
-      keyChar = KeyEvent.CHAR_UNDEFINED;
-
-    if (keyChar == KeyEvent.CHAR_UNDEFINED) {
-      int code = evt.getKeyCode();
-      if (code == KeyEvent.VK_CONTROL || code == KeyEvent.VK_SHIFT ||
-          code == KeyEvent.VK_META || code == KeyEvent.VK_ALT)
-        return;
-    }
-
-    //
-    // Key press or key release?
-    //
-
-    boolean down = (evt.getID() == KeyEvent.KEY_PRESSED);
-
-    int key;
-    if (evt.isActionKey()) {
-
-      //
-      // An action key should be one of the following.
-      // If not then just ignore the event.
-      //
-
-      switch(evt.getKeyCode()) {
-      case KeyEvent.VK_HOME:      key = 0xff50; break;
-      case KeyEvent.VK_LEFT:      key = 0xff51; break;
-      case KeyEvent.VK_UP:        key = 0xff52; break;
-      case KeyEvent.VK_RIGHT:     key = 0xff53; break;
-      case KeyEvent.VK_DOWN:      key = 0xff54; break;
-      case KeyEvent.VK_PAGE_UP:   key = 0xff55; break;
-      case KeyEvent.VK_PAGE_DOWN: key = 0xff56; break;
-      case KeyEvent.VK_END:       key = 0xff57; break;
-      case KeyEvent.VK_INSERT:    key = 0xff63; break;
-      case KeyEvent.VK_F1:        key = 0xffbe; break;
-      case KeyEvent.VK_F2:        key = 0xffbf; break;
-      case KeyEvent.VK_F3:        key = 0xffc0; break;
-      case KeyEvent.VK_F4:        key = 0xffc1; break;
-      case KeyEvent.VK_F5:        key = 0xffc2; break;
-      case KeyEvent.VK_F6:        key = 0xffc3; break;
-      case KeyEvent.VK_F7:        key = 0xffc4; break;
-      case KeyEvent.VK_F8:        key = 0xffc5; break;
-      case KeyEvent.VK_F9:        key = 0xffc6; break;
-      case KeyEvent.VK_F10:       key = 0xffc7; break;
-      case KeyEvent.VK_F11:       key = 0xffc8; break;
-      case KeyEvent.VK_F12:       key = 0xffc9; break;
-      default:
-        return;
-      }
-
-    } else {
-
-      //
-      // A "normal" key press.  Ordinary ASCII characters go straight through.
-      // For CTRL-<letter>, CTRL is sent separately so just send <letter>.
-      // Backspace, tab, return, escape and delete have special keysyms.
-      // Anything else we ignore.
-      //
-
-      key = keyChar;
-
-      if (key < 0x20) {
-        if (evt.isControlDown()) {
-          key += 0x60;
-        } else {
-          switch(key) {
-          case KeyEvent.VK_BACK_SPACE: key = 0xff08; break;
-          case KeyEvent.VK_TAB:        key = 0xff09; break;
-          case KeyEvent.VK_ENTER:      key = 0xff0d; break;
-          case KeyEvent.VK_ESCAPE:     key = 0xff1b; break;
-          }
-        }
-      } else if (key == 0x7f) {
-       // Delete
-       key = 0xffff;
-      } else if (key > 0xff) {
-       // JDK1.1 on X incorrectly passes some keysyms straight through,
-       // so we do too.  JDK1.1.4 seems to have fixed this.
-       // The keysyms passed are 0xff00 .. XK_BackSpace .. XK_Delete
-       // Also, we pass through foreign currency keysyms (0x20a0..0x20af).
-       if ((key < 0xff00 || key > 0xffff) &&
-           !(key >= 0x20a0 && key <= 0x20af))
-         return;
-      }
-    }
-
-    // Fake keyPresses for keys that only generates keyRelease events
-    if ((key == 0xe5) || (key == 0xc5) || // XK_aring / XK_Aring
-       (key == 0xe4) || (key == 0xc4) || // XK_adiaeresis / XK_Adiaeresis
-       (key == 0xf6) || (key == 0xd6) || // XK_odiaeresis / XK_Odiaeresis
-       (key == 0xa7) || (key == 0xbd) || // XK_section / XK_onehalf
-       (key == 0xa3)) {                  // XK_sterling
-      // Make sure we do not send keypress events twice on platforms
-      // with correct JVMs (those that actually report KeyPress for all
-      // keys)
-      if (down)
-       brokenKeyPressed = true;
-
-      if (!down && !brokenKeyPressed) {
-       // We've got a release event for this key, but haven't received
-        // a press. Fake it.
-       eventBufLen = 0;
-       writeModifierKeyEvents(evt.getModifiers());
-       writeKeyEvent(key, true);
-       os.write(eventBuf, 0, eventBufLen);
-      }
-
-      if (!down)
-       brokenKeyPressed = false;
-    }
-
-    eventBufLen = 0;
-    writeModifierKeyEvents(evt.getModifiers());
-    writeKeyEvent(key, down);
-
-    // Always release all modifiers after an "up" event
-    if (!down)
-      writeModifierKeyEvents(0);
-
-    os.write(eventBuf, 0, eventBufLen);
-  }
-
-
-  //
-  // Add a raw key event with the given X keysym to eventBuf.
-  //
-
-  void writeKeyEvent(int keysym, boolean down) {
-    eventBuf[eventBufLen++] = (byte) KeyboardEvent;
-    eventBuf[eventBufLen++] = (byte) (down ? 1 : 0);
-    eventBuf[eventBufLen++] = (byte) 0;
-    eventBuf[eventBufLen++] = (byte) 0;
-    eventBuf[eventBufLen++] = (byte) ((keysym >> 24) & 0xff);
-    eventBuf[eventBufLen++] = (byte) ((keysym >> 16) & 0xff);
-    eventBuf[eventBufLen++] = (byte) ((keysym >> 8) & 0xff);
-    eventBuf[eventBufLen++] = (byte) (keysym & 0xff);
-  }
-
-
-  //
-  // Write key events to set the correct modifier state.
-  //
-
-  int oldModifiers = 0;
-
-  void writeModifierKeyEvents(int newModifiers) {
-    if ((newModifiers & CTRL_MASK) != (oldModifiers & CTRL_MASK))
-      writeKeyEvent(0xffe3, (newModifiers & CTRL_MASK) != 0);
-
-    if ((newModifiers & SHIFT_MASK) != (oldModifiers & SHIFT_MASK))
-      writeKeyEvent(0xffe1, (newModifiers & SHIFT_MASK) != 0);
-
-    if ((newModifiers & META_MASK) != (oldModifiers & META_MASK))
-      writeKeyEvent(0xffe7, (newModifiers & META_MASK) != 0);
-
-    if ((newModifiers & ALT_MASK) != (oldModifiers & ALT_MASK))
-      writeKeyEvent(0xffe9, (newModifiers & ALT_MASK) != 0);
-
-    oldModifiers = newModifiers;
-  }
-
-
-  //
-  // Enable continuous updates for the specified area of the screen (but
-  // only if EnableContinuousUpdates message is supported by the server).
-  //
-
-  void tryEnableContinuousUpdates(int x, int y, int w, int h)
-    throws IOException
-  {
-    if (!clientMsgCaps.isEnabled(EnableContinuousUpdates)) {
-      System.out.println("Continuous updates not supported by the server");
-      return;
-    }
-
-    if (continuousUpdatesActive) {
-      System.out.println("Continuous updates already active");
-      return;
-    }
-
-    byte[] b = new byte[10];
-
-    b[0] = (byte) EnableContinuousUpdates;
-    b[1] = (byte) 1; // enable
-    b[2] = (byte) ((x >> 8) & 0xff);
-    b[3] = (byte) (x & 0xff);
-    b[4] = (byte) ((y >> 8) & 0xff);
-    b[5] = (byte) (y & 0xff);
-    b[6] = (byte) ((w >> 8) & 0xff);
-    b[7] = (byte) (w & 0xff);
-    b[8] = (byte) ((h >> 8) & 0xff);
-    b[9] = (byte) (h & 0xff);
-
-    os.write(b);
-
-    continuousUpdatesActive = true;
-    System.out.println("Continuous updates activated");
-  }
-
-
-  //
-  // Disable continuous updates (only if EnableContinuousUpdates message
-  // is supported by the server).
-  //
-
-  void tryDisableContinuousUpdates() throws IOException
-  {
-    if (!clientMsgCaps.isEnabled(EnableContinuousUpdates)) {
-      System.out.println("Continuous updates not supported by the server");
-      return;
-    }
-
-    if (!continuousUpdatesActive) {
-      System.out.println("Continuous updates already disabled");
-      return;
-    }
-
-    if (continuousUpdatesEnding)
-      return;
-
-    byte[] b = { (byte)EnableContinuousUpdates, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-    os.write(b);
-
-    if (!serverMsgCaps.isEnabled(EndOfContinuousUpdates)) {
-      // If the server did not advertise support for the
-      // EndOfContinuousUpdates message (should not normally happen
-      // when EnableContinuousUpdates is supported), then we clear
-      // 'continuousUpdatesActive' variable immediately. Normally,
-      // it will be reset on receiving EndOfContinuousUpdates message
-      // from the server.
-      continuousUpdatesActive = false;
-    } else {
-      // Indicate that we are waiting for EndOfContinuousUpdates.
-      continuousUpdatesEnding = true;
-    }
-  }
-
-
-  //
-  // Process EndOfContinuousUpdates message received from the server.
-  //
-
-  void endOfContinuousUpdates()
-  {
-    continuousUpdatesActive = false;
-    continuousUpdatesEnding = false;
-  }
-
-
-  //
-  // Check if continuous updates are in effect.
-  //
-
-  boolean continuousUpdatesAreActive()
-  {
-    return continuousUpdatesActive;
-  }
-
-  /**
-   * Send a rectangle selection to be treated as video by the server (but
-   * only if VideoRectangleSelection message is supported by the server).
-   * @param rect specifies coordinates and size of the rectangule.
-   * @throws java.io.IOException
-   */
-  void trySendVideoSelection(Rectangle rect) throws IOException
-  {
-    if (!clientMsgCaps.isEnabled(VideoRectangleSelection)) {
-      System.out.println("Video area selection is not supported by the server");
-      return;
-    }
-
-    // Send zero coordinates if the rectangle is empty.
-    if (rect.isEmpty()) {
-      rect = new Rectangle();
-    }
-
-    int x = rect.x;
-    int y = rect.y;
-    int w = rect.width;
-    int h = rect.height;
-
-    byte[] b = new byte[10];
-
-    b[0] = (byte) VideoRectangleSelection;
-    b[1] = (byte) 0; // reserved
-    b[2] = (byte) ((x >> 8) & 0xff);
-    b[3] = (byte) (x & 0xff);
-    b[4] = (byte) ((y >> 8) & 0xff);
-    b[5] = (byte) (y & 0xff);
-    b[6] = (byte) ((w >> 8) & 0xff);
-    b[7] = (byte) (w & 0xff);
-    b[8] = (byte) ((h >> 8) & 0xff);
-    b[9] = (byte) (h & 0xff);
-
-    os.write(b);
-
-    System.out.println("Video rectangle selection message sent");
-  }
-
-  void trySendVideoFreeze(boolean freeze) throws IOException
-  {
-    if (!clientMsgCaps.isEnabled(VideoFreeze)) {
-      System.out.println("Video freeze is not supported by the server");
-      return;
-    }
-
-    byte[] b = new byte[2];
-    byte fb = 0;
-    if (freeze) {
-      fb = 1;
-    }
-
-    b[0] = (byte) VideoFreeze;
-    b[1] = (byte) fb;
-
-    os.write(b);
-
-    System.out.println("Video freeze selection message sent");
-  }
-
-  public void startTiming() {
-    timing = true;
-
-    // Carry over up to 1s worth of previous rate for smoothing.
-
-    if (timeWaitedIn100us > 10000) {
-      timedKbits = timedKbits * 10000 / timeWaitedIn100us;
-      timeWaitedIn100us = 10000;
-    }
-  }
-
-  public void stopTiming() {
-    timing = false;
-    if (timeWaitedIn100us < timedKbits/2)
-      timeWaitedIn100us = timedKbits/2; // upper limit 20Mbit/s
-  }
-
-  public long kbitsPerSecond() {
-    return timedKbits * 10000 / timeWaitedIn100us;
-  }
-
-  public long timeWaited() {
-    return timeWaitedIn100us;
-  }
-
-  //
-  // Methods for reading data via our DataInputStream member variable (is).
-  //
-  // In addition to reading data, the readFully() methods updates variables
-  // used to estimate data throughput.
-  //
-
-  public void readFully(byte b[]) throws IOException {
-    readFully(b, 0, b.length);
-  }
-
-  public void readFully(byte b[], int off, int len) throws IOException {
-    long before = 0;
-    if (timing)
-      before = System.currentTimeMillis();
-
-    is.readFully(b, off, len);
-
-    if (timing) {
-      long after = System.currentTimeMillis();
-      long newTimeWaited = (after - before) * 10;
-      int newKbits = len * 8 / 1000;
-
-      // limit rate to between 10kbit/s and 40Mbit/s
-
-      if (newTimeWaited > newKbits*1000) newTimeWaited = newKbits*1000;
-      if (newTimeWaited < newKbits/4)    newTimeWaited = newKbits/4;
-
-      timeWaitedIn100us += newTimeWaited;
-      timedKbits += newKbits;
-    }
-
-    numBytesRead += len;
-  }
-
-  final int available() throws IOException {
-    return is.available();
-  }
-
-  // FIXME: DataInputStream::skipBytes() is not guaranteed to skip
-  //        exactly n bytes. Probably we don't want to use this method.
-  final int skipBytes(int n) throws IOException {
-    int r = is.skipBytes(n);
-    numBytesRead += r;
-    return r;
-  }
-
-  final int readU8() throws IOException {
-    int r = is.readUnsignedByte();
-    numBytesRead++;
-    return r;
-  }
-
-  final int readU16() throws IOException {
-    int r = is.readUnsignedShort();
-    numBytesRead += 2;
-    return r;
-  }
-
-  final int readU32() throws IOException {
-    int r = is.readInt();
-    numBytesRead += 4;
-    return r;
-  }
-}
diff --git a/java/src/com/tightvnc/vncviewer/SessionRecorder.java b/java/src/com/tightvnc/vncviewer/SessionRecorder.java
deleted file mode 100644 (file)
index 9e73531..0000000
+++ /dev/null
@@ -1,195 +0,0 @@
-//
-//  Copyright (C) 2002 Constantin Kaplinsky.  All Rights Reserved.
-//
-//  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.
-//
-
-//
-// SessionRecorder is a class to write FBS (FrameBuffer Stream) files.
-// FBS files are used to save RFB sessions for later playback.
-//
-
-package com.tightvnc.vncviewer;
-
-import java.io.*;
-
-class SessionRecorder {
-
-  protected FileOutputStream f;
-  protected DataOutputStream df;
-  protected long startTime, lastTimeOffset;
-
-  protected byte[] buffer;
-  protected int bufferSize;
-  protected int bufferBytes;
-
-  public SessionRecorder(String name, int bufsize) throws IOException {
-    f = new FileOutputStream(name);
-    df = new DataOutputStream(f);
-    startTime = System.currentTimeMillis();
-    lastTimeOffset = 0;
-    
-    bufferSize = bufsize;
-    bufferBytes = 0;
-    buffer = new byte[bufferSize];
-  }
-
-  public SessionRecorder(String name) throws IOException {
-    this(name, 65536);
-  }
-
-  //
-  // Close the file, free resources.
-  //
-
-  public void close() throws IOException {
-    try {
-      flush();
-    } catch (IOException e) {
-    }
-
-    df = null;
-    f.close();
-    f = null;
-    buffer = null;
-  }
-
-  //
-  // Write the FBS file header as defined in the rfbproxy utility.
-  //
-
-  public void writeHeader() throws IOException {
-    df.write("FBS 001.000\n".getBytes());
-  }
-
-  //
-  // Write one byte.
-  //
-
-  public void writeByte(int b) throws IOException {
-    prepareWriting();
-    buffer[bufferBytes++] = (byte)b;
-  }
-
-  //
-  // Write 16-bit value, big-endian.
-  //
-
-  public void writeShortBE(int v) throws IOException {
-    prepareWriting();
-    buffer[bufferBytes++] = (byte)(v >> 8);
-    buffer[bufferBytes++] = (byte)v;
-  }
-
-  //
-  // Write 32-bit value, big-endian.
-  //
-
-  public void writeIntBE(int v) throws IOException {
-    prepareWriting();
-    buffer[bufferBytes]     = (byte)(v >> 24);
-    buffer[bufferBytes + 1] = (byte)(v >> 16);
-    buffer[bufferBytes + 2] = (byte)(v >> 8);
-    buffer[bufferBytes + 3] = (byte)v;
-    bufferBytes += 4;
-  }
-
-  //
-  // Write 16-bit value, little-endian.
-  //
-
-  public void writeShortLE(int v) throws IOException {
-    prepareWriting();
-    buffer[bufferBytes++] = (byte)v;
-    buffer[bufferBytes++] = (byte)(v >> 8);
-  }
-
-  //
-  // Write 32-bit value, little-endian.
-  //
-
-  public void writeIntLE(int v) throws IOException {
-    prepareWriting();
-    buffer[bufferBytes]     = (byte)v;
-    buffer[bufferBytes + 1] = (byte)(v >> 8);
-    buffer[bufferBytes + 2] = (byte)(v >> 16);
-    buffer[bufferBytes + 3] = (byte)(v >> 24);
-    bufferBytes += 4;
-  }
-
-  //
-  // Write byte arrays.
-  //
-
-  public void write(byte b[], int off, int len) throws IOException {
-    prepareWriting();
-    while (len > 0) {
-      if (bufferBytes > bufferSize - 4)
-       flush(false);
-
-      int partLen;
-      if (bufferBytes + len > bufferSize) {
-       partLen = bufferSize - bufferBytes;
-      } else {
-       partLen = len;
-      }
-      System.arraycopy(b, off, buffer, bufferBytes, partLen);
-      bufferBytes += partLen;
-      off += partLen;
-      len -= partLen;
-    }
-  }
-
-  public void write(byte b[]) throws IOException {
-    write(b, 0, b.length);
-  }
-
-  //
-  // Flush the output. This method saves buffered data in the
-  // underlying file object adding data sizes and timestamps. If the
-  // updateTimeOffset is set to false, then the current time offset
-  // will not be changed for next write operation.
-  //
-
-  public void flush(boolean updateTimeOffset) throws IOException {
-    if (bufferBytes > 0) {
-      df.writeInt(bufferBytes);
-      df.write(buffer, 0, (bufferBytes + 3) & 0x7FFFFFFC);
-      df.writeInt((int)lastTimeOffset);
-      bufferBytes = 0;
-      if (updateTimeOffset)
-       lastTimeOffset = -1;
-    }
-  }
-
-  public void flush() throws IOException {
-    flush(true);
-  }
-
-  //
-  // Before writing any data, remember time offset and flush the
-  // buffer before it becomes full.
-  //
-
-  protected void prepareWriting() throws IOException {
-    if (lastTimeOffset == -1)
-      lastTimeOffset = System.currentTimeMillis() - startTime;
-    if (bufferBytes > bufferSize - 4)
-      flush(false);
-  }
-
-}
-
diff --git a/java/src/com/tightvnc/vncviewer/SocketFactory.java b/java/src/com/tightvnc/vncviewer/SocketFactory.java
deleted file mode 100644 (file)
index 966d1d3..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-//
-//  Copyright (C) 2002 HorizonLive.com, Inc.  All Rights Reserved.
-//
-//  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.
-//
-
-//
-// SocketFactory.java describes an interface used to substitute the
-// standard Socket class by its alternative implementations.
-//
-
-package com.tightvnc.vncviewer;
-
-import java.applet.*;
-import java.net.*;
-import java.io.*;
-
-public interface SocketFactory {
-
-  public Socket createSocket(String host, int port, Applet applet)
-    throws IOException;
-
-  public Socket createSocket(String host, int port, String[] args)
-    throws IOException;
-}
diff --git a/java/src/com/tightvnc/vncviewer/VncCanvas.java b/java/src/com/tightvnc/vncviewer/VncCanvas.java
deleted file mode 100644 (file)
index 4e5460f..0000000
+++ /dev/null
@@ -1,1315 +0,0 @@
-//
-//  Copyright (C) 2004 Horizon Wimba.  All Rights Reserved.
-//  Copyright (C) 2001-2003 HorizonLive.com, Inc.  All Rights Reserved.
-//  Copyright (C) 2001,2002 Constantin Kaplinsky.  All Rights Reserved.
-//  Copyright (C) 2000 Tridia Corporation.  All Rights Reserved.
-//  Copyright (C) 1999 AT&T Laboratories Cambridge.  All Rights Reserved.
-//
-//  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.
-//
-
-package com.tightvnc.vncviewer;
-
-import com.tightvnc.decoder.CoRREDecoder;
-import com.tightvnc.decoder.CopyRectDecoder;
-import com.tightvnc.decoder.HextileDecoder;
-import com.tightvnc.decoder.RREDecoder;
-import com.tightvnc.decoder.RawDecoder;
-import com.tightvnc.decoder.TightDecoder;
-import com.tightvnc.decoder.ZRLEDecoder;
-import com.tightvnc.decoder.ZlibDecoder;
-import com.tightvnc.decoder.common.Repaintable;
-import java.awt.*;
-import java.awt.event.*;
-import java.awt.image.*;
-import java.io.*;
-import java.lang.*;
-import java.util.zip.*;
-
-
-//
-// VncCanvas is a subclass of Canvas which draws a VNC desktop on it.
-//
-
-class VncCanvas extends Canvas
-  implements KeyListener, MouseListener, MouseMotionListener, Repaintable, Runnable {
-
-  VncViewer viewer;
-  RfbProto rfb;
-  ColorModel cm8, cm24;
-  int bytesPixel;
-
-  int maxWidth = 0, maxHeight = 0;
-  int scalingFactor;
-  int scaledWidth, scaledHeight;
-
-  Image memImage;
-  Graphics memGraphics;
-
-  //
-  // Decoders
-  //
-
-  RawDecoder rawDecoder;
-  RREDecoder rreDecoder;
-  CoRREDecoder correDecoder;
-  ZlibDecoder zlibDecoder;
-  HextileDecoder hextileDecoder;
-  ZRLEDecoder zrleDecoder;
-  TightDecoder tightDecoder;
-  CopyRectDecoder copyRectDecoder;
-
-  // Base decoder decoders array
-  RawDecoder []decoders = null;
-
-  // Update statistics.
-  long statStartTime;           // time on first framebufferUpdateRequest
-  long statNumUpdates;           // counter for FramebufferUpdate messages
-  long statNumTotalRects;        // rectangles in FramebufferUpdate messages
-  long statNumPixelRects;        // the same, but excluding pseudo-rectangles
-  long statNumRectsTight;        // Tight-encoded rectangles (including JPEG)
-  long statNumRectsTightJPEG;    // JPEG-compressed Tight-encoded rectangles
-  long statNumRectsZRLE;         // ZRLE-encoded rectangles
-  long statNumRectsHextile;      // Hextile-encoded rectangles
-  long statNumRectsRaw;          // Raw-encoded rectangles
-  long statNumRectsCopy;         // CopyRect rectangles
-  long statNumBytesEncoded;      // number of bytes in updates, as received
-  long statNumBytesDecoded;      // number of bytes, as if Raw encoding was used
-
-  // True if we process keyboard and mouse events.
-  boolean inputEnabled;
-
-  // True if was no one auto resize of canvas
-  boolean isFirstSizeAutoUpdate = true;
-
-  // Members for limiting sending mouse events to server
-  long lastMouseEventSendTime = System.currentTimeMillis();
-  long mouseMaxFreq = 20;
-
-  //
-  // The constructors.
-  //
-
-  public VncCanvas(VncViewer v, int maxWidth_, int maxHeight_)
-    throws IOException {
-
-    viewer = v;
-    maxWidth = maxWidth_;
-    maxHeight = maxHeight_;
-
-    rfb = viewer.rfb;
-    scalingFactor = viewer.options.scalingFactor;
-
-    cm8 = new DirectColorModel(8, 7, (7 << 3), (3 << 6));
-    cm24 = new DirectColorModel(24, 0xFF0000, 0x00FF00, 0x0000FF);
-
-    //
-    // Create decoders
-    //
-
-    // Input stream for decoders
-    RfbInputStream rfbis = new RfbInputStream(rfb);
-    // Create output stream for session recording
-    RecordOutputStream ros = new RecordOutputStream(rfb);
-
-    rawDecoder = new RawDecoder(memGraphics, rfbis);
-    rreDecoder = new RREDecoder(memGraphics, rfbis);
-    correDecoder = new CoRREDecoder(memGraphics, rfbis);
-    hextileDecoder = new HextileDecoder(memGraphics, rfbis);
-    tightDecoder = new TightDecoder(memGraphics, rfbis);
-    zlibDecoder = new ZlibDecoder(memGraphics, rfbis);
-    zrleDecoder = new ZRLEDecoder(memGraphics, rfbis);
-    copyRectDecoder = new CopyRectDecoder(memGraphics, rfbis);
-
-    //
-    // Set data for decoders that needs extra parameters
-    //
-
-    hextileDecoder.setRepainableControl(this);
-    tightDecoder.setRepainableControl(this);
-
-    //
-    // Create array that contains our decoders
-    //
-
-    decoders = new RawDecoder[8];
-    decoders[0] = rawDecoder;
-    decoders[1] = rreDecoder;
-    decoders[2] = correDecoder;
-    decoders[3] = hextileDecoder;
-    decoders[4] = zlibDecoder;
-    decoders[5] = tightDecoder;
-    decoders[6] = zrleDecoder;
-    decoders[7] = copyRectDecoder;
-
-    //
-    // Set session recorder for decoders
-    //
-
-    for (int i = 0; i < decoders.length; i++) {
-      decoders[i].setDataOutputStream(ros);
-    }
-
-    setPixelFormat();
-    resetSelection();
-
-    inputEnabled = false;
-    if (!viewer.options.viewOnly)
-      enableInput(true);
-
-    // Enable mouse and keyboard event listeners.
-    addKeyListener(this);
-    addMouseListener(this);
-    addMouseMotionListener(this);
-
-    // Create thread, that will send mouse movement events
-    // to VNC server.
-    Thread mouseThread = new Thread(this);
-    mouseThread.start();
-  }
-
-  public VncCanvas(VncViewer v) throws IOException {
-    this(v, 0, 0);
-  }
-
-  //
-  // Callback methods to determine geometry of our Component.
-  //
-
-  public Dimension getPreferredSize() {
-    return new Dimension(scaledWidth, scaledHeight);
-  }
-
-  public Dimension getMinimumSize() {
-    return new Dimension(scaledWidth, scaledHeight);
-  }
-
-  public Dimension getMaximumSize() {
-    return new Dimension(scaledWidth, scaledHeight);
-  }
-
-  //
-  // All painting is performed here.
-  //
-
-  public void update(Graphics g) {
-    paint(g);
-  }
-
-  public void paint(Graphics g) {
-    synchronized(memImage) {
-      if (rfb.framebufferWidth == scaledWidth) {
-        g.drawImage(memImage, 0, 0, null);
-      } else {
-        paintScaledFrameBuffer(g);
-      }
-    }
-    if (showSoftCursor) {
-      int x0 = cursorX - hotX, y0 = cursorY - hotY;
-      Rectangle r = new Rectangle(x0, y0, cursorWidth, cursorHeight);
-      if (r.intersects(g.getClipBounds())) {
-       g.drawImage(softCursor, x0, y0, null);
-      }
-    }
-    if (isInSelectionMode()) {
-      Rectangle r = getSelection(true);
-      if (r.width > 0 && r.height > 0) {
-        // Don't forget to correct the coordinates for the right and bottom
-        // borders, so that the borders are the part of the selection.
-        r.width -= 1;
-        r.height -= 1;
-        g.setXORMode(Color.yellow);
-        g.drawRect(r.x, r.y, r.width, r.height);
-      }
-    }
-  }
-
-  public void paintScaledFrameBuffer(Graphics g) {
-    g.drawImage(memImage, 0, 0, scaledWidth, scaledHeight, null);
-  }
-
-  //
-  // Start/stop receiving mouse events. Keyboard events are received
-  // even in view-only mode, because we want to map the 'r' key to the
-  // screen refreshing function.
-  //
-
-  public synchronized void enableInput(boolean enable) {
-    if (enable && !inputEnabled) {
-      inputEnabled = true;
-      if (viewer.showControls) {
-       viewer.buttonPanel.enableRemoteAccessControls(true);
-      }
-      createSoftCursor();      // scaled cursor
-    } else if (!enable && inputEnabled) {
-      inputEnabled = false;
-      if (viewer.showControls) {
-       viewer.buttonPanel.enableRemoteAccessControls(false);
-      }
-      createSoftCursor();      // non-scaled cursor
-    }
-  }
-
-  public void setPixelFormat() throws IOException {
-    if (viewer.options.eightBitColors) {
-      rfb.writeSetPixelFormat(8, 8, false, true, 7, 7, 3, 0, 3, 6);
-      bytesPixel = 1;
-    } else {
-      rfb.writeSetPixelFormat(32, 24, false, true, 255, 255, 255, 16, 8, 0);
-      bytesPixel = 4;
-    }
-    updateFramebufferSize();
-  }
-
-  void setScalingFactor(int sf) {
-    scalingFactor = sf;
-    updateFramebufferSize();
-    invalidate();
-  }
-
-  void updateFramebufferSize() {
-
-    // Useful shortcuts.
-    int fbWidth = rfb.framebufferWidth;
-    int fbHeight = rfb.framebufferHeight;
-
-    // FIXME: This part of code must be in VncViewer i think
-    if (viewer.options.autoScale) {
-      if (viewer.inAnApplet) {
-        maxWidth = viewer.getWidth();
-        maxHeight = viewer.getHeight();
-      } else {
-        if (viewer.vncFrame != null) {
-          if (isFirstSizeAutoUpdate) {
-            isFirstSizeAutoUpdate = false;
-            Dimension screenSize = viewer.vncFrame.getToolkit().getScreenSize();
-            maxWidth = (int)screenSize.getWidth() - 100;
-            maxHeight = (int)screenSize.getHeight() - 100;
-            viewer.vncFrame.setSize(maxWidth, maxHeight);
-          } else {
-            viewer.desktopScrollPane.doLayout();
-            maxWidth = viewer.desktopScrollPane.getWidth();
-            maxHeight = viewer.desktopScrollPane.getHeight();
-          }
-        } else {
-          maxWidth = fbWidth;
-          maxHeight = fbHeight;
-        }
-      }
-      int f1 = maxWidth * 100 / fbWidth;
-      int f2 = maxHeight * 100 / fbHeight;
-      scalingFactor = Math.min(f1, f2);
-      if (scalingFactor > 100)
-       scalingFactor = 100;
-      System.out.println("Scaling desktop at " + scalingFactor + "%");
-    }
-
-    // Update scaled framebuffer geometry.
-    scaledWidth = (fbWidth * scalingFactor + 50) / 100;
-    scaledHeight = (fbHeight * scalingFactor + 50) / 100;
-
-    // Create new off-screen image either if it does not exist, or if
-    // its geometry should be changed. It's not necessary to replace
-    // existing image if only pixel format should be changed.
-    if (memImage == null) {
-      memImage = viewer.vncContainer.createImage(fbWidth, fbHeight);
-      memGraphics = memImage.getGraphics();
-    } else if (memImage.getWidth(null) != fbWidth ||
-              memImage.getHeight(null) != fbHeight) {
-      synchronized(memImage) {
-       memImage = viewer.vncContainer.createImage(fbWidth, fbHeight);
-       memGraphics = memImage.getGraphics();
-      }
-    }
-
-    //
-    // Update decoders
-    //
-
-    //
-    // FIXME: Why decoders can be null here?
-    //
-
-    if (decoders != null) {
-      for (int i = 0; i < decoders.length; i++) {
-        //
-        // Set changes to every decoder that we can use
-        //
-
-        decoders[i].setBPP(bytesPixel);
-        decoders[i].setFrameBufferSize(fbWidth, fbHeight);
-        decoders[i].setGraphics(memGraphics);
-
-        //
-        // Update decoder
-        //
-
-        decoders[i].update();
-      }
-    }
-
-    // FIXME: This part of code must be in VncViewer i think
-    // Update the size of desktop containers.
-    if (viewer.inSeparateFrame) {
-      if (viewer.desktopScrollPane != null) {
-        if (!viewer.options.autoScale) {
-          resizeDesktopFrame();
-        } else {
-          setSize(scaledWidth, scaledHeight);
-          viewer.desktopScrollPane.setSize(maxWidth + 200,
-                                           maxHeight + 200);
-        }
-      }
-    } else {
-      setSize(scaledWidth, scaledHeight);
-    }
-    viewer.moveFocusToDesktop();
-  }
-
-  void resizeDesktopFrame() {
-    setSize(scaledWidth, scaledHeight);
-
-    // FIXME: Find a better way to determine correct size of a
-    // ScrollPane.  -- const
-    Insets insets = viewer.desktopScrollPane.getInsets();
-    viewer.desktopScrollPane.setSize(scaledWidth +
-                                    2 * Math.min(insets.left, insets.right),
-                                    scaledHeight +
-                                    2 * Math.min(insets.top, insets.bottom));
-
-    viewer.vncFrame.pack();
-
-    // Try to limit the frame size to the screen size.
-
-    Dimension screenSize = viewer.vncFrame.getToolkit().getScreenSize();
-    Dimension frameSize = viewer.vncFrame.getSize();
-    Dimension newSize = frameSize;
-
-    // Reduce Screen Size by 30 pixels in each direction;
-    // This is a (poor) attempt to account for
-    //     1) Menu bar on Macintosh (should really also account for
-    //        Dock on OSX).  Usually 22px on top of screen.
-    //     2) Taxkbar on Windows (usually about 28 px on bottom)
-    //     3) Other obstructions.
-
-    screenSize.height -= 30;
-    screenSize.width  -= 30;
-
-    boolean needToResizeFrame = false;
-    if (frameSize.height > screenSize.height) {
-      newSize.height = screenSize.height;
-      needToResizeFrame = true;
-    }
-    if (frameSize.width > screenSize.width) {
-      newSize.width = screenSize.width;
-      needToResizeFrame = true;
-    }
-    if (needToResizeFrame) {
-      viewer.vncFrame.setSize(newSize);
-    }
-
-    viewer.desktopScrollPane.doLayout();
-  }
-
-  //
-  // processNormalProtocol() - executed by the rfbThread to deal with the
-  // RFB socket.
-  //
-
-  public void processNormalProtocol() throws Exception {
-
-    // Start/stop session recording if necessary.
-    viewer.checkRecordingStatus();
-
-    rfb.writeFramebufferUpdateRequest(0, 0, rfb.framebufferWidth,
-                                     rfb.framebufferHeight, false);
-
-    if (viewer.options.continuousUpdates) {
-      rfb.tryEnableContinuousUpdates(0, 0, rfb.framebufferWidth,
-                                     rfb.framebufferHeight);
-    }
-
-    resetStats();
-    boolean statsRestarted = false;
-
-    //
-    // main dispatch loop
-    //
-
-    while (true) {
-
-      // Read message type from the server.
-      int msgType = rfb.readServerMessageType();
-
-      // Process the message depending on its type.
-      switch (msgType) {
-      case RfbProto.FramebufferUpdate:
-
-        if (statNumUpdates == viewer.debugStatsExcludeUpdates &&
-            !statsRestarted) {
-          resetStats();
-          statsRestarted = true;
-        } else if (statNumUpdates == viewer.debugStatsMeasureUpdates &&
-                   statsRestarted) {
-          viewer.disconnect();
-        }
-
-       rfb.readFramebufferUpdate();
-       statNumUpdates++;
-
-       boolean cursorPosReceived = false;
-
-       for (int i = 0; i < rfb.updateNRects; i++) {
-
-         rfb.readFramebufferUpdateRectHdr();
-         statNumTotalRects++;
-         int rx = rfb.updateRectX, ry = rfb.updateRectY;
-         int rw = rfb.updateRectW, rh = rfb.updateRectH;
-
-         if (rfb.updateRectEncoding == rfb.EncodingLastRect)
-           break;
-
-         if (rfb.updateRectEncoding == rfb.EncodingNewFBSize) {
-           rfb.setFramebufferSize(rw, rh);
-           updateFramebufferSize();
-           break;
-         }
-
-         if (rfb.updateRectEncoding == rfb.EncodingXCursor ||
-             rfb.updateRectEncoding == rfb.EncodingRichCursor) {
-           handleCursorShapeUpdate(rfb.updateRectEncoding, rx, ry, rw, rh);
-           continue;
-         }
-
-         if (rfb.updateRectEncoding == rfb.EncodingPointerPos) {
-           softCursorMove(rx, ry);
-           cursorPosReceived = true;
-           continue;
-         }
-
-          long numBytesReadBefore = rfb.getNumBytesRead();
-
-          rfb.startTiming();
-
-         switch (rfb.updateRectEncoding) {
-         case RfbProto.EncodingRaw:
-           statNumRectsRaw++;
-           handleRawRect(rx, ry, rw, rh);
-           break;
-         case RfbProto.EncodingCopyRect:
-           statNumRectsCopy++;
-           handleCopyRect(rx, ry, rw, rh);
-           break;
-         case RfbProto.EncodingRRE:
-           handleRRERect(rx, ry, rw, rh);
-           break;
-         case RfbProto.EncodingCoRRE:
-           handleCoRRERect(rx, ry, rw, rh);
-           break;
-         case RfbProto.EncodingHextile:
-           statNumRectsHextile++;
-           handleHextileRect(rx, ry, rw, rh);
-           break;
-         case RfbProto.EncodingZRLE:
-           statNumRectsZRLE++;
-           handleZRLERect(rx, ry, rw, rh);
-           break;
-         case RfbProto.EncodingZlib:
-            handleZlibRect(rx, ry, rw, rh);
-           break;
-         case RfbProto.EncodingTight:
-            if (tightDecoder != null) {
-             statNumRectsTightJPEG = tightDecoder.getNumJPEGRects();
-              //statNumRectsTight = tightDecoder.getNumTightRects();
-            }
-            statNumRectsTight++;
-           handleTightRect(rx, ry, rw, rh);
-           break;
-         default:
-           throw new Exception("Unknown RFB rectangle encoding " +
-                               rfb.updateRectEncoding);
-         }
-
-          rfb.stopTiming();
-
-          statNumPixelRects++;
-          statNumBytesDecoded += rw * rh * bytesPixel;
-          statNumBytesEncoded +=
-            (int)(rfb.getNumBytesRead() - numBytesReadBefore);
-       }
-
-       boolean fullUpdateNeeded = false;
-
-       // Start/stop session recording if necessary. Request full
-       // update if a new session file was opened.
-       if (viewer.checkRecordingStatus())
-         fullUpdateNeeded = true;
-
-       // Defer framebuffer update request if necessary. But wake up
-       // immediately on keyboard or mouse event. Also, don't sleep
-       // if there is some data to receive, or if the last update
-       // included a PointerPos message.
-       if (viewer.deferUpdateRequests > 0 &&
-           rfb.available() == 0 && !cursorPosReceived) {
-         synchronized(rfb) {
-           try {
-             rfb.wait(viewer.deferUpdateRequests);
-           } catch (InterruptedException e) {
-           }
-         }
-       }
-
-        viewer.autoSelectEncodings();
-
-       // Before requesting framebuffer update, check if the pixel
-       // format should be changed.
-       if (viewer.options.eightBitColors != (bytesPixel == 1)) {
-          // Pixel format should be changed.
-          if (!rfb.continuousUpdatesAreActive()) {
-            // Continuous updates are not used. In this case, we just
-            // set new pixel format and request full update.
-            setPixelFormat();
-            fullUpdateNeeded = true;
-          } else {
-            // Otherwise, disable continuous updates first. Pixel
-            // format will be set later when we are sure that there
-            // will be no unsolicited framebuffer updates.
-            rfb.tryDisableContinuousUpdates();
-            break; // skip the code below
-          }
-       }
-
-        // Enable/disable continuous updates to reflect the GUI setting.
-        boolean enable = viewer.options.continuousUpdates;
-        if (enable != rfb.continuousUpdatesAreActive()) {
-          if (enable) {
-            rfb.tryEnableContinuousUpdates(0, 0, rfb.framebufferWidth,
-                                           rfb.framebufferHeight);
-          } else {
-            rfb.tryDisableContinuousUpdates();
-          }
-        }
-
-        // Finally, request framebuffer update if needed.
-        if (fullUpdateNeeded) {
-          rfb.writeFramebufferUpdateRequest(0, 0, rfb.framebufferWidth,
-                                            rfb.framebufferHeight, false);
-        } else if (!rfb.continuousUpdatesAreActive()) {
-          rfb.writeFramebufferUpdateRequest(0, 0, rfb.framebufferWidth,
-                                            rfb.framebufferHeight, true);
-        }
-
-       break;
-
-      case RfbProto.SetColourMapEntries:
-       throw new Exception("Can't handle SetColourMapEntries message");
-
-      case RfbProto.Bell:
-        Toolkit.getDefaultToolkit().beep();
-       break;
-
-      case RfbProto.ServerCutText:
-       String s = rfb.readServerCutText();
-       viewer.clipboard.setCutText(s);
-       break;
-
-      case RfbProto.EndOfContinuousUpdates:
-        if (rfb.continuousUpdatesAreActive()) {
-          rfb.endOfContinuousUpdates();
-
-          // Change pixel format if such change was pending. Note that we
-          // could not change pixel format while continuous updates were
-          // in effect.
-          boolean incremental = true;
-          if (viewer.options.eightBitColors != (bytesPixel == 1)) {
-            setPixelFormat();
-            incremental = false;
-          }
-          // From this point, we ask for updates explicitly.
-          rfb.writeFramebufferUpdateRequest(0, 0, rfb.framebufferWidth,
-                                            rfb.framebufferHeight,
-                                            incremental);
-        }
-        break;
-
-      default:
-       throw new Exception("Unknown RFB message type " + msgType);
-      }
-    }
-  }
-
-  //
-  // Handle a raw rectangle. The second form with paint==false is used
-  // by the Hextile decoder for raw-encoded tiles.
-  //
-
-  void handleRawRect(int x, int y, int w, int h) throws IOException, Exception {
-    handleRawRect(x, y, w, h, true);
-  }
-
-  void handleRawRect(int x, int y, int w, int h, boolean paint)
-    throws IOException , Exception{
-    rawDecoder.handleRect(x, y, w, h);
-    if (paint)
-      scheduleRepaint(x, y, w, h);
-  }
-
-  //
-  // Handle a CopyRect rectangle.
-  //
-
-  void handleCopyRect(int x, int y, int w, int h) throws IOException {
-    copyRectDecoder.handleRect(x, y, w, h);
-    scheduleRepaint(x, y, w, h);
-  }
-
-  //
-  // Handle an RRE-encoded rectangle.
-  //
-
-  void handleRRERect(int x, int y, int w, int h) throws IOException {
-    rreDecoder.handleRect(x, y, w, h);
-    scheduleRepaint(x, y, w, h);
-  }
-
-  //
-  // Handle a CoRRE-encoded rectangle.
-  //
-
-  void handleCoRRERect(int x, int y, int w, int h) throws IOException {
-    correDecoder.handleRect(x, y, w, h);
-    scheduleRepaint(x, y, w, h);
-  }
-
-  //
-  // Handle a Hextile-encoded rectangle.
-  //
-
-  void handleHextileRect(int x, int y, int w, int h) throws IOException,
-                                                            Exception {
-    hextileDecoder.handleRect(x, y, w, h);
-  }
-
-  //
-  // Handle a ZRLE-encoded rectangle.
-  //
-  // FIXME: Currently, session recording is not fully supported for ZRLE.
-  //
-
-  void handleZRLERect(int x, int y, int w, int h) throws Exception {
-    zrleDecoder.handleRect(x, y, w, h);
-    scheduleRepaint(x, y, w, h);
-  }
-
-  //
-  // Handle a Zlib-encoded rectangle.
-  //
-
-  void handleZlibRect(int x, int y, int w, int h) throws Exception {
-    zlibDecoder.handleRect(x, y, w, h);
-    scheduleRepaint(x, y, w, h);
-  }
-
-  //
-  // Handle a Tight-encoded rectangle.
-  //
-
-  void handleTightRect(int x, int y, int w, int h) throws Exception {
-    tightDecoder.handleRect(x, y, w, h);
-    scheduleRepaint(x, y, w, h);
-  }
-
-  //
-  // Tell JVM to repaint specified desktop area.
-  //
-
-  public void scheduleRepaint(int x, int y, int w, int h) {
-    // Request repaint, deferred if necessary.
-    if (rfb.framebufferWidth == scaledWidth) {
-      repaint(viewer.deferScreenUpdates, x, y, w, h);
-    } else {
-      int sx = x * scalingFactor / 100;
-      int sy = y * scalingFactor / 100;
-      int sw = ((x + w) * scalingFactor + 49) / 100 - sx + 1;
-      int sh = ((y + h) * scalingFactor + 49) / 100 - sy + 1;
-      repaint(viewer.deferScreenUpdates, sx, sy, sw, sh);
-    }
-  }
-
-  //
-  // Handle events.
-  //
-
-  public void keyPressed(KeyEvent evt) {
-    processLocalKeyEvent(evt);
-  }
-  public void keyReleased(KeyEvent evt) {
-    processLocalKeyEvent(evt);
-  }
-  public void keyTyped(KeyEvent evt) {
-    evt.consume();
-  }
-
-  public void mousePressed(MouseEvent evt) {
-    processLocalMouseEvent(evt, false);
-  }
-  public void mouseReleased(MouseEvent evt) {
-    processLocalMouseEvent(evt, false);
-  }
-  public void mouseMoved(MouseEvent evt) {
-    processLocalMouseEvent(evt, true);
-  }
-  public void mouseDragged(MouseEvent evt) {
-    processLocalMouseEvent(evt, true);
-  }
-
-  private synchronized void trySendPointerEvent() {
-    if ((needToSendMouseEvent) && (mouseEvent!=null)) {
-      sendMouseEvent(mouseEvent, false);
-      needToSendMouseEvent = false;
-      lastMouseEventSendTime = System.currentTimeMillis();
-    }
-  }
-
-  public void run() {
-    while (true) {
-      // Send mouse movement if we have it
-      trySendPointerEvent();
-      // Sleep for some time
-      try {
-        Thread.sleep(1000 / mouseMaxFreq);
-      } catch (InterruptedException ex) {
-      }
-    }
-  }
-
-  //
-  // Ignored events.
-  //
-
-  public void mouseClicked(MouseEvent evt) {}
-  public void mouseEntered(MouseEvent evt) {}
-  public void mouseExited(MouseEvent evt) {}
-
-  //
-  // Actual event processing.
-  //
-
-  private void processLocalKeyEvent(KeyEvent evt) {
-    if (viewer.rfb != null && rfb.inNormalProtocol) {
-      if (!inputEnabled) {
-       if ((evt.getKeyChar() == 'r' || evt.getKeyChar() == 'R') &&
-           evt.getID() == KeyEvent.KEY_PRESSED ) {
-         // Request screen update.
-         try {
-           rfb.writeFramebufferUpdateRequest(0, 0, rfb.framebufferWidth,
-                                             rfb.framebufferHeight, false);
-         } catch (IOException e) {
-           e.printStackTrace();
-         }
-       }
-      } else {
-       // Input enabled.
-       synchronized(rfb) {
-         try {
-           rfb.writeKeyEvent(evt);
-         } catch (Exception e) {
-           e.printStackTrace();
-         }
-         rfb.notify();
-       }
-      }
-    }
-    // Don't ever pass keyboard events to AWT for default processing.
-    // Otherwise, pressing Tab would switch focus to ButtonPanel etc.
-    evt.consume();
-  }
-
-  private void processLocalMouseEvent(MouseEvent evt, boolean moved) {
-    if (viewer.rfb != null && rfb.inNormalProtocol) {
-      if (!inSelectionMode) {
-        if (inputEnabled) {
-          // If mouse not moved, but it's click event then
-          // send it to server immideanlty.
-          // Else, it's mouse movement - we can send it in
-          // our thread later.
-          if (!moved) {
-            sendMouseEvent(evt, moved);
-          } else {
-            mouseEvent = evt;
-            needToSendMouseEvent = true;
-          }
-        }
-      } else {
-        handleSelectionMouseEvent(evt);
-      }
-    }
-  }
-
-  private void sendMouseEvent(MouseEvent evt, boolean moved) {
-    if (moved) {
-      softCursorMove(evt.getX(), evt.getY());
-    }
-    if (rfb.framebufferWidth != scaledWidth) {
-      int sx = (evt.getX() * 100 + scalingFactor/2) / scalingFactor;
-      int sy = (evt.getY() * 100 + scalingFactor/2) / scalingFactor;
-      evt.translatePoint(sx - evt.getX(), sy - evt.getY());
-    }
-    synchronized(rfb) {
-      try {
-        rfb.writePointerEvent(evt);
-      } catch (Exception e) {
-        e.printStackTrace();
-      }
-      rfb.notify();
-      lastMouseEventSendTime = System.currentTimeMillis();
-    }
-  }
-
-  //
-  // Reset update statistics.
-  //
-
-  void resetStats() {
-    statStartTime = System.currentTimeMillis();
-    statNumUpdates = 0;
-    statNumTotalRects = 0;
-    statNumPixelRects = 0;
-    statNumRectsTight = 0;
-    statNumRectsTightJPEG = 0;
-    statNumRectsZRLE = 0;
-    statNumRectsHextile = 0;
-    statNumRectsRaw = 0;
-    statNumRectsCopy = 0;
-    statNumBytesEncoded = 0;
-    statNumBytesDecoded = 0;
-    if (tightDecoder != null) {
-      tightDecoder.setNumJPEGRects(0);
-      tightDecoder.setNumTightRects(0);
-    }
-  }
-
-  //////////////////////////////////////////////////////////////////
-  //
-  // Handle cursor shape updates (XCursor and RichCursor encodings).
-  //
-
-  boolean showSoftCursor = false;
-
-  MemoryImageSource softCursorSource;
-  Image softCursor;
-  MouseEvent mouseEvent = null;
-  boolean needToSendMouseEvent = false;
-  int cursorX = 0, cursorY = 0;
-  int cursorWidth, cursorHeight;
-  int origCursorWidth, origCursorHeight;
-  int hotX, hotY;
-  int origHotX, origHotY;
-
-  //
-  // Handle cursor shape update (XCursor and RichCursor encodings).
-  //
-
-  synchronized void
-    handleCursorShapeUpdate(int encodingType,
-                           int xhot, int yhot, int width, int height)
-    throws IOException {
-
-    softCursorFree();
-
-    if (width * height == 0)
-      return;
-
-    // Ignore cursor shape data if requested by user.
-    if (viewer.options.ignoreCursorUpdates) {
-      int bytesPerRow = (width + 7) / 8;
-      int bytesMaskData = bytesPerRow * height;
-
-      if (encodingType == rfb.EncodingXCursor) {
-       rfb.skipBytes(6 + bytesMaskData * 2);
-      } else {
-       // rfb.EncodingRichCursor
-       rfb.skipBytes(width * height + bytesMaskData);
-      }
-      return;
-    }
-
-    // Decode cursor pixel data.
-    softCursorSource = decodeCursorShape(encodingType, width, height);
-
-    // Set original (non-scaled) cursor dimensions.
-    origCursorWidth = width;
-    origCursorHeight = height;
-    origHotX = xhot;
-    origHotY = yhot;
-
-    // Create off-screen cursor image.
-    createSoftCursor();
-
-    // Show the cursor.
-    showSoftCursor = true;
-    repaint(viewer.deferCursorUpdates,
-           cursorX - hotX, cursorY - hotY, cursorWidth, cursorHeight);
-  }
-
-  //
-  // decodeCursorShape(). Decode cursor pixel data and return
-  // corresponding MemoryImageSource instance.
-  //
-
-  synchronized MemoryImageSource
-    decodeCursorShape(int encodingType, int width, int height)
-    throws IOException {
-
-    int bytesPerRow = (width + 7) / 8;
-    int bytesMaskData = bytesPerRow * height;
-
-    int[] softCursorPixels = new int[width * height];
-
-    if (encodingType == rfb.EncodingXCursor) {
-
-      // Read foreground and background colors of the cursor.
-      byte[] rgb = new byte[6];
-      rfb.readFully(rgb);
-      int[] colors = { (0xFF000000 | (rgb[3] & 0xFF) << 16 |
-                       (rgb[4] & 0xFF) << 8 | (rgb[5] & 0xFF)),
-                      (0xFF000000 | (rgb[0] & 0xFF) << 16 |
-                       (rgb[1] & 0xFF) << 8 | (rgb[2] & 0xFF)) };
-
-      // Read pixel and mask data.
-      byte[] pixBuf = new byte[bytesMaskData];
-      rfb.readFully(pixBuf);
-      byte[] maskBuf = new byte[bytesMaskData];
-      rfb.readFully(maskBuf);
-
-      // Decode pixel data into softCursorPixels[].
-      byte pixByte, maskByte;
-      int x, y, n, result;
-      int i = 0;
-      for (y = 0; y < height; y++) {
-       for (x = 0; x < width / 8; x++) {
-         pixByte = pixBuf[y * bytesPerRow + x];
-         maskByte = maskBuf[y * bytesPerRow + x];
-         for (n = 7; n >= 0; n--) {
-           if ((maskByte >> n & 1) != 0) {
-             result = colors[pixByte >> n & 1];
-           } else {
-             result = 0;       // Transparent pixel
-           }
-           softCursorPixels[i++] = result;
-         }
-       }
-       for (n = 7; n >= 8 - width % 8; n--) {
-         if ((maskBuf[y * bytesPerRow + x] >> n & 1) != 0) {
-           result = colors[pixBuf[y * bytesPerRow + x] >> n & 1];
-         } else {
-           result = 0;         // Transparent pixel
-         }
-         softCursorPixels[i++] = result;
-       }
-      }
-
-    } else {
-      // encodingType == rfb.EncodingRichCursor
-
-      // Read pixel and mask data.
-      byte[] pixBuf = new byte[width * height * bytesPixel];
-      rfb.readFully(pixBuf);
-      byte[] maskBuf = new byte[bytesMaskData];
-      rfb.readFully(maskBuf);
-
-      // Decode pixel data into softCursorPixels[].
-      byte pixByte, maskByte;
-      int x, y, n, result;
-      int i = 0;
-      for (y = 0; y < height; y++) {
-       for (x = 0; x < width / 8; x++) {
-         maskByte = maskBuf[y * bytesPerRow + x];
-         for (n = 7; n >= 0; n--) {
-           if ((maskByte >> n & 1) != 0) {
-             if (bytesPixel == 1) {
-               result = cm8.getRGB(pixBuf[i]);
-             } else {
-               result = 0xFF000000 |
-                 (pixBuf[i * 4 + 2] & 0xFF) << 16 |
-                 (pixBuf[i * 4 + 1] & 0xFF) << 8 |
-                 (pixBuf[i * 4] & 0xFF);
-             }
-           } else {
-             result = 0;       // Transparent pixel
-           }
-           softCursorPixels[i++] = result;
-         }
-       }
-       for (n = 7; n >= 8 - width % 8; n--) {
-         if ((maskBuf[y * bytesPerRow + x] >> n & 1) != 0) {
-           if (bytesPixel == 1) {
-             result = cm8.getRGB(pixBuf[i]);
-           } else {
-             result = 0xFF000000 |
-               (pixBuf[i * 4 + 2] & 0xFF) << 16 |
-               (pixBuf[i * 4 + 1] & 0xFF) << 8 |
-               (pixBuf[i * 4] & 0xFF);
-           }
-         } else {
-           result = 0;         // Transparent pixel
-         }
-         softCursorPixels[i++] = result;
-       }
-      }
-
-    }
-
-    return new MemoryImageSource(width, height, softCursorPixels, 0, width);
-  }
-
-  //
-  // createSoftCursor(). Assign softCursor new Image (scaled if necessary).
-  // Uses softCursorSource as a source for new cursor image.
-  //
-
-  synchronized void
-    createSoftCursor() {
-
-    if (softCursorSource == null)
-      return;
-
-    int scaleCursor = viewer.options.scaleCursor;
-    if (scaleCursor == 0 || !inputEnabled)
-      scaleCursor = 100;
-
-    // Save original cursor coordinates.
-    int x = cursorX - hotX;
-    int y = cursorY - hotY;
-    int w = cursorWidth;
-    int h = cursorHeight;
-
-    cursorWidth = (origCursorWidth * scaleCursor + 50) / 100;
-    cursorHeight = (origCursorHeight * scaleCursor + 50) / 100;
-    hotX = (origHotX * scaleCursor + 50) / 100;
-    hotY = (origHotY * scaleCursor + 50) / 100;
-    softCursor = Toolkit.getDefaultToolkit().createImage(softCursorSource);
-
-    if (scaleCursor != 100) {
-      softCursor = softCursor.getScaledInstance(cursorWidth, cursorHeight,
-                                               Image.SCALE_SMOOTH);
-    }
-
-    if (showSoftCursor) {
-      // Compute screen area to update.
-      x = Math.min(x, cursorX - hotX);
-      y = Math.min(y, cursorY - hotY);
-      w = Math.max(w, cursorWidth);
-      h = Math.max(h, cursorHeight);
-
-      repaint(viewer.deferCursorUpdates, x, y, w, h);
-    }
-  }
-
-  //
-  // softCursorMove(). Moves soft cursor into a particular location.
-  //
-
-  synchronized void softCursorMove(int x, int y) {
-    int oldX = cursorX;
-    int oldY = cursorY;
-    cursorX = x;
-    cursorY = y;
-    if (showSoftCursor) {
-      repaint(viewer.deferCursorUpdates,
-             oldX - hotX, oldY - hotY, cursorWidth, cursorHeight);
-      repaint(viewer.deferCursorUpdates,
-             cursorX - hotX, cursorY - hotY, cursorWidth, cursorHeight);
-    }
-  }
-
-  //
-  // softCursorFree(). Remove soft cursor, dispose resources.
-  //
-
-  synchronized void softCursorFree() {
-    if (showSoftCursor) {
-      showSoftCursor = false;
-      softCursor = null;
-      softCursorSource = null;
-
-      repaint(viewer.deferCursorUpdates,
-             cursorX - hotX, cursorY - hotY, cursorWidth, cursorHeight);
-    }
-  }
-
-  //////////////////////////////////////////////////////////////////
-  //
-  // Support for selecting a rectangular video area.
-  //
-
-  /** This flag is false in normal operation, and true in the selection mode. */
-  private boolean inSelectionMode;
-
-  /** The point where the selection was started. */
-  private Point selectionStart;
-
-  /** The second point of the selection. */
-  private Point selectionEnd;
-
-  /**
-   * We change cursor when enabling the selection mode. In this variable, we
-   * save the original cursor so we can restore it on returning to the normal
-   * mode.
-   */
-  private Cursor savedCursor;
-
-  /**
-   * Initialize selection-related varibles.
-   */
-  private synchronized void resetSelection() {
-    inSelectionMode = false;
-    selectionStart = new Point(0, 0);
-    selectionEnd = new Point(0, 0);
-
-    savedCursor = getCursor();
-  }
-
-  /**
-   * Check current state of the selection mode.
-   * @return true in the selection mode, false otherwise.
-   */
-  public boolean isInSelectionMode() {
-    return inSelectionMode;
-  }
-
-  /**
-   * Get current selection.
-   * @param useScreenCoords use screen coordinates if true, or framebuffer
-   * coordinates if false. This makes difference when scaling factor is not 100.
-   * @return The selection as a {@link Rectangle}.
-   */
-  private synchronized Rectangle getSelection(boolean useScreenCoords) {
-    int x0 = selectionStart.x;
-    int x1 = selectionEnd.x;
-    int y0 = selectionStart.y;
-    int y1 = selectionEnd.y;
-    // Make x and y point to the upper left corner of the selection.
-    if (x1 < x0) {
-      int t = x0; x0 = x1; x1 = t;
-    }
-    if (y1 < y0) {
-      int t = y0; y0 = y1; y1 = t;
-    }
-    // Include the borders in the selection (unless it's empty).
-    if (x0 != x1 && y0 != y1) {
-      x1 += 1;
-      y1 += 1;
-    }
-    // Translate from screen coordinates to framebuffer coordinates.
-    if (rfb.framebufferWidth != scaledWidth) {
-      x0 = (x0 * 100 + scalingFactor/2) / scalingFactor;
-      y0 = (y0 * 100 + scalingFactor/2) / scalingFactor;
-      x1 = (x1 * 100 + scalingFactor/2) / scalingFactor;
-      y1 = (y1 * 100 + scalingFactor/2) / scalingFactor;
-    }
-    // Clip the selection to framebuffer.
-    if (x0 < 0)
-      x0 = 0;
-    if (y0 < 0)
-      y0 = 0;
-    if (x1 > rfb.framebufferWidth)
-      x1 = rfb.framebufferWidth;
-    if (y1 > rfb.framebufferHeight)
-      y1 = rfb.framebufferHeight;
-    // Make width a multiple of 16.
-    int widthBlocks = (x1 - x0 + 8) / 16;
-    if (selectionStart.x <= selectionEnd.x) {
-      x1 = x0 + widthBlocks * 16;
-      if (x1 > rfb.framebufferWidth) {
-        x1 -= 16;
-      }
-    } else {
-      x0 = x1 - widthBlocks * 16;
-      if (x0 < 0) {
-        x0 += 16;
-      }
-    }
-    // Make height a multiple of 8.
-    int heightBlocks = (y1 - y0 + 4) / 8;
-    if (selectionStart.y <= selectionEnd.y) {
-      y1 = y0 + heightBlocks * 8;
-      if (y1 > rfb.framebufferHeight) {
-        y1 -= 8;
-      }
-    } else {
-      y0 = y1 - heightBlocks * 8;
-      if (y0 < 0) {
-        y0 += 8;
-      }
-    }
-    // Translate the selection back to screen coordinates if requested.
-    if (useScreenCoords && rfb.framebufferWidth != scaledWidth) {
-      x0 = (x0 * scalingFactor + 50) / 100;
-      y0 = (y0 * scalingFactor + 50) / 100;
-      x1 = (x1 * scalingFactor + 50) / 100;
-      y1 = (y1 * scalingFactor + 50) / 100;
-    }
-    // Construct and return the result.
-    return new Rectangle(x0, y0, x1 - x0, y1 - y0);
-  }
-
-  /**
-   * Enable or disable the selection mode.
-   * @param enable enables the selection mode if true, disables if fasle.
-   */
-  public synchronized void enableSelection(boolean enable) {
-    if (enable && !inSelectionMode) {
-      // Enter the selection mode.
-      inSelectionMode = true;
-      savedCursor = getCursor();
-      setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
-      repaint();
-    } else if (!enable && inSelectionMode) {
-      // Leave the selection mode.
-      inSelectionMode = false;
-      setCursor(savedCursor);
-      repaint();
-    }
-  }
-
-  /**
-   * Process mouse events in the selection mode.
-   *
-   * @param evt mouse event that was originally passed to
-   *   {@link MouseListener} or {@link MouseMotionListener}.
-   */
-  private synchronized void handleSelectionMouseEvent(MouseEvent evt) {
-    int id = evt.getID();
-    boolean button1 = (evt.getModifiers() & InputEvent.BUTTON1_MASK) != 0;
-
-    if (id == MouseEvent.MOUSE_PRESSED && button1) {
-      selectionStart = selectionEnd = evt.getPoint();
-      repaint();
-    }
-    if (id == MouseEvent.MOUSE_DRAGGED && button1) {
-      selectionEnd = evt.getPoint();
-      repaint();
-    }
-    if (id == MouseEvent.MOUSE_RELEASED && button1) {
-      try {
-        rfb.trySendVideoSelection(getSelection(false));
-      } catch (IOException e) {
-        e.printStackTrace();
-      }
-    }
-  }
-}
diff --git a/java/src/com/tightvnc/vncviewer/VncCanvas2.java b/java/src/com/tightvnc/vncviewer/VncCanvas2.java
deleted file mode 100644 (file)
index 502d26f..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-//
-//  Copyright (C) 2006 Constantin Kaplinsky.  All Rights Reserved.
-//
-//  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.
-//
-
-package com.tightvnc.vncviewer;
-
-import java.awt.*;
-import java.io.*;
-
-//
-// VncCanvas2 is a special version of VncCanvas which may use Java 2 API.
-//
-
-class VncCanvas2 extends VncCanvas {
-
-  public VncCanvas2(VncViewer v) throws IOException {
-    super(v);
-    disableFocusTraversalKeys();
-  }
-
-  public VncCanvas2(VncViewer v, int maxWidth_, int maxHeight_)
-    throws IOException {
-
-    super(v, maxWidth_, maxHeight_);
-    disableFocusTraversalKeys();
-  }
-
-  public void paintScaledFrameBuffer(Graphics g) {
-    Graphics2D g2d = (Graphics2D)g;
-    g2d.setRenderingHint(RenderingHints.KEY_RENDERING,
-                         RenderingHints.VALUE_RENDER_QUALITY);
-    g2d.drawImage(memImage, 0, 0, scaledWidth, scaledHeight, null);
-  }
-
-  //
-  // Try to disable focus traversal keys (JVMs 1.4 and higher).
-  //
-
-  private void disableFocusTraversalKeys() {
-    try {
-      Class[] argClasses = { Boolean.TYPE };
-      java.lang.reflect.Method method =
-        getClass().getMethod("setFocusTraversalKeysEnabled", argClasses);
-      Object[] argObjects = { new Boolean(false) };
-      method.invoke(this, argObjects);
-    } catch (Exception e) {}
-  }
-
-}
-
diff --git a/java/src/com/tightvnc/vncviewer/VncViewer.java b/java/src/com/tightvnc/vncviewer/VncViewer.java
deleted file mode 100644 (file)
index bdaee68..0000000
+++ /dev/null
@@ -1,1049 +0,0 @@
-//
-//  Copyright (C) 2001-2004 HorizonLive.com, Inc.  All Rights Reserved.
-//  Copyright (C) 2002 Constantin Kaplinsky.  All Rights Reserved.
-//  Copyright (C) 1999 AT&T Laboratories Cambridge.  All Rights Reserved.
-//
-//  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.
-//
-
-//
-// VncViewer.java - the VNC viewer applet.  This class mainly just sets up the
-// user interface, leaving it to the VncCanvas to do the actual rendering of
-// a VNC desktop.
-//
-
-package com.tightvnc.vncviewer;
-
-import java.awt.*;
-import java.awt.event.*;
-import java.io.*;
-import java.net.*;
-
-public class VncViewer extends java.applet.Applet
-  implements java.lang.Runnable, WindowListener, ComponentListener {
-
-  boolean inAnApplet = true;
-  boolean inSeparateFrame = false;
-
-  //
-  // main() is called when run as a java program from the command line.
-  // It simply runs the applet inside a newly-created frame.
-  //
-
-  public static void main(String[] argv) {
-    VncViewer v = new VncViewer();
-    v.mainArgs = argv;
-    v.inAnApplet = false;
-    v.inSeparateFrame = true;
-
-    v.init();
-    v.start();
-  }
-
-  String[] mainArgs;
-
-  RfbProto rfb;
-  Thread rfbThread;
-
-  Frame vncFrame;
-  Container vncContainer;
-  ScrollPane desktopScrollPane;
-  GridBagLayout gridbag;
-  ButtonPanel buttonPanel;
-  Label connStatusLabel;
-  VncCanvas vc;
-  OptionsFrame options;
-  ClipboardFrame clipboard;
-  RecordingFrame rec;
-
-  // Control session recording.
-  Object recordingSync;
-  String sessionFileName;
-  boolean recordingActive;
-  boolean recordingStatusChanged;
-  String cursorUpdatesDef;
-  String eightBitColorsDef;
-
-  // Variables read from parameter values.
-  String socketFactory;
-  String host;
-  int port;
-  String passwordParam;
-  boolean showControls;
-  boolean offerRelogin;
-  boolean showOfflineDesktop;
-  int deferScreenUpdates;
-  int deferCursorUpdates;
-  int deferUpdateRequests;
-  int debugStatsExcludeUpdates;
-  int debugStatsMeasureUpdates;
-
-  // Reference to this applet for inter-applet communication.
-  public static java.applet.Applet refApplet;
-
-  //
-  // init()
-  //
-
-  public void init() {
-
-    readParameters();
-
-    refApplet = this;
-
-    if (inSeparateFrame) {
-      vncFrame = new Frame("TigerVNC");
-      if (!inAnApplet) {
-       vncFrame.add("Center", this);
-      }
-      vncContainer = vncFrame;
-    } else {
-      vncContainer = this;
-    }
-
-    recordingSync = new Object();
-
-    options = new OptionsFrame(this);
-    clipboard = new ClipboardFrame(this);
-    if (RecordingFrame.checkSecurity())
-      rec = new RecordingFrame(this);
-
-    sessionFileName = null;
-    recordingActive = false;
-    recordingStatusChanged = false;
-    cursorUpdatesDef = null;
-    eightBitColorsDef = null;
-
-    if (inSeparateFrame) {
-      vncFrame.addWindowListener(this);
-      vncFrame.addComponentListener(this);
-    }
-
-    rfbThread = new Thread(this);
-    rfbThread.start();
-  }
-
-  public void update(Graphics g) {
-  }
-
-  //
-  // run() - executed by the rfbThread to deal with the RFB socket.
-  //
-
-  public void run() {
-
-    gridbag = new GridBagLayout();
-    vncContainer.setLayout(gridbag);
-
-    GridBagConstraints gbc = new GridBagConstraints();
-    gbc.gridwidth = GridBagConstraints.REMAINDER;
-    gbc.anchor = GridBagConstraints.NORTHWEST;
-
-    if (showControls) {
-      buttonPanel = new ButtonPanel(this);
-      gridbag.setConstraints(buttonPanel, gbc);
-      vncContainer.add(buttonPanel);
-    }
-
-    try {
-      connectAndAuthenticate();
-      doProtocolInitialisation();
-
-      if (showControls &&
-          rfb.clientMsgCaps.isEnabled(RfbProto.VideoRectangleSelection)) {
-        buttonPanel.addSelectButton();
-      }
-
-      if (showControls &&
-          rfb.clientMsgCaps.isEnabled(RfbProto.VideoFreeze)) {
-        buttonPanel.addVideoFreezeButton();
-      }
-
-      // FIXME: Use auto-scaling not only in a separate frame.
-      if (options.autoScale && inSeparateFrame) {
-       Dimension screenSize;
-       try {
-         screenSize = vncContainer.getToolkit().getScreenSize();
-       } catch (Exception e) {
-         screenSize = new Dimension(0, 0);
-       }
-       createCanvas(screenSize.width - 32, screenSize.height - 32);
-      } else {
-       createCanvas(0, 0);
-      }
-
-      gbc.weightx = 1.0;
-      gbc.weighty = 1.0;
-
-      if (inSeparateFrame) {
-
-       // Create a panel which itself is resizeable and can hold
-       // non-resizeable VncCanvas component at the top left corner.
-       Panel canvasPanel = new Panel();
-       canvasPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
-       canvasPanel.add(vc);
-
-       // Create a ScrollPane which will hold a panel with VncCanvas
-       // inside.
-       desktopScrollPane = new ScrollPane(ScrollPane.SCROLLBARS_AS_NEEDED);
-       gbc.fill = GridBagConstraints.BOTH;
-       gridbag.setConstraints(desktopScrollPane, gbc);
-       desktopScrollPane.add(canvasPanel);
-        // If auto scale is not enabled we don't need to set first frame
-        // size to fullscreen
-        if (!options.autoScale) {
-          vc.isFirstSizeAutoUpdate = false;
-        }
-
-       // Finally, add our ScrollPane to the Frame window.
-       vncFrame.add(desktopScrollPane);
-       vncFrame.setTitle(rfb.desktopName);
-       vncFrame.pack();
-       vc.resizeDesktopFrame();
-
-      } else {
-       // Just add the VncCanvas component to the Applet.
-       gridbag.setConstraints(vc, gbc);
-       add(vc);
-       validate();
-      }
-
-      if (showControls) {
-        buttonPanel.enableButtons();
-      }
-
-      moveFocusToDesktop();
-      processNormalProtocol();
-
-    } catch (NoRouteToHostException e) {
-      fatalError("Network error: no route to server: " + host, e);
-    } catch (UnknownHostException e) {
-      fatalError("Network error: server name unknown: " + host, e);
-    } catch (ConnectException e) {
-      fatalError("Network error: could not connect to server: " +
-                host + ":" + port, e);
-    } catch (EOFException e) {
-      if (showOfflineDesktop) {
-       e.printStackTrace();
-       System.out.println("Network error: remote side closed connection");
-       if (vc != null) {
-         vc.enableInput(false);
-       }
-       if (inSeparateFrame) {
-         vncFrame.setTitle(rfb.desktopName + " [disconnected]");
-       }
-       if (rfb != null && !rfb.closed())
-         rfb.close();
-       if (showControls && buttonPanel != null) {
-         buttonPanel.disableButtonsOnDisconnect();
-         if (inSeparateFrame) {
-           vncFrame.pack();
-         } else {
-           validate();
-         }
-       }
-      } else {
-       fatalError("Network error: remote side closed connection", e);
-      }
-    } catch (IOException e) {
-      String str = e.getMessage();
-      if (str != null && str.length() != 0) {
-       fatalError("Network Error: " + str, e);
-      } else {
-       fatalError(e.toString(), e);
-      }
-    } catch (Exception e) {
-      String str = e.getMessage();
-      if (str != null && str.length() != 0) {
-       fatalError("Error: " + str, e);
-      } else {
-       fatalError(e.toString(), e);
-      }
-    }
-    
-  }
-
-  //
-  // Create a VncCanvas instance.
-  //
-
-  void createCanvas(int maxWidth, int maxHeight) throws IOException {
-    // Determine if Java 2D API is available and use a special
-    // version of VncCanvas if it is present.
-    vc = null;
-    try {
-      // This throws ClassNotFoundException if there is no Java 2D API.
-      Class cl = Class.forName("java.awt.Graphics2D");
-      // If we could load Graphics2D class, then we can use VncCanvas2D.
-      cl = Class.forName("com.tightvnc.vncviewer.VncCanvas2");
-      Class[] argClasses = { this.getClass(), Integer.TYPE, Integer.TYPE };
-      java.lang.reflect.Constructor cstr = cl.getConstructor(argClasses);
-      Object[] argObjects =
-        { this, new Integer(maxWidth), new Integer(maxHeight) };
-      vc = (VncCanvas)cstr.newInstance(argObjects);
-    } catch (Exception e) {
-      System.out.println("Warning: Java 2D API is not available");
-    }
-
-    // If we failed to create VncCanvas2D, use old VncCanvas.
-    if (vc == null)
-      vc = new VncCanvas(this, maxWidth, maxHeight);
-  }
-
-
-  //
-  // Process RFB socket messages.
-  // If the rfbThread is being stopped, ignore any exceptions,
-  // otherwise rethrow the exception so it can be handled.
-  //
-  void processNormalProtocol() throws Exception {
-    try {
-      vc.processNormalProtocol();
-    } catch (Exception e) {
-      if (rfbThread == null) {
-       System.out.println("Ignoring RFB socket exceptions" +
-                          " because applet is stopping");
-      } else {
-       throw e;
-      }
-    }
-  }
-
-
-  //
-  // Connect to the RFB server and authenticate the user.
-  //
-
-  void connectAndAuthenticate() throws Exception
-  {
-    showConnectionStatus("Initializing...");
-    if (inSeparateFrame) {
-      vncFrame.pack();
-      vncFrame.show();
-    } else {
-      validate();
-    }
-
-    showConnectionStatus("Connecting to " + host + ", port " + port + "...");
-
-    rfb = new RfbProto(host, port, this);
-    showConnectionStatus("Connected to server");
-
-    rfb.readVersionMsg();
-    showConnectionStatus("RFB server supports protocol version " +
-                        rfb.serverMajor + "." + rfb.serverMinor);
-
-    rfb.writeVersionMsg();
-    showConnectionStatus("Using RFB protocol version " +
-                        rfb.clientMajor + "." + rfb.clientMinor);
-
-    int secType = rfb.negotiateSecurity();
-    int authType;
-    if (secType == RfbProto.SecTypeTight) {
-      showConnectionStatus("Enabling TightVNC protocol extensions");
-      rfb.setupTunneling();
-      authType = rfb.negotiateAuthenticationTight();
-    } else {
-      authType = secType;
-    }
-
-    switch (authType) {
-    case RfbProto.AuthNone:
-      showConnectionStatus("No authentication needed");
-      rfb.authenticateNone();
-      break;
-    case RfbProto.AuthVNC:
-      showConnectionStatus("Performing standard VNC authentication");
-      if (passwordParam != null) {
-        rfb.authenticateVNC(passwordParam);
-      } else {
-        String pw = askPassword();
-        rfb.authenticateVNC(pw);
-      }
-      break;
-    default:
-      throw new Exception("Unknown authentication scheme " + authType);
-    }
-  }
-
-
-  //
-  // Show a message describing the connection status.
-  // To hide the connection status label, use (msg == null).
-  //
-
-  void showConnectionStatus(String msg)
-  {
-    if (msg == null) {
-      if (vncContainer.isAncestorOf(connStatusLabel)) {
-       vncContainer.remove(connStatusLabel);
-      }
-      return;
-    }
-
-    System.out.println(msg);
-
-    if (connStatusLabel == null) {
-      connStatusLabel = new Label("Status: " + msg);
-      connStatusLabel.setFont(new Font("Helvetica", Font.PLAIN, 12));
-    } else {
-      connStatusLabel.setText("Status: " + msg);
-    }
-
-    if (!vncContainer.isAncestorOf(connStatusLabel)) {
-      GridBagConstraints gbc = new GridBagConstraints();
-      gbc.gridwidth = GridBagConstraints.REMAINDER;
-      gbc.fill = GridBagConstraints.HORIZONTAL;
-      gbc.anchor = GridBagConstraints.NORTHWEST;
-      gbc.weightx = 1.0;
-      gbc.weighty = 1.0;
-      gbc.insets = new Insets(20, 30, 20, 30);
-      gridbag.setConstraints(connStatusLabel, gbc);
-      vncContainer.add(connStatusLabel);
-    }
-
-    if (inSeparateFrame) {
-      vncFrame.pack();
-    } else {
-      validate();
-    }
-  }
-
-
-  //
-  // Show an authentication panel.
-  //
-
-  String askPassword() throws Exception
-  {
-    showConnectionStatus(null);
-
-    AuthPanel authPanel = new AuthPanel(this);
-
-    GridBagConstraints gbc = new GridBagConstraints();
-    gbc.gridwidth = GridBagConstraints.REMAINDER;
-    gbc.anchor = GridBagConstraints.NORTHWEST;
-    gbc.weightx = 1.0;
-    gbc.weighty = 1.0;
-    gbc.ipadx = 100;
-    gbc.ipady = 50;
-    gridbag.setConstraints(authPanel, gbc);
-    vncContainer.add(authPanel);
-
-    if (inSeparateFrame) {
-      vncFrame.pack();
-    } else {
-      validate();
-    }
-
-    authPanel.moveFocusToDefaultField();
-    String pw = authPanel.getPassword();
-    vncContainer.remove(authPanel);
-
-    return pw;
-  }
-
-
-  //
-  // Do the rest of the protocol initialisation.
-  //
-
-  void doProtocolInitialisation() throws IOException
-  {
-    rfb.writeClientInit();
-    rfb.readServerInit();
-
-    System.out.println("Desktop name is " + rfb.desktopName);
-    System.out.println("Desktop size is " + rfb.framebufferWidth + " x " +
-                      rfb.framebufferHeight);
-
-    setEncodings();
-
-    showConnectionStatus(null);
-  }
-
-
-  //
-  // Send current encoding list to the RFB server.
-  //
-
-  int[] encodingsSaved;
-  int nEncodingsSaved;
-
-  void setEncodings()        { setEncodings(false); }
-  void autoSelectEncodings() { setEncodings(true); }
-
-  void setEncodings(boolean autoSelectOnly) {
-    if (options == null || rfb == null || !rfb.inNormalProtocol)
-      return;
-
-    int preferredEncoding = options.preferredEncoding;
-    if (preferredEncoding == -1) {
-      long kbitsPerSecond = rfb.kbitsPerSecond();
-      if (nEncodingsSaved < 1) {
-        // Choose Tight or ZRLE encoding for the very first update.
-        System.out.println("Using Tight/ZRLE encodings");
-        preferredEncoding = RfbProto.EncodingTight;
-      } else if (kbitsPerSecond > 2000 &&
-                 encodingsSaved[0] != RfbProto.EncodingHextile) {
-        // Switch to Hextile if the connection speed is above 2Mbps.
-        System.out.println("Throughput " + kbitsPerSecond +
-                           " kbit/s - changing to Hextile encoding");
-        preferredEncoding = RfbProto.EncodingHextile;
-      } else if (kbitsPerSecond < 1000 &&
-                 encodingsSaved[0] != RfbProto.EncodingTight) {
-        // Switch to Tight/ZRLE if the connection speed is below 1Mbps.
-        System.out.println("Throughput " + kbitsPerSecond +
-                           " kbit/s - changing to Tight/ZRLE encodings");
-        preferredEncoding = RfbProto.EncodingTight;
-      } else {
-        // Don't change the encoder.
-        if (autoSelectOnly)
-          return;
-        preferredEncoding = encodingsSaved[0];
-      }
-    } else {
-      // Auto encoder selection is not enabled.
-      if (autoSelectOnly)
-        return;
-    }
-
-    int[] encodings = new int[20];
-    int nEncodings = 0;
-
-    encodings[nEncodings++] = preferredEncoding;
-    if (options.useCopyRect) {
-      encodings[nEncodings++] = RfbProto.EncodingCopyRect;
-    }
-
-    if (preferredEncoding != RfbProto.EncodingTight) {
-      encodings[nEncodings++] = RfbProto.EncodingTight;
-    }
-    if (preferredEncoding != RfbProto.EncodingZRLE) {
-      encodings[nEncodings++] = RfbProto.EncodingZRLE;
-    }
-    if (preferredEncoding != RfbProto.EncodingHextile) {
-      encodings[nEncodings++] = RfbProto.EncodingHextile;
-    }
-    if (preferredEncoding != RfbProto.EncodingZlib) {
-      encodings[nEncodings++] = RfbProto.EncodingZlib;
-    }
-    if (preferredEncoding != RfbProto.EncodingCoRRE) {
-      encodings[nEncodings++] = RfbProto.EncodingCoRRE;
-    }
-    if (preferredEncoding != RfbProto.EncodingRRE) {
-      encodings[nEncodings++] = RfbProto.EncodingRRE;
-    }
-
-    if (options.compressLevel >= 0 && options.compressLevel <= 9) {
-      encodings[nEncodings++] =
-        RfbProto.EncodingCompressLevel0 + options.compressLevel;
-    }
-    if (options.jpegQuality >= 0 && options.jpegQuality <= 9) {
-      encodings[nEncodings++] =
-        RfbProto.EncodingQualityLevel0 + options.jpegQuality;
-    }
-
-    if (options.requestCursorUpdates) {
-      encodings[nEncodings++] = RfbProto.EncodingXCursor;
-      encodings[nEncodings++] = RfbProto.EncodingRichCursor;
-      if (!options.ignoreCursorUpdates)
-       encodings[nEncodings++] = RfbProto.EncodingPointerPos;
-    }
-
-    encodings[nEncodings++] = RfbProto.EncodingLastRect;
-    encodings[nEncodings++] = RfbProto.EncodingNewFBSize;
-
-    boolean encodingsWereChanged = false;
-    if (nEncodings != nEncodingsSaved) {
-      encodingsWereChanged = true;
-    } else {
-      for (int i = 0; i < nEncodings; i++) {
-        if (encodings[i] != encodingsSaved[i]) {
-          encodingsWereChanged = true;
-          break;
-        }
-      }
-    }
-
-    if (encodingsWereChanged) {
-      try {
-        rfb.writeSetEncodings(encodings, nEncodings);
-        if (vc != null) {
-          vc.softCursorFree();
-        }
-      } catch (Exception e) {
-        e.printStackTrace();
-      }
-      encodingsSaved = encodings;
-      nEncodingsSaved = nEncodings;
-    }
-  }
-
-
-  //
-  // setCutText() - send the given cut text to the RFB server.
-  //
-
-  void setCutText(String text) {
-    try {
-      if (rfb != null && rfb.inNormalProtocol) {
-       rfb.writeClientCutText(text);
-      }
-    } catch (Exception e) {
-      e.printStackTrace();
-    }
-  }
-
-
-  //
-  // Order change in session recording status. To stop recording, pass
-  // null in place of the fname argument.
-  //
-
-  void setRecordingStatus(String fname) {
-    synchronized(recordingSync) {
-      sessionFileName = fname;
-      recordingStatusChanged = true;
-    }
-  }
-
-  //
-  // Start or stop session recording. Returns true if this method call
-  // causes recording of a new session.
-  //
-
-  boolean checkRecordingStatus() throws IOException {
-    synchronized(recordingSync) {
-      if (recordingStatusChanged) {
-       recordingStatusChanged = false;
-       if (sessionFileName != null) {
-         startRecording();
-         return true;
-       } else {
-         stopRecording();
-       }
-      }
-    }
-    return false;
-  }
-
-  //
-  // Start session recording.
-  //
-
-  protected void startRecording() throws IOException {
-    synchronized(recordingSync) {
-      if (!recordingActive) {
-       // Save settings to restore them after recording the session.
-       cursorUpdatesDef =
-         options.choices[options.cursorUpdatesIndex].getSelectedItem();
-       eightBitColorsDef =
-         options.choices[options.eightBitColorsIndex].getSelectedItem();
-       // Set options to values suitable for recording.
-       options.choices[options.cursorUpdatesIndex].select("Disable");
-       options.choices[options.cursorUpdatesIndex].setEnabled(false);
-       options.setEncodings();
-       options.choices[options.eightBitColorsIndex].select("No");
-       options.choices[options.eightBitColorsIndex].setEnabled(false);
-       options.setColorFormat();
-      } else {
-       rfb.closeSession();
-      }
-
-      System.out.println("Recording the session in " + sessionFileName);
-      rfb.startSession(sessionFileName);
-      recordingActive = true;
-    }
-  }
-
-  //
-  // Stop session recording.
-  //
-
-  protected void stopRecording() throws IOException {
-    synchronized(recordingSync) {
-      if (recordingActive) {
-       // Restore options.
-       options.choices[options.cursorUpdatesIndex].select(cursorUpdatesDef);
-       options.choices[options.cursorUpdatesIndex].setEnabled(true);
-       options.setEncodings();
-       options.choices[options.eightBitColorsIndex].select(eightBitColorsDef);
-       options.choices[options.eightBitColorsIndex].setEnabled(true);
-       options.setColorFormat();
-
-       rfb.closeSession();
-       System.out.println("Session recording stopped.");
-      }
-      sessionFileName = null;
-      recordingActive = false;
-    }
-  }
-
-
-  //
-  // readParameters() - read parameters from the html source or from the
-  // command line.  On the command line, the arguments are just a sequence of
-  // param_name/param_value pairs where the names and values correspond to
-  // those expected in the html applet tag source.
-  //
-
-  void readParameters() {
-    host = readParameter("HOST", !inAnApplet);
-    if (host == null) {
-      host = getCodeBase().getHost();
-      if (host.equals("")) {
-       fatalError("HOST parameter not specified");
-      }
-    }
-
-    port = readIntParameter("PORT", 5900);
-
-    // Read "ENCPASSWORD" or "PASSWORD" parameter if specified.
-    readPasswordParameters();
-
-    String str;
-    if (inAnApplet) {
-      str = readParameter("Open New Window", false);
-      if (str != null && str.equalsIgnoreCase("Yes"))
-       inSeparateFrame = true;
-    }
-
-    // "Show Controls" set to "No" disables button panel.
-    showControls = true;
-    str = readParameter("Show Controls", false);
-    if (str != null && str.equalsIgnoreCase("No"))
-      showControls = false;
-
-    // "Offer Relogin" set to "No" disables "Login again" and "Close
-    // window" buttons under error messages in applet mode.
-    offerRelogin = true;
-    str = readParameter("Offer Relogin", false);
-    if (str != null && str.equalsIgnoreCase("No"))
-      offerRelogin = false;
-
-    // Do we continue showing desktop on remote disconnect?
-    showOfflineDesktop = false;
-    str = readParameter("Show Offline Desktop", false);
-    if (str != null && str.equalsIgnoreCase("Yes"))
-      showOfflineDesktop = true;
-
-    // Fine tuning options.
-    deferScreenUpdates = readIntParameter("Defer screen updates", 20);
-    deferCursorUpdates = readIntParameter("Defer cursor updates", 10);
-    deferUpdateRequests = readIntParameter("Defer update requests", 0);
-
-    // Debugging options.
-    debugStatsExcludeUpdates = readIntParameter("DEBUG_XU", 0);
-    debugStatsMeasureUpdates = readIntParameter("DEBUG_CU", 0);
-
-    // SocketFactory.
-    socketFactory = readParameter("SocketFactory", false);
-  }
-
-  //
-  // Read password parameters. If an "ENCPASSWORD" parameter is set,
-  // then decrypt the password into the passwordParam string. Otherwise,
-  // try to read the "PASSWORD" parameter directly to passwordParam.
-  //
-
-  private void readPasswordParameters() {
-    String encPasswordParam = readParameter("ENCPASSWORD", false);
-    if (encPasswordParam == null) {
-      passwordParam = readParameter("PASSWORD", false);
-    } else {
-      // ENCPASSWORD is hexascii-encoded. Decode.
-      byte[] pw = {0, 0, 0, 0, 0, 0, 0, 0};
-      int len = encPasswordParam.length() / 2;
-      if (len > 8)
-        len = 8;
-      for (int i = 0; i < len; i++) {
-        String hex = encPasswordParam.substring(i*2, i*2+2);
-        Integer x = new Integer(Integer.parseInt(hex, 16));
-        pw[i] = x.byteValue();
-      }
-      // Decrypt the password.
-      byte[] key = {23, 82, 107, 6, 35, 78, 88, 7};
-      DesCipher des = new DesCipher(key);
-      des.decrypt(pw, 0, pw, 0);
-      passwordParam = new String(pw);
-    }
-  }
-
-  public String readParameter(String name, boolean required) {
-    if (inAnApplet) {
-      String s = getParameter(name);
-      if ((s == null) && required) {
-       fatalError(name + " parameter not specified");
-      }
-      return s;
-    }
-
-    for (int i = 0; i < mainArgs.length; i += 2) {
-      if (mainArgs[i].equalsIgnoreCase(name)) {
-       try {
-         return mainArgs[i+1];
-       } catch (Exception e) {
-         if (required) {
-           fatalError(name + " parameter not specified");
-         }
-         return null;
-       }
-      }
-    }
-    if (required) {
-      fatalError(name + " parameter not specified");
-    }
-    return null;
-  }
-
-  int readIntParameter(String name, int defaultValue) {
-    String str = readParameter(name, false);
-    int result = defaultValue;
-    if (str != null) {
-      try {
-       result = Integer.parseInt(str);
-      } catch (NumberFormatException e) { }
-    }
-    return result;
-  }
-
-  //
-  // moveFocusToDesktop() - move keyboard focus either to VncCanvas.
-  //
-
-  void moveFocusToDesktop() {
-    if (vncContainer != null) {
-      if (vc != null && vncContainer.isAncestorOf(vc))
-       vc.requestFocus();
-    }
-  }
-
-  //
-  // disconnect() - close connection to server.
-  //
-
-  synchronized public void disconnect() {
-    System.out.println("Disconnecting");
-
-    if (vc != null) {
-      double sec = (System.currentTimeMillis() - vc.statStartTime) / 1000.0;
-      double rate = Math.round(vc.statNumUpdates / sec * 100) / 100.0;
-      long nRealRects = vc.statNumPixelRects;
-      long nPseudoRects = vc.statNumTotalRects - vc.statNumPixelRects;
-      System.out.println("Updates received: " + vc.statNumUpdates + " (" +
-                         nRealRects + " rectangles + " + nPseudoRects +
-                         " pseudo), " + rate + " updates/sec");
-      long numRectsOther = nRealRects - vc.statNumRectsTight
-        - vc.statNumRectsZRLE - vc.statNumRectsHextile
-        - vc.statNumRectsRaw - vc.statNumRectsCopy;
-      System.out.println("Rectangles:" +
-                         " Tight=" + vc.statNumRectsTight +
-                         "(JPEG=" + vc.statNumRectsTightJPEG +
-                         ") ZRLE=" + vc.statNumRectsZRLE +
-                         " Hextile=" + vc.statNumRectsHextile +
-                         " Raw=" + vc.statNumRectsRaw +
-                         " CopyRect=" + vc.statNumRectsCopy +
-                         " other=" + numRectsOther);
-
-      long raw = vc.statNumBytesDecoded;
-      long compressed = vc.statNumBytesEncoded;
-      if (compressed > 0) {
-          double ratio = Math.round((double)raw / compressed * 1000) / 1000.0;
-          System.out.println("Pixel data: " + vc.statNumBytesDecoded +
-                             " bytes, " + vc.statNumBytesEncoded +
-                             " compressed, ratio " + ratio);
-      }
-    }
-
-    if (rfb != null && !rfb.closed())
-      rfb.close();
-    options.dispose();
-    clipboard.dispose();
-    if (rec != null)
-      rec.dispose();
-
-    if (inAnApplet) {
-      showMessage("Disconnected");
-    } else {
-      System.exit(0);
-    }
-  }
-
-  //
-  // fatalError() - print out a fatal error message.
-  // FIXME: Do we really need two versions of the fatalError() method?
-  //
-
-  synchronized public void fatalError(String str) {
-    System.out.println(str);
-
-    if (inAnApplet) {
-      // vncContainer null, applet not inited,
-      // can not present the error to the user.
-      Thread.currentThread().stop();
-    } else {
-      System.exit(1);
-    }
-  }
-
-  synchronized public void fatalError(String str, Exception e) {
-    if (rfb != null && rfb.closed()) {
-      // Not necessary to show error message if the error was caused
-      // by I/O problems after the rfb.close() method call.
-      System.out.println("RFB thread finished");
-      return;
-    }
-
-    System.out.println(str);
-    e.printStackTrace();
-
-    if (rfb != null)
-      rfb.close();
-
-    if (inAnApplet) {
-      showMessage(str);
-    } else {
-      System.exit(1);
-    }
-  }
-
-  //
-  // Show message text and optionally "Relogin" and "Close" buttons.
-  //
-
-  void showMessage(String msg) {
-    vncContainer.removeAll();
-
-    Label errLabel = new Label(msg, Label.CENTER);
-    errLabel.setFont(new Font("Helvetica", Font.PLAIN, 12));
-
-    if (offerRelogin) {
-
-      Panel gridPanel = new Panel(new GridLayout(0, 1));
-      Panel outerPanel = new Panel(new FlowLayout(FlowLayout.LEFT));
-      outerPanel.add(gridPanel);
-      vncContainer.setLayout(new FlowLayout(FlowLayout.LEFT, 30, 16));
-      vncContainer.add(outerPanel);
-      Panel textPanel = new Panel(new FlowLayout(FlowLayout.CENTER));
-      textPanel.add(errLabel);
-      gridPanel.add(textPanel);
-      gridPanel.add(new ReloginPanel(this));
-
-    } else {
-
-      vncContainer.setLayout(new FlowLayout(FlowLayout.LEFT, 30, 30));
-      vncContainer.add(errLabel);
-
-    }
-
-    if (inSeparateFrame) {
-      vncFrame.pack();
-    } else {
-      validate();
-    }
-  }
-
-  //
-  // Stop the applet.
-  // Main applet thread will terminate on first exception
-  // after seeing that rfbThread has been set to null.
-  //
-
-  public void stop() {
-    System.out.println("Stopping applet");
-    rfbThread = null;
-  }
-
-  //
-  // This method is called before the applet is destroyed.
-  //
-
-  public void destroy() {
-    System.out.println("Destroying applet");
-
-    vncContainer.removeAll();
-    options.dispose();
-    clipboard.dispose();
-    if (rec != null)
-      rec.dispose();
-    if (rfb != null && !rfb.closed())
-      rfb.close();
-    if (inSeparateFrame)
-      vncFrame.dispose();
-  }
-
-  //
-  // Start/stop receiving mouse events.
-  //
-
-  public void enableInput(boolean enable) {
-    vc.enableInput(enable);
-  }
-  
-  //
-  // Resize framebuffer if autoScale is enabled.
-  //
-  
-  public void componentResized(ComponentEvent e) {
-    if (e.getComponent() == vncFrame) {
-      if (options.autoScale) {
-        if (vc != null) {
-          if (!vc.isFirstSizeAutoUpdate) {
-            vc.updateFramebufferSize();
-          }
-        }
-      }
-    }
-  }
-  
-  //
-  // Ignore component events we're not interested in.
-  //
-  
-  public void componentShown(ComponentEvent e) { }
-  public void componentMoved(ComponentEvent e) { }
-  public void componentHidden(ComponentEvent e) { }
-
-  //
-  // Close application properly on window close event.
-  //
-
-  public void windowClosing(WindowEvent evt) {
-    System.out.println("Closing window");
-    if (rfb != null)
-      disconnect();
-
-    vncContainer.hide();
-
-    if (!inAnApplet) {
-      System.exit(0);
-    }
-  }
-
-  //
-  // Ignore window events we're not interested in.
-  //
-
-  public void windowActivated(WindowEvent evt) {}
-  public void windowDeactivated (WindowEvent evt) {}
-  public void windowOpened(WindowEvent evt) {}
-  public void windowClosed(WindowEvent evt) {}
-  public void windowIconified(WindowEvent evt) {}
-  public void windowDeiconified(WindowEvent evt) {}
-}
diff --git a/java/src/com/tightvnc/vncviewer/ZlibInStream.java b/java/src/com/tightvnc/vncviewer/ZlibInStream.java
deleted file mode 100644 (file)
index 636fb54..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
- * 
- * 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.
- */
-
-//
-// A ZlibInStream reads from a zlib.io.InputStream
-//
-
-package com.tightvnc.vncviewer;
-
-public class ZlibInStream extends InStream {
-
-  static final int defaultBufSize = 16384;
-
-  public ZlibInStream(int bufSize_) {
-    bufSize = bufSize_;
-    b = new byte[bufSize];
-    ptr = end = ptrOffset = 0;
-    inflater = new java.util.zip.Inflater();
-  }
-
-  public ZlibInStream() { this(defaultBufSize); }
-
-  public void setUnderlying(InStream is, int bytesIn_) {
-    underlying = is;
-    bytesIn = bytesIn_;
-    ptr = end = 0;
-  }
-
-  public void reset() throws Exception {
-    ptr = end = 0;
-    if (underlying == null) return;
-
-    while (bytesIn > 0) {
-      decompress();
-      end = 0; // throw away any data
-    }
-    underlying = null;
-  }
-
-  public int pos() { return ptrOffset + ptr; }
-
-  protected int overrun(int itemSize, int nItems) throws Exception {
-    if (itemSize > bufSize)
-      throw new Exception("ZlibInStream overrun: max itemSize exceeded");
-    if (underlying == null)
-      throw new Exception("ZlibInStream overrun: no underlying stream");
-
-    if (end - ptr != 0)
-      System.arraycopy(b, ptr, b, 0, end - ptr);
-
-    ptrOffset += ptr;
-    end -= ptr;
-    ptr = 0;
-
-    while (end < itemSize) {
-      decompress();
-    }
-
-    if (itemSize * nItems > end)
-      nItems = end / itemSize;
-
-    return nItems;
-  }
-
-  // decompress() calls the decompressor once.  Note that this won't
-  // necessarily generate any output data - it may just consume some input
-  // data.  Returns false if wait is false and we would block on the underlying
-  // stream.
-
-  private void decompress() throws Exception {
-    try {
-      underlying.check(1);
-      int avail_in = underlying.getend() - underlying.getptr();
-      if (avail_in > bytesIn)
-        avail_in = bytesIn;
-
-      if (inflater.needsInput()) {
-        inflater.setInput(underlying.getbuf(), underlying.getptr(), avail_in);
-      }
-
-      int n = inflater.inflate(b, end, bufSize - end); 
-
-      end += n;
-      if (inflater.needsInput()) {
-        bytesIn -= avail_in;
-        underlying.setptr(underlying.getptr() + avail_in);
-      }
-    } catch (java.util.zip.DataFormatException e) {
-      throw new Exception("ZlibInStream: inflate failed");
-    }
-  }
-
-  private InStream underlying;
-  private int bufSize;
-  private int ptrOffset;
-  private java.util.zip.Inflater inflater;
-  private int bytesIn;
-}
diff --git a/java/src/com/tightvnc/vncviewer/index.html b/java/src/com/tightvnc/vncviewer/index.html
deleted file mode 100644 (file)
index 96805dc..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-<!-- 
-     index.html - an example HTML page for TigerVNC Java viewer applet, to be
-     used with a standalone Web server running on the same machine where the
-     TigerVNC server is running. Before using this example, please MAKE SURE
-     to check the following:
-
-     * the value of the PORT parameter should be set correctly (normally, the
-       port number is 5900 + display number);
-
-     * the CODE and ARCHIVE attributes of the <APPLET> tag should point to
-       the correct directory (this example assumes that this page is in the
-       same directory with .jar and .class files);
-
-     * the WIDTH and HEIGHT attributes of the <APPLET> tag correspond to the
-       actual desktop size on the server (height should be increased to leave
-       enough space for the button panel).
--->
-
-<HTML>
-<TITLE>
-TigerVNC desktop
-</TITLE>
-<APPLET CODE="VncViewer.class" ARCHIVE="VncViewer.jar"
-        WIDTH="800" HEIGHT="632">
-<PARAM NAME="PORT" VALUE="5901">
-</APPLET>
-<BR>
-<A href="http://www.tigervnc.org/">TigerVNC site</A>
-</HTML>
diff --git a/java/src/com/tightvnc/vncviewer/index.vnc b/java/src/com/tightvnc/vncviewer/index.vnc
deleted file mode 100644 (file)
index f24df7c..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-<!-- 
-     index.vnc - default HTML page for TigerVNC Java viewer applet, to be
-     used with Xvnc. On any file ending in .vnc, the HTTP server embedded in
-     Xvnc will substitute the following variables when preceded by a dollar:
-     USER, DESKTOP, DISPLAY, APPLETWIDTH, APPLETHEIGHT, WIDTH, HEIGHT, PORT,
-     PARAMS. Use two dollar signs ($$) to get a dollar sign in the generated
-     HTML page.
-
-     NOTE: the $PARAMS variable is not supported by the standard VNC, so
-     make sure you have TigerVNC on the server side, if you're using this
-     variable.
--->
-
-<HTML>
-<TITLE>
-$USER's $DESKTOP desktop ($DISPLAY)
-</TITLE>
-<APPLET CODE=VncViewer.class ARCHIVE=VncViewer.jar
-        WIDTH=$APPLETWIDTH HEIGHT=$APPLETHEIGHT>
-<param name=PORT value=$PORT>
-$PARAMS
-</APPLET>
-<BR>
-<A href="http://www.tigervnc.org/">TigerVNC site</A>
-</HTML>