mirror of
https://github.com/sheumann/VNCviewGS.git
synced 2024-11-25 06:31:36 +00:00
d281a30f98
Specifically, use a union rather than pointer-based type punning to convert the Long value returned by GetContentOrigin() to a Point. This makes for more readable code and should also generate somewhat better assembly code.
302 lines
11 KiB
C++
302 lines
11 KiB
C++
#if __ORCAC__
|
|
#pragma lint -1
|
|
#pragma noroot
|
|
segment "VNCview GS";
|
|
#endif
|
|
|
|
#include <window.h>
|
|
#include <quickdraw.h>
|
|
#include <qdaux.h>
|
|
#include <desk.h>
|
|
#include <memory.h>
|
|
#include <resources.h>
|
|
#include <tcpip.h>
|
|
#include <menu.h>
|
|
#include <control.h>
|
|
#include <misctool.h>
|
|
#include <scrap.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <event.h>
|
|
#include <limits.h>
|
|
|
|
#include "vncsession.h"
|
|
#include "vncview.h"
|
|
#include "vncdisplay.h"
|
|
#include "colortables.h"
|
|
#include "menus.h"
|
|
#include "clipboard.h"
|
|
#include "desktopsize.h"
|
|
#include "mouse.h"
|
|
#include "keyboard.h"
|
|
#include "copyrect.h"
|
|
#include "raw.h"
|
|
#include "hextile.h"
|
|
|
|
static unsigned int hexXTiles, hexYTiles; /* For in-process hextile processing */
|
|
static unsigned int hexXTileNum, hexYTileNum;
|
|
static unsigned int hexTileWidth, hexTileHeight;
|
|
static unsigned char hexBackground, hexForeground;
|
|
|
|
static BOOLEAN extraByteAdvance;
|
|
|
|
/* Used in Hextile encoding */
|
|
#define Raw 0x01
|
|
#define BackgroundSpecified 0x02
|
|
#define ForegroundSpecified 0x04
|
|
#define AnySubrects 0x08
|
|
#define SubrectsColoured 0x10
|
|
|
|
#define hexWaitingForSubencoding 1
|
|
#define hexWaitingForMoreInfo 2
|
|
#define hexWaitingForSubrect 4
|
|
#define hexWaitingForRawData 8
|
|
|
|
static void HexNextTile (void) {
|
|
hexXTileNum++;
|
|
if (hexXTileNum == hexXTiles) {
|
|
hexYTileNum++;
|
|
if (hexYTileNum == hexYTiles) { /* Done with this Hextile rect */
|
|
NextRect();
|
|
return;
|
|
}
|
|
hexXTileNum = 0;
|
|
}
|
|
|
|
hexTileWidth = (hexXTileNum == hexXTiles - 1) ?
|
|
rectWidth - 16 * (hexXTiles - 1) : 16;
|
|
hexTileHeight = (hexYTileNum == hexYTiles - 1) ?
|
|
rectHeight - 16 * (hexYTiles - 1) : 16;
|
|
|
|
}
|
|
|
|
static void HexRawDraw (Origin contentOrigin, int rectWidth, int rectHeight) {
|
|
unsigned int i, j; /* Loop indices */
|
|
unsigned int n = 0;
|
|
unsigned char *dataPtr;
|
|
unsigned char pixels[128];
|
|
|
|
static Rect srcRect = {0,0,0,0};
|
|
|
|
dataPtr = (unsigned char *) *readBufferHndl;
|
|
|
|
if ((hRez==640 && (rectWidth & 0x03)) || (hRez==320 && (rectWidth & 0x01)))
|
|
extraByteAdvance = TRUE;
|
|
else
|
|
extraByteAdvance = FALSE;
|
|
|
|
for (j = 0; j < rectHeight; j++) {
|
|
for (i = 0; i < rectWidth; i++) {
|
|
if (hRez == 640) {
|
|
switch (i & 0x03) {
|
|
case 0x00: /* pixels 0, 4, 8, ... */
|
|
pixels[n] = pixTransTbl[ *(dataPtr +
|
|
(unsigned long) j*rectWidth + i)
|
|
] & 0xC0;
|
|
break;
|
|
case 0x01: /* pixels 1, 5, 9, ... */
|
|
pixels[n] += pixTransTbl[ *(dataPtr +
|
|
(unsigned long) j*rectWidth + i)
|
|
] & 0x30;
|
|
break;
|
|
case 0x02: /* pixels 2, 6, 10, ... */
|
|
pixels[n] += pixTransTbl[ *(dataPtr +
|
|
(unsigned long) j*rectWidth + i)
|
|
] & 0x0C;
|
|
break;
|
|
case 0x03: /* pixels 3, 7, 11, ... */
|
|
pixels[n] += pixTransTbl[ *(dataPtr +
|
|
(unsigned long) j*rectWidth + i)
|
|
] & 0x03;
|
|
n++;
|
|
} /* switch */
|
|
} /* if */
|
|
else { /* 320 mode */
|
|
switch(i & 0x01) {
|
|
case 0x00: /* pixels 0, 2, 4, ... */
|
|
pixels[n] = pixTransTbl[ *(dataPtr +
|
|
(unsigned long) j*rectWidth + i)
|
|
] & 0xF0;
|
|
break;
|
|
case 0x01: /* pixels 1, 3, 5, ... */
|
|
pixels[n] += pixTransTbl[ *(dataPtr +
|
|
(unsigned long) j*rectWidth + i)
|
|
] & 0x0F;
|
|
n++;
|
|
} /* switch */
|
|
} /* else */
|
|
} /* i loop */
|
|
|
|
/* When not ending a line on a byte boundary, the index isn't updated,
|
|
* so we do it here.
|
|
*/
|
|
if (extraByteAdvance)
|
|
n++;
|
|
} /* j loop */
|
|
|
|
srcLocInfo.ptrToPixImage = (void *) pixels;
|
|
srcLocInfo.boundsRect.v2 = rectHeight;
|
|
/* Since the lines are rounded up to integral numbers of bytes, this
|
|
* padding must be accounted for here.
|
|
*/
|
|
if (hRez == 640) {
|
|
switch (rectWidth & 0x03) {
|
|
case 0x00: srcLocInfo.boundsRect.h2 = rectWidth;
|
|
srcLocInfo.width = rectWidth/4; break;
|
|
case 0x01: srcLocInfo.boundsRect.h2 = rectWidth+3;
|
|
srcLocInfo.width = rectWidth/4 + 1; break;
|
|
case 0x02: srcLocInfo.boundsRect.h2 = rectWidth+2;
|
|
srcLocInfo.width = rectWidth/4 + 1; break;
|
|
case 0x03: srcLocInfo.boundsRect.h2 = rectWidth+1;
|
|
srcLocInfo.width = rectWidth/4 + 1;
|
|
}
|
|
}
|
|
else { /* hRez == 320 */
|
|
switch (rectWidth & 0x01) {
|
|
case 0x00: srcLocInfo.boundsRect.h2 = rectWidth;
|
|
srcLocInfo.width = rectWidth/2; break;
|
|
case 0x01: srcLocInfo.boundsRect.h2 = rectWidth+1;
|
|
srcLocInfo.width = rectWidth/2 + 1;
|
|
}
|
|
}
|
|
|
|
srcRect.v2 = hexTileHeight;
|
|
srcRect.h2 = hexTileWidth;
|
|
|
|
PPToPort(&srcLocInfo, &srcRect,
|
|
rectX + hexXTileNum * 16 - contentOrigin.pt.h,
|
|
rectY + hexYTileNum * 16 - contentOrigin.pt.v, modeCopy);
|
|
}
|
|
|
|
/* The macros below are used in HexDispatch() */
|
|
#define HexDispatch_NextTile() do { \
|
|
HexNextTile(); \
|
|
DoneWithReadBuffer(); \
|
|
/* Set up for next time */ \
|
|
status = hexWaitingForSubencoding; \
|
|
bytesNeeded = 1; \
|
|
return; \
|
|
} while (0)
|
|
|
|
#define HexDispatch_DrawRect(color, X, Y, width, height) do { \
|
|
SetSolidPenPat((color)); \
|
|
drawingRect.h1 = rectX + hexXTileNum * 16 + (X) - contentOrigin.pt.h; \
|
|
drawingRect.v1 = rectY + hexYTileNum * 16 + (Y) - contentOrigin.pt.v; \
|
|
drawingRect.h2 = rectX + hexXTileNum * 16 + (X) + (width) - contentOrigin.pt.h; \
|
|
drawingRect.v2 = rectY + hexYTileNum * 16 + (Y) + (height) - contentOrigin.pt.v; \
|
|
PaintRect(&drawingRect); \
|
|
} while (0)
|
|
|
|
#define HexDispatch_DrawBackground() \
|
|
HexDispatch_DrawRect(hexBackground, 0, 0, hexTileWidth, hexTileHeight)
|
|
|
|
void HexDispatch (void) {
|
|
static unsigned char status = hexWaitingForSubencoding;
|
|
static unsigned long bytesNeeded = 1;
|
|
static unsigned char subencoding;
|
|
static unsigned int numSubrects;
|
|
int i;
|
|
/* For use with GetContentOrigin() */
|
|
Origin contentOrigin;
|
|
int tileBytes;
|
|
unsigned int srX, srY, srWidth, srHeight;
|
|
Rect drawingRect;
|
|
static unsigned char pixels[128];
|
|
unsigned char *dataPtr;
|
|
|
|
contentOrigin.l = GetContentOrigin(vncWindow);
|
|
SetPort(vncWindow);
|
|
|
|
/* If we don't have the next bit of needed data yet, return. */
|
|
while (DoReadTCP(bytesNeeded)) {
|
|
dataPtr = *(unsigned char **) readBufferHndl;
|
|
/* If we're here, readBufferHndl contains bytesNeeded bytes of data. */
|
|
switch (status) {
|
|
case hexWaitingForSubencoding:
|
|
subencoding = *dataPtr;
|
|
if (subencoding & Raw) {
|
|
bytesNeeded = hexTileWidth * hexTileHeight;
|
|
status = hexWaitingForRawData;
|
|
}
|
|
else {
|
|
bytesNeeded = 0;
|
|
if (subencoding & BackgroundSpecified)
|
|
bytesNeeded++;
|
|
if (subencoding & ForegroundSpecified)
|
|
bytesNeeded++;
|
|
if (subencoding & AnySubrects)
|
|
bytesNeeded++;
|
|
else if (bytesNeeded == 0) {
|
|
/* No more data - just draw background */
|
|
HexDispatch_DrawBackground();
|
|
HexDispatch_NextTile();
|
|
}
|
|
status = hexWaitingForMoreInfo;
|
|
}
|
|
break;
|
|
|
|
case hexWaitingForRawData:
|
|
HexRawDraw(contentOrigin, hexTileWidth, hexTileHeight);
|
|
HexDispatch_NextTile();
|
|
break;
|
|
|
|
case hexWaitingForMoreInfo:
|
|
if (subencoding & BackgroundSpecified) {
|
|
hexBackground = pixTransTbl[*(dataPtr++)];
|
|
}
|
|
if (subencoding & ForegroundSpecified) {
|
|
hexForeground = pixTransTbl[*(dataPtr++)];
|
|
}
|
|
if (subencoding & AnySubrects) {
|
|
numSubrects = *dataPtr;
|
|
if (numSubrects) {
|
|
status = hexWaitingForSubrect;
|
|
bytesNeeded = numSubrects * ((subencoding & SubrectsColoured) ? 3 : 2);
|
|
break;
|
|
}
|
|
else
|
|
HexDispatch_NextTile();
|
|
}
|
|
else { /* no subrects */
|
|
HexDispatch_DrawBackground();
|
|
HexDispatch_NextTile();
|
|
}
|
|
|
|
case hexWaitingForSubrect: {
|
|
HexDispatch_DrawBackground();
|
|
while (numSubrects-- > 0) {
|
|
if (subencoding & SubrectsColoured) {
|
|
hexForeground = pixTransTbl[*(dataPtr++)];
|
|
}
|
|
srX = *dataPtr >> 4;
|
|
srY = *(dataPtr++) & 0x0F;
|
|
srWidth = (*dataPtr >> 4) + 1;
|
|
srHeight = (*(dataPtr++) & 0x0F) + 1;
|
|
HexDispatch_DrawRect(hexForeground, srX, srY, srWidth, srHeight);
|
|
}
|
|
HexDispatch_NextTile();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Called when we initially get a Hextile rect; set up to process it */
|
|
void DoHextileRect (void) {
|
|
hexXTiles = (rectWidth + 15) / 16;
|
|
hexYTiles = (rectHeight + 15) / 16;
|
|
|
|
hexXTileNum = 0;
|
|
hexYTileNum = 0;
|
|
|
|
displayInProgress = TRUE;
|
|
|
|
hexTileWidth = (hexYTileNum == hexXTiles - 1) ?
|
|
rectWidth - 16 * (hexXTiles - 1) : 16;
|
|
hexTileHeight = (hexYTileNum == hexYTiles - 1) ?
|
|
rectHeight - 16 * (hexYTiles - 1) : 16;
|
|
|
|
/* Set up for Hextile drawing */
|
|
srcRect.v1 = 0;
|
|
srcRect.h1 = 0;
|
|
}
|