/* 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.
*/
//
// CMsgReader - class for reading RFB messages on the client side
// (i.e. messages from server to client).
//
package rfb;
@SuppressWarnings({"unchecked", "deprecation", "serial"}) abstract public class CMsgReader {
abstract public void readServerInit();
// readMsg() reads a message, calling the handler as appropriate.
abstract public void readMsg();
public rdr.InStream getInStream() { return is; }
public byte[] getImageBuf(int required, int requested) {
int requiredBytes = required * (handler.cp.pf().bpp / 8);
int requestedBytes = requested * (handler.cp.pf().bpp / 8);
int size = requestedBytes;
if (size > imageBufIdealSize) size = imageBufIdealSize;
if (size < requiredBytes)
size = requiredBytes;
if (imageBufSize < size) {
imageBufSize = size;
imageBuf = new byte[imageBufSize];
}
return imageBuf;
}
public final int bpp() { return handler.cp.pf().bpp; }
protected CMsgReader(CMsgHandler handler_, rdr.InStream is_) {
handler = handler_;
is = is_;
decoders = new Decoder[Encodings.max+1];
}
protected void readSetColourMapEntries() {
is.skip(1);
int firstColour = is.readU16();
int nColours = is.readU16();
int[] rgbs = new int[nColours * 3];
for (int i = 0; i < nColours * 3; i++)
rgbs[i] = is.readU16();
endMsg();
handler.setColourMapEntries(firstColour, nColours, rgbs);
}
protected void readBell() {
endMsg();
handler.bell();
}
protected void readServerCutText() {
is.skip(3);
int len = is.readU32();
if (len > 256*1024) {
is.skip(len);
vlog.error("cut text too long ("+len+" bytes) - ignoring");
return;
}
byte[] buf = new byte[len];
is.readBytes(buf, 0, len);
endMsg();
handler.serverCutText(new String(buf, 0, len));
}
protected void endMsg() {}
protected void readFramebufferUpdateStart() {
endMsg();
handler.framebufferUpdateStart();
}
protected void readFramebufferUpdateEnd() {
endMsg();
handler.framebufferUpdateEnd();
}
protected void readRect(int x, int y, int w, int h, int encoding) {
if ((x+w > handler.cp.width) || (y+h > handler.cp.height)) {
vlog.error("Rect too big: "+w+"x"+h+" at "+x+","+y+" exceeds "+
handler.cp.width+"x"+handler.cp.height);
throw new Exception("Rect too big");
}
if (w*h == 0) {
vlog.info("Ignoring zero size rect");
return;
}
handler.beginRect(x,y,w,h, encoding);
if (encoding == Encodings.copyRect) {
readCopyRect(x,y,w,h);
} else {
if (decoders[encoding] == null) {
decoders[encoding] = Decoder.createDecoder(encoding, this);
if (decoders[encoding] == null) {
vlog.error("Unknown rect encoding "+encoding);
throw new Exception("Unknown rect encoding");
}
}
decoders[encoding].readRect(x,y,w,h, handler);
}
handler.endRect(x,y,w,h, encoding);
}
protected void readCopyRect(int x, int y, int w, int h) {
int srcX = is.readU16();
int srcY = is.readU16();
handler.copyRect(x,y,w,h, srcX, srcY);
}
protected void readSetCursor(int hotspotX, int hotspotY, int w, int h) {
int data_len = w * h * (handler.cp.pf().bpp/8);
int mask_len = ((w+7)/8) * h;
byte[] data = new byte[data_len];
byte[] mask = new byte[mask_len];
is.readBytes(data, 0, data_len);
is.readBytes(mask, 0, mask_len);
handler.setCursor(hotspotX, hotspotY, w, h, data, mask);
}
CMsgHandler handler;
rdr.InStream is;
Decoder[] decoders;
byte[] imageBuf;
int imageBufSize;
int imageBufIdealSize;
static LogWriter vlog = new LogWriter("CMsgReader");
}