mirror of
https://github.com/sheumann/VNCviewGS.git
synced 2024-11-28 11:50:59 +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.
319 lines
11 KiB
C++
319 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"
|
|
|
|
unsigned char * cursor = NULL; /* Cursor from server */
|
|
|
|
/* Send a DoPointerEvent reflecting the status of the mouse to the server */
|
|
/* This routine also maintains the appropriate cursor when using local cursor */
|
|
void DoPointerEvent (void) {
|
|
static struct {
|
|
unsigned char messageType;
|
|
unsigned char buttonMask;
|
|
unsigned int xPos;
|
|
unsigned int yPos;
|
|
} pointerEventStruct = { 5 /* message type */ };
|
|
|
|
Point mouseCoords;
|
|
Origin contentOrigin;
|
|
RegionHndl contentRgnHndl;
|
|
unsigned int oldButtonMask;
|
|
GrafPortPtr winPtr;
|
|
unsigned long key1 = 0x0000; /* Keys to release & re-press, if any */
|
|
unsigned long key2 = 0x0000;
|
|
|
|
if (viewOnlyMode)
|
|
return;
|
|
|
|
mouseCoords = myEvent.where;
|
|
|
|
SetPort(vncWindow);
|
|
|
|
/* Check if mouse is in content region of VNC window; don't send mouse
|
|
* updates if it isn't.
|
|
*/
|
|
if (FindWindow(&winPtr, myEvent.where.h, myEvent.where.v) != wInContent ||
|
|
winPtr != vncWindow) {
|
|
if (cursor && GetCursorAdr() == cursor)
|
|
InitCursor();
|
|
return;
|
|
}
|
|
|
|
GlobalToLocal(&mouseCoords);
|
|
|
|
contentOrigin.l = GetContentOrigin(vncWindow);
|
|
mouseCoords.h += contentOrigin.pt.h;
|
|
mouseCoords.v += contentOrigin.pt.v;
|
|
|
|
mouseCoords.h = SwapBytes2(mouseCoords.h);
|
|
mouseCoords.v = SwapBytes2(mouseCoords.v);
|
|
|
|
/* Set up correct state of mouse buttons */
|
|
oldButtonMask = pointerEventStruct.buttonMask;
|
|
pointerEventStruct.buttonMask = 0x00;
|
|
|
|
if ((myEvent.modifiers & btn0State) == 0x00) { /* Mouse button pressed */
|
|
if (emulate3ButtonMouse) {
|
|
if (myEvent.modifiers & optionKey) {
|
|
pointerEventStruct.buttonMask = 0x02;
|
|
key1 = 0xFFE9;
|
|
}
|
|
if (myEvent.modifiers & appleKey) {
|
|
pointerEventStruct.buttonMask |= 0x04;
|
|
key2 = 0xFFE7;
|
|
}
|
|
}
|
|
|
|
/* If no modifiers, just send a normal left click. */
|
|
if (pointerEventStruct.buttonMask == 0x00)
|
|
pointerEventStruct.buttonMask = 0x01;
|
|
}
|
|
if ((myEvent.modifiers & btn1State) == 0x00) /* If 2nd (right) */
|
|
pointerEventStruct.buttonMask |= 0x04; /* button is pressed */
|
|
|
|
/* Don't waste bandwidth by sending update if mouse hasn't changed.
|
|
* This may occasionally result in an initial mouse update not being
|
|
* sent. If this occurs, the user can simply move the mouse slightly
|
|
* in order to send it.
|
|
*/
|
|
if ( (pointerEventStruct.xPos == mouseCoords.h) &&
|
|
(pointerEventStruct.yPos == mouseCoords.v) &&
|
|
(pointerEventStruct.buttonMask == oldButtonMask) )
|
|
return;
|
|
|
|
pointerEventStruct.xPos = mouseCoords.h;
|
|
pointerEventStruct.yPos = mouseCoords.v;
|
|
|
|
if (key1)
|
|
SendKeyEvent(FALSE, key1);
|
|
if (key2)
|
|
SendKeyEvent(FALSE, key2);
|
|
|
|
TCPIPWriteTCP(hostIpid, (Pointer) &pointerEventStruct.messageType,
|
|
sizeof(pointerEventStruct), TRUE, FALSE);
|
|
/* Can't do useful error checking here */
|
|
|
|
if (key1)
|
|
SendKeyEvent(TRUE, key1);
|
|
if (key2)
|
|
SendKeyEvent(TRUE, key2);
|
|
|
|
//printf("Sent mouse update: x = %u, y = %u\n", mouseCoords.h, mouseCoords.v);
|
|
//printf(" xPos = %x, yPos = %x, buttons = %x\n", pointerEventStruct.xPos, pointerEventStruct.yPos, (int) pointerEventStruct.buttonMask);
|
|
|
|
/* Note that we don't have to request a display update here. That has
|
|
* been or will be done elsewhere when we're ready for it.
|
|
*/
|
|
|
|
if (cursor && GetCursorAdr() != cursor)
|
|
SetCursor(cursor);
|
|
}
|
|
|
|
void DoCursor (void) {
|
|
unsigned char *cursorPixels;
|
|
unsigned char *bitmask;
|
|
unsigned char *dataPtr;
|
|
/* Elements of the cursor structure (which isn't a C struct) */
|
|
unsigned int *cursorHeightPtr, *cursorWidthPtr;
|
|
unsigned char *cursorImage, *cursorMask;
|
|
unsigned int *hotSpotYPtr, *hotSpotXPtr;
|
|
unsigned long bitmaskByte;
|
|
unsigned long bitmaskLineBytes, lineWords;
|
|
unsigned int line, n, j; /* Loop counters */
|
|
unsigned char *maskLine, *imageLine;
|
|
unsigned char *oldCursor = cursor; /* So we can free() it later */
|
|
unsigned int outBytes640;
|
|
unsigned long outBytes320;
|
|
|
|
bitmaskLineBytes = ((unsigned long)rectWidth + 7) / 8;
|
|
|
|
if (!DoReadTCP((unsigned long)rectWidth * rectHeight + bitmaskLineBytes * rectHeight))
|
|
return; /* Try again later */
|
|
|
|
cursorPixels = (unsigned char *)(*readBufferHndl);
|
|
bitmask = (unsigned char *)(*readBufferHndl) + (unsigned long)rectWidth * rectHeight;
|
|
|
|
if (hRez == 640)
|
|
lineWords = ((unsigned long)rectWidth + 7) / 8 + 1;
|
|
else /* hRez == 320 */
|
|
lineWords = ((unsigned long)rectWidth + 3) / 4 + 1;
|
|
|
|
/* Don't overflow loop indices, and don't use really large cursors.
|
|
* (Is there a limit to the cursor sizes QuickDraw II can handle?) */
|
|
if (lineWords > 16 || rectHeight > 128 || rectWidth == 0 || rectHeight == 0) {
|
|
InitCursor();
|
|
cursor = NULL;
|
|
goto done;
|
|
}
|
|
|
|
cursor = malloc(8 + 4 * lineWords * rectHeight);
|
|
/* Sub-optimal error handling */
|
|
if (cursor == NULL) {
|
|
InitCursor();
|
|
goto done;
|
|
}
|
|
|
|
cursorHeightPtr = (unsigned int *)(void *)cursor;
|
|
cursorWidthPtr = cursorHeightPtr + 1;
|
|
cursorImage = cursor + 4;
|
|
cursorMask = cursorImage + lineWords * rectHeight * 2;
|
|
hotSpotYPtr = (unsigned int *)(cursorMask + lineWords * rectHeight * 2);
|
|
hotSpotXPtr = hotSpotYPtr + 1;
|
|
|
|
*cursorHeightPtr = rectHeight;
|
|
*cursorWidthPtr = lineWords;
|
|
*hotSpotYPtr = rectY;
|
|
*hotSpotXPtr = rectX;
|
|
|
|
/* Make cursorImage using translation tables */
|
|
/* Make cursorMask from bitmask */
|
|
|
|
dataPtr = cursorPixels;
|
|
|
|
if (hRez == 320) {
|
|
for (line = 0; line < rectHeight; line++) { /* for each line ... */
|
|
maskLine = cursorMask + line * lineWords * 2;
|
|
imageLine = cursorImage + line * lineWords * 2;
|
|
|
|
for (j = 0; j < bitmaskLineBytes; j++) {
|
|
bitmaskByte = *(bitmask + line*bitmaskLineBytes + j);
|
|
outBytes320 =
|
|
(((unsigned)bitmaskByte & 0x80) ) + (((unsigned)bitmaskByte & 0x80) >> 1) +
|
|
(((unsigned)bitmaskByte & 0x80) >> 2) + (((unsigned)bitmaskByte & 0x80) >> 3) +
|
|
(((unsigned)bitmaskByte & 0x40) >> 3) + (((unsigned)bitmaskByte & 0x40) >> 4) +
|
|
(((unsigned)bitmaskByte & 0x40) >> 5) + (((unsigned)bitmaskByte & 0x40) >> 6) +
|
|
(((unsigned)bitmaskByte & 0x20) << 10) + (((unsigned)bitmaskByte & 0x20) << 9) +
|
|
(((unsigned)bitmaskByte & 0x20) << 8) + (((unsigned)bitmaskByte & 0x20) << 7) +
|
|
(((unsigned)bitmaskByte & 0x10) << 7) + (((unsigned)bitmaskByte & 0x10) << 6) +
|
|
(((unsigned)bitmaskByte & 0x10) << 5) + (((unsigned)bitmaskByte & 0x10) << 4) +
|
|
((bitmaskByte & 0x08) << 20) + ((bitmaskByte & 0x08) << 19) +
|
|
((bitmaskByte & 0x08) << 18) + ((bitmaskByte & 0x08) << 17) +
|
|
((bitmaskByte & 0x04) << 17) + ((bitmaskByte & 0x04) << 16) +
|
|
((bitmaskByte & 0x04) << 15) + ((bitmaskByte & 0x04) << 14) +
|
|
((bitmaskByte & 0x02) << 30) + ((bitmaskByte & 0x02) << 29) +
|
|
((bitmaskByte & 0x02) << 28) + ((bitmaskByte & 0x02) << 27) +
|
|
((bitmaskByte & 0x01) << 27) + ((bitmaskByte & 0x01) << 26) +
|
|
((bitmaskByte & 0x01) << 25) + ((bitmaskByte & 0x01) << 24);
|
|
*((unsigned long *)maskLine + j) = outBytes320;
|
|
}
|
|
*((unsigned int *)maskLine + lineWords - 1) = 0;
|
|
|
|
for (n = 0; n < rectWidth/2; n++) {
|
|
*(imageLine + n) = coltab320[*(dataPtr++)] & 0xF0;
|
|
*(imageLine + n) += coltab320[*(dataPtr++)] & 0x0F;
|
|
*(imageLine + n) ^= 0xFF; /* Reverse color */
|
|
*(imageLine + n) &= *(maskLine + n);
|
|
}
|
|
if (rectWidth & 0x01) {
|
|
*(imageLine + n) = coltab320[*(dataPtr++)] & 0xF0;
|
|
*(imageLine + n) ^= 0xFF; /* Reverse color */
|
|
*(imageLine + n) &= *(maskLine + n);
|
|
n++;
|
|
}
|
|
*(imageLine + n) = 0;
|
|
*((unsigned int *)imageLine + lineWords - 1) = 0;
|
|
}
|
|
}
|
|
else { /* hRez == 640 */
|
|
for (line = 0; line < rectHeight; line++) { /* for each line ... */
|
|
maskLine = cursorMask + line * lineWords * 2;
|
|
imageLine = cursorImage + line * lineWords * 2;
|
|
|
|
for (j = 0; j < bitmaskLineBytes; j++) {
|
|
bitmaskByte = *(bitmask + line*bitmaskLineBytes + j);
|
|
outBytes640 =
|
|
(((unsigned)bitmaskByte & 0x80) ) + (((unsigned)bitmaskByte & 0xC0) >> 1) +
|
|
(((unsigned)bitmaskByte & 0x60) >> 2) + (((unsigned)bitmaskByte & 0x30) >> 3) +
|
|
(((unsigned)bitmaskByte & 0x10) >> 4) + (((unsigned)bitmaskByte & 0x08) << 12) +
|
|
(((unsigned)bitmaskByte & 0x0C) << 11) + (((unsigned)bitmaskByte & 0x06) << 10) +
|
|
(((unsigned)bitmaskByte & 0x03) << 9) + (((unsigned)bitmaskByte & 0x01) << 8);
|
|
*((unsigned int *)maskLine + j) = outBytes640;
|
|
}
|
|
*((unsigned int *)maskLine + lineWords - 1) = 0;
|
|
|
|
for (n = 0; n < rectWidth / 4; n++) {
|
|
*(imageLine + n) = coltab640[*(dataPtr++)] & 0xC0;
|
|
*(imageLine + n) += coltab640[*(dataPtr++)] & 0x30;
|
|
*(imageLine + n) += coltab640[*(dataPtr++)] & 0x0C;
|
|
*(imageLine + n) += coltab640[*(dataPtr++)] & 0x03;
|
|
*(imageLine + n) ^= 0xFF; /* Reverse color */
|
|
*(imageLine + n) &= *(maskLine + n);
|
|
}
|
|
|
|
if (rectWidth & 0x03) {
|
|
*(imageLine + n) = 0;
|
|
for (j = 0; j < (rectWidth & 0x03); j++) {
|
|
*(imageLine + n) += coltab640[*(dataPtr++)] & (0xC0 >> j*2);
|
|
}
|
|
*(imageLine + n) ^= 0xFF; /* Reverse color */
|
|
*(imageLine + n) &= *(maskLine + n);
|
|
n++;
|
|
}
|
|
*(unsigned int *)(imageLine + n) = 0;
|
|
*((unsigned int *)imageLine + lineWords - 1) = 0;
|
|
}
|
|
}
|
|
|
|
if (GetCursorAdr() == oldCursor)
|
|
SetCursor(cursor);
|
|
|
|
#if 0
|
|
/***************/
|
|
{
|
|
unsigned char * k;
|
|
FILE *foo = fopen("out.txt", "a");
|
|
fprintf(foo, "Width = %u, Height = %u, Hotspot X = %u, Hotspot Y = %u:\n",
|
|
rectWidth, rectHeight, rectX, rectY);
|
|
fprintf(foo, "\n");
|
|
for (k = cursor; k < cursorImage; k++)
|
|
fprintf(foo, "%02X ", *k);
|
|
fprintf(foo, "\n");
|
|
for (j = 0; j < lineWords * rectHeight * 4; j++) {
|
|
fprintf(foo, "%02X", *(cursorImage + j));
|
|
if ((j+1) % (lineWords * 2) == 0)
|
|
fprintf(foo, "\n");
|
|
}
|
|
for (k = cursorImage + j; k < cursorImage + j + 4; k = k + 1)
|
|
fprintf(foo, "%02X ", *k);
|
|
fprintf(foo, "\n");
|
|
fclose(foo);
|
|
}
|
|
/***************/
|
|
#endif
|
|
|
|
done:
|
|
free(oldCursor);
|
|
NextRect(); /* Prepare for next rect */
|
|
}
|