Note that this DOES NOT WORK as some TDE-specific changes to libvncserver will be required The commit is a "clean slate" for the TDE-specific changes to followpull/1/head
parent
dedd07e78d
commit
f6187cc4eb
@ -1,141 +0,0 @@
|
|||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char* filename; /* this file is the pipe (set by user) */
|
|
||||||
char is_server; /* this is set by open_control_file */
|
|
||||||
int fd; /* this is set by open_control_file */
|
|
||||||
} single_instance_struct;
|
|
||||||
|
|
||||||
/* returns fd, is_server is set to -1 if server, 0 if client */
|
|
||||||
int open_control_file(single_instance_struct* str)
|
|
||||||
{
|
|
||||||
struct stat buf;
|
|
||||||
|
|
||||||
if(stat(str->filename,&buf)) {
|
|
||||||
mkfifo(str->filename,128|256);
|
|
||||||
str->is_server=-1;
|
|
||||||
str->fd=open(str->filename,O_NONBLOCK|O_RDONLY);
|
|
||||||
} else {
|
|
||||||
str->fd=open(str->filename,O_NONBLOCK|O_WRONLY);
|
|
||||||
if(errno==ENXIO) {
|
|
||||||
str->is_server=-1;
|
|
||||||
str->fd=open(str->filename,O_NONBLOCK|O_RDONLY);
|
|
||||||
} else
|
|
||||||
str->is_server=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return(str->fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
void delete_control_file(single_instance_struct* str)
|
|
||||||
{
|
|
||||||
remove(str->filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
void close_control_file(single_instance_struct* str)
|
|
||||||
{
|
|
||||||
close(str->fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef void (*event_dispatcher)(char* message);
|
|
||||||
|
|
||||||
int get_next_message(char* buffer,int len,single_instance_struct* str,int usecs)
|
|
||||||
{
|
|
||||||
struct timeval tv;
|
|
||||||
fd_set fdset;
|
|
||||||
int num_fds;
|
|
||||||
|
|
||||||
FD_ZERO(&fdset);
|
|
||||||
FD_SET(str->fd,&fdset);
|
|
||||||
tv.tv_sec=0;
|
|
||||||
tv.tv_usec=usecs;
|
|
||||||
|
|
||||||
num_fds=select(str->fd+1,&fdset,NULL,NULL,&tv);
|
|
||||||
if(num_fds) {
|
|
||||||
int reallen;
|
|
||||||
|
|
||||||
reallen=read(str->fd,buffer,len);
|
|
||||||
if(reallen==0) {
|
|
||||||
close(str->fd);
|
|
||||||
str->fd=open(str->filename,O_NONBLOCK|O_RDONLY);
|
|
||||||
num_fds--;
|
|
||||||
}
|
|
||||||
buffer[reallen]=0;
|
|
||||||
#ifdef DEBUG_1INSTANCE
|
|
||||||
if(reallen!=0) fprintf(stderr,"message received: %s.\n",buffer);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
return(num_fds);
|
|
||||||
}
|
|
||||||
|
|
||||||
int dispatch_event(single_instance_struct* str,event_dispatcher dispatcher,int usecs)
|
|
||||||
{
|
|
||||||
char buffer[1024];
|
|
||||||
int num_fds;
|
|
||||||
|
|
||||||
if((num_fds=get_next_message(buffer,1024,str,usecs)) && buffer[0])
|
|
||||||
dispatcher(buffer);
|
|
||||||
|
|
||||||
return(num_fds);
|
|
||||||
}
|
|
||||||
|
|
||||||
int loop_if_server(single_instance_struct* str,event_dispatcher dispatcher)
|
|
||||||
{
|
|
||||||
open_control_file(str);
|
|
||||||
if(str->is_server) {
|
|
||||||
while(1)
|
|
||||||
dispatch_event(str,dispatcher,50);
|
|
||||||
}
|
|
||||||
|
|
||||||
return(str->fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
void send_message(single_instance_struct* str,char* message)
|
|
||||||
{
|
|
||||||
#ifdef DEBUG_1INSTANCE
|
|
||||||
int i=
|
|
||||||
#endif
|
|
||||||
write(str->fd,message,strlen(message));
|
|
||||||
#ifdef DEBUG_1INSTANCE
|
|
||||||
fprintf(stderr,"send: %s => %d(%d)\n",message,i,strlen(message));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG_MAIN
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
single_instance_struct str1 = { "/tmp/1instance" };
|
|
||||||
|
|
||||||
void my_dispatcher(char* message)
|
|
||||||
{
|
|
||||||
#ifdef DEBUG_1INSTANCE
|
|
||||||
fprintf(stderr,"Message arrived: %s.\n",message);
|
|
||||||
#endif
|
|
||||||
if(!strcmp(message,"quit")) {
|
|
||||||
delete_control_file(str1);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc,char** argv)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
loop_if_server(str1,my_dispatcher);
|
|
||||||
|
|
||||||
for(i=1;i<argc;i++)
|
|
||||||
send_event(str1,argv[i]);
|
|
||||||
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,75 +0,0 @@
|
|||||||
memory leaks squashed (localtime pseudo leak is still there :-)
|
|
||||||
small improvements for OSXvnc (still not working correctly)
|
|
||||||
synced with TightVNC 1.2.3
|
|
||||||
solaris compile cleanups
|
|
||||||
many x11vnc improvements
|
|
||||||
added backchannel, an encoding which needs special clients to pass
|
|
||||||
arbitrary data to the client
|
|
||||||
changes from Tim Jansen regarding multi threading and client blocking
|
|
||||||
as well as C++ compliancy
|
|
||||||
x11vnc can be controlled by starting again with special options if compiling
|
|
||||||
with LOCAL_CONTROL defined
|
|
||||||
0.3
|
|
||||||
added x11vnc, a x0rfbserver clone
|
|
||||||
regard deferUpdateTime in processEvents, if usec<0
|
|
||||||
initialize deferUpdateTime (memory "leak"!)
|
|
||||||
changed command line handling (arguments are parsed and then removed)
|
|
||||||
added very simple example: zippy
|
|
||||||
added rfbDrawLine, rfbDrawPixel
|
|
||||||
0.2
|
|
||||||
inserted a deferUpdate mechanism (X11 independent).
|
|
||||||
removed deletion of requestedRegion
|
|
||||||
added rfbLoadConsoleFont
|
|
||||||
fixed font colour handling.
|
|
||||||
added rfbSelectBox
|
|
||||||
added rfbDrawCharWithClip to allow for clipping and a background colour.
|
|
||||||
fixed font colours
|
|
||||||
added rfbFillRect
|
|
||||||
added IO function to check password.
|
|
||||||
rfbNewClient now sets the socket in the fd_set (for the select() call)
|
|
||||||
when compiling the library with HAVE_PTHREADS and an application
|
|
||||||
which includes "rfb.h" without, the structures got mixed up.
|
|
||||||
So, the pthreads section is now always at the end, and also
|
|
||||||
you get a linker error for rfbInitServer when using two different
|
|
||||||
pthread setups.
|
|
||||||
fixed two deadlocks: when setting a cursor and when using CopyRect
|
|
||||||
fixed CopyRect when copying modified regions (they lost the modified
|
|
||||||
property)
|
|
||||||
WIN32 target compiles and works for example :-)
|
|
||||||
fixed CopyRect (was using the wrong order of rectangles...)
|
|
||||||
should also work with pthreads, because copyrects are
|
|
||||||
always sent immediately (so that two consecutive copy rects
|
|
||||||
cannot conflict).
|
|
||||||
changed rfbUndrawCursor(rfbClientPtr) to (rfbScreenInfoPtr), because
|
|
||||||
this makes more sense!
|
|
||||||
flag backgroundLoop in rfbScreenInfo (if having pthreads)
|
|
||||||
CopyRect & CopyRegion were implemented.
|
|
||||||
if you use a rfbDoCopyR* function, it copies the data in the
|
|
||||||
framebuffer. If you prefer to do that yourself, use rfbScheduleCopyR*
|
|
||||||
instead; this doesn't modify the frameBuffer.
|
|
||||||
added flag to optionally not send XCursor updates, but only RichCursor,
|
|
||||||
or if that is not possible, fall back to server side cursor.
|
|
||||||
This is useful if your cursor has many nice colours.
|
|
||||||
fixed java viewer on server side:
|
|
||||||
SendCursorUpdate would send data even before the client pixel format
|
|
||||||
was set, but the java applet doesn't like the server's format.
|
|
||||||
fixed two pthread issues:
|
|
||||||
rfbSendFramebuffer was sent by a ProcessClientMessage function
|
|
||||||
(unprotected by updateMutex).
|
|
||||||
cursor coordinates were set without protection by cursorMutex
|
|
||||||
source is now equivalent to TridiaVNC 1.2.1
|
|
||||||
pthreads now work (use iterators!)
|
|
||||||
cursors are supported (rfbSetCursor automatically undraws cursor)
|
|
||||||
support for 3 bytes/pixel (slow!)
|
|
||||||
server side colourmap support
|
|
||||||
fixed rfbCloseClient not to close the connection (pthreads!)
|
|
||||||
this is done lazily (and with proper signalling).
|
|
||||||
cleaned up mac.c (from original OSXvnc); now compiles (untested!)
|
|
||||||
compiles cleanly on Linux, IRIX, BSD, Apple (Darwin)
|
|
||||||
fixed prototypes
|
|
||||||
0.1
|
|
||||||
rewrote API to use pseudo-methods instead of required functions.
|
|
||||||
lots of clean up.
|
|
||||||
Example can show symbols now.
|
|
||||||
All encodings
|
|
||||||
HTTP
|
|
@ -1,28 +0,0 @@
|
|||||||
#################################################
|
|
||||||
#
|
|
||||||
# (C) 2010-2011 Serghei Amelian
|
|
||||||
# serghei (DOT) amelian (AT) gmail.com
|
|
||||||
#
|
|
||||||
# Improvements and feedback are welcome
|
|
||||||
#
|
|
||||||
# This file is released under GPL >= 2
|
|
||||||
#
|
|
||||||
#################################################
|
|
||||||
|
|
||||||
include_directories(
|
|
||||||
${CMAKE_CURRENT_BINARY_DIR}
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
add_definitions( -DHAVE_PTHREADS -DALLOW24BPP )
|
|
||||||
|
|
||||||
|
|
||||||
##### vncserver (static) ########################
|
|
||||||
|
|
||||||
tde_add_library( vncserver STATIC_PIC AUTOMOC
|
|
||||||
SOURCES
|
|
||||||
main.cc rfbserver.c sraRegion.c auth.c sockets.c stats.c corre.c
|
|
||||||
hextile.c rre.c translate.c cutpaste.c zlib.c tight.c httpd.c
|
|
||||||
cursor.c font.c draw.c selbox.c d3des.c vncauth.c cargs.c
|
|
||||||
)
|
|
@ -1,16 +0,0 @@
|
|||||||
INCLUDES = $(all_includes)
|
|
||||||
|
|
||||||
METASOURCES = AUTO
|
|
||||||
|
|
||||||
noinst_LTLIBRARIES = libvncserver.la
|
|
||||||
|
|
||||||
libvncserver_la_SOURCES = main.cc rfbserver.c sraRegion.c auth.c sockets.c \
|
|
||||||
stats.c corre.c hextile.c rre.c translate.c cutpaste.c \
|
|
||||||
zlib.c tight.c httpd.c cursor.c font.c \
|
|
||||||
draw.c selbox.c d3des.c vncauth.c cargs.c
|
|
||||||
|
|
||||||
EXTRA_DIST = CHANGES COPYING README TODO
|
|
||||||
|
|
||||||
AM_CPPFLAGS = -DHAVE_PTHREADS -DALLOW24BPP
|
|
||||||
AM_CFLAGS = -Wno-unused
|
|
||||||
|
|
@ -1,417 +0,0 @@
|
|||||||
LibVNCServer: a library for easy implementation of a RDP/VNC server.
|
|
||||||
Copyright (C) 2001 Johannes E. Schindelin
|
|
||||||
|
|
||||||
What is it?
|
|
||||||
-----------
|
|
||||||
|
|
||||||
VNC is a set of programs using the RFB (Remote Frame Buffer) protocol. They
|
|
||||||
are designed to "export" a frame buffer via net (if you don't know VNC, I
|
|
||||||
suggest you read "Basics" below). It is already in wide use for
|
|
||||||
administration, but it is not that easy to program a server yourself.
|
|
||||||
|
|
||||||
This has been changed by LibVNCServer.
|
|
||||||
|
|
||||||
There are two examples included:
|
|
||||||
- example, a shared scribble sheet
|
|
||||||
- pnmshow, a program to show PNMs (pictures) over the net.
|
|
||||||
|
|
||||||
The examples are not too well documented, but easy straight forward and a
|
|
||||||
good starting point.
|
|
||||||
|
|
||||||
Try example: it outputs on which port it listens (default: 5900), so it is
|
|
||||||
display 0. To view, call
|
|
||||||
vncviewer :0
|
|
||||||
You should see a sheet with a gradient and "Hello World!" written on it. Try
|
|
||||||
to paint something. Note that everytime you click, there is some bigger blot.
|
|
||||||
The size depends on the mouse button you click. Open a second vncviewer with
|
|
||||||
the same parameters and watch it as you paint in the other window. This also
|
|
||||||
works over internet. You just have to know either the name or the IP of your
|
|
||||||
machine. Then it is
|
|
||||||
vncviewer machine.where.example.runs.com:0
|
|
||||||
or similar for the remote client. Now you are ready to type something. Be sure
|
|
||||||
that your mouse sits still, because everytime the mouse moves, the cursor is
|
|
||||||
reset! If you are done with that demo, just press Escape in the viewer. Note
|
|
||||||
that the server still runs, even if you closed both windows. When you
|
|
||||||
reconnect now, everything you painted and wrote is still there. So you press
|
|
||||||
"Page Up" for a blank page.
|
|
||||||
|
|
||||||
The demo pnmshow is much simpler: you either provide a filename as argument
|
|
||||||
or pipe a file through stdin. Note that the file has to be a raw pnm/ppm file,
|
|
||||||
i.e. a truecolour graphics. Only the Escape key is implemented. This may be
|
|
||||||
the best starting point if you want to learn how to use LibVNCServer. You
|
|
||||||
are confronted with the fact that the bytes per pixel can only be 8, 16 or 32.
|
|
||||||
|
|
||||||
How to use
|
|
||||||
----------
|
|
||||||
|
|
||||||
To make a server, you just have to initialise a server structure using the
|
|
||||||
function rfbDefaultScreenInit, like
|
|
||||||
rfbScreenInfoPtr rfbScreen =
|
|
||||||
rfbGetScreen(argc,argv,width,height,8,3,bpp);
|
|
||||||
where byte per pixel should be 1, 2 or 4. If performance doesn't matter,
|
|
||||||
you may try bpp=3 (internally one cannot use native data types in this
|
|
||||||
case; if you want to use this, look at pnmshow24).
|
|
||||||
|
|
||||||
|
|
||||||
You then can set hooks and io functions (see below) or other
|
|
||||||
options (see below).
|
|
||||||
|
|
||||||
And you allocate the frame buffer like this:
|
|
||||||
rfbScreen->frameBuffer = (char*)malloc(width*height*bpp);
|
|
||||||
|
|
||||||
After that, you initialize the server, like
|
|
||||||
rfbInitServer(rfbScreen);
|
|
||||||
|
|
||||||
You can use a blocking event loop, a background (pthread based) event loop,
|
|
||||||
or implement your own using the rfbProcessEvents function.
|
|
||||||
|
|
||||||
Making it interactive
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
Input is handled by IO functions (see below).
|
|
||||||
|
|
||||||
Whenever you change something in the frame buffer, call rfbMarkRectAsModified.
|
|
||||||
You should make sure that the cursor is not drawn before drawing yourself
|
|
||||||
by calling rfbUndrawCursor. You can also draw the cursor using rfbDrawCursor,
|
|
||||||
but it hardly seems necessary. For cursor details, see below.
|
|
||||||
|
|
||||||
Utility functions
|
|
||||||
-----------------
|
|
||||||
|
|
||||||
Whenever you draw something, you have to call
|
|
||||||
rfbMarkRectAsModified(screen,x1,y1,x2,y2).
|
|
||||||
This tells LibVNCServer to send updates to all connected clients.
|
|
||||||
|
|
||||||
Before you draw something, be sure to call
|
|
||||||
rfbUndrawCursor(screen).
|
|
||||||
This tells LibVNCServer to hide the cursor.
|
|
||||||
Remark: There are vncviewers out there, which know a cursor encoding, so
|
|
||||||
that network traffic is low, and also the cursor doesn't need to be
|
|
||||||
drawn the cursor everytime an update is sent. LibVNCServer handles
|
|
||||||
all the details. Just set the cursor and don't bother any more.
|
|
||||||
|
|
||||||
To set the mouse coordinates (or emulate mouse clicks), call
|
|
||||||
defaultPtrAddEvent(buttonMask,x,y,cl);
|
|
||||||
However, this works only if your client doesn't do local cursor drawing. There
|
|
||||||
is no way (to my knowledge) to set the pointer of a client via RFB protocol.
|
|
||||||
IMPORTANT: do this at the end of your function, because this actually draws
|
|
||||||
the cursor if no cursor encoding is active.
|
|
||||||
|
|
||||||
What is the difference between rfbScreenInfoPtr and rfbClientPtr?
|
|
||||||
-----------------------------------------------------------------
|
|
||||||
|
|
||||||
The rfbScreenInfoPtr is a pointer to a rfbScreenInfo structure, which
|
|
||||||
holds information about the server, like pixel format, io functions,
|
|
||||||
frame buffer etc.
|
|
||||||
|
|
||||||
The rfbClientPtr is a pointer to an rfbClientRec structure, which holds
|
|
||||||
information about a client, like pixel format, socket of the
|
|
||||||
connection, etc.
|
|
||||||
|
|
||||||
A server can have several clients, but needn't have any. So, if you
|
|
||||||
have a server and three clients are connected, you have one instance
|
|
||||||
of a rfbScreenInfo and three instances of rfbClientRec's.
|
|
||||||
|
|
||||||
The rfbClientRec structure holds a member
|
|
||||||
rfbScreenInfoPtr screen
|
|
||||||
which points to the server and a member
|
|
||||||
rfbClientPtr next
|
|
||||||
to the next client.
|
|
||||||
|
|
||||||
The rfbScreenInfo structure holds a member
|
|
||||||
rfbClientPtr rfbClientHead
|
|
||||||
which points to the first client.
|
|
||||||
|
|
||||||
So, to access the server from the client structure, you use client->screen.
|
|
||||||
To access all clients from a server, get screen->rfbClientHead and
|
|
||||||
iterate using client->next.
|
|
||||||
|
|
||||||
If you change client settings, be sure to use the provided iterator
|
|
||||||
rfbGetClientIterator(rfbScreen)
|
|
||||||
with
|
|
||||||
rfbClientIteratorNext(iterator)
|
|
||||||
and
|
|
||||||
rfbReleaseClientIterator
|
|
||||||
to prevent thread clashes.
|
|
||||||
|
|
||||||
Other options
|
|
||||||
-------------
|
|
||||||
|
|
||||||
These options have to be set between rfbGetScreen and rfbInitServer.
|
|
||||||
|
|
||||||
If you already have a socket to talk to, just set rfbScreen->inetdSock
|
|
||||||
(originally this is for inetd handling, but why not use it for your purpose?).
|
|
||||||
|
|
||||||
To also start an HTTP server (running on port 5800+display_number), you have
|
|
||||||
to set rfbScreen->httpdDir to a directory containing vncviewer.jar and
|
|
||||||
index.vnc (like the included "classes" directory).
|
|
||||||
|
|
||||||
Hooks and IO functions
|
|
||||||
----------------------
|
|
||||||
|
|
||||||
There exist the following IO functions as members of rfbScreen:
|
|
||||||
kbdAddEvent, kbdReleaseAllKeys, ptrAddEvent and setXCutText
|
|
||||||
|
|
||||||
kbdAddEvent(Bool down,KeySym key,rfbClientPtr cl)
|
|
||||||
is called when a key is pressed.
|
|
||||||
kbdReleaseAllKeys(rfbClientPtr cl)
|
|
||||||
is not called at all (maybe in the future).
|
|
||||||
ptrAddEvent(int buttonMask,int x,int y,rfbClientPtr cl)
|
|
||||||
is called when the mouse moves or a button is pressed.
|
|
||||||
WARNING: if you want to have proper cursor handling, call
|
|
||||||
defaultPtrAddEvent(buttonMask,x,y,cl)
|
|
||||||
in your own function. This sets the coordinates of the cursor.
|
|
||||||
setXCutText(char* str,int len,rfbClientPtr cl)
|
|
||||||
is called when the selection changes.
|
|
||||||
|
|
||||||
There are only two hooks:
|
|
||||||
newClientHook(rfbClientPtr cl)
|
|
||||||
is called when a new client has connected.
|
|
||||||
displayHook
|
|
||||||
is called just before a frame buffer update is sent.
|
|
||||||
|
|
||||||
You can also override the following methods:
|
|
||||||
getCursorPtr(rfbClientPtr cl)
|
|
||||||
This could be used to make an animated cursor (if you really want ...)
|
|
||||||
setTranslateFunction(rfbClientPtr cl)
|
|
||||||
If you insist on colour maps or something more obscure, you have to
|
|
||||||
implement this. Default is a trueColour mapping.
|
|
||||||
|
|
||||||
Cursor handling
|
|
||||||
---------------
|
|
||||||
|
|
||||||
The screen holds a pointer
|
|
||||||
rfbCursorPtr cursor
|
|
||||||
to the current cursor. Whenever you set it, remember that any dynamically
|
|
||||||
created cursor (like return value from rfbMakeXCursor) is not free'd!
|
|
||||||
|
|
||||||
The rfbCursor structure consists mainly of a mask and a source. The mask
|
|
||||||
describes, which pixels are drawn for the cursor (a cursor needn't be
|
|
||||||
rectangular). The source describes, which colour those pixels should have.
|
|
||||||
|
|
||||||
The standard is an XCursor: a cursor with a foreground and a background
|
|
||||||
colour (stored in backRed,backGreen,backBlue and the same for foreground
|
|
||||||
in a range from 0-0xffff). Therefore, the arrays "mask" and "source"
|
|
||||||
contain pixels as single bits stored in bytes in MSB order. The rows are
|
|
||||||
padded, such that each row begins with a new byte (i.e. a 10x4
|
|
||||||
cursor's mask has 2x4 bytes, because 2 bytes are needed to hold 10 bits).
|
|
||||||
|
|
||||||
It is however very easy to make a cursor like this:
|
|
||||||
|
|
||||||
char* cur=" "
|
|
||||||
" xx "
|
|
||||||
" x "
|
|
||||||
" ";
|
|
||||||
char* mask="xxxx"
|
|
||||||
"xxxx"
|
|
||||||
"xxxx"
|
|
||||||
"xxx ";
|
|
||||||
rfbCursorPtr c=rfbMakeXCursor(4,4,cur,mask);
|
|
||||||
|
|
||||||
You can even set "mask" to NULL in this call and LibVNCServer will calculate
|
|
||||||
a mask for you (dynamically, so you have to free it yourself).
|
|
||||||
|
|
||||||
There is also an array named "richSource" for colourful cursors. They have
|
|
||||||
the same format as the frameBuffer (i.e. if the server is 32 bit,
|
|
||||||
a 10x4 cursor has 4x10x4 bytes).
|
|
||||||
|
|
||||||
History
|
|
||||||
-------
|
|
||||||
|
|
||||||
LibVNCServer is based on Tridia VNC and OSXvnc, which in turn are based on
|
|
||||||
the original code from ORL/AT&T.
|
|
||||||
|
|
||||||
When I began hacking with computers, my first interest was speed. So, when I
|
|
||||||
got around assembler, I programmed the floppy to do much of the work, because
|
|
||||||
it's clock rate was higher than that of my C64. This was my first experience
|
|
||||||
with client/server techniques.
|
|
||||||
|
|
||||||
When I came around Xwindows (much later), I was at once intrigued by the
|
|
||||||
elegance of such connectedness between the different computers. I used it
|
|
||||||
a lot - not the least priority lay on games. However, when I tried it over
|
|
||||||
modem from home, it was no longer that much fun.
|
|
||||||
|
|
||||||
When I started working with ASP (Application Service Provider) programs, I
|
|
||||||
tumbled across Tarantella and Citrix. Being a security fanatic, the idea of
|
|
||||||
running a server on windows didn't appeal to me, so Citrix went down the
|
|
||||||
basket. However, Tarantella has it's own problems (security as well as the
|
|
||||||
high price). But at the same time somebody told me about this "great little
|
|
||||||
administrator's tool" named VNC. Being used to windows programs' sizes, the
|
|
||||||
surprise was reciprocal inverse to the size of VNC!
|
|
||||||
|
|
||||||
At the same time, the program "rdesktop" (a native Linux client for the
|
|
||||||
Terminal Services of Windows servers) came to my attention. There where even
|
|
||||||
works under way to make a protocol converter "rdp2vnc" out of this. However,
|
|
||||||
my primary goal was a slow connection and rdp2vnc could only speak RRE
|
|
||||||
encoding, which is not that funny with just 5kB/s. Tim Edmonds, the original
|
|
||||||
author of rdp2vnc, suggested that I adapt it to Hextile Encoding, which is
|
|
||||||
better. I first tried that, but had no success at all (crunchy pictures).
|
|
||||||
|
|
||||||
Also, I liked the idea of an HTTP server included and possibly other
|
|
||||||
encodings like the Tight Encodings from Const Kaplinsky. So I started looking
|
|
||||||
for libraries implementing a VNC server where I could steal what I can't make.
|
|
||||||
I found some programs based on the demo server from AT&T, which was also the
|
|
||||||
basis for rdp2vnc (can only speak Raw and RRE encoding). There were some
|
|
||||||
rumors that GGI has a VNC backend, but I didn't find any code, so probably
|
|
||||||
there wasn't a working version anyway.
|
|
||||||
|
|
||||||
All of a sudden, everything changed: I read on freshmeat that "OSXvnc" was
|
|
||||||
released. I looked at the code and it was not much of a problem to work out
|
|
||||||
a simple server - using every functionality there is in Xvnc. It became clear
|
|
||||||
to me that I *had* to build a library out of it, so everybody can use it.
|
|
||||||
Every change, every new feature can propagate to every user of it.
|
|
||||||
|
|
||||||
It also makes everything easier:
|
|
||||||
You don't care about the cursor, once set (or use the standard cursor).
|
|
||||||
You don't care about those sockets. You don't care about encodings.
|
|
||||||
You just change your frame buffer and inform the library about it. Every once
|
|
||||||
in a while you call rfbProcessEvents and that's it.
|
|
||||||
|
|
||||||
Basics
|
|
||||||
------
|
|
||||||
|
|
||||||
VNC (Virtual network computing) works like this: You set up a server and can
|
|
||||||
connect to it via vncviewers. The communication uses a protocol named RFB
|
|
||||||
(Remote Frame Buffer). If the server supports HTTP, you can also connect
|
|
||||||
using a java enabled browser. In this case, the server sends back a
|
|
||||||
vncviewer applet with the correct settings.
|
|
||||||
|
|
||||||
There exist several encodings for VNC, which are used to compress the regions
|
|
||||||
which have changed before they are sent to the client. A client need not be
|
|
||||||
able to understand every encoding, but at least Raw encoding. Which encoding
|
|
||||||
it understands is negotiated by the RFB protocol.
|
|
||||||
|
|
||||||
The following encodings are known to me:
|
|
||||||
Raw, RRE, CoRRE, Hextile, CopyRect from the original AT&T code and
|
|
||||||
Tight, ZLib, LastRect, XCursor, RichCursor from Const Kaplinsky et al.
|
|
||||||
|
|
||||||
If you are using a modem, you want to try the "new" encodings. Especially
|
|
||||||
with my 56k modem I like ZLib or Tight with Quality 0. In my tests, it even
|
|
||||||
beats Tarantella.
|
|
||||||
|
|
||||||
There is the possibility to set a password, which is also negotiated by the
|
|
||||||
RFB protocol, but IT IS NOT SECURE. Anybody sniffing your net can get the
|
|
||||||
password. You really should tunnel through SSH.
|
|
||||||
|
|
||||||
Windows or: why do you do that to me?
|
|
||||||
--------------------------------------------
|
|
||||||
|
|
||||||
If you love products from Redmod, you better skip this paragraph.
|
|
||||||
I am always amazed how people react whenever Microsoft(tm) puts in some
|
|
||||||
features into their products which were around for a long time. Especially
|
|
||||||
reporters seem to not know dick about what they are reporting about! But
|
|
||||||
what is everytime annoying again, is that they don't do it right. Every
|
|
||||||
concept has it's new name (remember what enumerators used to be until
|
|
||||||
Mickeysoft(tm) claimed that enumerators are what we thought were iterators.
|
|
||||||
Yeah right, enumerators are also containers. They are not separate. Muddy.)
|
|
||||||
|
|
||||||
There are three packages you want to get hold of: zlib, jpeg and pthreads.
|
|
||||||
The latter is not strictly necessary, but when you put something like this
|
|
||||||
into your source:
|
|
||||||
|
|
||||||
#define MUTEX(s)
|
|
||||||
struct {
|
|
||||||
int something;
|
|
||||||
MUTEX(latex);
|
|
||||||
}
|
|
||||||
|
|
||||||
Microsoft's C++ compiler doesn't do it. It complains that this is an error.
|
|
||||||
|
|
||||||
You can find the packages at
|
|
||||||
http://www.gimp.org/win32/extralibs-dev-20001007.zip
|
|
||||||
|
|
||||||
Thanks go to all the GIMP team!
|
|
||||||
|
|
||||||
What are those other targets in the Makefile?
|
|
||||||
---------------------------------------------
|
|
||||||
|
|
||||||
OSXvnc-server is the original OSXvnc adapted to use the library, which was in
|
|
||||||
turn adapted from OSXvnc. As you easily can see, the OSX dependend part is
|
|
||||||
minimal.
|
|
||||||
|
|
||||||
storepasswd is the original program to save a vnc style password in a file.
|
|
||||||
Unfortunately, authentication as every vncviewer speaks it means the server
|
|
||||||
has to know the plain password. You really should tunnel via ssh or use
|
|
||||||
your own PasswordCheck to build a PIN/TAN system.
|
|
||||||
|
|
||||||
sratest is a test unit. Run it to assert correct behaviour of sraRegion. I
|
|
||||||
wrote this to test my iterator implementation.
|
|
||||||
|
|
||||||
blooptest is a test of pthreads. It is just the example, but with a background
|
|
||||||
loop to hunt down thread lockups.
|
|
||||||
|
|
||||||
pnmshow24 is like pnmshow, but it uses 3 bytes/pixel internally, which is not
|
|
||||||
as efficient as 4 bytes/pixel for translation, because there is no native data
|
|
||||||
type of that size, so you have to memcpy pixels and be real cautious with
|
|
||||||
endianness. Anyway, it works.
|
|
||||||
|
|
||||||
fontsel is a test for rfbSelectBox and rfbLoadConsoleFont. If you have Linux
|
|
||||||
console fonts, you can browse them via VNC. Directory browsing not implemented
|
|
||||||
yet :-(
|
|
||||||
|
|
||||||
Why I don't feel bad about GPL
|
|
||||||
------------------------------
|
|
||||||
|
|
||||||
At the beginning of this projects I would have liked to make it a BSD
|
|
||||||
license. However, it is based on plenty of GPL'ed code, so it has to be
|
|
||||||
a GPL. I hear BeeGee complaining: "but that's invasive, every derivative
|
|
||||||
work, even just linking, makes my software GPL!"
|
|
||||||
|
|
||||||
Yeah. That's right. It is because there are nasty jarheads out there who
|
|
||||||
would take anybody's work and claim it their own, selling it for much too
|
|
||||||
much money, stealing freedom and innovation from others, saying they were
|
|
||||||
the maintainers of innovation, lying, making money with that.
|
|
||||||
|
|
||||||
The people at AT&T worked really well to produce something as clean and lean
|
|
||||||
as VNC. The managers decided that for their fame, they would release the
|
|
||||||
program for free. But not only that! They realized that by releasing also
|
|
||||||
the code for free, VNC would become an evolving little child, conquering
|
|
||||||
new worlds, making it's parents very proud. As well they can be! To protect
|
|
||||||
this innovation, they decided to make it GPL, not BSD. The principal
|
|
||||||
difference is: You can make closed source programs deriving from BSD, not
|
|
||||||
from GPL. You have to give proper credit with both.
|
|
||||||
|
|
||||||
Now, why not BSD? Well, imagine your child being some famous actor. Along
|
|
||||||
comes a manager who exploits your child exclusively, that is: nobody else
|
|
||||||
can profit from the child, it itself included. Got it?
|
|
||||||
|
|
||||||
What reason do you have now to use this library commercially?
|
|
||||||
|
|
||||||
Several: You don't have to give away your product. Then you have effectively
|
|
||||||
circumvented the GPL, because you have the benefits of other's work and you
|
|
||||||
don't give back anything and you will be in hell for that. In fact, this
|
|
||||||
library, as my other projects, is a payback for all the free software I can
|
|
||||||
use (and sometimes, make better). For example, just now, I am using XEmacs
|
|
||||||
on top X11, all running under Linux.
|
|
||||||
|
|
||||||
Better: Use a concept like MySQL. This is free software, however, they make
|
|
||||||
money with it. If you want something implemented, you have the choice:
|
|
||||||
Ask them to do it (and pay a fair price), or do it yourself, normally giving
|
|
||||||
back your enhancements to the free world of computing.
|
|
||||||
|
|
||||||
Learn from it: If you like the style this is written, learn how to imitate
|
|
||||||
it. If you don't like the style, learn how to avoid those things you don't
|
|
||||||
like. I learnt so much, just from looking at code like Linux, XEmacs,
|
|
||||||
LilyPond, STL, etc.
|
|
||||||
|
|
||||||
License
|
|
||||||
-------
|
|
||||||
|
|
||||||
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.dfdf
|
|
||||||
|
|
||||||
Contact
|
|
||||||
-------
|
|
||||||
|
|
||||||
To contact me, mail me: Johannes dot Schindelin at gmx dot de
|
|
@ -1,80 +0,0 @@
|
|||||||
immediate:
|
|
||||||
----------
|
|
||||||
|
|
||||||
x11vnc: clipboard, cursor, updates interruptible by input (doesn't work yet)
|
|
||||||
extra_bytes in rfbDrawCharWithClip.
|
|
||||||
tested mouse buttons make copy rect, but text is not marked as mod.
|
|
||||||
cursor drawing: set optional grain to mark bigger rectangles as drawn (else
|
|
||||||
you end up with thousands of one-pixel-rectangles to encode).
|
|
||||||
selectbox: scroll bars
|
|
||||||
documentation
|
|
||||||
hint that to mark very tiny regions as
|
|
||||||
modified is possibly inefficient for the encodings.
|
|
||||||
(a trail of points could better be a small rectangle).
|
|
||||||
|
|
||||||
later:
|
|
||||||
------
|
|
||||||
|
|
||||||
authentification schemes (secure vnc)
|
|
||||||
IO function ptr exists; now explain how to tunnel and implement a
|
|
||||||
client address restriction scheme.
|
|
||||||
autoconf? at least Sun Solaris and Windows compilation
|
|
||||||
(maybe Michael makes a small autconf)
|
|
||||||
using Hermes library for fast colour translations.
|
|
||||||
CORBA
|
|
||||||
internal HTTP tunnelling feature (needs a special GET target and a few
|
|
||||||
changes to java applet).
|
|
||||||
|
|
||||||
done:
|
|
||||||
-----
|
|
||||||
|
|
||||||
.x11vnc: sometimes XTest fails (but doesn't with x0rfbserver)
|
|
||||||
.DeferUpdateTime (timing problems!)
|
|
||||||
.empty cursor sending doesn't work.
|
|
||||||
.udp (need an rfbClientPtr udpClient in rfbScreen)
|
|
||||||
input only; nearly untested (don't have the clients).
|
|
||||||
.font handling: bpp>1
|
|
||||||
.test copyRect and pthreads.
|
|
||||||
.optionally dont draw rich cursors as xcursors
|
|
||||||
.cursor smears on IRIX with pthreads, then has bus error. has to be a mutex
|
|
||||||
problem in cursor routines.
|
|
||||||
.fix bug in http (java) client with big endian server: byte swapping is broken
|
|
||||||
(was a cursorshape which was sent too soon; java vncviewer assumes
|
|
||||||
a rich cursor shape to be always 1 byte per pixel, however, framebuffer
|
|
||||||
updates before setting the pixel format can be server format)
|
|
||||||
.rfbConnect, ConnectToTcpAddr
|
|
||||||
.update to newest TridiaVNC version (1.2.1).
|
|
||||||
.adapt rdp2vnc (rdesktop)
|
|
||||||
.pthreads concept: How to iterate over rfbClientPtr's? So that it can be
|
|
||||||
either called from rfbProcessEvents (which locks the list mutex)
|
|
||||||
or from the main thread (where the background loop sometimes
|
|
||||||
locks the list mutex).
|
|
||||||
- cursor drawing!
|
|
||||||
- cursor setting!
|
|
||||||
- rfbMarkRectAsModified
|
|
||||||
(did that by adding a refcount to clients secured by refCountMutex;
|
|
||||||
it also was necessary to check for cl->sock<0 in SendUpdateBuf)
|
|
||||||
.translate.c: warning about non 8-bit colourmaps
|
|
||||||
16-bit colourmaps are 192k -> no use without fast net.
|
|
||||||
.rfbCloseClient
|
|
||||||
.set colourmap
|
|
||||||
.support 3 bytes per pixel
|
|
||||||
.cursors
|
|
||||||
.cutpaste
|
|
||||||
.httpd
|
|
||||||
.other encodings
|
|
||||||
.test drawing of cursors when not using xcursor or rich cursor encoding
|
|
||||||
fix bug with odd width (depends on client depth: width has to be multiple of server.bytesPerPixel/client.bytesPerPixel). only raw!! -> bug of vncviewer!
|
|
||||||
.use sraRegion from Wez instead of miregion, because it is much smaller
|
|
||||||
. - connection gone and then reconnect is a problem
|
|
||||||
the reason: there are in fact three threads accessing
|
|
||||||
the clientPtr: input, output and the application thread.
|
|
||||||
if you kill the viewer or do rfbCloseClient, all of those
|
|
||||||
three have to be warned that this is happening.
|
|
||||||
-> rfbClientConnectionGone can only be called by the outer loop
|
|
||||||
(with background loop, it is input, else it is processEvents).
|
|
||||||
. fixed pthreads issues:
|
|
||||||
cursor deadlock,
|
|
||||||
CopyRect deadlock.
|
|
||||||
. when copying a region with modified parts, they were not marked
|
|
||||||
as modified
|
|
@ -1,109 +0,0 @@
|
|||||||
/*
|
|
||||||
* auth.c - deal with authentication.
|
|
||||||
*
|
|
||||||
* This file implements the VNC authentication protocol when setting up an RFB
|
|
||||||
* connection.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
|
|
||||||
* Original Xvnc code 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
|
||||||
* USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include "rfb.h"
|
|
||||||
|
|
||||||
static int rfbMaxPasswordWait = 120000; /* password timeout (ms) */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* rfbAuthNewClient is called when we reach the point of authenticating
|
|
||||||
* a new client. If authentication isn't being used then we simply send
|
|
||||||
* rfbNoAuth. Otherwise we send rfbVncAuth plus the challenge.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
rfbAuthNewClient(cl)
|
|
||||||
rfbClientPtr cl;
|
|
||||||
{
|
|
||||||
char buf[4 + CHALLENGESIZE];
|
|
||||||
int len;
|
|
||||||
|
|
||||||
cl->state = RFB_AUTHENTICATION;
|
|
||||||
|
|
||||||
if (cl->screen->rfbAuthPasswdData && !cl->reverseConnection) {
|
|
||||||
*(CARD32 *)buf = Swap32IfLE(rfbVncAuth);
|
|
||||||
vncRandomBytes(cl->authChallenge);
|
|
||||||
memcpy(&buf[4], (char *)cl->authChallenge, CHALLENGESIZE);
|
|
||||||
len = 4 + CHALLENGESIZE;
|
|
||||||
} else {
|
|
||||||
*(CARD32 *)buf = Swap32IfLE(rfbNoAuth);
|
|
||||||
len = 4;
|
|
||||||
cl->state = RFB_INITIALISATION;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (WriteExact(cl, buf, len) < 0) {
|
|
||||||
rfbLogPerror("rfbAuthNewClient: write");
|
|
||||||
rfbCloseClient(cl);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* rfbAuthProcessClientMessage is called when the client sends its
|
|
||||||
* authentication response.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
rfbAuthProcessClientMessage(cl)
|
|
||||||
rfbClientPtr cl;
|
|
||||||
{
|
|
||||||
int n;
|
|
||||||
CARD8 response[CHALLENGESIZE];
|
|
||||||
CARD32 authResult;
|
|
||||||
|
|
||||||
if ((n = ReadExactTimeout(cl, (char *)response, CHALLENGESIZE,
|
|
||||||
rfbMaxPasswordWait)) <= 0) {
|
|
||||||
if (n != 0)
|
|
||||||
rfbLogPerror("rfbAuthProcessClientMessage: read");
|
|
||||||
rfbCloseClient(cl);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!cl->screen->passwordCheck(cl,response,CHALLENGESIZE)) {
|
|
||||||
rfbLog("rfbAuthProcessClientMessage: password check failed\n");
|
|
||||||
authResult = Swap32IfLE(rfbVncAuthFailed);
|
|
||||||
if (WriteExact(cl, (char *)&authResult, 4) < 0) {
|
|
||||||
rfbLogPerror("rfbAuthProcessClientMessage: write");
|
|
||||||
}
|
|
||||||
rfbCloseClient(cl);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
authResult = Swap32IfLE(rfbVncAuthOK);
|
|
||||||
|
|
||||||
if (WriteExact(cl, (char *)&authResult, 4) < 0) {
|
|
||||||
rfbLogPerror("rfbAuthProcessClientMessage: write");
|
|
||||||
rfbCloseClient(cl);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cl->state = RFB_INITIALISATION;
|
|
||||||
}
|
|
@ -1,60 +0,0 @@
|
|||||||
#!/usr/bin/perl
|
|
||||||
|
|
||||||
@encodings=();
|
|
||||||
for($i=0;$i<256*5;$i++) {
|
|
||||||
$encodings[$i]="0";
|
|
||||||
}
|
|
||||||
|
|
||||||
$out="";
|
|
||||||
$counter=0;
|
|
||||||
$fontname="default";
|
|
||||||
|
|
||||||
$i=0;
|
|
||||||
$searchfor="";
|
|
||||||
$nullx="0x";
|
|
||||||
|
|
||||||
while(<>) {
|
|
||||||
if(/^FONT (.*)$/) {
|
|
||||||
$fontname=$1;
|
|
||||||
$fontname=~y/\"//d;
|
|
||||||
} elsif(/^ENCODING (.*)$/) {
|
|
||||||
$glyphindex=$1;
|
|
||||||
$searchfor="BBX";
|
|
||||||
$dwidth=0;
|
|
||||||
} elsif(/^DWIDTH (.*) (.*)/) {
|
|
||||||
$dwidth=$1;
|
|
||||||
} elsif(/^BBX (.*) (.*) (.*) (.*)$/) {
|
|
||||||
($width,$height,$x,$y)=($1,$2,$3,$4);
|
|
||||||
@encodings[$glyphindex*5..($glyphindex*5+4)]=($counter,$width,$height,$x,$y);
|
|
||||||
if($dwidth != 0) {
|
|
||||||
$encodings[$glyphindex*5+1]=$dwidth;
|
|
||||||
} else {
|
|
||||||
$dwidth=$width;
|
|
||||||
}
|
|
||||||
$searchfor="BITMAP";
|
|
||||||
} elsif(/^BITMAP/) {
|
|
||||||
$i=1;
|
|
||||||
} elsif($i>0) {
|
|
||||||
if($i>$height) {
|
|
||||||
$i=0;
|
|
||||||
$out.=" /* $glyphindex */\n";
|
|
||||||
} else {
|
|
||||||
if(int(($dwidth+7)/8) > int(($width+7)/8)) {
|
|
||||||
$_ .= "00"x(int(($dwidth+7)/8)-int(($width+7)/8));
|
|
||||||
}
|
|
||||||
$_=substr($_,0,(int(($dwidth+7)/8)*2));
|
|
||||||
$counter+=(int(($dwidth+7)/8));
|
|
||||||
s/(..)/$nullx$1,/g;
|
|
||||||
$out.=$_;
|
|
||||||
$i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
print "unsigned char " . $fontname . "FontData[$counter]={\n" . $out;
|
|
||||||
print "};\nint " . $fontname . "FontMetaData[256*5]={\n";
|
|
||||||
for($i=0;$i<256*5;$i++) {
|
|
||||||
print $encodings[$i] . ",";
|
|
||||||
}
|
|
||||||
print "};\nrfbFontData " . $fontname . "Font={" .
|
|
||||||
$fontname . "FontData, " . $fontname . "FontMetaData};\n";
|
|
@ -1,135 +0,0 @@
|
|||||||
/*
|
|
||||||
* This parses the command line arguments. It was seperated from main.c by
|
|
||||||
* Justin Dearing <jdeari01@longisland.poly.edu>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* LibVNCServer (C) 2001 Johannes E. Schindelin <Johannes.Schindelin@gmx.de>
|
|
||||||
* Original OSXvnc (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
|
|
||||||
* Original Xvnc (C) 1999 AT&T Laboratories Cambridge.
|
|
||||||
* All Rights Reserved.
|
|
||||||
*
|
|
||||||
* see GPL (latest version) for full details
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "rfb.h"
|
|
||||||
|
|
||||||
void
|
|
||||||
rfbUsage(void)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "-rfbport port TCP port for RFB protocol\n");
|
|
||||||
fprintf(stderr, "-rfbwait time max time in ms to wait for RFB client\n");
|
|
||||||
fprintf(stderr, "-rfbauth passwd-file use authentication on RFB protocol\n"
|
|
||||||
" (use 'storepasswd' to create a password file)\n");
|
|
||||||
fprintf(stderr, "-passwd plain-password use authentication \n"
|
|
||||||
" (use plain-password as password, USE AT YOUR RISK)\n");
|
|
||||||
fprintf(stderr, "-deferupdate time time in ms to defer updates "
|
|
||||||
"(default 40)\n");
|
|
||||||
fprintf(stderr, "-desktop name VNC desktop name (default \"LibVNCServer\")\n");
|
|
||||||
fprintf(stderr, "-alwaysshared always treat new clients as shared\n");
|
|
||||||
fprintf(stderr, "-nevershared never treat new clients as shared\n");
|
|
||||||
fprintf(stderr, "-dontdisconnect don't disconnect existing clients when a "
|
|
||||||
"new non-shared\n"
|
|
||||||
" connection comes in (refuse new connection "
|
|
||||||
"instead)\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* purges COUNT arguments from ARGV at POSITION and decrements ARGC.
|
|
||||||
POSITION points to the first non purged argument afterwards. */
|
|
||||||
void rfbPurgeArguments(int* argc,int* position,int count,char *argv[])
|
|
||||||
{
|
|
||||||
int amount=(*argc)-(*position)-count;
|
|
||||||
if(amount)
|
|
||||||
memmove(argv+(*position),argv+(*position)+count,sizeof(char*)*amount);
|
|
||||||
(*argc)-=count;
|
|
||||||
(*position)--;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
rfbProcessArguments(rfbScreenInfoPtr rfbScreen,int* argc, char *argv[])
|
|
||||||
{
|
|
||||||
int i,i1;
|
|
||||||
|
|
||||||
if(!argc) return;
|
|
||||||
|
|
||||||
for (i = i1 = 1; i < *argc; i++) {
|
|
||||||
if (strcmp(argv[i], "-help") == 0) {
|
|
||||||
rfbUsage();
|
|
||||||
exit(1);
|
|
||||||
} else if (strcmp(argv[i], "-rfbport") == 0) { /* -rfbport port */
|
|
||||||
if (i + 1 >= *argc) rfbUsage();
|
|
||||||
rfbScreen->rfbPort = atoi(argv[++i]);
|
|
||||||
} else if (strcmp(argv[i], "-rfbwait") == 0) { /* -rfbwait ms */
|
|
||||||
if (i + 1 >= *argc) rfbUsage();
|
|
||||||
rfbScreen->rfbMaxClientWait = atoi(argv[++i]);
|
|
||||||
} else if (strcmp(argv[i], "-rfbauth") == 0) { /* -rfbauth passwd-file */
|
|
||||||
if (i + 1 >= *argc) rfbUsage();
|
|
||||||
rfbScreen->rfbAuthPasswdData = argv[++i];
|
|
||||||
} else if (strcmp(argv[i], "-passwd") == 0) { /* -passwd password */
|
|
||||||
char **passwds = malloc(sizeof(char**)*2);
|
|
||||||
if (i + 1 >= *argc) rfbUsage();
|
|
||||||
passwds[0] = argv[++i];
|
|
||||||
passwds[1] = 0;
|
|
||||||
rfbScreen->rfbAuthPasswdData = (void*)passwds;
|
|
||||||
rfbScreen->passwordCheck = rfbCheckPasswordByList;
|
|
||||||
} else if (strcmp(argv[i], "-deferupdate") == 0) { /* -desktop desktop-name */
|
|
||||||
if (i + 1 >= *argc) rfbUsage();
|
|
||||||
rfbScreen->rfbDeferUpdateTime = atoi(argv[++i]);
|
|
||||||
} else if (strcmp(argv[i], "-desktop") == 0) { /* -desktop desktop-name */
|
|
||||||
if (i + 1 >= *argc) rfbUsage();
|
|
||||||
rfbScreen->desktopName = argv[++i];
|
|
||||||
} else if (strcmp(argv[i], "-alwaysshared") == 0) {
|
|
||||||
rfbScreen->rfbAlwaysShared = TRUE;
|
|
||||||
} else if (strcmp(argv[i], "-nevershared") == 0) {
|
|
||||||
rfbScreen->rfbNeverShared = TRUE;
|
|
||||||
} else if (strcmp(argv[i], "-dontdisconnect") == 0) {
|
|
||||||
rfbScreen->rfbDontDisconnect = TRUE;
|
|
||||||
} else if (strcmp(argv[i], "-width") == 0) {
|
|
||||||
rfbScreen->width = atoi(argv[++i]);
|
|
||||||
} else if (strcmp(argv[i], "-height") == 0) {
|
|
||||||
rfbScreen->height = atoi(argv[++i]);
|
|
||||||
} else {
|
|
||||||
/* we just remove the processed arguments from the list */
|
|
||||||
if(i != i1)
|
|
||||||
rfbPurgeArguments(argc,&i,i1-i,argv);
|
|
||||||
i1++;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*argc -= i-i1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void rfbSizeUsage()
|
|
||||||
{
|
|
||||||
fprintf(stderr, "-width sets the width of the framebuffer\n");
|
|
||||||
fprintf(stderr, "-height sets the height of the framebuffer\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
rfbProcessSizeArguments(int* width,int* height,int* bpp,int* argc, char *argv[])
|
|
||||||
{
|
|
||||||
int i,i1;
|
|
||||||
|
|
||||||
if(!argc) return;
|
|
||||||
for (i = i1 = 1; i < *argc-1; i++) {
|
|
||||||
if (strcmp(argv[i], "-bpp") == 0) {
|
|
||||||
*bpp = atoi(argv[++i]);
|
|
||||||
} else if (strcmp(argv[i], "-width") == 0) {
|
|
||||||
*width = atoi(argv[++i]);
|
|
||||||
} else if (strcmp(argv[i], "-height") == 0) {
|
|
||||||
*height = atoi(argv[++i]);
|
|
||||||
} else {
|
|
||||||
/* we just remove the processed arguments from the list */
|
|
||||||
if(i != i1) {
|
|
||||||
memmove(argv+i1,argv+i,sizeof(char*)*(*argc-i));
|
|
||||||
*argc -= i-i1;
|
|
||||||
}
|
|
||||||
i1++;
|
|
||||||
i = i1-1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*argc -= i-i1;
|
|
||||||
}
|
|
||||||
|
|
@ -1,355 +0,0 @@
|
|||||||
/*
|
|
||||||
* corre.c
|
|
||||||
*
|
|
||||||
* Routines to implement Compact Rise-and-Run-length Encoding (CoRRE). This
|
|
||||||
* code is based on krw's original javatel rfbserver.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
|
|
||||||
* Original Xvnc code 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
|
||||||
* USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include "rfb.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* rreBeforeBuf contains pixel data in the client's format.
|
|
||||||
* rreAfterBuf contains the RRE encoded version. If the RRE encoded version is
|
|
||||||
* larger than the raw data or if it exceeds rreAfterBufSize then
|
|
||||||
* raw encoding is used instead.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int rreBeforeBufSize = 0;
|
|
||||||
static char *rreBeforeBuf = NULL;
|
|
||||||
|
|
||||||
static int rreAfterBufSize = 0;
|
|
||||||
static char *rreAfterBuf = NULL;
|
|
||||||
static int rreAfterBufLen;
|
|
||||||
|
|
||||||
static int subrectEncode8(CARD8 *data, int w, int h);
|
|
||||||
static int subrectEncode16(CARD16 *data, int w, int h);
|
|
||||||
static int subrectEncode32(CARD32 *data, int w, int h);
|
|
||||||
static CARD32 getBgColour(char *data, int size, int bpp);
|
|
||||||
static Bool rfbSendSmallRectEncodingCoRRE(rfbClientPtr cl, int x, int y,
|
|
||||||
int w, int h);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* rfbSendRectEncodingCoRRE - send an arbitrary size rectangle using CoRRE
|
|
||||||
* encoding.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Bool
|
|
||||||
rfbSendRectEncodingCoRRE(cl, x, y, w, h)
|
|
||||||
rfbClientPtr cl;
|
|
||||||
int x, y, w, h;
|
|
||||||
{
|
|
||||||
if (h > cl->correMaxHeight) {
|
|
||||||
rfbSendRectEncodingCoRRE(cl, x, y, w, cl->correMaxHeight );
|
|
||||||
rfbSendRectEncodingCoRRE(cl, x, y + cl->correMaxHeight, w,
|
|
||||||
h - cl->correMaxHeight);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (w > cl->correMaxWidth) {
|
|
||||||
rfbSendRectEncodingCoRRE(cl, x, y, cl->correMaxWidth, h);
|
|
||||||
rfbSendRectEncodingCoRRE(cl, x + cl->correMaxWidth, y,
|
|
||||||
w - cl->correMaxWidth, h);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
rfbSendSmallRectEncodingCoRRE(cl, x, y, w, h);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* rfbSendSmallRectEncodingCoRRE - send a small (guaranteed < 256x256)
|
|
||||||
* rectangle using CoRRE encoding.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static Bool
|
|
||||||
rfbSendSmallRectEncodingCoRRE(cl, x, y, w, h)
|
|
||||||
rfbClientPtr cl;
|
|
||||||
int x, y, w, h;
|
|
||||||
{
|
|
||||||
rfbFramebufferUpdateRectHeader rect;
|
|
||||||
rfbRREHeader hdr;
|
|
||||||
int nSubrects;
|
|
||||||
int i;
|
|
||||||
char *fbptr = (cl->screen->frameBuffer + (cl->screen->paddedWidthInBytes * y)
|
|
||||||
+ (x * (cl->screen->bitsPerPixel / 8)));
|
|
||||||
|
|
||||||
int maxRawSize = (cl->screen->width * cl->screen->height
|
|
||||||
* (cl->format.bitsPerPixel / 8));
|
|
||||||
|
|
||||||
if (rreBeforeBufSize < maxRawSize) {
|
|
||||||
rreBeforeBufSize = maxRawSize;
|
|
||||||
if (rreBeforeBuf == NULL)
|
|
||||||
rreBeforeBuf = (char *)malloc(rreBeforeBufSize);
|
|
||||||
else
|
|
||||||
rreBeforeBuf = (char *)realloc(rreBeforeBuf, rreBeforeBufSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rreAfterBufSize < maxRawSize) {
|
|
||||||
rreAfterBufSize = maxRawSize;
|
|
||||||
if (rreAfterBuf == NULL)
|
|
||||||
rreAfterBuf = (char *)malloc(rreAfterBufSize);
|
|
||||||
else
|
|
||||||
rreAfterBuf = (char *)realloc(rreAfterBuf, rreAfterBufSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
(*cl->translateFn)(cl->translateLookupTable,&(cl->screen->rfbServerFormat),
|
|
||||||
&cl->format, fbptr, rreBeforeBuf,
|
|
||||||
cl->screen->paddedWidthInBytes, w, h);
|
|
||||||
|
|
||||||
switch (cl->format.bitsPerPixel) {
|
|
||||||
case 8:
|
|
||||||
nSubrects = subrectEncode8((CARD8 *)rreBeforeBuf, w, h);
|
|
||||||
break;
|
|
||||||
case 16:
|
|
||||||
nSubrects = subrectEncode16((CARD16 *)rreBeforeBuf, w, h);
|
|
||||||
break;
|
|
||||||
case 32:
|
|
||||||
nSubrects = subrectEncode32((CARD32 *)rreBeforeBuf, w, h);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
rfbLog("getBgColour: bpp %d?\n",cl->format.bitsPerPixel);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nSubrects < 0) {
|
|
||||||
|
|
||||||
/* RRE encoding was too large, use raw */
|
|
||||||
|
|
||||||
return rfbSendRectEncodingRaw(cl, x, y, w, h);
|
|
||||||
}
|
|
||||||
|
|
||||||
cl->rfbRectanglesSent[rfbEncodingCoRRE]++;
|
|
||||||
cl->rfbBytesSent[rfbEncodingCoRRE] += (sz_rfbFramebufferUpdateRectHeader
|
|
||||||
+ sz_rfbRREHeader + rreAfterBufLen);
|
|
||||||
|
|
||||||
if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbRREHeader
|
|
||||||
> UPDATE_BUF_SIZE)
|
|
||||||
{
|
|
||||||
if (!rfbSendUpdateBuf(cl))
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
rect.r.x = Swap16IfLE(x);
|
|
||||||
rect.r.y = Swap16IfLE(y);
|
|
||||||
rect.r.w = Swap16IfLE(w);
|
|
||||||
rect.r.h = Swap16IfLE(h);
|
|
||||||
rect.encoding = Swap32IfLE(rfbEncodingCoRRE);
|
|
||||||
|
|
||||||
memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
|
|
||||||
sz_rfbFramebufferUpdateRectHeader);
|
|
||||||
cl->ublen += sz_rfbFramebufferUpdateRectHeader;
|
|
||||||
|
|
||||||
hdr.nSubrects = Swap32IfLE(nSubrects);
|
|
||||||
|
|
||||||
memcpy(&cl->updateBuf[cl->ublen], (char *)&hdr, sz_rfbRREHeader);
|
|
||||||
cl->ublen += sz_rfbRREHeader;
|
|
||||||
|
|
||||||
for (i = 0; i < rreAfterBufLen;) {
|
|
||||||
|
|
||||||
int bytesToCopy = UPDATE_BUF_SIZE - cl->ublen;
|
|
||||||
|
|
||||||
if (i + bytesToCopy > rreAfterBufLen) {
|
|
||||||
bytesToCopy = rreAfterBufLen - i;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(&cl->updateBuf[cl->ublen], &rreAfterBuf[i], bytesToCopy);
|
|
||||||
|
|
||||||
cl->ublen += bytesToCopy;
|
|
||||||
i += bytesToCopy;
|
|
||||||
|
|
||||||
if (cl->ublen == UPDATE_BUF_SIZE) {
|
|
||||||
if (!rfbSendUpdateBuf(cl))
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* subrectEncode() encodes the given multicoloured rectangle as a background
|
|
||||||
* colour overwritten by single-coloured rectangles. It returns the number
|
|
||||||
* of subrectangles in the encoded buffer, or -1 if subrect encoding won't
|
|
||||||
* fit in the buffer. It puts the encoded rectangles in rreAfterBuf. The
|
|
||||||
* single-colour rectangle partition is not optimal, but does find the biggest
|
|
||||||
* horizontal or vertical rectangle top-left anchored to each consecutive
|
|
||||||
* coordinate position.
|
|
||||||
*
|
|
||||||
* The coding scheme is simply [<bgcolour><subrect><subrect>...] where each
|
|
||||||
* <subrect> is [<colour><x><y><w><h>].
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define DEFINE_SUBRECT_ENCODE(bpp) \
|
|
||||||
static int \
|
|
||||||
subrectEncode##bpp(data,w,h) \
|
|
||||||
CARD##bpp *data; \
|
|
||||||
int w; \
|
|
||||||
int h; \
|
|
||||||
{ \
|
|
||||||
CARD##bpp cl; \
|
|
||||||
rfbCoRRERectangle subrect; \
|
|
||||||
int x,y; \
|
|
||||||
int i,j; \
|
|
||||||
int hx=0,hy,vx=0,vy; \
|
|
||||||
int hyflag; \
|
|
||||||
CARD##bpp *seg; \
|
|
||||||
CARD##bpp *line; \
|
|
||||||
int hw,hh,vw,vh; \
|
|
||||||
int thex,they,thew,theh; \
|
|
||||||
int numsubs = 0; \
|
|
||||||
int newLen; \
|
|
||||||
CARD##bpp bg = (CARD##bpp)getBgColour((char*)data,w*h,bpp); \
|
|
||||||
\
|
|
||||||
*((CARD##bpp*)rreAfterBuf) = bg; \
|
|
||||||
\
|
|
||||||
rreAfterBufLen = (bpp/8); \
|
|
||||||
\
|
|
||||||
for (y=0; y<h; y++) { \
|
|
||||||
line = data+(y*w); \
|
|
||||||
for (x=0; x<w; x++) { \
|
|
||||||
if (line[x] != bg) { \
|
|
||||||
cl = line[x]; \
|
|
||||||
hy = y-1; \
|
|
||||||
hyflag = 1; \
|
|
||||||
for (j=y; j<h; j++) { \
|
|
||||||
seg = data+(j*w); \
|
|
||||||
if (seg[x] != cl) {break;} \
|
|
||||||
i = x; \
|
|
||||||
while ((seg[i] == cl) && (i < w)) i += 1; \
|
|
||||||
i -= 1; \
|
|
||||||
if (j == y) vx = hx = i; \
|
|
||||||
if (i < vx) vx = i; \
|
|
||||||
if ((hyflag > 0) && (i >= hx)) {hy += 1;} else {hyflag = 0;} \
|
|
||||||
} \
|
|
||||||
vy = j-1; \
|
|
||||||
\
|
|
||||||
/* We now have two possible subrects: (x,y,hx,hy) and (x,y,vx,vy) \
|
|
||||||
* We'll choose the bigger of the two. \
|
|
||||||
*/ \
|
|
||||||
hw = hx-x+1; \
|
|
||||||
hh = hy-y+1; \
|
|
||||||
vw = vx-x+1; \
|
|
||||||
vh = vy-y+1; \
|
|
||||||
\
|
|
||||||
thex = x; \
|
|
||||||
they = y; \
|
|
||||||
\
|
|
||||||
if ((hw*hh) > (vw*vh)) { \
|
|
||||||
thew = hw; \
|
|
||||||
theh = hh; \
|
|
||||||
} else { \
|
|
||||||
thew = vw; \
|
|
||||||
theh = vh; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
subrect.x = thex; \
|
|
||||||
subrect.y = they; \
|
|
||||||
subrect.w = thew; \
|
|
||||||
subrect.h = theh; \
|
|
||||||
\
|
|
||||||
newLen = rreAfterBufLen + (bpp/8) + sz_rfbCoRRERectangle; \
|
|
||||||
if ((newLen > (w * h * (bpp/8))) || (newLen > rreAfterBufSize)) \
|
|
||||||
return -1; \
|
|
||||||
\
|
|
||||||
numsubs += 1; \
|
|
||||||
*((CARD##bpp*)(rreAfterBuf + rreAfterBufLen)) = cl; \
|
|
||||||
rreAfterBufLen += (bpp/8); \
|
|
||||||
memcpy(&rreAfterBuf[rreAfterBufLen],&subrect,sz_rfbCoRRERectangle); \
|
|
||||||
rreAfterBufLen += sz_rfbCoRRERectangle; \
|
|
||||||
\
|
|
||||||
/* \
|
|
||||||
* Now mark the subrect as done. \
|
|
||||||
*/ \
|
|
||||||
for (j=they; j < (they+theh); j++) { \
|
|
||||||
for (i=thex; i < (thex+thew); i++) { \
|
|
||||||
data[j*w+i] = bg; \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
return numsubs; \
|
|
||||||
}
|
|
||||||
|
|
||||||
DEFINE_SUBRECT_ENCODE(8)
|
|
||||||
DEFINE_SUBRECT_ENCODE(16)
|
|
||||||
DEFINE_SUBRECT_ENCODE(32)
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* getBgColour() gets the most prevalent colour in a byte array.
|
|
||||||
*/
|
|
||||||
static CARD32
|
|
||||||
getBgColour(data,size,bpp)
|
|
||||||
char *data;
|
|
||||||
int size;
|
|
||||||
int bpp;
|
|
||||||
{
|
|
||||||
|
|
||||||
#define NUMCLRS 256
|
|
||||||
|
|
||||||
static int counts[NUMCLRS];
|
|
||||||
int i,j,k;
|
|
||||||
|
|
||||||
int maxcount = 0;
|
|
||||||
CARD8 maxclr = 0;
|
|
||||||
|
|
||||||
if (bpp != 8) {
|
|
||||||
if (bpp == 16) {
|
|
||||||
return ((CARD16 *)data)[0];
|
|
||||||
} else if (bpp == 32) {
|
|
||||||
return ((CARD32 *)data)[0];
|
|
||||||
} else {
|
|
||||||
rfbLog("getBgColour: bpp %d?\n",bpp);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0; i<NUMCLRS; i++) {
|
|
||||||
counts[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (j=0; j<size; j++) {
|
|
||||||
k = (int)(((CARD8 *)data)[j]);
|
|
||||||
if (k >= NUMCLRS) {
|
|
||||||
rfbLog("getBgColour: unusual colour = %d\n", k);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
counts[k] += 1;
|
|
||||||
if (counts[k] > maxcount) {
|
|
||||||
maxcount = counts[k];
|
|
||||||
maxclr = ((CARD8 *)data)[j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return maxclr;
|
|
||||||
}
|
|
@ -1,678 +0,0 @@
|
|||||||
/*
|
|
||||||
* cursor.c - support for cursor shape updates.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2000, 2001 Const 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
|
||||||
* USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "rfb.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Send cursor shape either in X-style format or in client pixel format.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Bool
|
|
||||||
rfbSendCursorShape(cl)
|
|
||||||
rfbClientPtr cl;
|
|
||||||
{
|
|
||||||
rfbCursorPtr pCursor;
|
|
||||||
rfbFramebufferUpdateRectHeader rect;
|
|
||||||
rfbXCursorColors colors;
|
|
||||||
int saved_ublen;
|
|
||||||
int bitmapRowBytes, maskBytes, dataBytes;
|
|
||||||
int i, j;
|
|
||||||
CARD8 *bitmapData;
|
|
||||||
CARD8 bitmapByte;
|
|
||||||
|
|
||||||
pCursor = cl->screen->getCursorPtr(cl);
|
|
||||||
/*if(!pCursor) return TRUE;*/
|
|
||||||
|
|
||||||
if (cl->useRichCursorEncoding) {
|
|
||||||
if(pCursor && !pCursor->richSource)
|
|
||||||
MakeRichCursorFromXCursor(cl->screen,pCursor);
|
|
||||||
rect.encoding = Swap32IfLE(rfbEncodingRichCursor);
|
|
||||||
} else {
|
|
||||||
if(pCursor && !pCursor->source)
|
|
||||||
MakeXCursorFromRichCursor(cl->screen,pCursor);
|
|
||||||
rect.encoding = Swap32IfLE(rfbEncodingXCursor);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If there is no cursor, send update with empty cursor data. */
|
|
||||||
|
|
||||||
if ( pCursor && pCursor->width == 1 &&
|
|
||||||
pCursor->height == 1 &&
|
|
||||||
pCursor->mask[0] == 0 ) {
|
|
||||||
pCursor = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pCursor == NULL) {
|
|
||||||
if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE ) {
|
|
||||||
if (!rfbSendUpdateBuf(cl))
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
rect.r.x = rect.r.y = 0;
|
|
||||||
rect.r.w = rect.r.h = 0;
|
|
||||||
memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
|
|
||||||
sz_rfbFramebufferUpdateRectHeader);
|
|
||||||
cl->ublen += sz_rfbFramebufferUpdateRectHeader;
|
|
||||||
|
|
||||||
cl->rfbCursorBytesSent += sz_rfbFramebufferUpdateRectHeader;
|
|
||||||
cl->rfbCursorUpdatesSent++;
|
|
||||||
|
|
||||||
if (!rfbSendUpdateBuf(cl))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Calculate data sizes. */
|
|
||||||
|
|
||||||
bitmapRowBytes = (pCursor->width + 7) / 8;
|
|
||||||
maskBytes = bitmapRowBytes * pCursor->height;
|
|
||||||
dataBytes = (cl->useRichCursorEncoding) ?
|
|
||||||
(pCursor->width * pCursor->height *
|
|
||||||
(cl->format.bitsPerPixel / 8)) : maskBytes;
|
|
||||||
|
|
||||||
/* Send buffer contents if needed. */
|
|
||||||
|
|
||||||
if ( cl->ublen + sz_rfbFramebufferUpdateRectHeader +
|
|
||||||
sz_rfbXCursorColors + maskBytes + dataBytes > UPDATE_BUF_SIZE ) {
|
|
||||||
if (!rfbSendUpdateBuf(cl))
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( cl->ublen + sz_rfbFramebufferUpdateRectHeader +
|
|
||||||
sz_rfbXCursorColors + maskBytes + dataBytes > UPDATE_BUF_SIZE ) {
|
|
||||||
return FALSE; /* FIXME. */
|
|
||||||
}
|
|
||||||
|
|
||||||
saved_ublen = cl->ublen;
|
|
||||||
|
|
||||||
/* Prepare rectangle header. */
|
|
||||||
|
|
||||||
rect.r.x = Swap16IfLE(pCursor->xhot);
|
|
||||||
rect.r.y = Swap16IfLE(pCursor->yhot);
|
|
||||||
rect.r.w = Swap16IfLE(pCursor->width);
|
|
||||||
rect.r.h = Swap16IfLE(pCursor->height);
|
|
||||||
|
|
||||||
memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader);
|
|
||||||
cl->ublen += sz_rfbFramebufferUpdateRectHeader;
|
|
||||||
|
|
||||||
/* Prepare actual cursor data (depends on encoding used). */
|
|
||||||
|
|
||||||
if (!cl->useRichCursorEncoding) {
|
|
||||||
/* XCursor encoding. */
|
|
||||||
colors.foreRed = (char)(pCursor->foreRed >> 8);
|
|
||||||
colors.foreGreen = (char)(pCursor->foreGreen >> 8);
|
|
||||||
colors.foreBlue = (char)(pCursor->foreBlue >> 8);
|
|
||||||
colors.backRed = (char)(pCursor->backRed >> 8);
|
|
||||||
colors.backGreen = (char)(pCursor->backGreen >> 8);
|
|
||||||
colors.backBlue = (char)(pCursor->backBlue >> 8);
|
|
||||||
|
|
||||||
memcpy(&cl->updateBuf[cl->ublen], (char *)&colors, sz_rfbXCursorColors);
|
|
||||||
cl->ublen += sz_rfbXCursorColors;
|
|
||||||
|
|
||||||
bitmapData = (CARD8 *)pCursor->source;
|
|
||||||
|
|
||||||
for (i = 0; i < pCursor->height; i++) {
|
|
||||||
for (j = 0; j < bitmapRowBytes; j++) {
|
|
||||||
bitmapByte = bitmapData[i * bitmapRowBytes + j];
|
|
||||||
cl->updateBuf[cl->ublen++] = (char)bitmapByte;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* RichCursor encoding. */
|
|
||||||
int bpp1=cl->screen->rfbServerFormat.bitsPerPixel/8,
|
|
||||||
bpp2=cl->format.bitsPerPixel/8;
|
|
||||||
(*cl->translateFn)(cl->translateLookupTable,
|
|
||||||
&(cl->screen->rfbServerFormat),
|
|
||||||
&cl->format, pCursor->richSource,
|
|
||||||
&cl->updateBuf[cl->ublen],
|
|
||||||
pCursor->width*bpp1, pCursor->width, pCursor->height);
|
|
||||||
|
|
||||||
cl->ublen += pCursor->width*bpp2*pCursor->height;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Prepare transparency mask. */
|
|
||||||
|
|
||||||
bitmapData = (CARD8 *)pCursor->mask;
|
|
||||||
|
|
||||||
for (i = 0; i < pCursor->height; i++) {
|
|
||||||
for (j = 0; j < bitmapRowBytes; j++) {
|
|
||||||
bitmapByte = bitmapData[i * bitmapRowBytes + j];
|
|
||||||
cl->updateBuf[cl->ublen++] = (char)bitmapByte;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Send everything we have prepared in the cl->updateBuf[]. */
|
|
||||||
|
|
||||||
cl->rfbCursorBytesSent += (cl->ublen - saved_ublen);
|
|
||||||
cl->rfbCursorUpdatesSent++;
|
|
||||||
|
|
||||||
if (!rfbSendUpdateBuf(cl))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Send soft cursor state and possibly image
|
|
||||||
*/
|
|
||||||
|
|
||||||
Bool
|
|
||||||
rfbSendSoftCursor(rfbClientPtr cl, Bool cursorWasChanged)
|
|
||||||
{
|
|
||||||
rfbCursorPtr pCursor;
|
|
||||||
rfbSoftCursorSetImage setImage;
|
|
||||||
rfbSoftCursorMove moveMsg;
|
|
||||||
rfbFramebufferUpdateRectHeader rect;
|
|
||||||
int saved_ublen, i, scOindex, scNindex, nlen, imgLen;
|
|
||||||
|
|
||||||
pCursor = cl->screen->getCursorPtr(cl);
|
|
||||||
if (cursorWasChanged && cl->softSource) {
|
|
||||||
free(cl->softSource);
|
|
||||||
cl->softSource = 0;
|
|
||||||
}
|
|
||||||
if (!cl->softSource)
|
|
||||||
MakeSoftCursor(cl, pCursor);
|
|
||||||
|
|
||||||
imgLen = cl->softSourceLen;
|
|
||||||
|
|
||||||
/* If there is no cursor, send update with empty cursor data. */
|
|
||||||
|
|
||||||
if ( pCursor && pCursor->width <= 1 &&
|
|
||||||
pCursor->height <= 1 &&
|
|
||||||
pCursor->mask[0] == 0 ) {
|
|
||||||
pCursor = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
setImage.imageLength = Swap16IfLE(imgLen);
|
|
||||||
|
|
||||||
scOindex = -1;
|
|
||||||
scNindex = -1;
|
|
||||||
for (i = 0; i < rfbSoftCursorMaxImages; i++) {
|
|
||||||
rfbSoftCursorSetImage *scsi = cl->softCursorImages[i];
|
|
||||||
if (!scsi) {
|
|
||||||
scNindex = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
setImage.imageIndex = scsi->imageIndex;
|
|
||||||
if (!memcmp((char*)scsi, (char*)&setImage, sizeof(setImage))) {
|
|
||||||
if (imgLen && !memcmp(((char*)scsi)+sizeof(rfbSoftCursorSetImage),
|
|
||||||
cl->softSource,
|
|
||||||
imgLen)) {
|
|
||||||
scOindex = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nlen = 0;
|
|
||||||
if (scOindex < 0) {
|
|
||||||
if (scNindex < 0) {
|
|
||||||
scNindex = cl->nextUnusedSoftCursorImage;
|
|
||||||
cl->nextUnusedSoftCursorImage = (cl->nextUnusedSoftCursorImage+1)
|
|
||||||
% rfbSoftCursorMaxImages;
|
|
||||||
free(cl->softCursorImages[scNindex]);
|
|
||||||
}
|
|
||||||
|
|
||||||
scOindex = scNindex;
|
|
||||||
setImage.imageIndex = scNindex + rfbSoftCursorSetIconOffset;
|
|
||||||
nlen = sizeof(setImage) + imgLen;
|
|
||||||
cl->softCursorImages[scNindex] = calloc(1, nlen);
|
|
||||||
memcpy((char*)cl->softCursorImages[scNindex], (char*)&setImage,
|
|
||||||
sizeof(setImage));
|
|
||||||
if (imgLen)
|
|
||||||
memcpy(((char*)cl->softCursorImages[scNindex])+sizeof(setImage),
|
|
||||||
(char*)cl->softSource, imgLen);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Send buffer contents if needed. */
|
|
||||||
|
|
||||||
if ( cl->ublen + sizeof(rfbSoftCursorMove) +
|
|
||||||
((scNindex >= 0 && cursorWasChanged) ?
|
|
||||||
(sizeof(rfbSoftCursorSetImage) + imgLen) : 0) > UPDATE_BUF_SIZE) {
|
|
||||||
|
|
||||||
if (!rfbSendUpdateBuf(cl))
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
saved_ublen = cl->ublen;
|
|
||||||
|
|
||||||
if (scNindex >= 0 && cursorWasChanged) {
|
|
||||||
rect.encoding = Swap32IfLE(rfbEncodingSoftCursor);
|
|
||||||
if (pCursor) {
|
|
||||||
rect.r.x = Swap16IfLE(pCursor->xhot);
|
|
||||||
rect.r.y = Swap16IfLE(pCursor->yhot);
|
|
||||||
rect.r.w = Swap16IfLE(pCursor->width);
|
|
||||||
rect.r.h = Swap16IfLE(pCursor->height);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
rect.r.x = 0;
|
|
||||||
rect.r.y = 0;
|
|
||||||
rect.r.w = 0;
|
|
||||||
rect.r.h = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(&cl->updateBuf[cl->ublen],
|
|
||||||
(char *)&rect,sz_rfbFramebufferUpdateRectHeader);
|
|
||||||
cl->ublen += sz_rfbFramebufferUpdateRectHeader;
|
|
||||||
memcpy(&cl->updateBuf[cl->ublen], (char*)cl->softCursorImages[scNindex], nlen);
|
|
||||||
cl->ublen += nlen;
|
|
||||||
cl->rfbCursorUpdatesSent++;
|
|
||||||
}
|
|
||||||
|
|
||||||
rect.encoding = Swap32IfLE(rfbEncodingSoftCursor);
|
|
||||||
rect.r.x = 0;
|
|
||||||
rect.r.y = 0;
|
|
||||||
rect.r.w = Swap16IfLE(cl->screen->cursorX);
|
|
||||||
rect.r.h = Swap16IfLE(cl->screen->cursorY);
|
|
||||||
moveMsg.imageIndex = scOindex;
|
|
||||||
moveMsg.buttonMask = 0; /* todo */
|
|
||||||
memcpy(&cl->updateBuf[cl->ublen],
|
|
||||||
(char *)&rect,sz_rfbFramebufferUpdateRectHeader);
|
|
||||||
cl->ublen += sz_rfbFramebufferUpdateRectHeader;
|
|
||||||
memcpy(&cl->updateBuf[cl->ublen], (char*)&moveMsg, sizeof(moveMsg));
|
|
||||||
cl->ublen += sizeof(moveMsg);
|
|
||||||
|
|
||||||
/* Send everything we have prepared in the cl->updateBuf[]. */
|
|
||||||
|
|
||||||
cl->rfbCursorBytesSent += (cl->ublen - saved_ublen);
|
|
||||||
cl->rfbCursorUpdatesSent++;
|
|
||||||
|
|
||||||
return rfbSendUpdateBuf(cl);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* conversion routine for predefined cursors in LSB order */
|
|
||||||
unsigned char rfbReverseByte[0x100] = {
|
|
||||||
/* copied from Xvnc/lib/font/util/utilbitmap.c */
|
|
||||||
0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
|
|
||||||
0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
|
|
||||||
0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
|
|
||||||
0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
|
|
||||||
0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
|
|
||||||
0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
|
|
||||||
0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
|
|
||||||
0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
|
|
||||||
0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
|
|
||||||
0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
|
|
||||||
0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
|
|
||||||
0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
|
|
||||||
0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
|
|
||||||
0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
|
|
||||||
0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
|
|
||||||
0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
|
|
||||||
0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
|
|
||||||
0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
|
|
||||||
0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
|
|
||||||
0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
|
|
||||||
0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
|
|
||||||
0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
|
|
||||||
0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
|
|
||||||
0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
|
|
||||||
0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
|
|
||||||
0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
|
|
||||||
0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
|
|
||||||
0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
|
|
||||||
0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
|
|
||||||
0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
|
|
||||||
0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
|
|
||||||
0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
|
|
||||||
};
|
|
||||||
|
|
||||||
void rfbConvertLSBCursorBitmapOrMask(int width,int height,unsigned char* bitmap)
|
|
||||||
{
|
|
||||||
int i,t=(width+7)/8*height;
|
|
||||||
for(i=0;i<t;i++)
|
|
||||||
bitmap[i]=rfbReverseByte[(int)bitmap[i]];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Cursor creation. You "paint" a cursor and let these routines do the work */
|
|
||||||
|
|
||||||
rfbCursorPtr rfbMakeXCursor(int width,int height,char* cursorString,char* maskString)
|
|
||||||
{
|
|
||||||
int i,j,w=(width+7)/8;
|
|
||||||
rfbCursorPtr cursor = (rfbCursorPtr)calloc(1,sizeof(rfbCursor));
|
|
||||||
char* cp;
|
|
||||||
unsigned char bit;
|
|
||||||
|
|
||||||
cursor->width=width;
|
|
||||||
cursor->height=height;
|
|
||||||
/*cursor->backRed=cursor->backGreen=cursor->backBlue=0xffff;*/
|
|
||||||
cursor->foreRed=cursor->foreGreen=cursor->foreBlue=0xffff;
|
|
||||||
|
|
||||||
cursor->source = (unsigned char*)calloc(w,height);
|
|
||||||
for(j=0,cp=cursorString;j<height;j++)
|
|
||||||
for(i=0,bit=0x80;i<width;i++,bit=(bit&1)?0x80:bit>>1,cp++)
|
|
||||||
if(*cp!=' ') ((char*)(cursor->source))[j*w+i/8]|=bit;
|
|
||||||
|
|
||||||
if(maskString) {
|
|
||||||
cursor->mask = (unsigned char*)calloc(w,height);
|
|
||||||
for(j=0,cp=maskString;j<height;j++)
|
|
||||||
for(i=0,bit=0x80;i<width;i++,bit=(bit&1)?0x80:bit>>1,cp++)
|
|
||||||
if(*cp!=' ') ((char*)(cursor->mask))[j*w+i/8]|=bit;
|
|
||||||
} else
|
|
||||||
cursor->mask = (unsigned char*)rfbMakeMaskForXCursor(width,height,(char*)(cursor->source));
|
|
||||||
|
|
||||||
return(cursor);
|
|
||||||
}
|
|
||||||
|
|
||||||
char* rfbMakeMaskForXCursor(int width,int height,char* source)
|
|
||||||
{
|
|
||||||
int i,j,w=(width+7)/8;
|
|
||||||
char* mask=(char*)calloc(w,height);
|
|
||||||
unsigned char c;
|
|
||||||
|
|
||||||
for(j=0;j<height;j++)
|
|
||||||
for(i=w-1;i>=0;i--) {
|
|
||||||
c=source[j*w+i];
|
|
||||||
if(j>0) c|=source[(j-1)*w+i];
|
|
||||||
if(j<height-1) c|=source[(j+1)*w+i];
|
|
||||||
|
|
||||||
if(i>0 && (c&0x80))
|
|
||||||
mask[j*w+i-1]|=0x01;
|
|
||||||
if(i<w-1 && (c&0x01))
|
|
||||||
mask[j*w+i+1]|=0x80;
|
|
||||||
|
|
||||||
mask[j*w+i]|=(c<<1)|c|(c>>1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return(mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rfbFreeCursor(rfbCursorPtr cursor)
|
|
||||||
{
|
|
||||||
if(cursor) {
|
|
||||||
if(cursor->richSource)
|
|
||||||
free(cursor->richSource);
|
|
||||||
free((char*)(cursor->source));
|
|
||||||
free((char*)(cursor->mask));
|
|
||||||
free(cursor);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* background and foregroud colour have to be set beforehand */
|
|
||||||
void MakeXCursorFromRichCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr cursor)
|
|
||||||
{
|
|
||||||
rfbPixelFormat* format=&rfbScreen->rfbServerFormat;
|
|
||||||
int i,j,w=(cursor->width+7)/8,bpp=format->bitsPerPixel/8,
|
|
||||||
width=cursor->width*bpp;
|
|
||||||
CARD32 background;
|
|
||||||
char *back=(char*)&background;
|
|
||||||
unsigned char bit;
|
|
||||||
|
|
||||||
cursor->source=(unsigned char*)calloc(w,cursor->height);
|
|
||||||
|
|
||||||
if(format->bigEndian)
|
|
||||||
back+=4-bpp;
|
|
||||||
|
|
||||||
background=cursor->backRed<<format->redShift|
|
|
||||||
cursor->backGreen<<format->greenShift|cursor->backBlue<<format->blueShift;
|
|
||||||
|
|
||||||
for(j=0;j<cursor->height;j++)
|
|
||||||
for(i=0,bit=0x80;i<cursor->width;i++,bit=(bit&1)?0x80:bit>>1)
|
|
||||||
if(memcmp(cursor->richSource+j*width+i*bpp,back,bpp))
|
|
||||||
((char*)(cursor->source))[j*w+i/8]|=bit;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MakeRichCursorFromXCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr cursor)
|
|
||||||
{
|
|
||||||
rfbPixelFormat* format=&rfbScreen->rfbServerFormat;
|
|
||||||
int i,j,w=(cursor->width+7)/8,bpp=format->bitsPerPixel/8;
|
|
||||||
CARD32 background,foreground;
|
|
||||||
char *back=(char*)&background,*fore=(char*)&foreground;
|
|
||||||
unsigned char *cp;
|
|
||||||
unsigned char bit;
|
|
||||||
|
|
||||||
cp=cursor->richSource=(unsigned char*)calloc(cursor->width*bpp,cursor->height);
|
|
||||||
|
|
||||||
if(format->bigEndian) {
|
|
||||||
back+=4-bpp;
|
|
||||||
fore+=4-bpp;
|
|
||||||
}
|
|
||||||
|
|
||||||
background=cursor->backRed<<format->redShift|
|
|
||||||
cursor->backGreen<<format->greenShift|cursor->backBlue<<format->blueShift;
|
|
||||||
foreground=cursor->foreRed<<format->redShift|
|
|
||||||
cursor->foreGreen<<format->greenShift|cursor->foreBlue<<format->blueShift;
|
|
||||||
|
|
||||||
for(j=0;j<cursor->height;j++)
|
|
||||||
for(i=0,bit=0x80;i<cursor->height;i++,bit=(bit&1)?0x80:bit>>1,cp+=bpp)
|
|
||||||
if(cursor->source[j*w+i/8]&bit) memcpy(cp,fore,bpp);
|
|
||||||
else memcpy(cp,back,bpp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MakeSoftCursor(rfbClientPtr cl, rfbCursorPtr cursor)
|
|
||||||
{
|
|
||||||
int w = (cursor->width+7)/8;
|
|
||||||
int bpp = cl->format.bitsPerPixel/8;
|
|
||||||
int sbpp= cl->screen->rfbServerFormat.bitsPerPixel/8;
|
|
||||||
unsigned char *cp, *sp, *translatedCursor;
|
|
||||||
int state; /* 0 = transparent, 1 otherwise */
|
|
||||||
CARD8 *counter;
|
|
||||||
unsigned char bit;
|
|
||||||
int i,j;
|
|
||||||
|
|
||||||
if ((!cursor) || (cl->softSource)) {
|
|
||||||
cl->softSourceLen = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!cursor->richSource)
|
|
||||||
MakeRichCursorFromXCursor(cl->screen, cursor);
|
|
||||||
|
|
||||||
sp = malloc(cursor->width*bpp*cursor->height);
|
|
||||||
|
|
||||||
(*cl->translateFn)(cl->translateLookupTable,
|
|
||||||
&(cl->screen->rfbServerFormat),
|
|
||||||
&cl->format, cursor->richSource,
|
|
||||||
sp, cursor->width*sbpp,
|
|
||||||
cursor->width, cursor->height);
|
|
||||||
|
|
||||||
translatedCursor = sp;
|
|
||||||
cp=cl->softSource=(unsigned char*)calloc(cursor->width*(bpp+2),cursor->height);
|
|
||||||
|
|
||||||
state = 0;
|
|
||||||
counter = cp++;
|
|
||||||
*counter = 0;
|
|
||||||
|
|
||||||
for(j=0;j<cursor->height;j++)
|
|
||||||
for(i=0,bit=0x80;i<cursor->width;i++,bit=(bit&1)?0x80:bit>>1)
|
|
||||||
if(cursor->mask[j*w+i/8]&bit) {
|
|
||||||
if (state) {
|
|
||||||
memcpy(cp,sp,bpp);
|
|
||||||
cp += bpp;
|
|
||||||
sp += bpp;
|
|
||||||
(*counter)++;
|
|
||||||
if (*counter == 255) {
|
|
||||||
state = 0;
|
|
||||||
counter = cp++;
|
|
||||||
*counter = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
state = 1;
|
|
||||||
counter = cp++;
|
|
||||||
*counter = 1;
|
|
||||||
memcpy(cp,sp,bpp);
|
|
||||||
cp += bpp;
|
|
||||||
sp += bpp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (!state) {
|
|
||||||
(*counter)++;
|
|
||||||
if (*counter == 255) {
|
|
||||||
state = 1;
|
|
||||||
counter = cp++;
|
|
||||||
*counter = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
state = 0;
|
|
||||||
counter = cp++;
|
|
||||||
*counter = 1;
|
|
||||||
}
|
|
||||||
sp += bpp;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(translatedCursor);
|
|
||||||
cl->softSourceLen = cp - cl->softSource;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* functions to draw/hide cursor directly in the frame buffer */
|
|
||||||
|
|
||||||
void rfbUndrawCursor(rfbScreenInfoPtr s)
|
|
||||||
{
|
|
||||||
rfbCursorPtr c=s->cursor;
|
|
||||||
int j,x1,x2,y1,y2,bpp=s->rfbServerFormat.bitsPerPixel/8,
|
|
||||||
rowstride=s->paddedWidthInBytes;
|
|
||||||
LOCK(s->cursorMutex);
|
|
||||||
if(!s->cursorIsDrawn) {
|
|
||||||
UNLOCK(s->cursorMutex);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* restore what is under the cursor */
|
|
||||||
x1=s->cursorX-c->xhot;
|
|
||||||
x2=x1+c->width;
|
|
||||||
if(x1<0) x1=0;
|
|
||||||
if(x2>=s->width) x2=s->width-1;
|
|
||||||
x2-=x1; if(x2<=0) {
|
|
||||||
UNLOCK(s->cursorMutex);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
y1=s->cursorY-c->yhot;
|
|
||||||
y2=y1+c->height;
|
|
||||||
if(y1<0) y1=0;
|
|
||||||
if(y2>=s->height) y2=s->height-1;
|
|
||||||
y2-=y1; if(y2<=0) {
|
|
||||||
UNLOCK(s->cursorMutex);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get saved data */
|
|
||||||
for(j=0;j<y2;j++)
|
|
||||||
memcpy(s->frameBuffer+(y1+j)*rowstride+x1*bpp,
|
|
||||||
s->underCursorBuffer+j*x2*bpp,
|
|
||||||
x2*bpp);
|
|
||||||
|
|
||||||
rfbMarkRectAsModified(s,x1,y1,x1+x2,y1+y2);
|
|
||||||
s->cursorIsDrawn = FALSE;
|
|
||||||
UNLOCK(s->cursorMutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rfbDrawCursor(rfbScreenInfoPtr s)
|
|
||||||
{
|
|
||||||
rfbCursorPtr c=s->cursor;
|
|
||||||
int i,j,x1,x2,y1,y2,i1,j1,bpp=s->rfbServerFormat.bitsPerPixel/8,
|
|
||||||
rowstride=s->paddedWidthInBytes,
|
|
||||||
bufSize,w;
|
|
||||||
if(!c) return;
|
|
||||||
LOCK(s->cursorMutex);
|
|
||||||
if(s->cursorIsDrawn) {
|
|
||||||
/* is already drawn */
|
|
||||||
UNLOCK(s->cursorMutex);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
bufSize=c->width*c->height*bpp;
|
|
||||||
w=(c->width+7)/8;
|
|
||||||
if(s->underCursorBufferLen<bufSize) {
|
|
||||||
if(s->underCursorBuffer!=NULL)
|
|
||||||
free(s->underCursorBuffer);
|
|
||||||
s->underCursorBuffer=malloc(bufSize);
|
|
||||||
s->underCursorBufferLen=bufSize;
|
|
||||||
}
|
|
||||||
/* save what is under the cursor */
|
|
||||||
i1=j1=0; /* offset in cursor */
|
|
||||||
x1=s->cursorX-c->xhot;
|
|
||||||
x2=x1+c->width;
|
|
||||||
if(x1<0) { i1=-x1; x1=0; }
|
|
||||||
if(x2>=s->width) x2=s->width-1;
|
|
||||||
x2-=x1; if(x2<=0) {
|
|
||||||
UNLOCK(s->cursorMutex);
|
|
||||||
return; /* nothing to do */
|
|
||||||
}
|
|
||||||
y1=s->cursorY-c->yhot;
|
|
||||||
y2=y1+c->height;
|
|
||||||
if(y1<0) { j1=-y1; y1=0; }
|
|
||||||
if(y2>=s->height) y2=s->height-1;
|
|
||||||
y2-=y1; if(y2<=0) {
|
|
||||||
UNLOCK(s->cursorMutex);
|
|
||||||
return; /* nothing to do */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* save data */
|
|
||||||
for(j=0;j<y2;j++)
|
|
||||||
memcpy(s->underCursorBuffer+j*x2*bpp,
|
|
||||||
s->frameBuffer+(y1+j)*rowstride+x1*bpp,
|
|
||||||
x2*bpp);
|
|
||||||
|
|
||||||
if(!c->richSource)
|
|
||||||
MakeRichCursorFromXCursor(s,c);
|
|
||||||
|
|
||||||
/* now the cursor has to be drawn */
|
|
||||||
for(j=0;j<y2;j++)
|
|
||||||
for(i=0;i<x2;i++)
|
|
||||||
if((c->mask[(j+j1)*w+(i+i1)/8]<<((i+i1)&7))&0x80)
|
|
||||||
memcpy(s->frameBuffer+(j+y1)*rowstride+(i+x1)*bpp,
|
|
||||||
c->richSource+(j+j1)*c->width*bpp+(i+i1)*bpp,bpp);
|
|
||||||
|
|
||||||
|
|
||||||
rfbMarkRectAsModified(s,x1,y1,x1+x2,y1+y2);
|
|
||||||
s->cursorIsDrawn = TRUE;
|
|
||||||
UNLOCK(s->cursorMutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* for debugging */
|
|
||||||
|
|
||||||
void rfbPrintXCursor(rfbCursorPtr cursor)
|
|
||||||
{
|
|
||||||
int i,i1,j,w=(cursor->width+7)/8;
|
|
||||||
unsigned char bit;
|
|
||||||
for(j=0;j<cursor->height;j++) {
|
|
||||||
for(i=0,i1=0,bit=0x80;i1<cursor->width;i1++,i+=(bit&1)?1:0,bit=(bit&1)?0x80:bit>>1)
|
|
||||||
if(cursor->source[j*w+i]&bit) putchar('#'); else putchar(' ');
|
|
||||||
putchar(':');
|
|
||||||
for(i=0,i1=0,bit=0x80;i1<cursor->width;i1++,i+=(bit&1)?1:0,bit=(bit&1)?0x80:bit>>1)
|
|
||||||
if(cursor->mask[j*w+i]&bit) putchar('#'); else putchar(' ');
|
|
||||||
putchar('\n');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extern void rfbSetCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr c,Bool freeOld)
|
|
||||||
{
|
|
||||||
LOCK(rfbScreen->cursorMutex);
|
|
||||||
while(rfbScreen->cursorIsDrawn) {
|
|
||||||
UNLOCK(rfbScreen->cursorMutex);
|
|
||||||
rfbUndrawCursor(rfbScreen);
|
|
||||||
LOCK(rfbScreen->cursorMutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(freeOld && rfbScreen->cursor)
|
|
||||||
rfbFreeCursor(rfbScreen->cursor);
|
|
||||||
|
|
||||||
rfbScreen->cursor = c;
|
|
||||||
|
|
||||||
UNLOCK(rfbScreen->cursorMutex);
|
|
||||||
}
|
|
@ -1,39 +0,0 @@
|
|||||||
/*
|
|
||||||
* cutpaste.c - routines to deal with cut & paste buffers / selection.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
|
|
||||||
* Original Xvnc code 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
|
||||||
* USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "rfb.h"
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* rfbSetXCutText sets the cut buffer to be the given string. We also clear
|
|
||||||
* the primary selection. Ideally we'd like to set it to the same thing, but I
|
|
||||||
* can't work out how to do that without some kind of helper X client.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void rfbGotXCutText(rfbScreenInfoPtr rfbScreen, char *str, int len)
|
|
||||||
{
|
|
||||||
rfbSendServerCutText(rfbScreen, str, len);
|
|
||||||
}
|
|
@ -1,442 +0,0 @@
|
|||||||
/*
|
|
||||||
* This is D3DES (V5.09) by Richard Outerbridge with the double and
|
|
||||||
* triple-length support removed for use in VNC. Also the bytebit[] array
|
|
||||||
* has been reversed so that the most significant bit in each byte of the
|
|
||||||
* key is ignored, not the least significant.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* D3DES (V5.09) -
|
|
||||||
*
|
|
||||||
* A portable, public domain, version of the Data Encryption Standard.
|
|
||||||
*
|
|
||||||
* Written with Symantec's THINK (Lightspeed) C by Richard Outerbridge.
|
|
||||||
* Thanks to: Dan Hoey for his excellent Initial and Inverse permutation
|
|
||||||
* code; Jim Gillogly & Phil Karn for the DES key schedule code; Dennis
|
|
||||||
* Ferguson, Eric Young and Dana How for comparing notes; and Ray Lau,
|
|
||||||
* for humouring me on.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge.
|
|
||||||
* (GEnie : OUTER; CIS : [71755,204]) Graven Imagery, 1992.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "d3des.h"
|
|
||||||
|
|
||||||
static void scrunch(unsigned char *, unsigned long *);
|
|
||||||
static void unscrun(unsigned long *, unsigned char *);
|
|
||||||
static void desfunc(unsigned long *, unsigned long *);
|
|
||||||
static void cookey(unsigned long *);
|
|
||||||
|
|
||||||
static unsigned long KnL[32] = { 0L };
|
|
||||||
/*
|
|
||||||
static unsigned long KnR[32] = { 0L };
|
|
||||||
static unsigned long Kn3[32] = { 0L };
|
|
||||||
static unsigned char Df_Key[24] = {
|
|
||||||
0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,
|
|
||||||
0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10,
|
|
||||||
0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67 };
|
|
||||||
*/
|
|
||||||
|
|
||||||
static unsigned short bytebit[8] = {
|
|
||||||
01, 02, 04, 010, 020, 040, 0100, 0200 };
|
|
||||||
|
|
||||||
static unsigned long bigbyte[24] = {
|
|
||||||
0x800000L, 0x400000L, 0x200000L, 0x100000L,
|
|
||||||
0x80000L, 0x40000L, 0x20000L, 0x10000L,
|
|
||||||
0x8000L, 0x4000L, 0x2000L, 0x1000L,
|
|
||||||
0x800L, 0x400L, 0x200L, 0x100L,
|
|
||||||
0x80L, 0x40L, 0x20L, 0x10L,
|
|
||||||
0x8L, 0x4L, 0x2L, 0x1L };
|
|
||||||
|
|
||||||
/* Use the key schedule specified in the Standard (ANSI X3.92-1981). */
|
|
||||||
|
|
||||||
static unsigned char pc1[56] = {
|
|
||||||
56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17,
|
|
||||||
9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35,
|
|
||||||
62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21,
|
|
||||||
13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 };
|
|
||||||
|
|
||||||
static unsigned char totrot[16] = {
|
|
||||||
1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 };
|
|
||||||
|
|
||||||
static unsigned char pc2[48] = {
|
|
||||||
13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9,
|
|
||||||
22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1,
|
|
||||||
40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
|
|
||||||
43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 };
|
|
||||||
|
|
||||||
void deskey(key, edf) /* Thanks to James Gillogly & Phil Karn! */
|
|
||||||
unsigned char *key;
|
|
||||||
int edf;
|
|
||||||
{
|
|
||||||
register int i, j, l, m, n;
|
|
||||||
unsigned char pc1m[56], pcr[56];
|
|
||||||
unsigned long kn[32];
|
|
||||||
|
|
||||||
for ( j = 0; j < 56; j++ ) {
|
|
||||||
l = pc1[j];
|
|
||||||
m = l & 07;
|
|
||||||
pc1m[j] = (key[l >> 3] & bytebit[m]) ? 1 : 0;
|
|
||||||
}
|
|
||||||
for( i = 0; i < 16; i++ ) {
|
|
||||||
if( edf == DE1 ) m = (15 - i) << 1;
|
|
||||||
else m = i << 1;
|
|
||||||
n = m + 1;
|
|
||||||
kn[m] = kn[n] = 0L;
|
|
||||||
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]] ) kn[m] |= bigbyte[j];
|
|
||||||
if( pcr[pc2[j+24]] ) kn[n] |= bigbyte[j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cookey(kn);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void cookey(raw1)
|
|
||||||
register unsigned long *raw1;
|
|
||||||
{
|
|
||||||
register unsigned long *cook, *raw0;
|
|
||||||
unsigned long dough[32];
|
|
||||||
register int i;
|
|
||||||
|
|
||||||
cook = dough;
|
|
||||||
for( i = 0; i < 16; i++, raw1++ ) {
|
|
||||||
raw0 = raw1++;
|
|
||||||
*cook = (*raw0 & 0x00fc0000L) << 6;
|
|
||||||
*cook |= (*raw0 & 0x00000fc0L) << 10;
|
|
||||||
*cook |= (*raw1 & 0x00fc0000L) >> 10;
|
|
||||||
*cook++ |= (*raw1 & 0x00000fc0L) >> 6;
|
|
||||||
*cook = (*raw0 & 0x0003f000L) << 12;
|
|
||||||
*cook |= (*raw0 & 0x0000003fL) << 16;
|
|
||||||
*cook |= (*raw1 & 0x0003f000L) >> 4;
|
|
||||||
*cook++ |= (*raw1 & 0x0000003fL);
|
|
||||||
}
|
|
||||||
usekey(dough);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cpkey(into)
|
|
||||||
register unsigned long *into;
|
|
||||||
{
|
|
||||||
register unsigned long *from, *endp;
|
|
||||||
|
|
||||||
from = KnL, endp = &KnL[32];
|
|
||||||
while( from < endp ) *into++ = *from++;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void usekey(from)
|
|
||||||
register unsigned long *from;
|
|
||||||
{
|
|
||||||
register unsigned long *to, *endp;
|
|
||||||
|
|
||||||
to = KnL, endp = &KnL[32];
|
|
||||||
while( to < endp ) *to++ = *from++;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void des(inblock, outblock)
|
|
||||||
unsigned char *inblock, *outblock;
|
|
||||||
{
|
|
||||||
unsigned long work[2];
|
|
||||||
|
|
||||||
scrunch(inblock, work);
|
|
||||||
desfunc(work, KnL);
|
|
||||||
unscrun(work, outblock);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void scrunch(outof, into)
|
|
||||||
register unsigned char *outof;
|
|
||||||
register unsigned long *into;
|
|
||||||
{
|
|
||||||
*into = (*outof++ & 0xffL) << 24;
|
|
||||||
*into |= (*outof++ & 0xffL) << 16;
|
|
||||||
*into |= (*outof++ & 0xffL) << 8;
|
|
||||||
*into++ |= (*outof++ & 0xffL);
|
|
||||||
*into = (*outof++ & 0xffL) << 24;
|
|
||||||
*into |= (*outof++ & 0xffL) << 16;
|
|
||||||
*into |= (*outof++ & 0xffL) << 8;
|
|
||||||
*into |= (*outof & 0xffL);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void unscrun(outof, into)
|
|
||||||
register unsigned long *outof;
|
|
||||||
register unsigned char *into;
|
|
||||||
{
|
|
||||||
*into++ = (unsigned char)((*outof >> 24) & 0xffL);
|
|
||||||
*into++ = (unsigned char)((*outof >> 16) & 0xffL);
|
|
||||||
*into++ = (unsigned char)((*outof >> 8) & 0xffL);
|
|
||||||
*into++ = (unsigned char)( *outof++ & 0xffL);
|
|
||||||
*into++ = (unsigned char)((*outof >> 24) & 0xffL);
|
|
||||||
*into++ = (unsigned char)((*outof >> 16) & 0xffL);
|
|
||||||
*into++ = (unsigned char)((*outof >> 8) & 0xffL);
|
|
||||||
*into = (unsigned char)( *outof & 0xffL);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned long SP1[64] = {
|
|
||||||
0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L,
|
|
||||||
0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L,
|
|
||||||
0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L,
|
|
||||||
0x01000404L, 0x01010004L, 0x01000000L, 0x00000004L,
|
|
||||||
0x00000404L, 0x01000400L, 0x01000400L, 0x00010400L,
|
|
||||||
0x00010400L, 0x01010000L, 0x01010000L, 0x01000404L,
|
|
||||||
0x00010004L, 0x01000004L, 0x01000004L, 0x00010004L,
|
|
||||||
0x00000000L, 0x00000404L, 0x00010404L, 0x01000000L,
|
|
||||||
0x00010000L, 0x01010404L, 0x00000004L, 0x01010000L,
|
|
||||||
0x01010400L, 0x01000000L, 0x01000000L, 0x00000400L,
|
|
||||||
0x01010004L, 0x00010000L, 0x00010400L, 0x01000004L,
|
|
||||||
0x00000400L, 0x00000004L, 0x01000404L, 0x00010404L,
|
|
||||||
0x01010404L, 0x00010004L, 0x01010000L, 0x01000404L,
|
|
||||||
0x01000004L, 0x00000404L, 0x00010404L, 0x01010400L,
|
|
||||||
0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L,
|
|
||||||
0x00010004L, 0x00010400L, 0x00000000L, 0x01010004L };
|
|
||||||
|
|
||||||
static unsigned long SP2[64] = {
|
|
||||||
0x80108020L, 0x80008000L, 0x00008000L, 0x00108020L,
|
|
||||||
0x00100000L, 0x00000020L, 0x80100020L, 0x80008020L,
|
|
||||||
0x80000020L, 0x80108020L, 0x80108000L, 0x80000000L,
|
|
||||||
0x80008000L, 0x00100000L, 0x00000020L, 0x80100020L,
|
|
||||||
0x00108000L, 0x00100020L, 0x80008020L, 0x00000000L,
|
|
||||||
0x80000000L, 0x00008000L, 0x00108020L, 0x80100000L,
|
|
||||||
0x00100020L, 0x80000020L, 0x00000000L, 0x00108000L,
|
|
||||||
0x00008020L, 0x80108000L, 0x80100000L, 0x00008020L,
|
|
||||||
0x00000000L, 0x00108020L, 0x80100020L, 0x00100000L,
|
|
||||||
0x80008020L, 0x80100000L, 0x80108000L, 0x00008000L,
|
|
||||||
0x80100000L, 0x80008000L, 0x00000020L, 0x80108020L,
|
|
||||||
0x00108020L, 0x00000020L, 0x00008000L, 0x80000000L,
|
|
||||||
0x00008020L, 0x80108000L, 0x00100000L, 0x80000020L,
|
|
||||||
0x00100020L, 0x80008020L, 0x80000020L, 0x00100020L,
|
|
||||||
0x00108000L, 0x00000000L, 0x80008000L, 0x00008020L,
|
|
||||||
0x80000000L, 0x80100020L, 0x80108020L, 0x00108000L };
|
|
||||||
|
|
||||||
static unsigned long SP3[64] = {
|
|
||||||
0x00000208L, 0x08020200L, 0x00000000L, 0x08020008L,
|
|
||||||
0x08000200L, 0x00000000L, 0x00020208L, 0x08000200L,
|
|
||||||
0x00020008L, 0x08000008L, 0x08000008L, 0x00020000L,
|
|
||||||
0x08020208L, 0x00020008L, 0x08020000L, 0x00000208L,
|
|
||||||
0x08000000L, 0x00000008L, 0x08020200L, 0x00000200L,
|
|
||||||
0x00020200L, 0x08020000L, 0x08020008L, 0x00020208L,
|
|
||||||
0x08000208L, 0x00020200L, 0x00020000L, 0x08000208L,
|
|
||||||
0x00000008L, 0x08020208L, 0x00000200L, 0x08000000L,
|
|
||||||
0x08020200L, 0x08000000L, 0x00020008L, 0x00000208L,
|
|
||||||
0x00020000L, 0x08020200L, 0x08000200L, 0x00000000L,
|
|
||||||
0x00000200L, 0x00020008L, 0x08020208L, 0x08000200L,
|
|
||||||
0x08000008L, 0x00000200L, 0x00000000L, 0x08020008L,
|
|
||||||
0x08000208L, 0x00020000L, 0x08000000L, 0x08020208L,
|
|
||||||
0x00000008L, 0x00020208L, 0x00020200L, 0x08000008L,
|
|
||||||
0x08020000L, 0x08000208L, 0x00000208L, 0x08020000L,
|
|
||||||
0x00020208L, 0x00000008L, 0x08020008L, 0x00020200L };
|
|
||||||
|
|
||||||
static unsigned long SP4[64] = {
|
|
||||||
0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
|
|
||||||
0x00802080L, 0x00800081L, 0x00800001L, 0x00002001L,
|
|
||||||
0x00000000L, 0x00802000L, 0x00802000L, 0x00802081L,
|
|
||||||
0x00000081L, 0x00000000L, 0x00800080L, 0x00800001L,
|
|
||||||
0x00000001L, 0x00002000L, 0x00800000L, 0x00802001L,
|
|
||||||
0x00000080L, 0x00800000L, 0x00002001L, 0x00002080L,
|
|
||||||
0x00800081L, 0x00000001L, 0x00002080L, 0x00800080L,
|
|
||||||
0x00002000L, 0x00802080L, 0x00802081L, 0x00000081L,
|
|
||||||
0x00800080L, 0x00800001L, 0x00802000L, 0x00802081L,
|
|
||||||
0x00000081L, 0x00000000L, 0x00000000L, 0x00802000L,
|
|
||||||
0x00002080L, 0x00800080L, 0x00800081L, 0x00000001L,
|
|
||||||
0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
|
|
||||||
0x00802081L, 0x00000081L, 0x00000001L, 0x00002000L,
|
|
||||||
0x00800001L, 0x00002001L, 0x00802080L, 0x00800081L,
|
|
||||||
0x00002001L, 0x00002080L, 0x00800000L, 0x00802001L,
|
|
||||||
0x00000080L, 0x00800000L, 0x00002000L, 0x00802080L };
|
|
||||||
|
|
||||||
static unsigned long SP5[64] = {
|
|
||||||
0x00000100L, 0x02080100L, 0x02080000L, 0x42000100L,
|
|
||||||
0x00080000L, 0x00000100L, 0x40000000L, 0x02080000L,
|
|
||||||
0x40080100L, 0x00080000L, 0x02000100L, 0x40080100L,
|
|
||||||
0x42000100L, 0x42080000L, 0x00080100L, 0x40000000L,
|
|
||||||
0x02000000L, 0x40080000L, 0x40080000L, 0x00000000L,
|
|
||||||
0x40000100L, 0x42080100L, 0x42080100L, 0x02000100L,
|
|
||||||
0x42080000L, 0x40000100L, 0x00000000L, 0x42000000L,
|
|
||||||
0x02080100L, 0x02000000L, 0x42000000L, 0x00080100L,
|
|
||||||
0x00080000L, 0x42000100L, 0x00000100L, 0x02000000L,
|
|
||||||
0x40000000L, 0x02080000L, 0x42000100L, 0x40080100L,
|
|
||||||
0x02000100L, 0x40000000L, 0x42080000L, 0x02080100L,
|
|
||||||
0x40080100L, 0x00000100L, 0x02000000L, 0x42080000L,
|
|
||||||
0x42080100L, 0x00080100L, 0x42000000L, 0x42080100L,
|
|
||||||
0x02080000L, 0x00000000L, 0x40080000L, 0x42000000L,
|
|
||||||
0x00080100L, 0x02000100L, 0x40000100L, 0x00080000L,
|
|
||||||
0x00000000L, 0x40080000L, 0x02080100L, 0x40000100L };
|
|
||||||
|
|
||||||
static unsigned long SP6[64] = {
|
|
||||||
0x20000010L, 0x20400000L, 0x00004000L, 0x20404010L,
|
|
||||||
0x20400000L, 0x00000010L, 0x20404010L, 0x00400000L,
|
|
||||||
0x20004000L, 0x00404010L, 0x00400000L, 0x20000010L,
|
|
||||||
0x00400010L, 0x20004000L, 0x20000000L, 0x00004010L,
|
|
||||||
0x00000000L, 0x00400010L, 0x20004010L, 0x00004000L,
|
|
||||||
0x00404000L, 0x20004010L, 0x00000010L, 0x20400010L,
|
|
||||||
0x20400010L, 0x00000000L, 0x00404010L, 0x20404000L,
|
|
||||||
0x00004010L, 0x00404000L, 0x20404000L, 0x20000000L,
|
|
||||||
0x20004000L, 0x00000010L, 0x20400010L, 0x00404000L,
|
|
||||||
0x20404010L, 0x00400000L, 0x00004010L, 0x20000010L,
|
|
||||||
0x00400000L, 0x20004000L, 0x20000000L, 0x00004010L,
|
|
||||||
0x20000010L, 0x20404010L, 0x00404000L, 0x20400000L,
|
|
||||||
0x00404010L, 0x20404000L, 0x00000000L, 0x20400010L,
|
|
||||||
0x00000010L, 0x00004000L, 0x20400000L, 0x00404010L,
|
|
||||||
0x00004000L, 0x00400010L, 0x20004010L, 0x00000000L,
|
|
||||||
0x20404000L, 0x20000000L, 0x00400010L, 0x20004010L };
|
|
||||||
|
|
||||||
static unsigned long SP7[64] = {
|
|
||||||
0x00200000L, 0x04200002L, 0x04000802L, 0x00000000L,
|
|
||||||
0x00000800L, 0x04000802L, 0x00200802L, 0x04200800L,
|
|
||||||
0x04200802L, 0x00200000L, 0x00000000L, 0x04000002L,
|
|
||||||
0x00000002L, 0x04000000L, 0x04200002L, 0x00000802L,
|
|
||||||
0x04000800L, 0x00200802L, 0x00200002L, 0x04000800L,
|
|
||||||
0x04000002L, 0x04200000L, 0x04200800L, 0x00200002L,
|
|
||||||
0x04200000L, 0x00000800L, 0x00000802L, 0x04200802L,
|
|
||||||
0x00200800L, 0x00000002L, 0x04000000L, 0x00200800L,
|
|
||||||
0x04000000L, 0x00200800L, 0x00200000L, 0x04000802L,
|
|
||||||
0x04000802L, 0x04200002L, 0x04200002L, 0x00000002L,
|
|
||||||
0x00200002L, 0x04000000L, 0x04000800L, 0x00200000L,
|
|
||||||
0x04200800L, 0x00000802L, 0x00200802L, 0x04200800L,
|
|
||||||
0x00000802L, 0x04000002L, 0x04200802L, 0x04200000L,
|
|
||||||
0x00200800L, 0x00000000L, 0x00000002L, 0x04200802L,
|
|
||||||
0x00000000L, 0x00200802L, 0x04200000L, 0x00000800L,
|
|
||||||
0x04000002L, 0x04000800L, 0x00000800L, 0x00200002L };
|
|
||||||
|
|
||||||
static unsigned long SP8[64] = {
|
|
||||||
0x10001040L, 0x00001000L, 0x00040000L, 0x10041040L,
|
|
||||||
0x10000000L, 0x10001040L, 0x00000040L, 0x10000000L,
|
|
||||||
0x00040040L, 0x10040000L, 0x10041040L, 0x00041000L,
|
|
||||||
0x10041000L, 0x00041040L, 0x00001000L, 0x00000040L,
|
|
||||||
0x10040000L, 0x10000040L, 0x10001000L, 0x00001040L,
|
|
||||||
0x00041000L, 0x00040040L, 0x10040040L, 0x10041000L,
|
|
||||||
0x00001040L, 0x00000000L, 0x00000000L, 0x10040040L,
|
|
||||||
0x10000040L, 0x10001000L, 0x00041040L, 0x00040000L,
|
|
||||||
0x00041040L, 0x00040000L, 0x10041000L, 0x00001000L,
|
|
||||||
0x00000040L, 0x10040040L, 0x00001000L, 0x00041040L,
|
|
||||||
0x10001000L, 0x00000040L, 0x10000040L, 0x10040000L,
|
|
||||||
0x10040040L, 0x10000000L, 0x00040000L, 0x10001040L,
|
|
||||||
0x00000000L, 0x10041040L, 0x00040040L, 0x10000040L,
|
|
||||||
0x10040000L, 0x10001000L, 0x10001040L, 0x00000000L,
|
|
||||||
0x10041040L, 0x00041000L, 0x00041000L, 0x00001040L,
|
|
||||||
0x00001040L, 0x00040040L, 0x10000000L, 0x10041000L };
|
|
||||||
|
|
||||||
static void desfunc(block, keys)
|
|
||||||
register unsigned long *block, *keys;
|
|
||||||
{
|
|
||||||
register unsigned long fval, work, right, leftt;
|
|
||||||
register int round;
|
|
||||||
|
|
||||||
leftt = block[0];
|
|
||||||
right = block[1];
|
|
||||||
work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL;
|
|
||||||
right ^= work;
|
|
||||||
leftt ^= (work << 4);
|
|
||||||
work = ((leftt >> 16) ^ right) & 0x0000ffffL;
|
|
||||||
right ^= work;
|
|
||||||
leftt ^= (work << 16);
|
|
||||||
work = ((right >> 2) ^ leftt) & 0x33333333L;
|
|
||||||
leftt ^= work;
|
|
||||||
right ^= (work << 2);
|
|
||||||
work = ((right >> 8) ^ leftt) & 0x00ff00ffL;
|
|
||||||
leftt ^= work;
|
|
||||||
right ^= (work << 8);
|
|
||||||
right = ((right << 1) | ((right >> 31) & 1L)) & 0xffffffffL;
|
|
||||||
work = (leftt ^ right) & 0xaaaaaaaaL;
|
|
||||||
leftt ^= work;
|
|
||||||
right ^= work;
|
|
||||||
leftt = ((leftt << 1) | ((leftt >> 31) & 1L)) & 0xffffffffL;
|
|
||||||
|
|
||||||
for( round = 0; round < 8; round++ ) {
|
|
||||||
work = (right << 28) | (right >> 4);
|
|
||||||
work ^= *keys++;
|
|
||||||
fval = SP7[ work & 0x3fL];
|
|
||||||
fval |= SP5[(work >> 8) & 0x3fL];
|
|
||||||
fval |= SP3[(work >> 16) & 0x3fL];
|
|
||||||
fval |= SP1[(work >> 24) & 0x3fL];
|
|
||||||
work = right ^ *keys++;
|
|
||||||
fval |= SP8[ work & 0x3fL];
|
|
||||||
fval |= SP6[(work >> 8) & 0x3fL];
|
|
||||||
fval |= SP4[(work >> 16) & 0x3fL];
|
|
||||||
fval |= SP2[(work >> 24) & 0x3fL];
|
|
||||||
leftt ^= fval;
|
|
||||||
work = (leftt << 28) | (leftt >> 4);
|
|
||||||
work ^= *keys++;
|
|
||||||
fval = SP7[ work & 0x3fL];
|
|
||||||
fval |= SP5[(work >> 8) & 0x3fL];
|
|
||||||
fval |= SP3[(work >> 16) & 0x3fL];
|
|
||||||
fval |= SP1[(work >> 24) & 0x3fL];
|
|
||||||
work = leftt ^ *keys++;
|
|
||||||
fval |= SP8[ work & 0x3fL];
|
|
||||||
fval |= SP6[(work >> 8) & 0x3fL];
|
|
||||||
fval |= SP4[(work >> 16) & 0x3fL];
|
|
||||||
fval |= SP2[(work >> 24) & 0x3fL];
|
|
||||||
right ^= fval;
|
|
||||||
}
|
|
||||||
|
|
||||||
right = (right << 31) | (right >> 1);
|
|
||||||
work = (leftt ^ right) & 0xaaaaaaaaL;
|
|
||||||
leftt ^= work;
|
|
||||||
right ^= work;
|
|
||||||
leftt = (leftt << 31) | (leftt >> 1);
|
|
||||||
work = ((leftt >> 8) ^ right) & 0x00ff00ffL;
|
|
||||||
right ^= work;
|
|
||||||
leftt ^= (work << 8);
|
|
||||||
work = ((leftt >> 2) ^ right) & 0x33333333L;
|
|
||||||
right ^= work;
|
|
||||||
leftt ^= (work << 2);
|
|
||||||
work = ((right >> 16) ^ leftt) & 0x0000ffffL;
|
|
||||||
leftt ^= work;
|
|
||||||
right ^= (work << 16);
|
|
||||||
work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL;
|
|
||||||
leftt ^= work;
|
|
||||||
right ^= (work << 4);
|
|
||||||
*block++ = right;
|
|
||||||
*block = leftt;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Validation sets:
|
|
||||||
*
|
|
||||||
* Single-length key, single-length plaintext -
|
|
||||||
* Key : 0123 4567 89ab cdef
|
|
||||||
* Plain : 0123 4567 89ab cde7
|
|
||||||
* Cipher : c957 4425 6a5e d31d
|
|
||||||
*
|
|
||||||
* Double-length key, single-length plaintext -
|
|
||||||
* Key : 0123 4567 89ab cdef fedc ba98 7654 3210
|
|
||||||
* Plain : 0123 4567 89ab cde7
|
|
||||||
* Cipher : 7f1d 0a77 826b 8aff
|
|
||||||
*
|
|
||||||
* Double-length key, double-length plaintext -
|
|
||||||
* Key : 0123 4567 89ab cdef fedc ba98 7654 3210
|
|
||||||
* Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff
|
|
||||||
* Cipher : 27a0 8440 406a df60 278f 47cf 42d6 15d7
|
|
||||||
*
|
|
||||||
* Triple-length key, single-length plaintext -
|
|
||||||
* Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567
|
|
||||||
* Plain : 0123 4567 89ab cde7
|
|
||||||
* Cipher : de0b 7c06 ae5e 0ed5
|
|
||||||
*
|
|
||||||
* Triple-length key, double-length plaintext -
|
|
||||||
* Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567
|
|
||||||
* Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff
|
|
||||||
* Cipher : ad0d 1b30 ac17 cf07 0ed1 1c63 81e4 4de5
|
|
||||||
*
|
|
||||||
* d3des V5.0a rwo 9208.07 18:44 Graven Imagery
|
|
||||||
**********************************************************************/
|
|
@ -1,56 +0,0 @@
|
|||||||
#ifndef D3DES_H
|
|
||||||
#define D3DES_H
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This is D3DES (V5.09) by Richard Outerbridge with the double and
|
|
||||||
* triple-length support removed for use in VNC.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* d3des.h -
|
|
||||||
*
|
|
||||||
* Headers and defines for d3des.c
|
|
||||||
* Graven Imagery, 1992.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge
|
|
||||||
* (GEnie : OUTER; CIS : [71755,204])
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define EN0 0 /* MODE == encrypt */
|
|
||||||
#define DE1 1 /* MODE == decrypt */
|
|
||||||
|
|
||||||
extern void deskey(unsigned char *, int);
|
|
||||||
/* hexkey[8] MODE
|
|
||||||
* Sets the internal key register according to the hexadecimal
|
|
||||||
* key contained in the 8 bytes of hexkey, according to the DES,
|
|
||||||
* for encryption or decryption according to MODE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
extern void usekey(unsigned long *);
|
|
||||||
/* cookedkey[32]
|
|
||||||
* Loads the internal key register with the data in cookedkey.
|
|
||||||
*/
|
|
||||||
|
|
||||||
extern void cpkey(unsigned long *);
|
|
||||||
/* cookedkey[32]
|
|
||||||
* Copies the contents of the internal key register into the storage
|
|
||||||
* located at &cookedkey[0].
|
|
||||||
*/
|
|
||||||
|
|
||||||
extern void des(unsigned char *, unsigned char *);
|
|
||||||
/* from[8] to[8]
|
|
||||||
* Encrypts/Decrypts (according to the key currently loaded in the
|
|
||||||
* internal key register) one block of eight bytes at address 'from'
|
|
||||||
* into the block at address 'to'. They can be the same.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* d3des.h V5.09 rwo 9208.04 15:06 Graven Imagery
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,261 +0,0 @@
|
|||||||
unsigned char default8x16FontData[4096+1]={
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x7e,0x81,0xa5,0x81,0x81,0xbd,0x99,0x81,0x81,0x7e,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x7e,0xff,0xdb,0xff,0xff,0xc3,0xe7,0xff,0xff,0x7e,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x6c,0xfe,0xfe,0xfe,0xfe,0x7c,0x38,0x10,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x10,0x38,0x7c,0xfe,0x7c,0x38,0x10,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x18,0x3c,0x3c,0xe7,0xe7,0xe7,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x18,0x3c,0x7e,0xff,0xff,0x7e,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x3c,0x3c,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0xff,0xff,0xff,0xff,0xff,0xff,0xe7,0xc3,0xc3,0xe7,0xff,0xff,0xff,0xff,0xff,0xff,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x3c,0x66,0x42,0x42,0x66,0x3c,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0xff,0xff,0xff,0xff,0xff,0xc3,0x99,0xbd,0xbd,0x99,0xc3,0xff,0xff,0xff,0xff,0xff,
|
|
||||||
0x00,0x00,0x1e,0x0e,0x1a,0x32,0x78,0xcc,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x3c,0x66,0x66,0x66,0x66,0x3c,0x18,0x7e,0x18,0x18,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x3f,0x33,0x3f,0x30,0x30,0x30,0x30,0x70,0xf0,0xe0,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x7f,0x63,0x7f,0x63,0x63,0x63,0x63,0x67,0xe7,0xe6,0xc0,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x18,0x18,0xdb,0x3c,0xe7,0x3c,0xdb,0x18,0x18,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfe,0xf8,0xf0,0xe0,0xc0,0x80,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x02,0x06,0x0e,0x1e,0x3e,0xfe,0x3e,0x1e,0x0e,0x06,0x02,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x18,0x3c,0x7e,0x18,0x18,0x18,0x7e,0x3c,0x18,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x66,0x66,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x7f,0xdb,0xdb,0xdb,0x7b,0x1b,0x1b,0x1b,0x1b,0x1b,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x7c,0xc6,0x60,0x38,0x6c,0xc6,0xc6,0x6c,0x38,0x0c,0xc6,0x7c,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xfe,0xfe,0xfe,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x18,0x3c,0x7e,0x18,0x18,0x18,0x7e,0x3c,0x18,0x7e,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x18,0x3c,0x7e,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7e,0x3c,0x18,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x18,0x0c,0xfe,0x0c,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x30,0x60,0xfe,0x60,0x30,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xc0,0xc0,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x24,0x66,0xff,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x10,0x38,0x38,0x7c,0x7c,0xfe,0xfe,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0xfe,0xfe,0x7c,0x7c,0x38,0x38,0x10,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x18,0x3c,0x3c,0x3c,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x66,0x66,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x6c,0x6c,0xfe,0x6c,0x6c,0x6c,0xfe,0x6c,0x6c,0x00,0x00,0x00,0x00,
|
|
||||||
0x18,0x18,0x7c,0xc6,0xc2,0xc0,0x7c,0x06,0x06,0x86,0xc6,0x7c,0x18,0x18,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0xc2,0xc6,0x0c,0x18,0x30,0x60,0xc6,0x86,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x38,0x6c,0x6c,0x38,0x76,0xdc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x30,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x0c,0x18,0x30,0x30,0x30,0x30,0x30,0x30,0x18,0x0c,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x30,0x18,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x18,0x30,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x66,0x3c,0xff,0x3c,0x66,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7e,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x02,0x06,0x0c,0x18,0x30,0x60,0xc0,0x80,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x7c,0xc6,0xc6,0xce,0xde,0xf6,0xe6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x18,0x38,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x7e,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x7c,0xc6,0x06,0x0c,0x18,0x30,0x60,0xc0,0xc6,0xfe,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x7c,0xc6,0x06,0x06,0x3c,0x06,0x06,0x06,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x0c,0x1c,0x3c,0x6c,0xcc,0xfe,0x0c,0x0c,0x0c,0x1e,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0xfe,0xc0,0xc0,0xc0,0xfc,0x06,0x06,0x06,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x38,0x60,0xc0,0xc0,0xfc,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0xfe,0xc6,0x06,0x06,0x0c,0x18,0x30,0x30,0x30,0x30,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x7c,0xc6,0xc6,0xc6,0x7c,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x7c,0xc6,0xc6,0xc6,0x7e,0x06,0x06,0x06,0x0c,0x78,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x30,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x06,0x0c,0x18,0x30,0x60,0x30,0x18,0x0c,0x06,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x7e,0x00,0x00,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x60,0x30,0x18,0x0c,0x06,0x0c,0x18,0x30,0x60,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x7c,0xc6,0xc6,0x0c,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xde,0xde,0xde,0xdc,0xc0,0x7c,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x10,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0xfc,0x66,0x66,0x66,0x7c,0x66,0x66,0x66,0x66,0xfc,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x3c,0x66,0xc2,0xc0,0xc0,0xc0,0xc0,0xc2,0x66,0x3c,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0xf8,0x6c,0x66,0x66,0x66,0x66,0x66,0x66,0x6c,0xf8,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0xfe,0x66,0x62,0x68,0x78,0x68,0x60,0x62,0x66,0xfe,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0xfe,0x66,0x62,0x68,0x78,0x68,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x3c,0x66,0xc2,0xc0,0xc0,0xde,0xc6,0xc6,0x66,0x3a,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x3c,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x1e,0x0c,0x0c,0x0c,0x0c,0x0c,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0xe6,0x66,0x66,0x6c,0x78,0x78,0x6c,0x66,0x66,0xe6,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0xf0,0x60,0x60,0x60,0x60,0x60,0x60,0x62,0x66,0xfe,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0xc3,0xe7,0xff,0xff,0xdb,0xc3,0xc3,0xc3,0xc3,0xc3,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0xc6,0xe6,0xf6,0xfe,0xde,0xce,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0xfc,0x66,0x66,0x66,0x7c,0x60,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xd6,0xde,0x7c,0x0c,0x0e,0x00,0x00,
|
|
||||||
0x00,0x00,0xfc,0x66,0x66,0x66,0x7c,0x6c,0x66,0x66,0x66,0xe6,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x7c,0xc6,0xc6,0x60,0x38,0x0c,0x06,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0xff,0xdb,0x99,0x18,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0x66,0x3c,0x18,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0xc3,0xc3,0xc3,0xc3,0xc3,0xdb,0xdb,0xff,0x66,0x66,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0xc3,0xc3,0x66,0x3c,0x18,0x18,0x3c,0x66,0xc3,0xc3,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0xc3,0xc3,0xc3,0x66,0x3c,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0xff,0xc3,0x86,0x0c,0x18,0x30,0x60,0xc1,0xc3,0xff,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x3c,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3c,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x80,0xc0,0xe0,0x70,0x38,0x1c,0x0e,0x06,0x02,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x3c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x3c,0x00,0x00,0x00,0x00,
|
|
||||||
0x10,0x38,0x6c,0xc6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,
|
|
||||||
0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0xe0,0x60,0x60,0x78,0x6c,0x66,0x66,0x66,0x66,0x7c,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0xc0,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x1c,0x0c,0x0c,0x3c,0x6c,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x38,0x6c,0x64,0x60,0xf0,0x60,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x76,0xcc,0xcc,0xcc,0xcc,0xcc,0x7c,0x0c,0xcc,0x78,0x00,
|
|
||||||
0x00,0x00,0xe0,0x60,0x60,0x6c,0x76,0x66,0x66,0x66,0x66,0xe6,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x18,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x06,0x06,0x00,0x0e,0x06,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3c,0x00,
|
|
||||||
0x00,0x00,0xe0,0x60,0x60,0x66,0x6c,0x78,0x78,0x6c,0x66,0xe6,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0xe6,0xff,0xdb,0xdb,0xdb,0xdb,0xdb,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0xdc,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0xdc,0x66,0x66,0x66,0x66,0x66,0x7c,0x60,0x60,0xf0,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x76,0xcc,0xcc,0xcc,0xcc,0xcc,0x7c,0x0c,0x0c,0x1e,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0xdc,0x76,0x66,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0x60,0x38,0x0c,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x10,0x30,0x30,0xfc,0x30,0x30,0x30,0x30,0x36,0x1c,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0xc3,0xc3,0xc3,0xc3,0x66,0x3c,0x18,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0xc3,0xc3,0xc3,0xdb,0xdb,0xff,0x66,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0xc3,0x66,0x3c,0x18,0x3c,0x66,0xc3,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7e,0x06,0x0c,0xf8,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0xfe,0xcc,0x18,0x30,0x60,0xc6,0xfe,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x0e,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0e,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x70,0x18,0x18,0x18,0x0e,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x76,0xdc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x10,0x38,0x6c,0xc6,0xc6,0xc6,0xfe,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x3c,0x66,0xc2,0xc0,0xc0,0xc0,0xc2,0x66,0x3c,0x0c,0x06,0x7c,0x00,0x00,
|
|
||||||
0x00,0x00,0xcc,0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x0c,0x18,0x30,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x10,0x38,0x6c,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0xcc,0x00,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x60,0x30,0x18,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x38,0x6c,0x38,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x3c,0x66,0x60,0x60,0x66,0x3c,0x0c,0x06,0x3c,0x00,0x00,0x00,
|
|
||||||
0x00,0x10,0x38,0x6c,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0xc6,0x00,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x60,0x30,0x18,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x66,0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x18,0x3c,0x66,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x60,0x30,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0xc6,0x00,0x10,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00,
|
|
||||||
0x38,0x6c,0x38,0x00,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00,
|
|
||||||
0x18,0x30,0x60,0x00,0xfe,0x66,0x60,0x7c,0x60,0x60,0x66,0xfe,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x6e,0x3b,0x1b,0x7e,0xd8,0xdc,0x77,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x3e,0x6c,0xcc,0xcc,0xfe,0xcc,0xcc,0xcc,0xcc,0xce,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x10,0x38,0x6c,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0xc6,0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x60,0x30,0x18,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x30,0x78,0xcc,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x60,0x30,0x18,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0xc6,0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7e,0x06,0x0c,0x78,0x00,
|
|
||||||
0x00,0xc6,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0xc6,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x18,0x18,0x7e,0xc3,0xc0,0xc0,0xc0,0xc3,0x7e,0x18,0x18,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x38,0x6c,0x64,0x60,0xf0,0x60,0x60,0x60,0x60,0xe6,0xfc,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0xc3,0x66,0x3c,0x18,0xff,0x18,0xff,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0xfc,0x66,0x66,0x7c,0x62,0x66,0x6f,0x66,0x66,0x66,0xf3,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x0e,0x1b,0x18,0x18,0x18,0x7e,0x18,0x18,0x18,0x18,0x18,0xd8,0x70,0x00,0x00,
|
|
||||||
0x00,0x18,0x30,0x60,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x0c,0x18,0x30,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x18,0x30,0x60,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x18,0x30,0x60,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x76,0xdc,0x00,0xdc,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00,
|
|
||||||
0x76,0xdc,0x00,0xc6,0xe6,0xf6,0xfe,0xde,0xce,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x3c,0x6c,0x6c,0x3e,0x00,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x38,0x6c,0x6c,0x38,0x00,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x30,0x30,0x00,0x30,0x30,0x60,0xc0,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0xc0,0xc0,0xc2,0xc6,0xcc,0x18,0x30,0x60,0xce,0x9b,0x06,0x0c,0x1f,0x00,0x00,
|
|
||||||
0x00,0xc0,0xc0,0xc2,0xc6,0xcc,0x18,0x30,0x66,0xce,0x96,0x3e,0x06,0x06,0x00,0x00,
|
|
||||||
0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x18,0x3c,0x3c,0x3c,0x18,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x36,0x6c,0xd8,0x6c,0x36,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0xd8,0x6c,0x36,0x6c,0xd8,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,
|
|
||||||
0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,
|
|
||||||
0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,
|
|
||||||
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
|
||||||
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
|
||||||
0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
|
||||||
0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xf6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0xf8,0x18,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
|
||||||
0x36,0x36,0x36,0x36,0x36,0xf6,0x06,0xf6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
|
||||||
0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0xfe,0x06,0xf6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
|
||||||
0x36,0x36,0x36,0x36,0x36,0xf6,0x06,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
|
||||||
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
|
||||||
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
|
||||||
0x18,0x18,0x18,0x18,0x18,0x1f,0x18,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
|
||||||
0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
|
||||||
0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x3f,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
|
||||||
0x36,0x36,0x36,0x36,0x36,0xf7,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xf7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
|
||||||
0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x36,0x36,0x36,0x36,0x36,0xf7,0x00,0xf7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
|
||||||
0x18,0x18,0x18,0x18,0x18,0xff,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
|
||||||
0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x18,0x18,0x18,0x18,0x18,0x1f,0x18,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x1f,0x18,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
|
||||||
0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xff,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
|
||||||
0x18,0x18,0x18,0x18,0x18,0xff,0x18,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
|
||||||
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
|
||||||
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
|
||||||
0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,
|
|
||||||
0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,
|
|
||||||
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x76,0xdc,0xd8,0xd8,0xd8,0xdc,0x76,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x78,0xcc,0xcc,0xcc,0xd8,0xcc,0xc6,0xc6,0xc6,0xcc,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0xfe,0xc6,0xc6,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0xfe,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0xfe,0xc6,0x60,0x30,0x18,0x30,0x60,0xc6,0xfe,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x7e,0xd8,0xd8,0xd8,0xd8,0xd8,0x70,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x7c,0x60,0x60,0xc0,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x76,0xdc,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x7e,0x18,0x3c,0x66,0x66,0x66,0x3c,0x18,0x7e,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0x6c,0x38,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x38,0x6c,0xc6,0xc6,0xc6,0x6c,0x6c,0x6c,0x6c,0xee,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x1e,0x30,0x18,0x0c,0x3e,0x66,0x66,0x66,0x66,0x3c,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x7e,0xdb,0xdb,0xdb,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x03,0x06,0x7e,0xdb,0xdb,0xf3,0x7e,0x60,0xc0,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x1c,0x30,0x60,0x60,0x7c,0x60,0x60,0x60,0x30,0x1c,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0xfe,0x00,0x00,0xfe,0x00,0x00,0xfe,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x18,0x18,0x7e,0x18,0x18,0x00,0x00,0xff,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x30,0x18,0x0c,0x06,0x0c,0x18,0x30,0x00,0x7e,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x0c,0x18,0x30,0x60,0x30,0x18,0x0c,0x00,0x7e,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x0e,0x1b,0x1b,0x1b,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
|
||||||
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xd8,0xd8,0xd8,0x70,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x7e,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x76,0xdc,0x00,0x76,0xdc,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x38,0x6c,0x6c,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x0f,0x0c,0x0c,0x0c,0x0c,0x0c,0xec,0x6c,0x6c,0x3c,0x1c,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0xd8,0x6c,0x6c,0x6c,0x6c,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x70,0xd8,0x30,0x60,0xc8,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
};
|
|
||||||
int default8x16FontMetaData[256*5+1]={
|
|
||||||
0,8,16,0,0,16,8,16,0,0,32,8,16,0,0,48,8,16,0,0,64,8,16,0,0,80,8,16,0,0,96,8,16,0,0,112,8,16,0,0,128,8,16,0,0,144,8,16,0,0,160,8,16,0,0,176,8,16,0,0,192,8,16,0,0,208,8,16,0,0,224,8,16,0,0,240,8,16,0,0,256,8,16,0,0,272,8,16,0,0,288,8,16,0,0,304,8,16,0,0,320,8,16,0,0,336,8,16,0,0,352,8,16,0,0,368,8,16,0,0,384,8,16,0,0,400,8,16,0,0,416,8,16,0,0,432,8,16,0,0,448,8,16,0,0,464,8,16,0,0,480,8,16,0,0,496,8,16,0,0,512,8,16,0,0,528,8,16,0,0,544,8,16,0,0,560,8,16,0,0,576,8,16,0,0,592,8,16,0,0,608,8,16,0,0,624,8,16,0,0,640,8,16,0,0,656,8,16,0,0,672,8,16,0,0,688,8,16,0,0,704,8,16,0,0,720,8,16,0,0,736,8,16,0,0,752,8,16,0,0,768,8,16,0,0,784,8,16,0,0,800,8,16,0,0,816,8,16,0,0,832,8,16,0,0,848,8,16,0,0,864,8,16,0,0,880,8,16,0,0,896,8,16,0,0,912,8,16,0,0,928,8,16,0,0,944,8,16,0,0,960,8,16,0,0,976,8,16,0,0,992,8,16,0,0,1008,8,16,0,0,1024,8,16,0,0,1040,8,16,0,0,1056,8,16,0,0,1072,8,16,0,0,1088,8,16,0,0,1104,8,16,0,0,1120,8,16,0,0,1136,8,16,0,0,1152,8,16,0,0,1168,8,16,0,0,1184,8,16,0,0,1200,8,16,0,0,1216,8,16,0,0,1232,8,16,0,0,1248,8,16,0,0,1264,8,16,0,0,1280,8,16,0,0,1296,8,16,0,0,1312,8,16,0,0,1328,8,16,0,0,1344,8,16,0,0,1360,8,16,0,0,1376,8,16,0,0,1392,8,16,0,0,1408,8,16,0,0,1424,8,16,0,0,1440,8,16,0,0,1456,8,16,0,0,1472,8,16,0,0,1488,8,16,0,0,1504,8,16,0,0,1520,8,16,0,0,1536,8,16,0,0,1552,8,16,0,0,1568,8,16,0,0,1584,8,16,0,0,1600,8,16,0,0,1616,8,16,0,0,1632,8,16,0,0,1648,8,16,0,0,1664,8,16,0,0,1680,8,16,0,0,1696,8,16,0,0,1712,8,16,0,0,1728,8,16,0,0,1744,8,16,0,0,1760,8,16,0,0,1776,8,16,0,0,1792,8,16,0,0,1808,8,16,0,0,1824,8,16,0,0,1840,8,16,0,0,1856,8,16,0,0,1872,8,16,0,0,1888,8,16,0,0,1904,8,16,0,0,1920,8,16,0,0,1936,8,16,0,0,1952,8,16,0,0,1968,8,16,0,0,1984,8,16,0,0,2000,8,16,0,0,2016,8,16,0,0,2032,8,16,0,0,2048,8,16,0,0,2064,8,16,0,0,2080,8,16,0,0,2096,8,16,0,0,2112,8,16,0,0,2128,8,16,0,0,2144,8,16,0,0,2160,8,16,0,0,2176,8,16,0,0,2192,8,16,0,0,2208,8,16,0,0,2224,8,16,0,0,2240,8,16,0,0,2256,8,16,0,0,2272,8,16,0,0,2288,8,16,0,0,2304,8,16,0,0,2320,8,16,0,0,2336,8,16,0,0,2352,8,16,0,0,2368,8,16,0,0,2384,8,16,0,0,2400,8,16,0,0,2416,8,16,0,0,2432,8,16,0,0,2448,8,16,0,0,2464,8,16,0,0,2480,8,16,0,0,2496,8,16,0,0,2512,8,16,0,0,2528,8,16,0,0,2544,8,16,0,0,2560,8,16,0,0,2576,8,16,0,0,2592,8,16,0,0,2608,8,16,0,0,2624,8,16,0,0,2640,8,16,0,0,2656,8,16,0,0,2672,8,16,0,0,2688,8,16,0,0,2704,8,16,0,0,2720,8,16,0,0,2736,8,16,0,0,2752,8,16,0,0,2768,8,16,0,0,2784,8,16,0,0,2800,8,16,0,0,2816,8,16,0,0,2832,8,16,0,0,2848,8,16,0,0,2864,8,16,0,0,2880,8,16,0,0,2896,8,16,0,0,2912,8,16,0,0,2928,8,16,0,0,2944,8,16,0,0,2960,8,16,0,0,2976,8,16,0,0,2992,8,16,0,0,3008,8,16,0,0,3024,8,16,0,0,3040,8,16,0,0,3056,8,16,0,0,3072,8,16,0,0,3088,8,16,0,0,3104,8,16,0,0,3120,8,16,0,0,3136,8,16,0,0,3152,8,16,0,0,3168,8,16,0,0,3184,8,16,0,0,3200,8,16,0,0,3216,8,16,0,0,3232,8,16,0,0,3248,8,16,0,0,3264,8,16,0,0,3280,8,16,0,0,3296,8,16,0,0,3312,8,16,0,0,3328,8,16,0,0,3344,8,16,0,0,3360,8,16,0,0,3376,8,16,0,0,3392,8,16,0,0,3408,8,16,0,0,3424,8,16,0,0,3440,8,16,0,0,3456,8,16,0,0,3472,8,16,0,0,3488,8,16,0,0,3504,8,16,0,0,3520,8,16,0,0,3536,8,16,0,0,3552,8,16,0,0,3568,8,16,0,0,3584,8,16,0,0,3600,8,16,0,0,3616,8,16,0,0,3632,8,16,0,0,3648,8,16,0,0,3664,8,16,0,0,3680,8,16,0,0,3696,8,16,0,0,3712,8,16,0,0,3728,8,16,0,0,3744,8,16,0,0,3760,8,16,0,0,3776,8,16,0,0,3792,8,16,0,0,3808,8,16,0,0,3824,8,16,0,0,3840,8,16,0,0,3856,8,16,0,0,3872,8,16,0,0,3888,8,16,0,0,3904,8,16,0,0,3920,8,16,0,0,3936,8,16,0,0,3952,8,16,0,0,3968,8,16,0,0,3984,8,16,0,0,4000,8,16,0,0,4016,8,16,0,0,4032,8,16,0,0,4048,8,16,0,0,4064,8,16,0,0,4080,8,16,0,0,};
|
|
||||||
rfbFontData default8x16Font = { default8x16FontData, default8x16FontMetaData };
|
|
@ -1,61 +0,0 @@
|
|||||||
#include "rfb.h"
|
|
||||||
|
|
||||||
void rfbFillRect(rfbScreenInfoPtr s,int x1,int y1,int x2,int y2,Pixel col)
|
|
||||||
{
|
|
||||||
int rowstride = s->paddedWidthInBytes, bpp = s->bitsPerPixel>>3;
|
|
||||||
int i,j;
|
|
||||||
char* colour=(char*)&col;
|
|
||||||
|
|
||||||
if(!rfbEndianTest)
|
|
||||||
colour += 4-bpp;
|
|
||||||
for(j=y1;j<y2;j++)
|
|
||||||
for(i=x1;i<x2;i++)
|
|
||||||
memcpy(s->frameBuffer+j*rowstride+i*bpp,colour,bpp);
|
|
||||||
rfbMarkRectAsModified(s,x1,y1,x2,y2);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define SETPIXEL(x,y) \
|
|
||||||
memcpy(s->frameBuffer+(y)*rowstride+(x)*bpp,colour,bpp)
|
|
||||||
|
|
||||||
void rfbDrawPixel(rfbScreenInfoPtr s,int x,int y,Pixel col)
|
|
||||||
{
|
|
||||||
int rowstride = s->paddedWidthInBytes, bpp = s->bitsPerPixel>>3;
|
|
||||||
char* colour=(char*)&col;
|
|
||||||
|
|
||||||
if(!rfbEndianTest)
|
|
||||||
colour += 4-bpp;
|
|
||||||
SETPIXEL(x,y);
|
|
||||||
rfbMarkRectAsModified(s,x,y,x+1,y+1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rfbDrawLine(rfbScreenInfoPtr s,int x1,int y1,int x2,int y2,Pixel col)
|
|
||||||
{
|
|
||||||
int rowstride = s->paddedWidthInBytes, bpp = s->bitsPerPixel>>3;
|
|
||||||
int i;
|
|
||||||
char* colour=(char*)&col;
|
|
||||||
|
|
||||||
if(!rfbEndianTest)
|
|
||||||
colour += 4-bpp;
|
|
||||||
|
|
||||||
#define SWAPPOINTS { i=x1; x1=x2; x2=i; i=y1; y1=y2; y2=i; }
|
|
||||||
if(abs(x1-x2)<abs(y1-y2)) {
|
|
||||||
if(y1>y2)
|
|
||||||
SWAPPOINTS
|
|
||||||
for(i=y1;i<=y2;i++)
|
|
||||||
SETPIXEL(x1+(i-y1)*(x2-x1)/(y2-y1),i);
|
|
||||||
/* TODO: Maybe make this more intelligently? */
|
|
||||||
if(x2<x1) { i=x1; x1=x2; x2=i; }
|
|
||||||
rfbMarkRectAsModified(s,x1,y1,x2+1,y2+1);
|
|
||||||
} else {
|
|
||||||
if(x1>x2)
|
|
||||||
SWAPPOINTS
|
|
||||||
else if(x1==x2) {
|
|
||||||
rfbDrawPixel(s,x1,y1,col);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for(i=x1;i<=x2;i++)
|
|
||||||
SETPIXEL(i,y1+(i-x1)*(y2-y1)/(x2-x1));
|
|
||||||
if(y2<y1) { i=y1; y1=y2; y2=i; }
|
|
||||||
rfbMarkRectAsModified(s,x1,y1,x2+1,y2+1);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,279 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* This is an example of how to use libvncserver.
|
|
||||||
*
|
|
||||||
* libvncserver example
|
|
||||||
* Copyright (C) 2001 Johannes E. Schindelin <Johannes.Schindelin@gmx.de>
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
|
||||||
* USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
#define sleep Sleep
|
|
||||||
#else
|
|
||||||
#include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __IRIX__
|
|
||||||
#include <netdb.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "rfb.h"
|
|
||||||
#include "keysym.h"
|
|
||||||
|
|
||||||
const int maxx=640, maxy=480, bpp=4;
|
|
||||||
/* TODO: odd maxx doesn't work (vncviewer bug) */
|
|
||||||
|
|
||||||
/* This initializes a nice (?) background */
|
|
||||||
|
|
||||||
void initBuffer(unsigned char* buffer)
|
|
||||||
{
|
|
||||||
int i,j;
|
|
||||||
for(j=0;j<maxy;++j) {
|
|
||||||
for(i=0;i<maxx;++i) {
|
|
||||||
buffer[(j*maxx+i)*bpp+0]=(i+j)*128/(maxx+maxy); /* red */
|
|
||||||
buffer[(j*maxx+i)*bpp+1]=i*128/maxx; /* green */
|
|
||||||
buffer[(j*maxx+i)*bpp+2]=j*256/maxy; /* blue */
|
|
||||||
}
|
|
||||||
buffer[j*maxx*bpp+0]=0xff;
|
|
||||||
buffer[j*maxx*bpp+1]=0xff;
|
|
||||||
buffer[j*maxx*bpp+2]=0xff;
|
|
||||||
buffer[j*maxx*bpp+3]=0xff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Here we create a structure so that every client has it's own pointer */
|
|
||||||
|
|
||||||
typedef struct ClientData {
|
|
||||||
Bool oldButton;
|
|
||||||
int oldx,oldy;
|
|
||||||
} ClientData;
|
|
||||||
|
|
||||||
void clientgone(rfbClientPtr cl)
|
|
||||||
{
|
|
||||||
free(cl->clientData);
|
|
||||||
}
|
|
||||||
|
|
||||||
enum rfbNewClientAction newclient(rfbClientPtr cl)
|
|
||||||
{
|
|
||||||
cl->clientData = (void*)calloc(sizeof(ClientData),1);
|
|
||||||
cl->clientGoneHook = clientgone;
|
|
||||||
return RFB_CLIENT_ACCEPT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* aux function to draw a line */
|
|
||||||
|
|
||||||
void drawline(unsigned char* buffer,int rowstride,int bpp,int x1,int y1,int x2,int y2)
|
|
||||||
{
|
|
||||||
int i,j;
|
|
||||||
i=x1-x2; j=y1-y2;
|
|
||||||
if(i==0 && j==0) {
|
|
||||||
for(i=0;i<bpp;i++)
|
|
||||||
buffer[y1*rowstride+x1*bpp+i]=0xff;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(i<0) i=-i;
|
|
||||||
if(j<0) j=-j;
|
|
||||||
if(i<j) {
|
|
||||||
if(y1>y2) { i=y2; y2=y1; y1=i; i=x2; x2=x1; x1=i; }
|
|
||||||
if(y2==y1) { if(y2>0) y1--; else y2++; }
|
|
||||||
for(j=y1;j<=y2;j++)
|
|
||||||
for(i=0;i<bpp;i++)
|
|
||||||
buffer[j*rowstride+(x1+(j-y1)*(x2-x1)/(y2-y1))*bpp+i]=0xff;
|
|
||||||
} else {
|
|
||||||
if(x1>x2) { i=y2; y2=y1; y1=i; i=x2; x2=x1; x1=i; }
|
|
||||||
for(i=x1;i<=x2;i++)
|
|
||||||
for(j=0;j<bpp;j++)
|
|
||||||
buffer[(y1+(i-x1)*(y2-y1)/(x2-x1))*rowstride+i*bpp+j]=0xff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Here the pointer events are handled */
|
|
||||||
|
|
||||||
void doptr(int buttonMask,int x,int y,rfbClientPtr cl)
|
|
||||||
{
|
|
||||||
ClientData* cd=cl->clientData;
|
|
||||||
|
|
||||||
if(cl->screen->cursorIsDrawn)
|
|
||||||
rfbUndrawCursor(cl->screen);
|
|
||||||
|
|
||||||
if(x>=0 && y>=0 && x<maxx && y<maxy) {
|
|
||||||
if(buttonMask) {
|
|
||||||
int i,j,x1,x2,y1,y2;
|
|
||||||
|
|
||||||
if(cd->oldButton==buttonMask) { /* draw a line */
|
|
||||||
drawline(cl->screen->frameBuffer,cl->screen->paddedWidthInBytes,bpp,
|
|
||||||
x,y,cd->oldx,cd->oldy);
|
|
||||||
rfbMarkRectAsModified(cl->screen,x,y,cd->oldx,cd->oldy);
|
|
||||||
} else { /* draw a point (diameter depends on button) */
|
|
||||||
int w=cl->screen->paddedWidthInBytes;
|
|
||||||
x1=x-buttonMask; if(x1<0) x1=0;
|
|
||||||
x2=x+buttonMask; if(x2>maxx) x2=maxx;
|
|
||||||
y1=y-buttonMask; if(y1<0) y1=0;
|
|
||||||
y2=y+buttonMask; if(y2>maxy) y2=maxy;
|
|
||||||
|
|
||||||
for(i=x1*bpp;i<x2*bpp;i++)
|
|
||||||
for(j=y1;j<y2;j++)
|
|
||||||
cl->screen->frameBuffer[j*w+i]=(char)0xff;
|
|
||||||
rfbMarkRectAsModified(cl->screen,x1,y1,x2-1,y2-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* we could get a selection like that:
|
|
||||||
rfbGotXCutText(cl->screen,"Hallo",5);
|
|
||||||
*/
|
|
||||||
} else
|
|
||||||
cd->oldButton=0;
|
|
||||||
|
|
||||||
cd->oldx=x; cd->oldy=y; cd->oldButton=buttonMask;
|
|
||||||
}
|
|
||||||
defaultPtrAddEvent(buttonMask,x,y,cl);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* aux function to draw a character to x, y */
|
|
||||||
|
|
||||||
#include "radon.h"
|
|
||||||
|
|
||||||
/* Here the key events are handled */
|
|
||||||
|
|
||||||
void dokey(Bool down,KeySym key,rfbClientPtr cl)
|
|
||||||
{
|
|
||||||
if(down) {
|
|
||||||
if(key==XK_Escape)
|
|
||||||
rfbCloseClient(cl);
|
|
||||||
else if(key==XK_Page_Up) {
|
|
||||||
if(cl->screen->cursorIsDrawn)
|
|
||||||
rfbUndrawCursor(cl->screen);
|
|
||||||
initBuffer(cl->screen->frameBuffer);
|
|
||||||
rfbMarkRectAsModified(cl->screen,0,0,maxx,maxy);
|
|
||||||
} else if(key>=' ' && key<0x100) {
|
|
||||||
ClientData* cd=cl->clientData;
|
|
||||||
int x1=cd->oldx,y1=cd->oldy,x2,y2;
|
|
||||||
if(cl->screen->cursorIsDrawn)
|
|
||||||
rfbUndrawCursor(cl->screen);
|
|
||||||
cd->oldx+=rfbDrawChar(cl->screen,&radonFont,cd->oldx,cd->oldy,(char)key,0x00ffffff);
|
|
||||||
rfbFontBBox(&radonFont,(char)key,&x1,&y1,&x2,&y2);
|
|
||||||
rfbMarkRectAsModified(cl->screen,x1,y1,x2-1,y2-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Example for an XCursor (foreground/background only) */
|
|
||||||
|
|
||||||
int exampleXCursorWidth=9,exampleXCursorHeight=7;
|
|
||||||
char exampleXCursor[]=
|
|
||||||
" "
|
|
||||||
" xx xx "
|
|
||||||
" xx xx "
|
|
||||||
" xxx "
|
|
||||||
" xx xx "
|
|
||||||
" xx xx "
|
|
||||||
" ";
|
|
||||||
|
|
||||||
/* Example for a rich cursor (full-colour) */
|
|
||||||
|
|
||||||
void MakeRichCursor(rfbScreenInfoPtr rfbScreen)
|
|
||||||
{
|
|
||||||
int i,j,w=32,h=32;
|
|
||||||
rfbCursorPtr c = rfbScreen->cursor;
|
|
||||||
char bitmap[]=
|
|
||||||
" "
|
|
||||||
" xxxxxx "
|
|
||||||
" xxxxxxxxxxxxxxxxx "
|
|
||||||
" xxxxxxxxxxxxxxxxxxxxxx "
|
|
||||||
" xxxxx xxxxxxxx xxxxxxxx "
|
|
||||||
" xxxxxxxxxxxxxxxxxxxxxxxxxxx "
|
|
||||||
" xxxxxxxxxxxxxxxxxxxxxxxxxxxxx "
|
|
||||||
" xxxxx xxxxxxxxxxx xxxxxxx "
|
|
||||||
" xxxx xxxxxxxxx xxxxxx "
|
|
||||||
" xxxxx xxxxxxxxxxx xxxxxxx "
|
|
||||||
" xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx "
|
|
||||||
" xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx "
|
|
||||||
" xxxxxxxxxxxx xxxxxxxxxxxxxxx "
|
|
||||||
" xxxxxxxxxxxxxxxxxxxxxxxxxxxx "
|
|
||||||
" xxxxxxxxxxxxxxxxxxxxxxxxxxxx "
|
|
||||||
" xxxxxxxxxxx xxxxxxxxxxxxxx "
|
|
||||||
" xxxxxxxxxx xxxxxxxxxxxx "
|
|
||||||
" xxxxxxxxx xxxxxxxxx "
|
|
||||||
" xxxxxxxxxx xxxxxxxxx "
|
|
||||||
" xxxxxxxxxxxxxxxxxxx "
|
|
||||||
" xxxxxxxxxxxxxxxxxxx "
|
|
||||||
" xxxxxxxxxxxxxxxxxxx "
|
|
||||||
" xxxxxxxxxxxxxxxxx "
|
|
||||||
" xxxxxxxxxxxxxxx "
|
|
||||||
" xxxx xxxxxxxxxxxxx "
|
|
||||||
" xx x xxxxxxxxxxx "
|
|
||||||
" xxx xxxxxxxxxxx "
|
|
||||||
" xxxx xxxxxxxxxxx "
|
|
||||||
" xxxxxx xxxxxxxxxxxx "
|
|
||||||
" xxxxxxxxxxxxxxxxxxxxxx "
|
|
||||||
" xxxxxxxxxxxxxxxx "
|
|
||||||
" ";
|
|
||||||
c=rfbScreen->cursor = rfbMakeXCursor(w,h,bitmap,bitmap);
|
|
||||||
c->xhot = 16; c->yhot = 24;
|
|
||||||
|
|
||||||
c->richSource = malloc(w*h*bpp);
|
|
||||||
for(j=0;j<h;j++) {
|
|
||||||
for(i=0;i<w;i++) {
|
|
||||||
c->richSource[j*w*bpp+i*bpp+0]=i*0xff/w;
|
|
||||||
c->richSource[j*w*bpp+i*bpp+1]=(i+j)*0xff/(w+h);
|
|
||||||
c->richSource[j*w*bpp+i*bpp+2]=j*0xff/h;
|
|
||||||
c->richSource[j*w*bpp+i*bpp+3]=0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialization */
|
|
||||||
|
|
||||||
int main(int argc,char** argv)
|
|
||||||
{
|
|
||||||
rfbScreenInfoPtr rfbScreen =
|
|
||||||
rfbGetScreen(&argc,argv,maxx,maxy,8,3,bpp);
|
|
||||||
rfbScreen->desktopName = "LibVNCServer Example";
|
|
||||||
rfbScreen->frameBuffer = (char*)malloc(maxx*maxy*bpp);
|
|
||||||
rfbScreen->rfbAlwaysShared = TRUE;
|
|
||||||
rfbScreen->ptrAddEvent = doptr;
|
|
||||||
rfbScreen->kbdAddEvent = dokey;
|
|
||||||
rfbScreen->newClientHook = newclient;
|
|
||||||
rfbScreen->httpDir = "./classes";
|
|
||||||
|
|
||||||
initBuffer(rfbScreen->frameBuffer);
|
|
||||||
rfbDrawString(rfbScreen,&radonFont,20,100,"Hello, World!",0xffffff);
|
|
||||||
|
|
||||||
/* This call creates a mask and then a cursor: */
|
|
||||||
/* rfbScreen->defaultCursor =
|
|
||||||
rfbMakeXCursor(exampleCursorWidth,exampleCursorHeight,exampleCursor,0);
|
|
||||||
*/
|
|
||||||
|
|
||||||
MakeRichCursor(rfbScreen);
|
|
||||||
|
|
||||||
/* initialize the server */
|
|
||||||
rfbInitServer(rfbScreen);
|
|
||||||
|
|
||||||
#ifndef BACKGROUND_LOOP_TEST
|
|
||||||
/* this is the blocking event loop, i.e. it never returns */
|
|
||||||
/* 40000 are the microseconds, i.e. 0.04 seconds */
|
|
||||||
rfbRunEventLoop(rfbScreen,40000,FALSE);
|
|
||||||
#elif !defined(HAVE_PTHREADS)
|
|
||||||
#error "I need pthreads for that."
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* this is the non-blocking event loop; a background thread is started */
|
|
||||||
rfbRunEventLoop(rfbScreen,-1,TRUE);
|
|
||||||
/* now we could do some cool things like rendering */
|
|
||||||
while(1) sleep(5); /* render(); */
|
|
||||||
|
|
||||||
return(0);
|
|
||||||
}
|
|
@ -1,192 +0,0 @@
|
|||||||
#include "rfb.h"
|
|
||||||
|
|
||||||
int rfbDrawChar(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,
|
|
||||||
int x,int y,unsigned char c,Pixel col)
|
|
||||||
{
|
|
||||||
int i,j,width,height;
|
|
||||||
unsigned char* data=font->data+font->metaData[c*5];
|
|
||||||
unsigned char d=*data;
|
|
||||||
int rowstride=rfbScreen->paddedWidthInBytes;
|
|
||||||
int bpp=rfbScreen->rfbServerFormat.bitsPerPixel/8;
|
|
||||||
char *colour=(char*)&col;
|
|
||||||
|
|
||||||
if(!rfbEndianTest)
|
|
||||||
colour += 4-bpp;
|
|
||||||
|
|
||||||
width=font->metaData[c*5+1];
|
|
||||||
height=font->metaData[c*5+2];
|
|
||||||
x+=font->metaData[c*5+3];
|
|
||||||
y+=-font->metaData[c*5+4]-height+1;
|
|
||||||
|
|
||||||
for(j=0;j<height;j++) {
|
|
||||||
for(i=0;i<width;i++) {
|
|
||||||
if((i&7)==0) {
|
|
||||||
d=*data;
|
|
||||||
data++;
|
|
||||||
}
|
|
||||||
if(d&0x80)
|
|
||||||
memcpy(rfbScreen->frameBuffer+(y+j)*rowstride+(x+i)*bpp,colour,bpp);
|
|
||||||
d<<=1;
|
|
||||||
}
|
|
||||||
/* if((i&7)!=0) data++; */
|
|
||||||
}
|
|
||||||
return(width);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rfbDrawString(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,
|
|
||||||
int x,int y,const char* string,Pixel colour)
|
|
||||||
{
|
|
||||||
while(*string) {
|
|
||||||
x+=rfbDrawChar(rfbScreen,font,x,y,*string,colour);
|
|
||||||
string++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO: these two functions need to be more efficient */
|
|
||||||
int rfbDrawCharWithClip(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,
|
|
||||||
int x,int y,unsigned char c,
|
|
||||||
int x1,int y1,int x2,int y2,
|
|
||||||
Pixel col,Pixel bcol)
|
|
||||||
{
|
|
||||||
int i,j,width,height;
|
|
||||||
unsigned char* data=font->data+font->metaData[c*5];
|
|
||||||
unsigned char d;
|
|
||||||
int rowstride=rfbScreen->paddedWidthInBytes;
|
|
||||||
int bpp=rfbScreen->rfbServerFormat.bitsPerPixel/8,extra_bytes=0;
|
|
||||||
char* colour=(char*)&col;
|
|
||||||
char* bcolour=(char*)&bcol;
|
|
||||||
|
|
||||||
if(!rfbEndianTest) {
|
|
||||||
colour+=4-bpp;
|
|
||||||
bcolour+=4-bpp;
|
|
||||||
}
|
|
||||||
|
|
||||||
width=font->metaData[c*5+1];
|
|
||||||
height=font->metaData[c*5+2];
|
|
||||||
x+=font->metaData[c*5+3];
|
|
||||||
y+=-font->metaData[c*5+4]-height+1;
|
|
||||||
|
|
||||||
/* after clipping, x2 will be count of bytes between rows,
|
|
||||||
* x1 start of i, y1 start of j, width and height will be adjusted. */
|
|
||||||
if(y1>y) { y1-=y; data+=(width+7)/8; height-=y1; y+=y1; } else y1=0;
|
|
||||||
if(x1>x) { x1-=x; data+=x1; width-=x1; x+=x1; extra_bytes+=x1/8; } else x1=0;
|
|
||||||
if(y2<y+height) height-=y+height-y2;
|
|
||||||
if(x2<x+width) { extra_bytes+=(x1+width)/8-(x+width-x2+7)/8; width-=x+width-x2; }
|
|
||||||
|
|
||||||
d=*data;
|
|
||||||
for(j=y1;j<height;j++) {
|
|
||||||
if((x1&7)!=0)
|
|
||||||
d=data[-1]; /* TODO: check if in this case extra_bytes is correct! */
|
|
||||||
for(i=x1;i<width;i++) {
|
|
||||||
if((i&7)==0) {
|
|
||||||
d=*data;
|
|
||||||
data++;
|
|
||||||
}
|
|
||||||
/* if(x+i>=x1 && x+i<x2 && y+j>=y1 && y+j<y2) */ {
|
|
||||||
if(d&0x80) {
|
|
||||||
memcpy(rfbScreen->frameBuffer+(y+j)*rowstride+(x+i)*bpp,
|
|
||||||
colour,bpp);
|
|
||||||
} else if(bcol!=col) {
|
|
||||||
memcpy(rfbScreen->frameBuffer+(y+j)*rowstride+(x+i)*bpp,
|
|
||||||
bcolour,bpp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
d<<=1;
|
|
||||||
}
|
|
||||||
/* if((i&7)==0) data++; */
|
|
||||||
data += extra_bytes;
|
|
||||||
}
|
|
||||||
return(width);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rfbDrawStringWithClip(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,
|
|
||||||
int x,int y,const char* string,
|
|
||||||
int x1,int y1,int x2,int y2,
|
|
||||||
Pixel colour,Pixel backColour)
|
|
||||||
{
|
|
||||||
while(*string) {
|
|
||||||
x+=rfbDrawCharWithClip(rfbScreen,font,x,y,*string,x1,y1,x2,y2,
|
|
||||||
colour,backColour);
|
|
||||||
string++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int rfbWidthOfString(rfbFontDataPtr font,const char* string)
|
|
||||||
{
|
|
||||||
int i=0;
|
|
||||||
while(*string) {
|
|
||||||
i+=font->metaData[*string*5+1];
|
|
||||||
string++;
|
|
||||||
}
|
|
||||||
return(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
int rfbWidthOfChar(rfbFontDataPtr font,unsigned char c)
|
|
||||||
{
|
|
||||||
return(font->metaData[c*5+1]+font->metaData[c*5+3]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rfbFontBBox(rfbFontDataPtr font,unsigned char c,int* x1,int* y1,int* x2,int* y2)
|
|
||||||
{
|
|
||||||
*x1+=font->metaData[c*5+3];
|
|
||||||
*y1+=-font->metaData[c*5+4]-font->metaData[c*5+2]+1;
|
|
||||||
*x2=*x1+font->metaData[c*5+1];
|
|
||||||
*y2=*y1+font->metaData[c*5+2];
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef INT_MAX
|
|
||||||
#define INT_MAX 0x7fffffff
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void rfbWholeFontBBox(rfbFontDataPtr font,
|
|
||||||
int *x1, int *y1, int *x2, int *y2)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
int* m=font->metaData;
|
|
||||||
|
|
||||||
(*x1)=(*y1)=INT_MAX; (*x2)=(*y2)=-INT_MAX+1;
|
|
||||||
for(i=0;i<256;i++) {
|
|
||||||
if(m[i*5+1]-m[i*5+3]>(*x2))
|
|
||||||
(*x2)=m[i*5+1]-m[i*5+3];
|
|
||||||
if(-m[i*5+2]+m[i*5+4]<(*y1))
|
|
||||||
(*y1)=-m[i*5+2]+m[i*5+4];
|
|
||||||
if(m[i*5+3]<(*x1))
|
|
||||||
(*x1)=m[i*5+3];
|
|
||||||
if(-m[i*5+4]>(*y2))
|
|
||||||
(*y2)=-m[i*5+4];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rfbFontDataPtr rfbLoadConsoleFont(char *filename)
|
|
||||||
{
|
|
||||||
FILE *f=fopen(filename,"rb");
|
|
||||||
rfbFontDataPtr p;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if(!f) return(0);
|
|
||||||
|
|
||||||
p=(rfbFontDataPtr)malloc(sizeof(rfbFontData));
|
|
||||||
p->data=(unsigned char*)malloc(4096);
|
|
||||||
if(1!=fread(p->data,4096,1,f)) {
|
|
||||||
free(p->data);
|
|
||||||
free(p);
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
fclose(f);
|
|
||||||
p->metaData=(int*)malloc(256*5*sizeof(int));
|
|
||||||
for(i=0;i<256;i++) {
|
|
||||||
p->metaData[i*5+0]=i*16; /* offset */
|
|
||||||
p->metaData[i*5+1]=8; /* width */
|
|
||||||
p->metaData[i*5+2]=16; /* height */
|
|
||||||
p->metaData[i*5+3]=0; /* xhot */
|
|
||||||
p->metaData[i*5+4]=0; /* yhot */
|
|
||||||
}
|
|
||||||
return(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rfbFreeFont(rfbFontDataPtr f)
|
|
||||||
{
|
|
||||||
free(f->data);
|
|
||||||
free(f->metaData);
|
|
||||||
free(f);
|
|
||||||
}
|
|
@ -1,71 +0,0 @@
|
|||||||
#include "rfb.h"
|
|
||||||
|
|
||||||
#define FONTDIR "/usr/lib/kbd/consolefonts/"
|
|
||||||
#define DEFAULTFONT FONTDIR "default8x16"
|
|
||||||
|
|
||||||
char *fontlist[50]={
|
|
||||||
"8x16alt", "b.fnt", "c.fnt", "default8x16", "m.fnt", "ml.fnt", "mod_d.fnt",
|
|
||||||
"mod_s.fnt", "mr.fnt", "mu.fnt", "r.fnt", "rl.fnt", "ro.fnt", "s.fnt",
|
|
||||||
"sc.fnt", "scrawl_s.fnt", "scrawl_w.fnt", "sd.fnt", "t.fnt",
|
|
||||||
0
|
|
||||||
};
|
|
||||||
|
|
||||||
rfbScreenInfoPtr rfbScreen = 0;
|
|
||||||
rfbFontDataPtr curFont = 0;
|
|
||||||
void showFont(int index)
|
|
||||||
{
|
|
||||||
char buffer[1024];
|
|
||||||
|
|
||||||
if(!rfbScreen) return;
|
|
||||||
|
|
||||||
if(curFont)
|
|
||||||
rfbFreeFont(curFont);
|
|
||||||
|
|
||||||
strcpy(buffer,FONTDIR);
|
|
||||||
strcat(buffer,fontlist[index]);
|
|
||||||
curFont = rfbLoadConsoleFont(buffer);
|
|
||||||
|
|
||||||
rfbFillRect(rfbScreen,210,30-20,210+10*16,30-20+256*20/16,0xb77797);
|
|
||||||
if(curFont) {
|
|
||||||
int i,j;
|
|
||||||
for(j=0;j<256;j+=16)
|
|
||||||
for(i=0;i<16;i++)
|
|
||||||
rfbDrawCharWithClip(rfbScreen,curFont,210+10*i,30+j*20/16,j+i,
|
|
||||||
0,0,640,480,0xffffff,0x000000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc,char** argv)
|
|
||||||
{
|
|
||||||
rfbFontDataPtr font;
|
|
||||||
rfbScreenInfoPtr s=rfbGetScreen(&argc,argv,640,480,8,3,3);
|
|
||||||
int i,j;
|
|
||||||
|
|
||||||
s->frameBuffer=(char*)malloc(640*480*3);
|
|
||||||
rfbInitServer(s);
|
|
||||||
|
|
||||||
for(j=0;j<480;j++)
|
|
||||||
for(i=0;i<640;i++) {
|
|
||||||
s->frameBuffer[(j*640+i)*3+0]=j*256/480;
|
|
||||||
s->frameBuffer[(j*640+i)*3+1]=i*256/640;
|
|
||||||
s->frameBuffer[(j*640+i)*3+2]=(i+j)*256/(480+640);
|
|
||||||
}
|
|
||||||
|
|
||||||
rfbScreen = s;
|
|
||||||
font=rfbLoadConsoleFont(DEFAULTFONT);
|
|
||||||
if(!font) {
|
|
||||||
fprintf(stderr,"Couldn't find %s\n",DEFAULTFONT);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(j=0;j<0;j++)
|
|
||||||
rfbProcessEvents(s,900000);
|
|
||||||
|
|
||||||
i = rfbSelectBox(s,font,fontlist,10,20,200,300,0xffdfdf,0x602040,2,showFont);
|
|
||||||
fprintf(stderr,"Selection: %d: %s\n",i,(i>=0)?fontlist[i]:"cancelled");
|
|
||||||
|
|
||||||
rfbFreeFont(font);
|
|
||||||
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
@ -1,347 +0,0 @@
|
|||||||
/*
|
|
||||||
* hextile.c
|
|
||||||
*
|
|
||||||
* Routines to implement Hextile Encoding
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
|
|
||||||
* Original Xvnc code 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
|
||||||
* USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "rfb.h"
|
|
||||||
|
|
||||||
static Bool sendHextiles8(rfbClientPtr cl, int x, int y, int w, int h);
|
|
||||||
static Bool sendHextiles16(rfbClientPtr cl, int x, int y, int w, int h);
|
|
||||||
static Bool sendHextiles32(rfbClientPtr cl, int x, int y, int w, int h);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* rfbSendRectEncodingHextile - send a rectangle using hextile encoding.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Bool
|
|
||||||
rfbSendRectEncodingHextile(cl, x, y, w, h)
|
|
||||||
rfbClientPtr cl;
|
|
||||||
int x, y, w, h;
|
|
||||||
{
|
|
||||||
rfbFramebufferUpdateRectHeader rect;
|
|
||||||
|
|
||||||
if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
|
|
||||||
if (!rfbSendUpdateBuf(cl))
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
rect.r.x = Swap16IfLE(x);
|
|
||||||
rect.r.y = Swap16IfLE(y);
|
|
||||||
rect.r.w = Swap16IfLE(w);
|
|
||||||
rect.r.h = Swap16IfLE(h);
|
|
||||||
rect.encoding = Swap32IfLE(rfbEncodingHextile);
|
|
||||||
|
|
||||||
memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
|
|
||||||
sz_rfbFramebufferUpdateRectHeader);
|
|
||||||
cl->ublen += sz_rfbFramebufferUpdateRectHeader;
|
|
||||||
|
|
||||||
cl->rfbRectanglesSent[rfbEncodingHextile]++;
|
|
||||||
cl->rfbBytesSent[rfbEncodingHextile] += sz_rfbFramebufferUpdateRectHeader;
|
|
||||||
|
|
||||||
switch (cl->format.bitsPerPixel) {
|
|
||||||
case 8:
|
|
||||||
return sendHextiles8(cl, x, y, w, h);
|
|
||||||
case 16:
|
|
||||||
return sendHextiles16(cl, x, y, w, h);
|
|
||||||
case 32:
|
|
||||||
return sendHextiles32(cl, x, y, w, h);
|
|
||||||
}
|
|
||||||
|
|
||||||
rfbLog("rfbSendRectEncodingHextile: bpp %d?\n", cl->format.bitsPerPixel);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define PUT_PIXEL8(pix) (cl->updateBuf[cl->ublen++] = (pix))
|
|
||||||
|
|
||||||
#define PUT_PIXEL16(pix) (cl->updateBuf[cl->ublen++] = ((char*)&(pix))[0], \
|
|
||||||
cl->updateBuf[cl->ublen++] = ((char*)&(pix))[1])
|
|
||||||
|
|
||||||
#define PUT_PIXEL32(pix) (cl->updateBuf[cl->ublen++] = ((char*)&(pix))[0], \
|
|
||||||
cl->updateBuf[cl->ublen++] = ((char*)&(pix))[1], \
|
|
||||||
cl->updateBuf[cl->ublen++] = ((char*)&(pix))[2], \
|
|
||||||
cl->updateBuf[cl->ublen++] = ((char*)&(pix))[3])
|
|
||||||
|
|
||||||
|
|
||||||
#define DEFINE_SEND_HEXTILES(bpp) \
|
|
||||||
\
|
|
||||||
\
|
|
||||||
static Bool subrectEncode##bpp(rfbClientPtr cli, CARD##bpp *data, int w, int h, \
|
|
||||||
CARD##bpp bg, CARD##bpp fg, Bool mono); \
|
|
||||||
static void testColours##bpp(CARD##bpp *data, int size, Bool *mono, \
|
|
||||||
Bool *solid, CARD##bpp *bg, CARD##bpp *fg); \
|
|
||||||
\
|
|
||||||
\
|
|
||||||
/* \
|
|
||||||
* rfbSendHextiles \
|
|
||||||
*/ \
|
|
||||||
\
|
|
||||||
static Bool \
|
|
||||||
sendHextiles##bpp(cl, rx, ry, rw, rh) \
|
|
||||||
rfbClientPtr cl; \
|
|
||||||
int rx, ry, rw, rh; \
|
|
||||||
{ \
|
|
||||||
int x, y, w, h; \
|
|
||||||
int startUblen; \
|
|
||||||
char *fbptr; \
|
|
||||||
CARD##bpp bg = 0, fg = 0, newBg, newFg; \
|
|
||||||
Bool mono, solid; \
|
|
||||||
Bool validBg = FALSE; \
|
|
||||||
Bool validFg = FALSE; \
|
|
||||||
CARD##bpp clientPixelData[16*16*(bpp/8)]; \
|
|
||||||
\
|
|
||||||
for (y = ry; y < ry+rh; y += 16) { \
|
|
||||||
for (x = rx; x < rx+rw; x += 16) { \
|
|
||||||
w = h = 16; \
|
|
||||||
if (rx+rw - x < 16) \
|
|
||||||
w = rx+rw - x; \
|
|
||||||
if (ry+rh - y < 16) \
|
|
||||||
h = ry+rh - y; \
|
|
||||||
\
|
|
||||||
if ((cl->ublen + 1 + (2 + 16 * 16) * (bpp/8)) > \
|
|
||||||
UPDATE_BUF_SIZE) { \
|
|
||||||
if (!rfbSendUpdateBuf(cl)) \
|
|
||||||
return FALSE; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
fbptr = (cl->screen->frameBuffer + (cl->screen->paddedWidthInBytes * y) \
|
|
||||||
+ (x * (cl->screen->bitsPerPixel / 8))); \
|
|
||||||
\
|
|
||||||
(*cl->translateFn)(cl->translateLookupTable, &(cl->screen->rfbServerFormat), \
|
|
||||||
&cl->format, fbptr, (char *)clientPixelData, \
|
|
||||||
cl->screen->paddedWidthInBytes, w, h); \
|
|
||||||
\
|
|
||||||
startUblen = cl->ublen; \
|
|
||||||
cl->updateBuf[startUblen] = 0; \
|
|
||||||
cl->ublen++; \
|
|
||||||
\
|
|
||||||
testColours##bpp(clientPixelData, w * h, \
|
|
||||||
&mono, &solid, &newBg, &newFg); \
|
|
||||||
\
|
|
||||||
if (!validBg || (newBg != bg)) { \
|
|
||||||
validBg = TRUE; \
|
|
||||||
bg = newBg; \
|
|
||||||
cl->updateBuf[startUblen] |= rfbHextileBackgroundSpecified; \
|
|
||||||
PUT_PIXEL##bpp(bg); \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
if (solid) { \
|
|
||||||
cl->rfbBytesSent[rfbEncodingHextile] += cl->ublen - startUblen; \
|
|
||||||
continue; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
cl->updateBuf[startUblen] |= rfbHextileAnySubrects; \
|
|
||||||
\
|
|
||||||
if (mono) { \
|
|
||||||
if (!validFg || (newFg != fg)) { \
|
|
||||||
validFg = TRUE; \
|
|
||||||
fg = newFg; \
|
|
||||||
cl->updateBuf[startUblen] |= rfbHextileForegroundSpecified; \
|
|
||||||
PUT_PIXEL##bpp(fg); \
|
|
||||||
} \
|
|
||||||
} else { \
|
|
||||||
validFg = FALSE; \
|
|
||||||
cl->updateBuf[startUblen] |= rfbHextileSubrectsColoured; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
if (!subrectEncode##bpp(cl, clientPixelData, w, h, bg, fg, mono)) { \
|
|
||||||
/* encoding was too large, use raw */ \
|
|
||||||
validBg = FALSE; \
|
|
||||||
validFg = FALSE; \
|
|
||||||
cl->ublen = startUblen; \
|
|
||||||
cl->updateBuf[cl->ublen++] = rfbHextileRaw; \
|
|
||||||
(*cl->translateFn)(cl->translateLookupTable, \
|
|
||||||
&(cl->screen->rfbServerFormat), &cl->format, fbptr, \
|
|
||||||
(char *)clientPixelData, \
|
|
||||||
cl->screen->paddedWidthInBytes, w, h); \
|
|
||||||
\
|
|
||||||
memcpy(&cl->updateBuf[cl->ublen], (char *)clientPixelData, \
|
|
||||||
w * h * (bpp/8)); \
|
|
||||||
\
|
|
||||||
cl->ublen += w * h * (bpp/8); \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
cl->rfbBytesSent[rfbEncodingHextile] += cl->ublen - startUblen; \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
return TRUE; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
\
|
|
||||||
static Bool \
|
|
||||||
subrectEncode##bpp(rfbClientPtr cl, CARD##bpp *data, int w, int h, \
|
|
||||||
CARD##bpp bg, CARD##bpp fg, Bool mono) \
|
|
||||||
{ \
|
|
||||||
CARD##bpp cl2; \
|
|
||||||
int x,y; \
|
|
||||||
int i,j; \
|
|
||||||
int hx=0,hy,vx=0,vy; \
|
|
||||||
int hyflag; \
|
|
||||||
CARD##bpp *seg; \
|
|
||||||
CARD##bpp *line; \
|
|
||||||
int hw,hh,vw,vh; \
|
|
||||||
int thex,they,thew,theh; \
|
|
||||||
int numsubs = 0; \
|
|
||||||
int newLen; \
|
|
||||||
int nSubrectsUblen; \
|
|
||||||
\
|
|
||||||
nSubrectsUblen = cl->ublen; \
|
|
||||||
cl->ublen++; \
|
|
||||||
\
|
|
||||||
for (y=0; y<h; y++) { \
|
|
||||||
line = data+(y*w); \
|
|
||||||
for (x=0; x<w; x++) { \
|
|
||||||
if (line[x] != bg) { \
|
|
||||||
cl2 = line[x]; \
|
|
||||||
hy = y-1; \
|
|
||||||
hyflag = 1; \
|
|
||||||
for (j=y; j<h; j++) { \
|
|
||||||
seg = data+(j*w); \
|
|
||||||
if (seg[x] != cl2) {break;} \
|
|
||||||
i = x; \
|
|
||||||
while ((seg[i] == cl2) && (i < w)) i += 1; \
|
|
||||||
i -= 1; \
|
|
||||||
if (j == y) vx = hx = i; \
|
|
||||||
if (i < vx) vx = i; \
|
|
||||||
if ((hyflag > 0) && (i >= hx)) { \
|
|
||||||
hy += 1; \
|
|
||||||
} else { \
|
|
||||||
hyflag = 0; \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
vy = j-1; \
|
|
||||||
\
|
|
||||||
/* We now have two possible subrects: (x,y,hx,hy) and \
|
|
||||||
* (x,y,vx,vy). We'll choose the bigger of the two. \
|
|
||||||
*/ \
|
|
||||||
hw = hx-x+1; \
|
|
||||||
hh = hy-y+1; \
|
|
||||||
vw = vx-x+1; \
|
|
||||||
vh = vy-y+1; \
|
|
||||||
\
|
|
||||||
thex = x; \
|
|
||||||
they = y; \
|
|
||||||
\
|
|
||||||
if ((hw*hh) > (vw*vh)) { \
|
|
||||||
thew = hw; \
|
|
||||||
theh = hh; \
|
|
||||||
} else { \
|
|
||||||
thew = vw; \
|
|
||||||
theh = vh; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
if (mono) { \
|
|
||||||
newLen = cl->ublen - nSubrectsUblen + 2; \
|
|
||||||
} else { \
|
|
||||||
newLen = cl->ublen - nSubrectsUblen + bpp/8 + 2; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
if (newLen > (w * h * (bpp/8))) \
|
|
||||||
return FALSE; \
|
|
||||||
\
|
|
||||||
numsubs += 1; \
|
|
||||||
\
|
|
||||||
if (!mono) PUT_PIXEL##bpp(cl2); \
|
|
||||||
\
|
|
||||||
cl->updateBuf[cl->ublen++] = rfbHextilePackXY(thex,they); \
|
|
||||||
cl->updateBuf[cl->ublen++] = rfbHextilePackWH(thew,theh); \
|
|
||||||
\
|
|
||||||
/* \
|
|
||||||
* Now mark the subrect as done. \
|
|
||||||
*/ \
|
|
||||||
for (j=they; j < (they+theh); j++) { \
|
|
||||||
for (i=thex; i < (thex+thew); i++) { \
|
|
||||||
data[j*w+i] = bg; \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
cl->updateBuf[nSubrectsUblen] = numsubs; \
|
|
||||||
\
|
|
||||||
return TRUE; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
\
|
|
||||||
/* \
|
|
||||||
* testColours() tests if there are one (solid), two (mono) or more \
|
|
||||||
* colours in a tile and gets a reasonable guess at the best background \
|
|
||||||
* pixel, and the foreground pixel for mono. \
|
|
||||||
*/ \
|
|
||||||
\
|
|
||||||
static void \
|
|
||||||
testColours##bpp(data,size,mono,solid,bg,fg) \
|
|
||||||
CARD##bpp *data; \
|
|
||||||
int size; \
|
|
||||||
Bool *mono; \
|
|
||||||
Bool *solid; \
|
|
||||||
CARD##bpp *bg; \
|
|
||||||
CARD##bpp *fg; \
|
|
||||||
{ \
|
|
||||||
CARD##bpp colour1 = 0, colour2 = 0; \
|
|
||||||
int n1 = 0, n2 = 0; \
|
|
||||||
*mono = TRUE; \
|
|
||||||
*solid = TRUE; \
|
|
||||||
\
|
|
||||||
for (; size > 0; size--, data++) { \
|
|
||||||
\
|
|
||||||
if (n1 == 0) \
|
|
||||||
colour1 = *data; \
|
|
||||||
\
|
|
||||||
if (*data == colour1) { \
|
|
||||||
n1++; \
|
|
||||||
continue; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
if (n2 == 0) { \
|
|
||||||
*solid = FALSE; \
|
|
||||||
colour2 = *data; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
if (*data == colour2) { \
|
|
||||||
n2++; \
|
|
||||||
continue; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
*mono = FALSE; \
|
|
||||||
break; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
if (n1 > n2) { \
|
|
||||||
*bg = colour1; \
|
|
||||||
*fg = colour2; \
|
|
||||||
} else { \
|
|
||||||
*bg = colour2; \
|
|
||||||
*fg = colour1; \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
DEFINE_SEND_HEXTILES(8)
|
|
||||||
DEFINE_SEND_HEXTILES(16)
|
|
||||||
DEFINE_SEND_HEXTILES(32)
|
|
@ -1,423 +0,0 @@
|
|||||||
/*
|
|
||||||
* httpd.c - a simple HTTP server
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
|
||||||
* USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#ifdef WIN32
|
|
||||||
#include <winsock.h>
|
|
||||||
#define close closesocket
|
|
||||||
#else
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <netinet/tcp.h>
|
|
||||||
#include <netdb.h>
|
|
||||||
#include <pwd.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#endif
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#ifdef __osf__
|
|
||||||
typedef int socklen_t;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_LIBWRAP
|
|
||||||
#include <tcpd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "rfb.h"
|
|
||||||
|
|
||||||
#define NOT_FOUND_STR "HTTP/1.0 404 Not found\n\n" \
|
|
||||||
"<HEAD><TITLE>File Not Found</TITLE></HEAD>\n" \
|
|
||||||
"<BODY><H1>File Not Found</H1></BODY>\n"
|
|
||||||
|
|
||||||
#define OK_STR "HTTP/1.0 200 OK\nContent-Type: text/html\n\n"
|
|
||||||
|
|
||||||
static void httpProcessInput();
|
|
||||||
static Bool compareAndSkip(char **ptr, const char *str);
|
|
||||||
|
|
||||||
/*
|
|
||||||
int httpPort = 0;
|
|
||||||
char *httpDir = NULL;
|
|
||||||
|
|
||||||
int httpListenSock = -1;
|
|
||||||
int httpSock = -1;
|
|
||||||
FILE* httpFP = NULL;
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define BUF_SIZE 32768
|
|
||||||
|
|
||||||
static char buf[BUF_SIZE];
|
|
||||||
static size_t buf_filled=0;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* httpInitSockets sets up the TCP socket to listen for HTTP connections.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
httpInitSockets(rfbScreenInfoPtr rfbScreen)
|
|
||||||
{
|
|
||||||
if (rfbScreen->httpInitDone)
|
|
||||||
return;
|
|
||||||
|
|
||||||
rfbScreen->httpInitDone = TRUE;
|
|
||||||
|
|
||||||
if (!rfbScreen->httpDir)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (rfbScreen->httpPort == 0) {
|
|
||||||
rfbScreen->httpPort = rfbScreen->rfbPort-100;
|
|
||||||
}
|
|
||||||
|
|
||||||
rfbLog("Listening for HTTP connections on TCP port %d\n", rfbScreen->httpPort);
|
|
||||||
|
|
||||||
rfbLog(" URL http://%s:%d\n",rfbScreen->rfbThisHost,rfbScreen->httpPort);
|
|
||||||
|
|
||||||
if ((rfbScreen->httpListenSock = ListenOnTCPPort(rfbScreen->httpPort)) < 0) {
|
|
||||||
rfbLogPerror("ListenOnTCPPort");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*AddEnabledDevice(httpListenSock);*/
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* httpCheckFds is called from ProcessInputEvents to check for input on the
|
|
||||||
* HTTP socket(s). If there is input to process, httpProcessInput is called.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
httpCheckFds(rfbScreenInfoPtr rfbScreen)
|
|
||||||
{
|
|
||||||
int nfds;
|
|
||||||
fd_set fds;
|
|
||||||
struct timeval tv;
|
|
||||||
struct sockaddr_in addr;
|
|
||||||
size_t addrlen = sizeof(addr);
|
|
||||||
|
|
||||||
if (!rfbScreen->httpDir)
|
|
||||||
return;
|
|
||||||
|
|
||||||
FD_ZERO(&fds);
|
|
||||||
FD_SET(rfbScreen->httpListenSock, &fds);
|
|
||||||
if (rfbScreen->httpSock >= 0) {
|
|
||||||
FD_SET(rfbScreen->httpSock, &fds);
|
|
||||||
}
|
|
||||||
tv.tv_sec = 0;
|
|
||||||
tv.tv_usec = 0;
|
|
||||||
nfds = select(max(rfbScreen->httpSock,rfbScreen->httpListenSock) + 1, &fds, NULL, NULL, &tv);
|
|
||||||
if (nfds == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (nfds < 0) {
|
|
||||||
#ifdef WIN32
|
|
||||||
errno = WSAGetLastError();
|
|
||||||
#endif
|
|
||||||
rfbLogPerror("httpCheckFds: select");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((rfbScreen->httpSock >= 0) && FD_ISSET(rfbScreen->httpSock, &fds)) {
|
|
||||||
httpProcessInput(rfbScreen);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FD_ISSET(rfbScreen->httpListenSock, &fds)) {
|
|
||||||
int flags;
|
|
||||||
if (rfbScreen->httpSock >= 0) close(rfbScreen->httpSock);
|
|
||||||
|
|
||||||
if ((rfbScreen->httpSock = accept(rfbScreen->httpListenSock,
|
|
||||||
(struct sockaddr *)&addr, &addrlen)) < 0) {
|
|
||||||
rfbLogPerror("httpCheckFds: accept");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#ifdef USE_LIBWRAP
|
|
||||||
if(!hosts_ctl("vnc",STRING_UNKNOWN,inet_ntoa(addr.sin_addr),
|
|
||||||
STRING_UNKNOWN)) {
|
|
||||||
rfbLog("Rejected connection from client %s\n",
|
|
||||||
inet_ntoa(addr.sin_addr));
|
|
||||||
#else
|
|
||||||
if ((rfbScreen->httpFP = fdopen(rfbScreen->httpSock, "r+")) == NULL) {
|
|
||||||
rfbLogPerror("httpCheckFds: fdopen");
|
|
||||||
#endif
|
|
||||||
close(rfbScreen->httpSock);
|
|
||||||
rfbScreen->httpSock = -1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
flags=fcntl(rfbScreen->httpSock,F_GETFL);
|
|
||||||
if(flags==-1 ||
|
|
||||||
fcntl(rfbScreen->httpSock,F_SETFL,flags|O_NONBLOCK)==-1) {
|
|
||||||
rfbLogPerror("httpCheckFds: fcntl");
|
|
||||||
close(rfbScreen->httpSock);
|
|
||||||
rfbScreen->httpSock=-1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*AddEnabledDevice(httpSock);*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
httpCloseSock(rfbScreenInfoPtr rfbScreen)
|
|
||||||
{
|
|
||||||
fclose(rfbScreen->httpFP);
|
|
||||||
rfbScreen->httpFP = NULL;
|
|
||||||
/*RemoveEnabledDevice(httpSock);*/
|
|
||||||
rfbScreen->httpSock = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static rfbClientRec cl;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* httpProcessInput is called when input is received on the HTTP socket.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void
|
|
||||||
httpProcessInput(rfbScreenInfoPtr rfbScreen)
|
|
||||||
{
|
|
||||||
struct sockaddr_in addr;
|
|
||||||
size_t addrlen = sizeof(addr);
|
|
||||||
char fullFname[256];
|
|
||||||
char *fname;
|
|
||||||
unsigned int maxFnameLen;
|
|
||||||
FILE* fd;
|
|
||||||
Bool performSubstitutions = FALSE;
|
|
||||||
char str[256];
|
|
||||||
#ifndef WIN32
|
|
||||||
struct passwd *user = getpwuid(getuid());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
cl.sock=rfbScreen->httpSock;
|
|
||||||
|
|
||||||
if (strlen(rfbScreen->httpDir) > 200) {
|
|
||||||
rfbLog("-httpd directory too long\n");
|
|
||||||
httpCloseSock(rfbScreen);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
strcpy(fullFname, rfbScreen->httpDir);
|
|
||||||
fname = &fullFname[strlen(fullFname)];
|
|
||||||
maxFnameLen = 255 - strlen(fullFname);
|
|
||||||
|
|
||||||
/* Read data from the HTTP client until we get a complete request. */
|
|
||||||
while (1) {
|
|
||||||
ssize_t got = read (rfbScreen->httpSock, buf + buf_filled,
|
|
||||||
sizeof (buf) - buf_filled - 1);
|
|
||||||
|
|
||||||
if (got <= 0) {
|
|
||||||
if (got == 0) {
|
|
||||||
rfbLog("httpd: premature connection close\n");
|
|
||||||
} else {
|
|
||||||
if (errno == EAGAIN) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
rfbLogPerror("httpProcessInput: read");
|
|
||||||
}
|
|
||||||
httpCloseSock(rfbScreen);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
buf_filled += got;
|
|
||||||
buf[buf_filled] = '\0';
|
|
||||||
|
|
||||||
/* Is it complete yet (is there a blank line)? */
|
|
||||||
if (strstr (buf, "\r\r") || strstr (buf, "\n\n") ||
|
|
||||||
strstr (buf, "\r\n\r\n") || strstr (buf, "\n\r\n\r"))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Process the request. */
|
|
||||||
if (strncmp(buf, "GET ", 4)) {
|
|
||||||
rfbLog("no GET line\n");
|
|
||||||
httpCloseSock(rfbScreen);
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
/* Only use the first line. */
|
|
||||||
buf[strcspn(buf, "\n\r")] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strlen(buf) > maxFnameLen) {
|
|
||||||
rfbLog("GET line too long\n");
|
|
||||||
httpCloseSock(rfbScreen);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sscanf(buf, "GET %s HTTP/1.0", fname) != 1) {
|
|
||||||
rfbLog("couldn't parse GET line\n");
|
|
||||||
httpCloseSock(rfbScreen);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fname[0] != '/') {
|
|
||||||
rfbLog("filename didn't begin with '/'\n");
|
|
||||||
WriteExact(&cl, NOT_FOUND_STR, strlen(NOT_FOUND_STR));
|
|
||||||
httpCloseSock(rfbScreen);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strchr(fname+1, '/') != NULL) {
|
|
||||||
rfbLog("asking for file in other directory\n");
|
|
||||||
WriteExact(&cl, NOT_FOUND_STR, strlen(NOT_FOUND_STR));
|
|
||||||
httpCloseSock(rfbScreen);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
getpeername(rfbScreen->httpSock, (struct sockaddr *)&addr, &addrlen);
|
|
||||||
rfbLog("httpd: get '%s' for %s\n", fname+1,
|
|
||||||
inet_ntoa(addr.sin_addr));
|
|
||||||
|
|
||||||
/* If we were asked for '/', actually read the file index.vnc */
|
|
||||||
|
|
||||||
if (strcmp(fname, "/") == 0) {
|
|
||||||
strcpy(fname, "/index.vnc");
|
|
||||||
rfbLog("httpd: defaulting to '%s'\n", fname+1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Substitutions are performed on files ending .vnc */
|
|
||||||
|
|
||||||
if (strlen(fname) >= 4 && strcmp(&fname[strlen(fname)-4], ".vnc") == 0) {
|
|
||||||
performSubstitutions = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Open the file */
|
|
||||||
|
|
||||||
if ((fd = fopen(fullFname, "r")) <= 0) {
|
|
||||||
rfbLogPerror("httpProcessInput: open");
|
|
||||||
WriteExact(&cl, NOT_FOUND_STR, strlen(NOT_FOUND_STR));
|
|
||||||
httpCloseSock(rfbScreen);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
WriteExact(&cl, OK_STR, strlen(OK_STR));
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
int n = fread(buf, 1, BUF_SIZE-1, fd);
|
|
||||||
if (n < 0) {
|
|
||||||
rfbLogPerror("httpProcessInput: read");
|
|
||||||
fclose(fd);
|
|
||||||
httpCloseSock(rfbScreen);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (n == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (performSubstitutions) {
|
|
||||||
|
|
||||||
/* Substitute $WIDTH, $HEIGHT, etc with the appropriate values.
|
|
||||||
This won't quite work properly if the .vnc file is longer than
|
|
||||||
BUF_SIZE, but it's reasonable to assume that .vnc files will
|
|
||||||
always be short. */
|
|
||||||
|
|
||||||
char *ptr = buf;
|
|
||||||
char *dollar;
|
|
||||||
buf[n] = 0; /* make sure it's null-terminated */
|
|
||||||
|
|
||||||
while ((dollar = strchr(ptr, '$'))!=NULL) {
|
|
||||||
WriteExact(&cl, ptr, (dollar - ptr));
|
|
||||||
|
|
||||||
ptr = dollar;
|
|
||||||
|
|
||||||
if (compareAndSkip(&ptr, "$WIDTH")) {
|
|
||||||
|
|
||||||
sprintf(str, "%d", rfbScreen->width);
|
|
||||||
WriteExact(&cl, str, strlen(str));
|
|
||||||
|
|
||||||
} else if (compareAndSkip(&ptr, "$HEIGHT")) {
|
|
||||||
|
|
||||||
sprintf(str, "%d", rfbScreen->height);
|
|
||||||
WriteExact(&cl, str, strlen(str));
|
|
||||||
|
|
||||||
} else if (compareAndSkip(&ptr, "$APPLETWIDTH")) {
|
|
||||||
|
|
||||||
sprintf(str, "%d", rfbScreen->width);
|
|
||||||
WriteExact(&cl, str, strlen(str));
|
|
||||||
|
|
||||||
} else if (compareAndSkip(&ptr, "$APPLETHEIGHT")) {
|
|
||||||
|
|
||||||
sprintf(str, "%d", rfbScreen->height + 32);
|
|
||||||
WriteExact(&cl, str, strlen(str));
|
|
||||||
|
|
||||||
} else if (compareAndSkip(&ptr, "$PORT")) {
|
|
||||||
|
|
||||||
sprintf(str, "%d", rfbScreen->rfbPort);
|
|
||||||
WriteExact(&cl, str, strlen(str));
|
|
||||||
|
|
||||||
} else if (compareAndSkip(&ptr, "$DESKTOP")) {
|
|
||||||
|
|
||||||
WriteExact(&cl, rfbScreen->desktopName, strlen(rfbScreen->desktopName));
|
|
||||||
|
|
||||||
} else if (compareAndSkip(&ptr, "$DISPLAY")) {
|
|
||||||
|
|
||||||
sprintf(str, "%s:%d", rfbScreen->rfbThisHost, rfbScreen->rfbPort-5900);
|
|
||||||
WriteExact(&cl, str, strlen(str));
|
|
||||||
|
|
||||||
} else if (compareAndSkip(&ptr, "$USER")) {
|
|
||||||
#ifndef WIN32
|
|
||||||
if (user) {
|
|
||||||
WriteExact(&cl, user->pw_name,
|
|
||||||
strlen(user->pw_name));
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
WriteExact(&cl, "?", 1);
|
|
||||||
} else {
|
|
||||||
if (!compareAndSkip(&ptr, "$$"))
|
|
||||||
ptr++;
|
|
||||||
|
|
||||||
if (WriteExact(&cl, "$", 1) < 0) {
|
|
||||||
fclose(fd);
|
|
||||||
httpCloseSock(rfbScreen);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (WriteExact(&cl, ptr, (&buf[n] - ptr)) < 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
/* For files not ending .vnc, just write out the buffer */
|
|
||||||
|
|
||||||
if (WriteExact(&cl, buf, n) < 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(fd);
|
|
||||||
httpCloseSock(rfbScreen);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static Bool
|
|
||||||
compareAndSkip(char **ptr, const char *str)
|
|
||||||
{
|
|
||||||
if (strncmp(*ptr, str, strlen(str)) == 0) {
|
|
||||||
*ptr += strlen(str);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@ -1,604 +0,0 @@
|
|||||||
|
|
||||||
/*
|
|
||||||
* OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
|
|
||||||
* Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
|
|
||||||
* All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Cut in two parts by Johannes Schindelin (2001): libvncserver and OSXvnc.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* This file implements every system specific function for Mac OS X.
|
|
||||||
*
|
|
||||||
* It includes the keyboard functions:
|
|
||||||
*
|
|
||||||
void KbdAddEvent(down, keySym, cl)
|
|
||||||
Bool down;
|
|
||||||
KeySym keySym;
|
|
||||||
rfbClientPtr cl;
|
|
||||||
void KbdReleaseAllKeys()
|
|
||||||
*
|
|
||||||
* the mouse functions:
|
|
||||||
*
|
|
||||||
void PtrAddEvent(buttonMask, x, y, cl)
|
|
||||||
int buttonMask;
|
|
||||||
int x;
|
|
||||||
int y;
|
|
||||||
rfbClientPtr cl;
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define LOCAL_CONTROL
|
|
||||||
|
|
||||||
#ifdef LOCAL_CONTROL
|
|
||||||
#include "1instance.c"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <ApplicationServices/ApplicationServices.h>
|
|
||||||
#include <Carbon/Carbon.h>
|
|
||||||
/* zlib doesn't like Byte already defined */
|
|
||||||
#undef Byte
|
|
||||||
#undef TRUE
|
|
||||||
#undef Bool
|
|
||||||
#include "rfb.h"
|
|
||||||
#include "keysym.h"
|
|
||||||
|
|
||||||
#include <IOKit/pwr_mgt/IOPMLib.h>
|
|
||||||
#include <IOKit/pwr_mgt/IOPM.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <pthread.h>
|
|
||||||
|
|
||||||
Bool rfbNoDimming = FALSE;
|
|
||||||
Bool rfbNoSleep = TRUE;
|
|
||||||
|
|
||||||
static pthread_mutex_t dimming_mutex;
|
|
||||||
static unsigned long dim_time;
|
|
||||||
static unsigned long sleep_time;
|
|
||||||
static mach_port_t master_dev_port;
|
|
||||||
static io_connect_t power_mgt;
|
|
||||||
static Bool initialized = FALSE;
|
|
||||||
static Bool dim_time_saved = FALSE;
|
|
||||||
static Bool sleep_time_saved = FALSE;
|
|
||||||
|
|
||||||
static int
|
|
||||||
saveDimSettings(void)
|
|
||||||
{
|
|
||||||
if (IOPMGetAggressiveness(power_mgt,
|
|
||||||
kPMMinutesToDim,
|
|
||||||
&dim_time) != kIOReturnSuccess)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
dim_time_saved = TRUE;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
restoreDimSettings(void)
|
|
||||||
{
|
|
||||||
if (!dim_time_saved)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (IOPMSetAggressiveness(power_mgt,
|
|
||||||
kPMMinutesToDim,
|
|
||||||
dim_time) != kIOReturnSuccess)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
dim_time_saved = FALSE;
|
|
||||||
dim_time = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
saveSleepSettings(void)
|
|
||||||
{
|
|
||||||
if (IOPMGetAggressiveness(power_mgt,
|
|
||||||
kPMMinutesToSleep,
|
|
||||||
&sleep_time) != kIOReturnSuccess)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
sleep_time_saved = TRUE;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
restoreSleepSettings(void)
|
|
||||||
{
|
|
||||||
if (!sleep_time_saved)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (IOPMSetAggressiveness(power_mgt,
|
|
||||||
kPMMinutesToSleep,
|
|
||||||
sleep_time) != kIOReturnSuccess)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
sleep_time_saved = FALSE;
|
|
||||||
sleep_time = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
rfbDimmingInit(void)
|
|
||||||
{
|
|
||||||
pthread_mutex_init(&dimming_mutex, NULL);
|
|
||||||
|
|
||||||
if (IOMasterPort(bootstrap_port, &master_dev_port) != kIOReturnSuccess)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (!(power_mgt = IOPMFindPowerManagement(master_dev_port)))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (rfbNoDimming) {
|
|
||||||
if (saveDimSettings() < 0)
|
|
||||||
return -1;
|
|
||||||
if (IOPMSetAggressiveness(power_mgt,
|
|
||||||
kPMMinutesToDim, 0) != kIOReturnSuccess)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rfbNoSleep) {
|
|
||||||
if (saveSleepSettings() < 0)
|
|
||||||
return -1;
|
|
||||||
if (IOPMSetAggressiveness(power_mgt,
|
|
||||||
kPMMinutesToSleep, 0) != kIOReturnSuccess)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
initialized = TRUE;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
rfbUndim(void)
|
|
||||||
{
|
|
||||||
int result = -1;
|
|
||||||
|
|
||||||
pthread_mutex_lock(&dimming_mutex);
|
|
||||||
|
|
||||||
if (!initialized)
|
|
||||||
goto DONE;
|
|
||||||
|
|
||||||
if (!rfbNoDimming) {
|
|
||||||
if (saveDimSettings() < 0)
|
|
||||||
goto DONE;
|
|
||||||
if (IOPMSetAggressiveness(power_mgt, kPMMinutesToDim, 0) != kIOReturnSuccess)
|
|
||||||
goto DONE;
|
|
||||||
if (restoreDimSettings() < 0)
|
|
||||||
goto DONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!rfbNoSleep) {
|
|
||||||
if (saveSleepSettings() < 0)
|
|
||||||
goto DONE;
|
|
||||||
if (IOPMSetAggressiveness(power_mgt, kPMMinutesToSleep, 0) != kIOReturnSuccess)
|
|
||||||
goto DONE;
|
|
||||||
if (restoreSleepSettings() < 0)
|
|
||||||
goto DONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = 0;
|
|
||||||
|
|
||||||
DONE:
|
|
||||||
pthread_mutex_unlock(&dimming_mutex);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
rfbDimmingShutdown(void)
|
|
||||||
{
|
|
||||||
int result = -1;
|
|
||||||
|
|
||||||
if (!initialized)
|
|
||||||
goto DONE;
|
|
||||||
|
|
||||||
pthread_mutex_lock(&dimming_mutex);
|
|
||||||
if (dim_time_saved)
|
|
||||||
if (restoreDimSettings() < 0)
|
|
||||||
goto DONE;
|
|
||||||
if (sleep_time_saved)
|
|
||||||
if (restoreSleepSettings() < 0)
|
|
||||||
goto DONE;
|
|
||||||
|
|
||||||
result = 0;
|
|
||||||
|
|
||||||
DONE:
|
|
||||||
pthread_mutex_unlock(&dimming_mutex);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
rfbScreenInfoPtr rfbScreen;
|
|
||||||
|
|
||||||
void rfbShutdown(rfbClientPtr cl);
|
|
||||||
|
|
||||||
/* some variables to enable special behaviour */
|
|
||||||
int startTime = -1, maxSecsToConnect = 0;
|
|
||||||
Bool disconnectAfterFirstClient = TRUE;
|
|
||||||
|
|
||||||
/* Where do I get the "official" list of Mac key codes?
|
|
||||||
Ripped these out of a Mac II emulator called Basilisk II
|
|
||||||
that I found on the net. */
|
|
||||||
static int keyTable[] = {
|
|
||||||
/* The alphabet */
|
|
||||||
XK_A, 0, /* A */
|
|
||||||
XK_B, 11, /* B */
|
|
||||||
XK_C, 8, /* C */
|
|
||||||
XK_D, 2, /* D */
|
|
||||||
XK_E, 14, /* E */
|
|
||||||
XK_F, 3, /* F */
|
|
||||||
XK_G, 5, /* G */
|
|
||||||
XK_H, 4, /* H */
|
|
||||||
XK_I, 34, /* I */
|
|
||||||
XK_J, 38, /* J */
|
|
||||||
XK_K, 40, /* K */
|
|
||||||
XK_L, 37, /* L */
|
|
||||||
XK_M, 46, /* M */
|
|
||||||
XK_N, 45, /* N */
|
|
||||||
XK_O, 31, /* O */
|
|
||||||
XK_P, 35, /* P */
|
|
||||||
XK_Q, 12, /* Q */
|
|
||||||
XK_R, 15, /* R */
|
|
||||||
XK_S, 1, /* S */
|
|
||||||
XK_T, 17, /* T */
|
|
||||||
XK_U, 32, /* U */
|
|
||||||
XK_V, 9, /* V */
|
|
||||||
XK_W, 13, /* W */
|
|
||||||
XK_X, 7, /* X */
|
|
||||||
XK_Y, 16, /* Y */
|
|
||||||
XK_Z, 6, /* Z */
|
|
||||||
XK_a, 0, /* a */
|
|
||||||
XK_b, 11, /* b */
|
|
||||||
XK_c, 8, /* c */
|
|
||||||
XK_d, 2, /* d */
|
|
||||||
XK_e, 14, /* e */
|
|
||||||
XK_f, 3, /* f */
|
|
||||||
XK_g, 5, /* g */
|
|
||||||
XK_h, 4, /* h */
|
|
||||||
XK_i, 34, /* i */
|
|
||||||
XK_j, 38, /* j */
|
|
||||||
XK_k, 40, /* k */
|
|
||||||
XK_l, 37, /* l */
|
|
||||||
XK_m, 46, /* m */
|
|
||||||
XK_n, 45, /* n */
|
|
||||||
XK_o, 31, /* o */
|
|
||||||
XK_p, 35, /* p */
|
|
||||||
XK_q, 12, /* q */
|
|
||||||
XK_r, 15, /* r */
|
|
||||||
XK_s, 1, /* s */
|
|
||||||
XK_t, 17, /* t */
|
|
||||||
XK_u, 32, /* u */
|
|
||||||
XK_v, 9, /* v */
|
|
||||||
XK_w, 13, /* w */
|
|
||||||
XK_x, 7, /* x */
|
|
||||||
XK_y, 16, /* y */
|
|
||||||
XK_z, 6, /* z */
|
|
||||||
|
|
||||||
/* Numbers */
|
|
||||||
XK_0, 29, /* 0 */
|
|
||||||
XK_1, 18, /* 1 */
|
|
||||||
XK_2, 19, /* 2 */
|
|
||||||
XK_3, 20, /* 3 */
|
|
||||||
XK_4, 21, /* 4 */
|
|
||||||
XK_5, 23, /* 5 */
|
|
||||||
XK_6, 22, /* 6 */
|
|
||||||
XK_7, 26, /* 7 */
|
|
||||||
XK_8, 28, /* 8 */
|
|
||||||
XK_9, 25, /* 9 */
|
|
||||||
|
|
||||||
/* Symbols */
|
|
||||||
XK_exclam, 18, /* ! */
|
|
||||||
XK_at, 19, /* @ */
|
|
||||||
XK_numbersign, 20, /* # */
|
|
||||||
XK_dollar, 21, /* $ */
|
|
||||||
XK_percent, 23, /* % */
|
|
||||||
XK_asciicircum, 22, /* ^ */
|
|
||||||
XK_ampersand, 26, /* & */
|
|
||||||
XK_asterisk, 28, /* * */
|
|
||||||
XK_parenleft, 25, /* ( */
|
|
||||||
XK_parenright, 29, /* ) */
|
|
||||||
XK_minus, 27, /* - */
|
|
||||||
XK_underscore, 27, /* _ */
|
|
||||||
XK_equal, 24, /* = */
|
|
||||||
XK_plus, 24, /* + */
|
|
||||||
XK_grave, 10, /* ` */ /* XXX ? */
|
|
||||||
XK_asciitilde, 10, /* ~ */
|
|
||||||
XK_bracketleft, 33, /* [ */
|
|
||||||
XK_braceleft, 33, /* { */
|
|
||||||
XK_bracketright, 30, /* ] */
|
|
||||||
XK_braceright, 30, /* } */
|
|
||||||
XK_semicolon, 41, /* ; */
|
|
||||||
XK_colon, 41, /* : */
|
|
||||||
XK_apostrophe, 39, /* ' */
|
|
||||||
XK_quotedbl, 39, /* " */
|
|
||||||
XK_comma, 43, /* , */
|
|
||||||
XK_less, 43, /* < */
|
|
||||||
XK_period, 47, /* . */
|
|
||||||
XK_greater, 47, /* > */
|
|
||||||
XK_slash, 44, /* / */
|
|
||||||
XK_question, 44, /* ? */
|
|
||||||
XK_backslash, 42, /* \ */
|
|
||||||
XK_bar, 42, /* | */
|
|
||||||
|
|
||||||
/* "Special" keys */
|
|
||||||
XK_space, 49, /* Space */
|
|
||||||
XK_Return, 36, /* Return */
|
|
||||||
XK_Delete, 117, /* Delete */
|
|
||||||
XK_Tab, 48, /* Tab */
|
|
||||||
XK_Escape, 53, /* Esc */
|
|
||||||
XK_Caps_Lock, 57, /* Caps Lock */
|
|
||||||
XK_Num_Lock, 71, /* Num Lock */
|
|
||||||
XK_Scroll_Lock, 107, /* Scroll Lock */
|
|
||||||
XK_Pause, 113, /* Pause */
|
|
||||||
XK_BackSpace, 51, /* Backspace */
|
|
||||||
XK_Insert, 114, /* Insert */
|
|
||||||
|
|
||||||
/* Cursor movement */
|
|
||||||
XK_Up, 126, /* Cursor Up */
|
|
||||||
XK_Down, 125, /* Cursor Down */
|
|
||||||
XK_Left, 123, /* Cursor Left */
|
|
||||||
XK_Right, 124, /* Cursor Right */
|
|
||||||
XK_Page_Up, 116, /* Page Up */
|
|
||||||
XK_Page_Down, 121, /* Page Down */
|
|
||||||
XK_Home, 115, /* Home */
|
|
||||||
XK_End, 119, /* End */
|
|
||||||
|
|
||||||
/* Numeric keypad */
|
|
||||||
XK_KP_0, 82, /* KP 0 */
|
|
||||||
XK_KP_1, 83, /* KP 1 */
|
|
||||||
XK_KP_2, 84, /* KP 2 */
|
|
||||||
XK_KP_3, 85, /* KP 3 */
|
|
||||||
XK_KP_4, 86, /* KP 4 */
|
|
||||||
XK_KP_5, 87, /* KP 5 */
|
|
||||||
XK_KP_6, 88, /* KP 6 */
|
|
||||||
XK_KP_7, 89, /* KP 7 */
|
|
||||||
XK_KP_8, 91, /* KP 8 */
|
|
||||||
XK_KP_9, 92, /* KP 9 */
|
|
||||||
XK_KP_Enter, 76, /* KP Enter */
|
|
||||||
XK_KP_Decimal, 65, /* KP . */
|
|
||||||
XK_KP_Add, 69, /* KP + */
|
|
||||||
XK_KP_Subtract, 78, /* KP - */
|
|
||||||
XK_KP_Multiply, 67, /* KP * */
|
|
||||||
XK_KP_Divide, 75, /* KP / */
|
|
||||||
|
|
||||||
/* Function keys */
|
|
||||||
XK_F1, 122, /* F1 */
|
|
||||||
XK_F2, 120, /* F2 */
|
|
||||||
XK_F3, 99, /* F3 */
|
|
||||||
XK_F4, 118, /* F4 */
|
|
||||||
XK_F5, 96, /* F5 */
|
|
||||||
XK_F6, 97, /* F6 */
|
|
||||||
XK_F7, 98, /* F7 */
|
|
||||||
XK_F8, 100, /* F8 */
|
|
||||||
XK_F9, 101, /* F9 */
|
|
||||||
XK_F10, 109, /* F10 */
|
|
||||||
XK_F11, 103, /* F11 */
|
|
||||||
XK_F12, 111, /* F12 */
|
|
||||||
|
|
||||||
/* Modifier keys */
|
|
||||||
XK_Shift_L, 56, /* Shift Left */
|
|
||||||
XK_Shift_R, 56, /* Shift Right */
|
|
||||||
XK_Control_L, 59, /* Ctrl Left */
|
|
||||||
XK_Control_R, 59, /* Ctrl Right */
|
|
||||||
XK_Meta_L, 58, /* Logo Left (-> Option) */
|
|
||||||
XK_Meta_R, 58, /* Logo Right (-> Option) */
|
|
||||||
XK_Alt_L, 55, /* Alt Left (-> Command) */
|
|
||||||
XK_Alt_R, 55, /* Alt Right (-> Command) */
|
|
||||||
|
|
||||||
/* Weirdness I can't figure out */
|
|
||||||
/* XK_3270_PrintScreen, 105, /* PrintScrn */ /* XXX ? */
|
|
||||||
/* ??? 94, 50, /* International */
|
|
||||||
XK_Menu, 50, /* Menu (-> International) */
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
|
||||||
KbdAddEvent(Bool down, KeySym keySym, struct _rfbClientRec* cl)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
CGKeyCode keyCode = -1;
|
|
||||||
int found = 0;
|
|
||||||
|
|
||||||
if(((int)cl->clientData)==-1) return; /* viewOnly */
|
|
||||||
|
|
||||||
rfbUndim();
|
|
||||||
|
|
||||||
for (i = 0; i < (sizeof(keyTable) / sizeof(int)); i += 2) {
|
|
||||||
if (keyTable[i] == keySym) {
|
|
||||||
keyCode = keyTable[i+1];
|
|
||||||
found = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found) {
|
|
||||||
rfbLog("warning: couldn't figure out keycode for X keysym %d (0x%x)\n",
|
|
||||||
(int)keySym, (int)keySym);
|
|
||||||
} else {
|
|
||||||
/* Hopefully I can get away with not specifying a CGCharCode.
|
|
||||||
(Why would you need both?) */
|
|
||||||
CGPostKeyboardEvent((CGCharCode)0, keyCode, down);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PtrAddEvent(buttonMask, x, y, cl)
|
|
||||||
int buttonMask;
|
|
||||||
int x;
|
|
||||||
int y;
|
|
||||||
rfbClientPtr cl;
|
|
||||||
{
|
|
||||||
CGPoint position;
|
|
||||||
|
|
||||||
if(((int)cl->clientData)==-1) return; /* viewOnly */
|
|
||||||
|
|
||||||
rfbUndim();
|
|
||||||
|
|
||||||
position.x = x;
|
|
||||||
position.y = y;
|
|
||||||
|
|
||||||
CGPostMouseEvent(position, TRUE, 8,
|
|
||||||
(buttonMask & (1 << 0)) ? TRUE : FALSE,
|
|
||||||
(buttonMask & (1 << 1)) ? TRUE : FALSE,
|
|
||||||
(buttonMask & (1 << 2)) ? TRUE : FALSE,
|
|
||||||
(buttonMask & (1 << 3)) ? TRUE : FALSE,
|
|
||||||
(buttonMask & (1 << 4)) ? TRUE : FALSE,
|
|
||||||
(buttonMask & (1 << 5)) ? TRUE : FALSE,
|
|
||||||
(buttonMask & (1 << 6)) ? TRUE : FALSE,
|
|
||||||
(buttonMask & (1 << 7)) ? TRUE : FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
Bool viewOnly = FALSE, sharedMode = FALSE;
|
|
||||||
|
|
||||||
void
|
|
||||||
ScreenInit(int argc, char**argv)
|
|
||||||
{
|
|
||||||
int bitsPerSample=CGDisplayBitsPerSample(kCGDirectMainDisplay);
|
|
||||||
rfbScreen = rfbGetScreen(&argc,argv,
|
|
||||||
CGDisplayPixelsWide(kCGDirectMainDisplay),
|
|
||||||
CGDisplayPixelsHigh(kCGDirectMainDisplay),
|
|
||||||
bitsPerSample,
|
|
||||||
CGDisplaySamplesPerPixel(kCGDirectMainDisplay),4);
|
|
||||||
rfbScreen->rfbServerFormat.redShift = bitsPerSample*2;
|
|
||||||
rfbScreen->rfbServerFormat.greenShift = bitsPerSample*1;
|
|
||||||
rfbScreen->rfbServerFormat.blueShift = 0;
|
|
||||||
|
|
||||||
gethostname(rfbScreen->rfbThisHost, 255);
|
|
||||||
rfbScreen->paddedWidthInBytes = CGDisplayBytesPerRow(kCGDirectMainDisplay);
|
|
||||||
rfbScreen->frameBuffer =
|
|
||||||
(char *)CGDisplayBaseAddress(kCGDirectMainDisplay);
|
|
||||||
|
|
||||||
rfbScreen->ptrAddEvent = PtrAddEvent;
|
|
||||||
rfbScreen->kbdAddEvent = KbdAddEvent;
|
|
||||||
|
|
||||||
if(sharedMode) {
|
|
||||||
rfbScreen->rfbAlwaysShared = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
rfbInitServer(rfbScreen);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef LOCAL_CONTROL
|
|
||||||
single_instance_struct single_instance = { "/tmp/OSXvnc_control" };
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void
|
|
||||||
refreshCallback(CGRectCount count, const CGRect *rectArray, void *ignore)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
#ifdef LOCAL_CONTROL
|
|
||||||
char message[1024];
|
|
||||||
|
|
||||||
if(get_next_message(message,1024,&single_instance,50)) {
|
|
||||||
if(message[0]=='l' && message[1]==0) {
|
|
||||||
rfbClientPtr cl;
|
|
||||||
int i;
|
|
||||||
for(i=0,cl=rfbScreen->rfbClientHead;cl;cl=cl->next,i++)
|
|
||||||
fprintf(stderr,"%02d: %s\n",i,cl->host);
|
|
||||||
} else if(message[0]=='t') {
|
|
||||||
rfbClientPtr cl;
|
|
||||||
for(cl=rfbScreen->rfbClientHead;cl;cl=cl->next)
|
|
||||||
if(!strcmp(message+1,cl->host)) {
|
|
||||||
cl->clientData=(void*)((cl->clientData==0)?-1:0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifdef BACKCHANNEL
|
|
||||||
else if(message[0]=='b')
|
|
||||||
rfbSendBackChannel(rfbScreen,message+1,strlen(message+1));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(startTime>0 && time(0)>startTime+maxSecsToConnect)
|
|
||||||
rfbShutdown(0);
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
rfbMarkRectAsModified(rfbScreen,
|
|
||||||
rectArray[i].origin.x,rectArray[i].origin.y,
|
|
||||||
rectArray[i].origin.x + rectArray[i].size.width,
|
|
||||||
rectArray[i].origin.y + rectArray[i].size.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
void clientGone(rfbClientPtr cl)
|
|
||||||
{
|
|
||||||
rfbShutdown(cl);
|
|
||||||
}
|
|
||||||
|
|
||||||
enum rfbNewClientAction newClient(rfbClientPtr cl)
|
|
||||||
{
|
|
||||||
if(startTime>0 && time(0)>startTime+maxSecsToConnect)
|
|
||||||
rfbShutdown(cl);
|
|
||||||
|
|
||||||
if(disconnectAfterFirstClient)
|
|
||||||
cl->clientGoneHook = clientGone;
|
|
||||||
|
|
||||||
cl->clientData=(void*)((viewOnly)?-1:0);
|
|
||||||
|
|
||||||
return(RFB_CLIENT_ACCEPT);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc,char *argv[])
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
#ifdef LOCAL_CONTROL
|
|
||||||
char message[1024];
|
|
||||||
|
|
||||||
open_control_file(&single_instance);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for(i=argc-1;i>0;i--)
|
|
||||||
#ifdef LOCAL_CONTROL
|
|
||||||
if(i<argc-1 && !strcmp(argv[i],"-toggleviewonly")) {
|
|
||||||
snprintf(message, sizeof(message), "t%s",argv[i+1]);
|
|
||||||
send_message(&single_instance,message);
|
|
||||||
exit(0);
|
|
||||||
} else if(!strcmp(argv[i],"-listclients")) {
|
|
||||||
fprintf(stderr,"list clients\n");
|
|
||||||
send_message(&single_instance,"l");
|
|
||||||
exit(0);
|
|
||||||
} else
|
|
||||||
#ifdef BACKCHANNEL
|
|
||||||
if(i<argc-1 && !strcmp(argv[i],"-backchannel")) {
|
|
||||||
snprintf(message, sizeof(message), "b%s",argv[i+1]);
|
|
||||||
send_message(&single_instance,message);
|
|
||||||
exit(0);
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
if(i<argc-1 && strcmp(argv[i],"-wait4client")==0) {
|
|
||||||
maxSecsToConnect = atoi(argv[i+1])/1000;
|
|
||||||
startTime = time(0);
|
|
||||||
} else if(strcmp(argv[i],"-runforever")==0) {
|
|
||||||
disconnectAfterFirstClient = FALSE;
|
|
||||||
} else if(strcmp(argv[i],"-viewonly")==0) {
|
|
||||||
viewOnly=TRUE;
|
|
||||||
} else if(strcmp(argv[i],"-shared")==0) {
|
|
||||||
sharedMode=TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
rfbDimmingInit();
|
|
||||||
|
|
||||||
ScreenInit(argc,argv);
|
|
||||||
rfbScreen->newClientHook = newClient;
|
|
||||||
|
|
||||||
/* enter background event loop */
|
|
||||||
rfbRunEventLoop(rfbScreen,40,TRUE);
|
|
||||||
|
|
||||||
/* enter OS X loop */
|
|
||||||
CGRegisterScreenRefreshCallback(refreshCallback, NULL);
|
|
||||||
RunApplicationEventLoop();
|
|
||||||
|
|
||||||
rfbDimmingShutdown();
|
|
||||||
|
|
||||||
return(0); /* never ... */
|
|
||||||
}
|
|
||||||
|
|
||||||
void rfbShutdown(rfbClientPtr cl)
|
|
||||||
{
|
|
||||||
rfbScreenCleanup(rfbScreen);
|
|
||||||
rfbDimmingShutdown();
|
|
||||||
exit(0);
|
|
||||||
}
|
|
@ -1,830 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is called main.c, because it contains most of the new functions
|
|
||||||
* for use with LibVNCServer.
|
|
||||||
*
|
|
||||||
* LibVNCServer (C) 2001 Johannes E. Schindelin <Johannes.Schindelin@gmx.de>
|
|
||||||
* Original OSXvnc (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
|
|
||||||
* Original Xvnc (C) 1999 AT&T Laboratories Cambridge.
|
|
||||||
* All Rights Reserved.
|
|
||||||
*
|
|
||||||
* see GPL (latest version) for full details
|
|
||||||
*/
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#ifndef false
|
|
||||||
#define false 0
|
|
||||||
#define true -1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#ifdef __osf__
|
|
||||||
typedef int socklen_t;
|
|
||||||
#endif
|
|
||||||
#ifndef WIN32
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#endif
|
|
||||||
#include <signal.h>
|
|
||||||
#include <time.h>
|
|
||||||
}
|
|
||||||
|
|
||||||
#include <ntqobject.h>
|
|
||||||
#include <ntqvariant.h>
|
|
||||||
#include <ntqtimer.h>
|
|
||||||
#include <ntqthread.h>
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include "rfb.h"
|
|
||||||
#include "sraRegion.h"
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "main.h"
|
|
||||||
|
|
||||||
/* minimum interval between attempts to send something */
|
|
||||||
#define PING_MS 10000
|
|
||||||
|
|
||||||
MUTEX(logMutex);
|
|
||||||
|
|
||||||
int rfbEnableLogging=1;
|
|
||||||
|
|
||||||
/* we cannot compare to _LITTLE_ENDIAN, because some systems
|
|
||||||
(as Solaris) assume little endian if _LITTLE_ENDIAN is
|
|
||||||
defined, even if _BYTE_ORDER is not _LITTLE_ENDIAN */
|
|
||||||
char rfbEndianTest = (_BYTE_ORDER == 1234);
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
/* from rfbserver.c */
|
|
||||||
void rfbIncrClientRef(rfbClientPtr cl);
|
|
||||||
void rfbDecrClientRef(rfbClientPtr cl);
|
|
||||||
}
|
|
||||||
|
|
||||||
ControlPipeHandlerObject* mControlPipeHandler = NULL;
|
|
||||||
TQEventLoopThread* mControlPipeHandlerThread = NULL;
|
|
||||||
|
|
||||||
OnHoldClientHandlerObject* mOnHoldClientHandler = NULL;
|
|
||||||
TQEventLoopThread* mOnHoldClientHandlerThread = NULL;
|
|
||||||
|
|
||||||
void rfbLogEnable(int enabled) {
|
|
||||||
rfbEnableLogging=enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* rfbLog prints a time-stamped message to the log file (stderr).
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
rfbLog(const char *format, ...)
|
|
||||||
{
|
|
||||||
va_list args;
|
|
||||||
char buf[256];
|
|
||||||
time_t log_clock;
|
|
||||||
|
|
||||||
if(!rfbEnableLogging)
|
|
||||||
return;
|
|
||||||
|
|
||||||
LOCK(logMutex);
|
|
||||||
va_start(args, format);
|
|
||||||
|
|
||||||
time(&log_clock);
|
|
||||||
strftime(buf, 255, "%d/%m/%Y %T ", localtime(&log_clock));
|
|
||||||
fprintf(stderr, "%s", buf);
|
|
||||||
|
|
||||||
vfprintf(stderr, format, args);
|
|
||||||
fflush(stderr);
|
|
||||||
|
|
||||||
va_end(args);
|
|
||||||
UNLOCK(logMutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rfbLogPerror(const char *str)
|
|
||||||
{
|
|
||||||
rfbLog("%s: %s\n", str, strerror(errno));
|
|
||||||
}
|
|
||||||
|
|
||||||
void rfbScheduleCopyRegion(rfbScreenInfoPtr rfbScreen,sraRegionPtr copyRegion,int dx,int dy)
|
|
||||||
{
|
|
||||||
rfbClientIteratorPtr iterator;
|
|
||||||
rfbClientPtr cl;
|
|
||||||
|
|
||||||
rfbUndrawCursor(rfbScreen);
|
|
||||||
|
|
||||||
iterator=rfbGetClientIterator(rfbScreen);
|
|
||||||
while((cl=rfbClientIteratorNext(iterator))) {
|
|
||||||
LOCK(cl->updateMutex);
|
|
||||||
if(cl->useCopyRect) {
|
|
||||||
sraRegionPtr modifiedRegionBackup;
|
|
||||||
if(!sraRgnEmpty(cl->copyRegion)) {
|
|
||||||
if(cl->copyDX!=dx || cl->copyDY!=dy) {
|
|
||||||
/* if a copyRegion was not yet executed, treat it as a
|
|
||||||
* modifiedRegion. The idea: in this case it could be
|
|
||||||
* source of the new copyRect or modified anyway. */
|
|
||||||
sraRgnOr(cl->modifiedRegion,cl->copyRegion);
|
|
||||||
sraRgnMakeEmpty(cl->copyRegion);
|
|
||||||
} else {
|
|
||||||
/* we have to set the intersection of the source of the copy
|
|
||||||
* and the old copy to modified. */
|
|
||||||
modifiedRegionBackup=sraRgnCreateRgn(copyRegion);
|
|
||||||
sraRgnOffset(modifiedRegionBackup,-dx,-dy);
|
|
||||||
sraRgnAnd(modifiedRegionBackup,cl->copyRegion);
|
|
||||||
sraRgnOr(cl->modifiedRegion,modifiedRegionBackup);
|
|
||||||
sraRgnDestroy(modifiedRegionBackup);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sraRgnOr(cl->copyRegion,copyRegion);
|
|
||||||
cl->copyDX = dx;
|
|
||||||
cl->copyDY = dy;
|
|
||||||
|
|
||||||
/* if there were modified regions, which are now copied,
|
|
||||||
* mark them as modified, because the source of these can be overlapped
|
|
||||||
* either by new modified or now copied regions. */
|
|
||||||
modifiedRegionBackup=sraRgnCreateRgn(cl->modifiedRegion);
|
|
||||||
sraRgnOffset(modifiedRegionBackup,dx,dy);
|
|
||||||
sraRgnAnd(modifiedRegionBackup,cl->copyRegion);
|
|
||||||
sraRgnOr(cl->modifiedRegion,modifiedRegionBackup);
|
|
||||||
sraRgnDestroy(modifiedRegionBackup);
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
//TODO: is this needed? Or does it mess up deferring?
|
|
||||||
/* while(!sraRgnEmpty(cl->copyRegion)) */ {
|
|
||||||
#ifdef HAVE_PTHREADS
|
|
||||||
if(!cl->screen->backgroundLoop)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
sraRegionPtr updateRegion = sraRgnCreateRgn(cl->modifiedRegion);
|
|
||||||
sraRgnOr(updateRegion,cl->copyRegion);
|
|
||||||
UNLOCK(cl->updateMutex);
|
|
||||||
rfbSendFramebufferUpdate(cl,updateRegion);
|
|
||||||
sraRgnDestroy(updateRegion);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
sraRgnOr(cl->modifiedRegion,copyRegion);
|
|
||||||
}
|
|
||||||
TSIGNAL(cl->updateCond);
|
|
||||||
UNLOCK(cl->updateMutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
rfbReleaseClientIterator(iterator);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rfbDoCopyRegion(rfbScreenInfoPtr rfbScreen,sraRegionPtr copyRegion,int dx,int dy)
|
|
||||||
{
|
|
||||||
sraRectangleIterator* i;
|
|
||||||
sraRect rect;
|
|
||||||
int j,widthInBytes,bpp=rfbScreen->rfbServerFormat.bitsPerPixel/8,
|
|
||||||
rowstride=rfbScreen->paddedWidthInBytes;
|
|
||||||
char *in,*out;
|
|
||||||
|
|
||||||
rfbUndrawCursor(rfbScreen);
|
|
||||||
|
|
||||||
/* copy it, really */
|
|
||||||
i = sraRgnGetReverseIterator(copyRegion,dx<0,dy<0);
|
|
||||||
while(sraRgnIteratorNext(i,&rect)) {
|
|
||||||
widthInBytes = (rect.x2-rect.x1)*bpp;
|
|
||||||
out = rfbScreen->frameBuffer+rect.x1*bpp+rect.y1*rowstride;
|
|
||||||
in = rfbScreen->frameBuffer+(rect.x1-dx)*bpp+(rect.y1-dy)*rowstride;
|
|
||||||
if(dy<0)
|
|
||||||
for(j=rect.y1;j<rect.y2;j++,out+=rowstride,in+=rowstride)
|
|
||||||
memmove(out,in,widthInBytes);
|
|
||||||
else {
|
|
||||||
out += rowstride*(rect.y2-rect.y1-1);
|
|
||||||
in += rowstride*(rect.y2-rect.y1-1);
|
|
||||||
for(j=rect.y2-1;j>=rect.y1;j--,out-=rowstride,in-=rowstride)
|
|
||||||
memmove(out,in,widthInBytes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rfbScheduleCopyRegion(rfbScreen,copyRegion,dx,dy);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rfbDoCopyRect(rfbScreenInfoPtr rfbScreen,int x1,int y1,int x2,int y2,int dx,int dy)
|
|
||||||
{
|
|
||||||
sraRegionPtr region = sraRgnCreateRect(x1,y1,x2,y2);
|
|
||||||
rfbDoCopyRegion(rfbScreen,region,dx,dy);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rfbScheduleCopyRect(rfbScreenInfoPtr rfbScreen,int x1,int y1,int x2,int y2,int dx,int dy)
|
|
||||||
{
|
|
||||||
sraRegionPtr region = sraRgnCreateRect(x1,y1,x2,y2);
|
|
||||||
rfbScheduleCopyRegion(rfbScreen,region,dx,dy);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rfbMarkRegionAsModified(rfbScreenInfoPtr rfbScreen,sraRegionPtr modRegion)
|
|
||||||
{
|
|
||||||
rfbClientIteratorPtr iterator;
|
|
||||||
rfbClientPtr cl;
|
|
||||||
|
|
||||||
iterator=rfbGetClientIterator(rfbScreen);
|
|
||||||
while((cl=rfbClientIteratorNext(iterator))) {
|
|
||||||
LOCK(cl->updateMutex);
|
|
||||||
sraRgnOr(cl->modifiedRegion,modRegion);
|
|
||||||
TSIGNAL(cl->updateCond);
|
|
||||||
UNLOCK(cl->updateMutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
rfbReleaseClientIterator(iterator);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rfbMarkRectAsModified(rfbScreenInfoPtr rfbScreen,int x1,int y1,int x2,int y2)
|
|
||||||
{
|
|
||||||
sraRegionPtr region;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if(x1>x2) { i=x1; x1=x2; x2=i; }
|
|
||||||
if(x1<0) x1=0;
|
|
||||||
if(x2>=rfbScreen->width) x2=rfbScreen->width-1;
|
|
||||||
if(x1==x2) return;
|
|
||||||
|
|
||||||
if(y1>y2) { i=y1; y1=y2; y2=i; }
|
|
||||||
if(y1<0) y1=0;
|
|
||||||
if(y2>=rfbScreen->height) y2=rfbScreen->height-1;
|
|
||||||
if(y1==y2) return;
|
|
||||||
|
|
||||||
region = sraRgnCreateRect(x1,y1,x2,y2);
|
|
||||||
rfbMarkRegionAsModified(rfbScreen,region);
|
|
||||||
sraRgnDestroy(region);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_PTHREADS
|
|
||||||
static void *
|
|
||||||
clientOutput(void *data)
|
|
||||||
{
|
|
||||||
rfbClientPtr cl = (rfbClientPtr)data;
|
|
||||||
Bool haveUpdate;
|
|
||||||
sraRegion* updateRegion;
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
haveUpdate = false;
|
|
||||||
while (!haveUpdate) {
|
|
||||||
if (cl->sock == -1) {
|
|
||||||
/* Client has disconnected. */
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
LOCK(cl->updateMutex);
|
|
||||||
haveUpdate = FB_UPDATE_PENDING(cl);
|
|
||||||
if(!haveUpdate) {
|
|
||||||
updateRegion = sraRgnCreateRgn(cl->modifiedRegion);
|
|
||||||
haveUpdate = sraRgnAnd(updateRegion,cl->requestedRegion);
|
|
||||||
sraRgnDestroy(updateRegion);
|
|
||||||
}
|
|
||||||
UNLOCK(cl->updateMutex);
|
|
||||||
|
|
||||||
if (!haveUpdate) {
|
|
||||||
LOCK(cl->updateMutex);
|
|
||||||
TIMEDWAIT(cl->updateCond, cl->updateMutex, PING_MS);
|
|
||||||
UNLOCK(cl->updateMutex); /* we really needn't lock now. */
|
|
||||||
if (!haveUpdate)
|
|
||||||
rfbSendPing(cl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* OK, now, to save bandwidth, wait a little while for more
|
|
||||||
updates to come along. */
|
|
||||||
usleep(cl->screen->rfbDeferUpdateTime * 1000);
|
|
||||||
|
|
||||||
/* Now, get the region we're going to update, and remove
|
|
||||||
it from cl->modifiedRegion _before_ we send the update.
|
|
||||||
That way, if anything that overlaps the region we're sending
|
|
||||||
is updated, we'll be sure to do another update later. */
|
|
||||||
LOCK(cl->updateMutex);
|
|
||||||
updateRegion = sraRgnCreateRgn(cl->modifiedRegion);
|
|
||||||
UNLOCK(cl->updateMutex);
|
|
||||||
|
|
||||||
/* Now actually send the update. */
|
|
||||||
rfbIncrClientRef(cl);
|
|
||||||
rfbSendFramebufferUpdate(cl, updateRegion);
|
|
||||||
rfbDecrClientRef(cl);
|
|
||||||
|
|
||||||
sraRgnDestroy(updateRegion);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *
|
|
||||||
clientInput(void *data)
|
|
||||||
{
|
|
||||||
rfbClientPtr cl = (rfbClientPtr)data;
|
|
||||||
|
|
||||||
/* Start output thread */
|
|
||||||
TQEventLoopThread* clientOutputHandlerThread = new TQEventLoopThread();
|
|
||||||
ClientOutputHandlerObject* clientOutputHandler = new ClientOutputHandlerObject();
|
|
||||||
clientOutputHandler->d = cl;
|
|
||||||
clientOutputHandler->moveToThread(clientOutputHandlerThread);
|
|
||||||
TQTimer::singleShot(0, clientOutputHandler, SLOT(run()));
|
|
||||||
clientOutputHandlerThread->start();
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
rfbProcessClientMessage(cl);
|
|
||||||
if (cl->sock == -1) {
|
|
||||||
/* Client has disconnected. */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get rid of the output thread */
|
|
||||||
LOCK(cl->updateMutex);
|
|
||||||
TSIGNAL(cl->updateCond);
|
|
||||||
UNLOCK(cl->updateMutex);
|
|
||||||
clientOutputHandlerThread->wait();
|
|
||||||
delete clientOutputHandlerThread;
|
|
||||||
clientOutputHandlerThread = NULL;
|
|
||||||
delete clientOutputHandler;
|
|
||||||
clientOutputHandler = NULL;
|
|
||||||
|
|
||||||
rfbClientConnectionGone(cl);
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void*
|
|
||||||
listenerRun(void *data)
|
|
||||||
{
|
|
||||||
rfbScreenInfoPtr rfbScreen=(rfbScreenInfoPtr)data;
|
|
||||||
int client_fd;
|
|
||||||
struct sockaddr_in peer;
|
|
||||||
rfbClientPtr cl;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
if (rfbScreen->inetdSock != -1) {
|
|
||||||
cl = rfbNewClient(rfbScreen, rfbScreen->inetdSock);
|
|
||||||
if (cl && !cl->onHold)
|
|
||||||
rfbStartOnHoldClient(cl);
|
|
||||||
else if (rfbScreen->inetdDisconnectHook && !cl)
|
|
||||||
rfbScreen->inetdDisconnectHook();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
len = sizeof(peer);
|
|
||||||
|
|
||||||
/* TODO: this thread wont die by restarting the server */
|
|
||||||
while ((client_fd = accept(rfbScreen->rfbListenSock,
|
|
||||||
(struct sockaddr*)&peer, (socklen_t*)(&len))) >= 0) {
|
|
||||||
cl = rfbNewClient(rfbScreen,client_fd);
|
|
||||||
len = sizeof(peer);
|
|
||||||
|
|
||||||
if (cl && !cl->onHold )
|
|
||||||
rfbStartOnHoldClient(cl);
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
rfbStartOnHoldClient(rfbClientPtr cl)
|
|
||||||
{
|
|
||||||
mOnHoldClientHandlerThread = new TQEventLoopThread();
|
|
||||||
mOnHoldClientHandler = new OnHoldClientHandlerObject();
|
|
||||||
mOnHoldClientHandler->d = cl;
|
|
||||||
mOnHoldClientHandler->moveToThread(mOnHoldClientHandlerThread);
|
|
||||||
TQTimer::singleShot(0, mOnHoldClientHandler, SLOT(run()));
|
|
||||||
mOnHoldClientHandlerThread->start();
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
void
|
|
||||||
rfbStartOnHoldClient(rfbClientPtr cl)
|
|
||||||
{
|
|
||||||
cl->onHold = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void
|
|
||||||
rfbRefuseOnHoldClient(rfbClientPtr cl)
|
|
||||||
{
|
|
||||||
rfbCloseClient(cl);
|
|
||||||
rfbClientConnectionGone(cl);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
defaultKbdAddEvent(Bool down, KeySym keySym, rfbClientPtr cl)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
defaultPtrAddEvent(int buttonMask, int x, int y, rfbClientPtr cl)
|
|
||||||
{
|
|
||||||
if(x!=cl->screen->cursorX || y!=cl->screen->cursorY) {
|
|
||||||
cl->cursorWasMoved = TRUE;
|
|
||||||
if(cl->screen->cursorIsDrawn)
|
|
||||||
rfbUndrawCursor(cl->screen);
|
|
||||||
LOCK(cl->screen->cursorMutex);
|
|
||||||
if(!cl->screen->cursorIsDrawn) {
|
|
||||||
cl->screen->cursorX = x;
|
|
||||||
cl->screen->cursorY = y;
|
|
||||||
}
|
|
||||||
UNLOCK(cl->screen->cursorMutex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void defaultSetXCutText(char* text, int len, rfbClientPtr cl)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO: add a nice VNC or RFB cursor */
|
|
||||||
|
|
||||||
#if defined(WIN32) || defined(sparc) || defined(_AIX) || defined(__osf__)
|
|
||||||
static rfbCursor myCursor =
|
|
||||||
{
|
|
||||||
"\000\102\044\030\044\102\000",
|
|
||||||
"\347\347\176\074\176\347\347",
|
|
||||||
8, 7, 3, 3,
|
|
||||||
0, 0, 0,
|
|
||||||
0xffff, 0xffff, 0xffff,
|
|
||||||
0
|
|
||||||
};
|
|
||||||
#else
|
|
||||||
static rfbCursor myCursor =
|
|
||||||
{
|
|
||||||
source: "\000\102\044\030\044\102\000",
|
|
||||||
mask: "\347\347\176\074\176\347\347",
|
|
||||||
width: 8, height: 7, xhot: 3, yhot: 3,
|
|
||||||
/*
|
|
||||||
width: 8, height: 7, xhot: 0, yhot: 0,
|
|
||||||
source: "\000\074\176\146\176\074\000",
|
|
||||||
mask: "\176\377\377\377\377\377\176",
|
|
||||||
*/
|
|
||||||
foreRed: 0, foreGreen: 0, foreBlue: 0,
|
|
||||||
backRed: 0xffff, backGreen: 0xffff, backBlue: 0xffff,
|
|
||||||
richSource: 0
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
rfbCursorPtr defaultGetCursorPtr(rfbClientPtr cl)
|
|
||||||
{
|
|
||||||
return(cl->screen->cursor);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* response is cl->authChallenge vncEncrypted with passwd */
|
|
||||||
Bool defaultPasswordCheck(rfbClientPtr cl,const char* response,int len)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
char *passwd = vncDecryptPasswdFromFile((char*)(cl->screen->rfbAuthPasswdData));
|
|
||||||
|
|
||||||
if(!passwd) {
|
|
||||||
rfbLog("Couldn't read password file: %s\n",cl->screen->rfbAuthPasswdData);
|
|
||||||
return(FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
vncEncryptBytes(cl->authChallenge, passwd);
|
|
||||||
|
|
||||||
/* Lose the password from memory */
|
|
||||||
for (i = strlen(passwd); i >= 0; i--) {
|
|
||||||
passwd[i] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
free(passwd);
|
|
||||||
|
|
||||||
if (memcmp(cl->authChallenge, response, len) != 0) {
|
|
||||||
rfbLog("rfbAuthProcessClientMessage: authentication failed from %s\n",
|
|
||||||
cl->host);
|
|
||||||
return(FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
return(TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* for this method, rfbAuthPasswdData is really a pointer to an array
|
|
||||||
of char*'s, where the last pointer is 0. */
|
|
||||||
Bool rfbCheckPasswordByList(rfbClientPtr cl,const char* response,int len)
|
|
||||||
{
|
|
||||||
char **passwds;
|
|
||||||
|
|
||||||
for(passwds=(char**)cl->screen->rfbAuthPasswdData;*passwds;passwds++) {
|
|
||||||
vncEncryptBytes(cl->authChallenge, *passwds);
|
|
||||||
|
|
||||||
if (memcmp(cl->authChallenge, response, len) == 0)
|
|
||||||
return(TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
rfbLog("rfbAuthProcessClientMessage: authentication failed from %s\n",
|
|
||||||
cl->host);
|
|
||||||
return(FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void doNothingWithClient(rfbClientPtr cl)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
enum rfbNewClientAction defaultNewClientHook(rfbClientPtr cl)
|
|
||||||
{
|
|
||||||
return RFB_CLIENT_ACCEPT;
|
|
||||||
}
|
|
||||||
|
|
||||||
rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv,
|
|
||||||
int width,int height,int bitsPerSample,int samplesPerPixel,
|
|
||||||
int bytesPerPixel)
|
|
||||||
{
|
|
||||||
rfbScreenInfoPtr rfbScreen=(rfbScreenInfoPtr)(malloc(sizeof(rfbScreenInfo)));
|
|
||||||
rfbPixelFormat* format=&rfbScreen->rfbServerFormat;
|
|
||||||
|
|
||||||
INIT_MUTEX(logMutex);
|
|
||||||
|
|
||||||
if(width&3)
|
|
||||||
fprintf(stderr,"WARNING: Width (%d) is not a multiple of 4. VncViewer has problems with that.\n",width);
|
|
||||||
|
|
||||||
rfbScreen->autoPort=FALSE;
|
|
||||||
rfbScreen->rfbClientHead=0;
|
|
||||||
rfbScreen->rfbPort=5900;
|
|
||||||
rfbScreen->socketInitDone=FALSE;
|
|
||||||
|
|
||||||
rfbScreen->inetdInitDone = FALSE;
|
|
||||||
rfbScreen->inetdSock=-1;
|
|
||||||
|
|
||||||
rfbScreen->udpSock=-1;
|
|
||||||
rfbScreen->udpSockConnected=FALSE;
|
|
||||||
rfbScreen->udpPort=0;
|
|
||||||
rfbScreen->udpClient=0;
|
|
||||||
|
|
||||||
rfbScreen->maxFd=0;
|
|
||||||
rfbScreen->rfbListenSock=-1;
|
|
||||||
|
|
||||||
rfbScreen->httpInitDone=FALSE;
|
|
||||||
rfbScreen->httpPort=0;
|
|
||||||
rfbScreen->httpDir=NULL;
|
|
||||||
rfbScreen->httpListenSock=-1;
|
|
||||||
rfbScreen->httpSock=-1;
|
|
||||||
rfbScreen->httpFP=NULL;
|
|
||||||
|
|
||||||
rfbScreen->desktopName = "LibVNCServer";
|
|
||||||
rfbScreen->rfbAlwaysShared = FALSE;
|
|
||||||
rfbScreen->rfbNeverShared = FALSE;
|
|
||||||
rfbScreen->rfbDontDisconnect = FALSE;
|
|
||||||
rfbScreen->rfbAuthPasswdData = 0;
|
|
||||||
|
|
||||||
rfbScreen->width = width;
|
|
||||||
rfbScreen->height = height;
|
|
||||||
rfbScreen->bitsPerPixel = rfbScreen->depth = 8*bytesPerPixel;
|
|
||||||
|
|
||||||
rfbScreen->passwordCheck = defaultPasswordCheck;
|
|
||||||
|
|
||||||
rfbProcessArguments(rfbScreen,argc,argv);
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
{
|
|
||||||
DWORD dummy=255;
|
|
||||||
GetComputerName(rfbScreen->rfbThisHost,&dummy);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
gethostname(rfbScreen->rfbThisHost, 255);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
rfbScreen->paddedWidthInBytes = width*bytesPerPixel;
|
|
||||||
|
|
||||||
/* format */
|
|
||||||
|
|
||||||
format->bitsPerPixel = rfbScreen->bitsPerPixel;
|
|
||||||
format->depth = rfbScreen->depth;
|
|
||||||
format->bigEndian = rfbEndianTest?FALSE:TRUE;
|
|
||||||
format->trueColour = TRUE;
|
|
||||||
rfbScreen->colourMap.count = 0;
|
|
||||||
rfbScreen->colourMap.is16 = 0;
|
|
||||||
rfbScreen->colourMap.data.bytes = NULL;
|
|
||||||
|
|
||||||
if(bytesPerPixel == 1) {
|
|
||||||
format->redMax = 7;
|
|
||||||
format->greenMax = 7;
|
|
||||||
format->blueMax = 3;
|
|
||||||
format->redShift = 0;
|
|
||||||
format->greenShift = 3;
|
|
||||||
format->blueShift = 6;
|
|
||||||
} else {
|
|
||||||
format->redMax = (1 << bitsPerSample) - 1;
|
|
||||||
format->greenMax = (1 << bitsPerSample) - 1;
|
|
||||||
format->blueMax = (1 << bitsPerSample) - 1;
|
|
||||||
if(rfbEndianTest) {
|
|
||||||
format->redShift = 0;
|
|
||||||
format->greenShift = bitsPerSample;
|
|
||||||
format->blueShift = bitsPerSample * 2;
|
|
||||||
} else {
|
|
||||||
if(bytesPerPixel==3) {
|
|
||||||
format->redShift = bitsPerSample*2;
|
|
||||||
format->greenShift = bitsPerSample*1;
|
|
||||||
format->blueShift = 0;
|
|
||||||
} else {
|
|
||||||
format->redShift = bitsPerSample*3;
|
|
||||||
format->greenShift = bitsPerSample*2;
|
|
||||||
format->blueShift = bitsPerSample;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* cursor */
|
|
||||||
|
|
||||||
rfbScreen->cursorIsDrawn = FALSE;
|
|
||||||
rfbScreen->dontSendFramebufferUpdate = FALSE;
|
|
||||||
rfbScreen->cursorX=rfbScreen->cursorY=rfbScreen->underCursorBufferLen=0;
|
|
||||||
rfbScreen->underCursorBuffer=NULL;
|
|
||||||
rfbScreen->dontConvertRichCursorToXCursor = FALSE;
|
|
||||||
rfbScreen->cursor = &myCursor;
|
|
||||||
INIT_MUTEX(rfbScreen->cursorMutex);
|
|
||||||
|
|
||||||
IF_PTHREADS(rfbScreen->backgroundLoop = FALSE);
|
|
||||||
|
|
||||||
rfbScreen->rfbDeferUpdateTime=5;
|
|
||||||
|
|
||||||
/* proc's and hook's */
|
|
||||||
|
|
||||||
rfbScreen->kbdAddEvent = defaultKbdAddEvent;
|
|
||||||
rfbScreen->kbdReleaseAllKeys = doNothingWithClient;
|
|
||||||
rfbScreen->ptrAddEvent = defaultPtrAddEvent;
|
|
||||||
rfbScreen->setXCutText = defaultSetXCutText;
|
|
||||||
rfbScreen->getCursorPtr = defaultGetCursorPtr;
|
|
||||||
rfbScreen->setTranslateFunction = rfbSetTranslateFunction;
|
|
||||||
rfbScreen->newClientHook = defaultNewClientHook;
|
|
||||||
rfbScreen->displayHook = 0;
|
|
||||||
rfbScreen->inetdDisconnectHook = 0;
|
|
||||||
|
|
||||||
/* initialize client list and iterator mutex */
|
|
||||||
rfbClientListInit(rfbScreen);
|
|
||||||
|
|
||||||
return(rfbScreen);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rfbScreenCleanup(rfbScreenInfoPtr rfbScreen)
|
|
||||||
{
|
|
||||||
rfbClientIteratorPtr i=rfbGetClientIterator(rfbScreen);
|
|
||||||
rfbClientPtr cl,cl1=rfbClientIteratorNext(i);
|
|
||||||
while(cl1) {
|
|
||||||
cl=rfbClientIteratorNext(i);
|
|
||||||
rfbClientConnectionGone(cl1);
|
|
||||||
cl1=cl;
|
|
||||||
}
|
|
||||||
rfbReleaseClientIterator(i);
|
|
||||||
|
|
||||||
if (mOnHoldClientHandlerThread) {
|
|
||||||
mOnHoldClientHandlerThread->exit();
|
|
||||||
delete mOnHoldClientHandlerThread;
|
|
||||||
mOnHoldClientHandlerThread = NULL;
|
|
||||||
delete mOnHoldClientHandler;
|
|
||||||
mOnHoldClientHandler = NULL;
|
|
||||||
}
|
|
||||||
if (mControlPipeHandlerThread) {
|
|
||||||
mControlPipeHandlerThread->exit();
|
|
||||||
delete mControlPipeHandlerThread;
|
|
||||||
mControlPipeHandlerThread = NULL;
|
|
||||||
delete mControlPipeHandler;
|
|
||||||
mControlPipeHandler = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO: hang up on all clients and free all reserved memory */
|
|
||||||
#define FREE_IF(x) if(rfbScreen->x) free(rfbScreen->x)
|
|
||||||
FREE_IF(colourMap.data.bytes);
|
|
||||||
FREE_IF(underCursorBuffer);
|
|
||||||
TINI_MUTEX(rfbScreen->cursorMutex);
|
|
||||||
free(rfbScreen);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rfbInitServer(rfbScreenInfoPtr rfbScreen)
|
|
||||||
{
|
|
||||||
#ifdef WIN32
|
|
||||||
WSADATA trash;
|
|
||||||
int i=WSAStartup(MAKEWORD(2,2),&trash);
|
|
||||||
#endif
|
|
||||||
rfbInitSockets(rfbScreen);
|
|
||||||
httpInitSockets(rfbScreen);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <conio.h>
|
|
||||||
#include <sys/timeb.h>
|
|
||||||
|
|
||||||
void gettimeofday(struct timeval* tv,char* dummy)
|
|
||||||
{
|
|
||||||
SYSTEMTIME t;
|
|
||||||
GetSystemTime(&t);
|
|
||||||
tv->tv_sec=t.wHour*3600+t.wMinute*60+t.wSecond;
|
|
||||||
tv->tv_usec=t.wMilliseconds*1000;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void
|
|
||||||
rfbProcessEvents(rfbScreenInfoPtr rfbScreen,long usec)
|
|
||||||
{
|
|
||||||
rfbClientIteratorPtr i;
|
|
||||||
rfbClientPtr cl,clPrev;
|
|
||||||
struct timeval tv;
|
|
||||||
|
|
||||||
if(usec<0)
|
|
||||||
usec=rfbScreen->rfbDeferUpdateTime*1000;
|
|
||||||
|
|
||||||
rfbCheckFds(rfbScreen,usec);
|
|
||||||
httpCheckFds(rfbScreen);
|
|
||||||
#ifdef CORBA
|
|
||||||
corbaCheckFds(rfbScreen);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
i = rfbGetClientIterator(rfbScreen);
|
|
||||||
cl=rfbClientIteratorNext(i);
|
|
||||||
while(cl) {
|
|
||||||
if(cl->sock>=0 && (!cl->onHold) && FB_UPDATE_PENDING(cl)) {
|
|
||||||
if(cl->screen->rfbDeferUpdateTime == 0) {
|
|
||||||
rfbSendFramebufferUpdate(cl,cl->modifiedRegion);
|
|
||||||
} else if(cl->startDeferring.tv_usec == 0) {
|
|
||||||
gettimeofday(&cl->startDeferring,NULL);
|
|
||||||
if(cl->startDeferring.tv_usec == 0)
|
|
||||||
cl->startDeferring.tv_usec++;
|
|
||||||
} else {
|
|
||||||
gettimeofday(&tv,NULL);
|
|
||||||
if(tv.tv_sec < cl->startDeferring.tv_sec /* at midnight */
|
|
||||||
|| ((tv.tv_sec-cl->startDeferring.tv_sec)*1000
|
|
||||||
+(tv.tv_usec-cl->startDeferring.tv_usec)/1000)
|
|
||||||
> cl->screen->rfbDeferUpdateTime) {
|
|
||||||
cl->startDeferring.tv_usec = 0;
|
|
||||||
rfbSendFramebufferUpdate(cl,cl->modifiedRegion);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
clPrev=cl;
|
|
||||||
cl=rfbClientIteratorNext(i);
|
|
||||||
if(clPrev->sock==-1)
|
|
||||||
rfbClientConnectionGone(clPrev);
|
|
||||||
}
|
|
||||||
rfbReleaseClientIterator(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rfbRunEventLoop(rfbScreenInfoPtr rfbScreen, long usec, Bool runInBackground)
|
|
||||||
{
|
|
||||||
if (runInBackground) {
|
|
||||||
#ifdef HAVE_PTHREADS
|
|
||||||
rfbScreen->backgroundLoop = TRUE;
|
|
||||||
|
|
||||||
mControlPipeHandlerThread = new TQEventLoopThread();
|
|
||||||
mControlPipeHandler = new ControlPipeHandlerObject();
|
|
||||||
mControlPipeHandler->d = rfbScreen;
|
|
||||||
mControlPipeHandler->moveToThread(mControlPipeHandlerThread);
|
|
||||||
TQTimer::singleShot(0, mControlPipeHandler, SLOT(run()));
|
|
||||||
mControlPipeHandlerThread->start();
|
|
||||||
return;
|
|
||||||
#else
|
|
||||||
fprintf(stderr,"Can't run in background, because I don't have PThreads!\n");
|
|
||||||
exit(-1);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
if (usec<0) {
|
|
||||||
usec=rfbScreen->rfbDeferUpdateTime*1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
rfbProcessEvents(rfbScreen,usec);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ControlPipeHandlerObject::ControlPipeHandlerObject() : TQObject() {
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
ControlPipeHandlerObject::~ControlPipeHandlerObject() {
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
void ControlPipeHandlerObject::run(void) {
|
|
||||||
listenerRun(d);
|
|
||||||
|
|
||||||
// Terminate thread
|
|
||||||
TQThread::exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
OnHoldClientHandlerObject::OnHoldClientHandlerObject() : TQObject() {
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
OnHoldClientHandlerObject::~OnHoldClientHandlerObject() {
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnHoldClientHandlerObject::run(void) {
|
|
||||||
clientInput(d);
|
|
||||||
|
|
||||||
// Terminate thread
|
|
||||||
TQThread::exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
ClientOutputHandlerObject::ClientOutputHandlerObject() : TQObject() {
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
ClientOutputHandlerObject::~ClientOutputHandlerObject() {
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientOutputHandlerObject::run(void) {
|
|
||||||
clientOutput(d);
|
|
||||||
|
|
||||||
// Terminate thread
|
|
||||||
TQThread::exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "main.moc"
|
|
@ -1,58 +0,0 @@
|
|||||||
/*
|
|
||||||
* LibVNCServer (C) 2001 Johannes E. Schindelin <Johannes.Schindelin@gmx.de>
|
|
||||||
* Original OSXvnc (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
|
|
||||||
* Original Xvnc (C) 1999 AT&T Laboratories Cambridge.
|
|
||||||
* All Rights Reserved.
|
|
||||||
*
|
|
||||||
* see GPL (latest version) for full details
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _MAIN_H
|
|
||||||
#define _MAIN_H
|
|
||||||
|
|
||||||
class ControlPipeHandlerObject : public TQObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
ControlPipeHandlerObject();
|
|
||||||
~ControlPipeHandlerObject();
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void run();
|
|
||||||
|
|
||||||
public:
|
|
||||||
rfbScreenInfoPtr d;
|
|
||||||
};
|
|
||||||
|
|
||||||
class OnHoldClientHandlerObject : public TQObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
OnHoldClientHandlerObject();
|
|
||||||
~OnHoldClientHandlerObject();
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void run();
|
|
||||||
|
|
||||||
public:
|
|
||||||
rfbClientPtr d;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ClientOutputHandlerObject : public TQObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
ClientOutputHandlerObject();
|
|
||||||
~ClientOutputHandlerObject();
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void run();
|
|
||||||
|
|
||||||
public:
|
|
||||||
rfbClientPtr d;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // _MAIN_H
|
|
@ -1,81 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
#include "rfb.h"
|
|
||||||
#include "keysym.h"
|
|
||||||
|
|
||||||
void HandleKey(Bool down,KeySym key,rfbClientPtr cl)
|
|
||||||
{
|
|
||||||
if(down && (key==XK_Escape || key=='q' || key=='Q'))
|
|
||||||
rfbCloseClient(cl);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc,char** argv)
|
|
||||||
{
|
|
||||||
FILE* in=stdin;
|
|
||||||
int i,j,k,width,height,paddedWidth;
|
|
||||||
unsigned char buffer[1024];
|
|
||||||
rfbScreenInfoPtr rfbScreen;
|
|
||||||
|
|
||||||
if(argc>1) {
|
|
||||||
in=fopen(argv[1],"rb");
|
|
||||||
if(!in) {
|
|
||||||
printf("Couldn't find file %s.\n",argv[1]);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fgets(buffer,1024,in);
|
|
||||||
if(strncmp(buffer,"P6",2)) {
|
|
||||||
printf("Not a ppm.\n");
|
|
||||||
exit(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* skip comments */
|
|
||||||
do {
|
|
||||||
fgets(buffer,1024,in);
|
|
||||||
} while(buffer[0]=='#');
|
|
||||||
|
|
||||||
/* get width & height */
|
|
||||||
sscanf(buffer,"%d %d",&width,&height);
|
|
||||||
fprintf(stderr,"Got width %d and height %d.\n",width,height);
|
|
||||||
fgets(buffer,1024,in);
|
|
||||||
|
|
||||||
/* vncviewers have problems with widths which are no multiple of 4. */
|
|
||||||
paddedWidth = width;
|
|
||||||
if(width&3)
|
|
||||||
paddedWidth+=4-(width&3);
|
|
||||||
|
|
||||||
/* initialize data for vnc server */
|
|
||||||
rfbScreen = rfbGetScreen(&argc,argv,paddedWidth,height,8,3,4);
|
|
||||||
if(argc>1)
|
|
||||||
rfbScreen->desktopName = argv[1];
|
|
||||||
else
|
|
||||||
rfbScreen->desktopName = "Picture";
|
|
||||||
rfbScreen->rfbAlwaysShared = TRUE;
|
|
||||||
rfbScreen->kbdAddEvent = HandleKey;
|
|
||||||
|
|
||||||
/* enable http */
|
|
||||||
rfbScreen->httpDir = "./classes";
|
|
||||||
|
|
||||||
/* allocate picture and read it */
|
|
||||||
rfbScreen->frameBuffer = (char*)malloc(paddedWidth*4*height);
|
|
||||||
fread(rfbScreen->frameBuffer,width*3,height,in);
|
|
||||||
fclose(in);
|
|
||||||
|
|
||||||
/* correct the format to 4 bytes instead of 3 (and pad to paddedWidth) */
|
|
||||||
for(j=height-1;j>=0;j--) {
|
|
||||||
for(i=width-1;i>=0;i--)
|
|
||||||
for(k=2;k>=0;k--)
|
|
||||||
rfbScreen->frameBuffer[(j*paddedWidth+i)*4+k]=
|
|
||||||
rfbScreen->frameBuffer[(j*width+i)*3+k];
|
|
||||||
for(i=width*4;i<paddedWidth*4;i++)
|
|
||||||
rfbScreen->frameBuffer[j*paddedWidth*4+i]=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* initialize server */
|
|
||||||
rfbInitServer(rfbScreen);
|
|
||||||
|
|
||||||
/* run event loop */
|
|
||||||
rfbRunEventLoop(rfbScreen,40000,FALSE);
|
|
||||||
|
|
||||||
return(0);
|
|
||||||
}
|
|
@ -1,90 +0,0 @@
|
|||||||
#ifndef ALLOW24BPP
|
|
||||||
#error "I need the ALLOW24BPP flag to work"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "rfb.h"
|
|
||||||
#include "keysym.h"
|
|
||||||
|
|
||||||
void HandleKey(Bool down,KeySym key,rfbClientPtr cl)
|
|
||||||
{
|
|
||||||
if(down && (key==XK_Escape || key=='q' || key=='Q'))
|
|
||||||
rfbCloseClient(cl);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc,char** argv)
|
|
||||||
{
|
|
||||||
FILE* in=stdin;
|
|
||||||
int j,width,height,paddedWidth;
|
|
||||||
unsigned char buffer[1024];
|
|
||||||
rfbScreenInfoPtr rfbScreen;
|
|
||||||
|
|
||||||
if(argc>1) {
|
|
||||||
in=fopen(argv[1],"rb");
|
|
||||||
if(!in) {
|
|
||||||
printf("Couldn't find file %s.\n",argv[1]);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fgets(buffer,1024,in);
|
|
||||||
if(strncmp(buffer,"P6",2)) {
|
|
||||||
printf("Not a ppm.\n");
|
|
||||||
exit(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* skip comments */
|
|
||||||
do {
|
|
||||||
fgets(buffer,1024,in);
|
|
||||||
} while(buffer[0]=='#');
|
|
||||||
|
|
||||||
/* get width & height */
|
|
||||||
sscanf(buffer,"%d %d",&width,&height);
|
|
||||||
fprintf(stderr,"Got width %d and height %d.\n",width,height);
|
|
||||||
fgets(buffer,1024,in);
|
|
||||||
|
|
||||||
/* vncviewers have problems with widths which are no multiple of 4. */
|
|
||||||
paddedWidth = width;
|
|
||||||
|
|
||||||
/* if your vncviewer doesn't have problems with a width
|
|
||||||
which is not a multiple of 4, you can comment this. */
|
|
||||||
if(width&3)
|
|
||||||
paddedWidth+=4-(width&3);
|
|
||||||
|
|
||||||
/* initialize data for vnc server */
|
|
||||||
rfbScreen = rfbGetScreen(&argc,argv,paddedWidth,height,8,3,3);
|
|
||||||
if(argc>1)
|
|
||||||
rfbScreen->desktopName = argv[1];
|
|
||||||
else
|
|
||||||
rfbScreen->desktopName = "Picture";
|
|
||||||
rfbScreen->rfbAlwaysShared = TRUE;
|
|
||||||
rfbScreen->kbdAddEvent = HandleKey;
|
|
||||||
|
|
||||||
/* enable http */
|
|
||||||
rfbScreen->httpDir = "./classes";
|
|
||||||
|
|
||||||
/* allocate picture and read it */
|
|
||||||
rfbScreen->frameBuffer = (char*)malloc(paddedWidth*3*height);
|
|
||||||
fread(rfbScreen->frameBuffer,width*3,height,in);
|
|
||||||
fclose(in);
|
|
||||||
|
|
||||||
/* pad to paddedWidth */
|
|
||||||
if(width != paddedWidth) {
|
|
||||||
int padCount = 3*(paddedWidth - width);
|
|
||||||
for(j=height-1;j>=0;j--) {
|
|
||||||
memmove(rfbScreen->frameBuffer+3*paddedWidth*j,
|
|
||||||
rfbScreen->frameBuffer+3*width*j,
|
|
||||||
3*width);
|
|
||||||
memset(rfbScreen->frameBuffer+3*paddedWidth*(j+1)-padCount,
|
|
||||||
0,padCount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* initialize server */
|
|
||||||
rfbInitServer(rfbScreen);
|
|
||||||
|
|
||||||
/* run event loop */
|
|
||||||
rfbRunEventLoop(rfbScreen,40000,FALSE);
|
|
||||||
|
|
||||||
return(0);
|
|
||||||
}
|
|
@ -1,195 +0,0 @@
|
|||||||
unsigned char radonFontData[2280]={
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 32 */
|
|
||||||
0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x10,0x10,0x00,0x00, /* 33 */
|
|
||||||
0x00,0x28,0x28,0x28,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 34 */
|
|
||||||
0x00,0x44,0x44,0xba,0x44,0x44,0x44,0xba,0x44,0x44,0x00,0x00, /* 35 */
|
|
||||||
0x10,0x7e,0x80,0x90,0x80,0x7c,0x02,0x12,0x02,0xfc,0x10,0x00, /* 36 */
|
|
||||||
0x00,0x62,0x92,0x94,0x68,0x10,0x2c,0x52,0x92,0x8c,0x00,0x00, /* 37 */
|
|
||||||
0x00,0x60,0x90,0x90,0x40,0x20,0x90,0x8a,0x84,0x7a,0x00,0x00, /* 38 */
|
|
||||||
0x00,0x10,0x10,0x10,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 39 */
|
|
||||||
0x00,0x08,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x08,0x00,0x00, /* 40 */
|
|
||||||
0x00,0x10,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x10,0x00,0x00, /* 41 */
|
|
||||||
0x00,0x10,0x92,0x54,0x10,0x10,0x54,0x92,0x10,0x00,0x00,0x00, /* 42 */
|
|
||||||
0x00,0x00,0x10,0x10,0x10,0xd6,0x10,0x10,0x10,0x00,0x00,0x00, /* 43 */
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x08,0x30,0x00, /* 44 */
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0x00,0x00,0x00, /* 45 */
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x10,0x00,0x00, /* 46 */
|
|
||||||
0x00,0x02,0x02,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x00,0x00, /* 47 */
|
|
||||||
0x00,0x7c,0x82,0x82,0x82,0xba,0x82,0x82,0x82,0x7c,0x00,0x00, /* 48 */
|
|
||||||
0x00,0x08,0x28,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x00,0x00, /* 49 */
|
|
||||||
0x00,0xfc,0x02,0x02,0x02,0x7c,0x80,0x80,0x00,0xfe,0x00,0x00, /* 50 */
|
|
||||||
0x00,0xfc,0x02,0x02,0x02,0x3c,0x02,0x02,0x02,0xfc,0x00,0x00, /* 51 */
|
|
||||||
0x00,0x82,0x82,0x82,0x82,0x7a,0x02,0x02,0x02,0x02,0x00,0x00, /* 52 */
|
|
||||||
0x00,0xfe,0x00,0x80,0x80,0x7c,0x02,0x02,0x02,0xfc,0x00,0x00, /* 53 */
|
|
||||||
0x00,0x7c,0x80,0x80,0xbc,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 54 */
|
|
||||||
0x00,0xfc,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x00, /* 55 */
|
|
||||||
0x00,0x7c,0x82,0x82,0x82,0x7c,0x82,0x82,0x82,0x7c,0x00,0x00, /* 56 */
|
|
||||||
0x00,0x7c,0x82,0x82,0x82,0x82,0x7a,0x02,0x02,0xfc,0x00,0x00, /* 57 */
|
|
||||||
0x00,0x00,0x10,0x10,0x00,0x00,0x00,0x10,0x10,0x00,0x00,0x00, /* 58 */
|
|
||||||
0x00,0x00,0x10,0x10,0x00,0x00,0x00,0x10,0x10,0x60,0x00,0x00, /* 59 */
|
|
||||||
0x00,0x08,0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x08,0x00,0x00, /* 60 */
|
|
||||||
0x00,0x00,0x00,0x00,0xfe,0x00,0xfe,0x00,0x00,0x00,0x00,0x00, /* 61 */
|
|
||||||
0x00,0x10,0x10,0x08,0x04,0x02,0x04,0x08,0x10,0x10,0x00,0x00, /* 62 */
|
|
||||||
0x00,0xfc,0x02,0x02,0x02,0x1c,0x20,0x20,0x00,0x20,0x00,0x00, /* 63 */
|
|
||||||
0x00,0x7c,0x82,0x8a,0x92,0x92,0x92,0x8c,0x80,0x7c,0x00,0x00, /* 64 */
|
|
||||||
0x00,0x7c,0x82,0x82,0x82,0x82,0xba,0x82,0x82,0x82,0x00,0x00, /* 65 */
|
|
||||||
0x00,0xbc,0x82,0x82,0x82,0xbc,0x82,0x82,0x82,0xbc,0x00,0x00, /* 66 */
|
|
||||||
0x00,0x7c,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x7c,0x00,0x00, /* 67 */
|
|
||||||
0x00,0xbc,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0xbc,0x00,0x00, /* 68 */
|
|
||||||
0x00,0x7c,0x80,0x80,0x80,0xb8,0x80,0x80,0x80,0x7c,0x00,0x00, /* 69 */
|
|
||||||
0x00,0x7c,0x80,0x80,0x80,0xb8,0x80,0x80,0x80,0x80,0x00,0x00, /* 70 */
|
|
||||||
0x00,0x7c,0x80,0x80,0x80,0x80,0x9a,0x82,0x82,0x7c,0x00,0x00, /* 71 */
|
|
||||||
0x00,0x82,0x82,0x82,0x82,0xba,0x82,0x82,0x82,0x82,0x00,0x00, /* 72 */
|
|
||||||
0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 73 */
|
|
||||||
0x00,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x84,0x78,0x00,0x00, /* 74 */
|
|
||||||
0x00,0x82,0x82,0x82,0x82,0xbc,0x82,0x82,0x82,0x82,0x00,0x00, /* 75 */
|
|
||||||
0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x7e,0x00,0x00, /* 76 */
|
|
||||||
0x00,0x7c,0x82,0x92,0x92,0x92,0x92,0x82,0x82,0x82,0x00,0x00, /* 77 */
|
|
||||||
0x00,0x7c,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x00,0x00, /* 78 */
|
|
||||||
0x00,0x7c,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 79 */
|
|
||||||
0x00,0xbc,0x82,0x82,0x82,0xbc,0x80,0x80,0x80,0x80,0x00,0x00, /* 80 */
|
|
||||||
0x00,0x7c,0x82,0x82,0x82,0x82,0x8a,0x8a,0x82,0x7c,0x00,0x00, /* 81 */
|
|
||||||
0x00,0xbc,0x82,0x82,0x82,0xbc,0x82,0x82,0x82,0x82,0x00,0x00, /* 82 */
|
|
||||||
0x00,0x7e,0x80,0x80,0x80,0x7c,0x02,0x02,0x02,0xfc,0x00,0x00, /* 83 */
|
|
||||||
0x00,0xfe,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 84 */
|
|
||||||
0x00,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 85 */
|
|
||||||
0x00,0x82,0x82,0x82,0x82,0x82,0x84,0x88,0x90,0xa0,0x00,0x00, /* 86 */
|
|
||||||
0x00,0x82,0x82,0x82,0x82,0x92,0x92,0x92,0x82,0x7c,0x00,0x00, /* 87 */
|
|
||||||
0x00,0x82,0x82,0x82,0x82,0x7c,0x82,0x82,0x82,0x82,0x00,0x00, /* 88 */
|
|
||||||
0x00,0x82,0x82,0x82,0x82,0x7c,0x00,0x10,0x10,0x10,0x00,0x00, /* 89 */
|
|
||||||
0x00,0xfc,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x7e,0x00,0x00, /* 90 */
|
|
||||||
0x00,0x1c,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x1c,0x00,0x00, /* 91 */
|
|
||||||
0x00,0x80,0x80,0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x00,0x00, /* 92 */
|
|
||||||
0x00,0x38,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x38,0x00,0x00, /* 93 */
|
|
||||||
0x00,0x38,0x44,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 94 */
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00, /* 95 */
|
|
||||||
0x00,0x08,0x08,0x08,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 96 */
|
|
||||||
0x00,0x00,0x00,0x00,0x3c,0x02,0x3a,0x42,0x42,0x3c,0x00,0x00, /* 97 */
|
|
||||||
0x00,0x00,0x40,0x40,0x5c,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 98 */
|
|
||||||
0x00,0x00,0x00,0x00,0x3c,0x40,0x40,0x40,0x40,0x3c,0x00,0x00, /* 99 */
|
|
||||||
0x00,0x00,0x02,0x02,0x3a,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 100 */
|
|
||||||
0x00,0x00,0x00,0x00,0x3c,0x42,0x42,0x5c,0x40,0x3c,0x00,0x00, /* 101 */
|
|
||||||
0x00,0x00,0x0c,0x10,0x10,0x10,0x54,0x10,0x10,0x10,0x00,0x00, /* 102 */
|
|
||||||
0x00,0x00,0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x3a,0x02,0x3c, /* 103 */
|
|
||||||
0x00,0x00,0x40,0x40,0x5c,0x42,0x42,0x42,0x42,0x42,0x00,0x00, /* 104 */
|
|
||||||
0x00,0x00,0x08,0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00,0x00, /* 105 */
|
|
||||||
0x00,0x00,0x08,0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x30, /* 106 */
|
|
||||||
0x00,0x00,0x40,0x40,0x42,0x42,0x5c,0x42,0x42,0x42,0x00,0x00, /* 107 */
|
|
||||||
0x00,0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x00,0x00, /* 108 */
|
|
||||||
0x00,0x00,0x00,0x00,0x7c,0x82,0x92,0x92,0x92,0x92,0x00,0x00, /* 109 */
|
|
||||||
0x00,0x00,0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x42,0x00,0x00, /* 110 */
|
|
||||||
0x00,0x00,0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 111 */
|
|
||||||
0x00,0x00,0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x5c,0x40,0x40, /* 112 */
|
|
||||||
0x00,0x00,0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x3a,0x02,0x02, /* 113 */
|
|
||||||
0x00,0x00,0x00,0x00,0x0c,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 114 */
|
|
||||||
0x00,0x00,0x00,0x00,0x3e,0x40,0x3c,0x02,0x02,0x7c,0x00,0x00, /* 115 */
|
|
||||||
0x00,0x00,0x10,0x10,0x10,0x54,0x10,0x10,0x10,0x0c,0x00,0x00, /* 116 */
|
|
||||||
0x00,0x00,0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 117 */
|
|
||||||
0x00,0x00,0x00,0x00,0x42,0x42,0x42,0x44,0x48,0x50,0x00,0x00, /* 118 */
|
|
||||||
0x00,0x00,0x00,0x00,0x92,0x92,0x92,0x92,0x82,0x7c,0x00,0x00, /* 119 */
|
|
||||||
0x00,0x00,0x00,0x00,0x42,0x42,0x3c,0x42,0x42,0x42,0x00,0x00, /* 120 */
|
|
||||||
0x00,0x00,0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x3a,0x02,0x3c, /* 121 */
|
|
||||||
0x00,0x00,0x00,0x00,0x7c,0x02,0x0c,0x30,0x40,0x3e,0x00,0x00, /* 122 */
|
|
||||||
0x00,0x1c,0x20,0x20,0x20,0x40,0x20,0x20,0x20,0x1c,0x00,0x00, /* 123 */
|
|
||||||
0x00,0x10,0x10,0x10,0x10,0x00,0x10,0x10,0x10,0x10,0x00,0x00, /* 124 */
|
|
||||||
0x00,0x38,0x04,0x04,0x04,0x02,0x04,0x04,0x04,0x38,0x00,0x00, /* 125 */
|
|
||||||
0x00,0x04,0x38,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 126 */
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 160 */
|
|
||||||
0x00,0x10,0x10,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 161 */
|
|
||||||
0x00,0x00,0x08,0x3e,0x40,0x48,0x48,0x40,0x3e,0x08,0x00,0x00, /* 162 */
|
|
||||||
0x00,0x1c,0x20,0x20,0x20,0xa8,0x20,0x20,0x42,0xbc,0x00,0x00, /* 163 */
|
|
||||||
0x00,0x00,0x82,0x38,0x44,0x44,0x44,0x38,0x82,0x00,0x00,0x00, /* 164 */
|
|
||||||
0x00,0x82,0x82,0x82,0x7c,0x00,0x54,0x10,0x54,0x10,0x00,0x00, /* 165 */
|
|
||||||
0x00,0x10,0x10,0x10,0x00,0x00,0x00,0x10,0x10,0x10,0x00,0x00, /* 166 */
|
|
||||||
0x00,0x38,0x40,0x38,0x44,0x44,0x44,0x44,0x38,0x04,0x38,0x00, /* 167 */
|
|
||||||
0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 168 */
|
|
||||||
0x00,0x7c,0x82,0x9a,0xa2,0xa2,0xa2,0x9a,0x82,0x7c,0x00,0x00, /* 169 */
|
|
||||||
0x38,0x04,0x34,0x44,0x38,0x00,0x7c,0x00,0x00,0x00,0x00,0x00, /* 170 */
|
|
||||||
0x00,0x00,0x00,0x24,0x48,0x00,0x48,0x24,0x00,0x00,0x00,0x00, /* 171 */
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0xfc,0x02,0x02,0x02,0x00,0x00,0x00, /* 172 */
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x7c,0x00,0x00,0x00,0x00,0x00,0x00, /* 173 */
|
|
||||||
0x00,0x7c,0x82,0x92,0xaa,0xb2,0xaa,0xaa,0x82,0x7c,0x00,0x00, /* 174 */
|
|
||||||
0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 175 */
|
|
||||||
0x38,0x44,0x44,0x44,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 176 */
|
|
||||||
0x00,0x10,0x10,0xd6,0x10,0x10,0x00,0xfe,0x00,0x00,0x00,0x00, /* 177 */
|
|
||||||
0x38,0x04,0x18,0x20,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 178 */
|
|
||||||
0x38,0x04,0x38,0x04,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 179 */
|
|
||||||
0x18,0x20,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 180 */
|
|
||||||
0x00,0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x58,0x40,0x40, /* 181 */
|
|
||||||
0x00,0x79,0xfa,0xfa,0xfa,0x7a,0x02,0x0a,0x0a,0x0a,0x0a,0x00, /* 182 */
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00, /* 183 */
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0x00, /* 184 */
|
|
||||||
0x08,0x18,0x08,0x08,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 185 */
|
|
||||||
0x38,0x44,0x44,0x38,0x00,0x7c,0x00,0x00,0x00,0x00,0x00,0x00, /* 186 */
|
|
||||||
0x00,0x00,0x00,0x48,0x24,0x00,0x24,0x48,0x00,0x00,0x00,0x00, /* 187 */
|
|
||||||
0x20,0xa2,0x22,0x22,0x24,0x08,0x10,0x29,0x49,0x85,0x01,0x01, /* 188 */
|
|
||||||
0x20,0xa2,0x22,0x22,0x24,0x08,0x10,0x2e,0x41,0x86,0x08,0x0f, /* 189 */
|
|
||||||
0xe0,0x12,0xe2,0x12,0xe4,0x08,0x10,0x29,0x49,0x85,0x01,0x01, /* 190 */
|
|
||||||
0x00,0x08,0x00,0x08,0x08,0x70,0x80,0x80,0x80,0x7e,0x00,0x00, /* 191 */
|
|
||||||
0x20,0x18,0x00,0x7c,0x82,0x82,0x82,0xba,0x82,0x82,0x00,0x00, /* 192 */
|
|
||||||
0x08,0x30,0x00,0x7c,0x82,0x82,0x82,0xba,0x82,0x82,0x00,0x00, /* 193 */
|
|
||||||
0x38,0x44,0x00,0x7c,0x82,0x82,0x82,0xba,0x82,0x82,0x00,0x00, /* 194 */
|
|
||||||
0x32,0x4c,0x00,0x7c,0x82,0x82,0x82,0xba,0x82,0x82,0x00,0x00, /* 195 */
|
|
||||||
0x6c,0x00,0x00,0x7c,0x82,0x82,0x82,0xba,0x82,0x82,0x00,0x00, /* 196 */
|
|
||||||
0x38,0x44,0x38,0x7c,0x82,0x82,0x82,0xba,0x82,0x82,0x00,0x00, /* 197 */
|
|
||||||
0x00,0x77,0x88,0x88,0x88,0x8b,0xa8,0x88,0x88,0x8b,0x00,0x00, /* 198 */
|
|
||||||
0x00,0x7c,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x6c,0x10,0x20, /* 199 */
|
|
||||||
0x20,0x18,0x00,0x7c,0x80,0x80,0xb8,0x80,0x80,0x7c,0x00,0x00, /* 200 */
|
|
||||||
0x08,0x30,0x00,0x7c,0x80,0x80,0xb8,0x80,0x80,0x7c,0x00,0x00, /* 201 */
|
|
||||||
0x38,0x44,0x00,0x7c,0x80,0x80,0xb8,0x80,0x80,0x7c,0x00,0x00, /* 202 */
|
|
||||||
0x6c,0x00,0x00,0x7c,0x80,0x80,0xb8,0x80,0x80,0x7c,0x00,0x00, /* 203 */
|
|
||||||
0x20,0x18,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 204 */
|
|
||||||
0x08,0x30,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 205 */
|
|
||||||
0x38,0x44,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 206 */
|
|
||||||
0x6c,0x00,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 207 */
|
|
||||||
0x00,0xbc,0x82,0x82,0x82,0xb2,0x82,0x82,0x82,0xbc,0x00,0x00, /* 208 */
|
|
||||||
0x32,0x4c,0x00,0x7c,0x82,0x82,0x82,0x82,0x82,0x82,0x00,0x00, /* 209 */
|
|
||||||
0x20,0x18,0x00,0x7c,0x82,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 210 */
|
|
||||||
0x08,0x30,0x00,0x7c,0x82,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 211 */
|
|
||||||
0x38,0x44,0x00,0x7c,0x82,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 212 */
|
|
||||||
0x32,0x4c,0x00,0x7c,0x82,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 213 */
|
|
||||||
0x6c,0x00,0x00,0x7c,0x82,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 214 */
|
|
||||||
0x00,0x00,0x00,0x00,0x44,0x28,0x00,0x28,0x44,0x00,0x00,0x00, /* 215 */
|
|
||||||
0x00,0x7a,0x84,0x82,0x8a,0x92,0xa2,0x82,0x42,0xbc,0x00,0x00, /* 216 */
|
|
||||||
0x20,0x18,0x00,0x82,0x82,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 217 */
|
|
||||||
0x08,0x30,0x00,0x82,0x82,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 218 */
|
|
||||||
0x38,0x44,0x00,0x82,0x82,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 219 */
|
|
||||||
0x6c,0x00,0x00,0x82,0x82,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 220 */
|
|
||||||
0x08,0xb2,0x82,0x82,0x82,0x7c,0x00,0x10,0x10,0x10,0x00,0x00, /* 221 */
|
|
||||||
0x00,0x80,0x80,0xbc,0x82,0x82,0x82,0xbc,0x80,0x80,0x00,0x00, /* 222 */
|
|
||||||
0x00,0x3c,0x42,0x42,0x42,0x5c,0x42,0x42,0x42,0x9c,0x00,0x00, /* 223 */
|
|
||||||
0x20,0x18,0x00,0x00,0x3c,0x02,0x3a,0x42,0x42,0x3c,0x00,0x00, /* 224 */
|
|
||||||
0x08,0x30,0x00,0x00,0x3c,0x02,0x3a,0x42,0x42,0x3c,0x00,0x00, /* 225 */
|
|
||||||
0x38,0x44,0x00,0x00,0x3c,0x02,0x3a,0x42,0x42,0x3c,0x00,0x00, /* 226 */
|
|
||||||
0x32,0x4c,0x00,0x00,0x3c,0x02,0x3a,0x42,0x42,0x3c,0x00,0x00, /* 227 */
|
|
||||||
0x6c,0x00,0x00,0x00,0x3c,0x02,0x3a,0x42,0x42,0x3c,0x00,0x00, /* 228 */
|
|
||||||
0x18,0x24,0x18,0x00,0x3c,0x02,0x3a,0x42,0x42,0x3c,0x00,0x00, /* 229 */
|
|
||||||
0x00,0x00,0x00,0x00,0x6c,0x12,0x52,0x94,0x90,0x6e,0x00,0x00, /* 230 */
|
|
||||||
0x00,0x00,0x00,0x00,0x3c,0x40,0x40,0x40,0x40,0x34,0x08,0x10, /* 231 */
|
|
||||||
0x20,0x18,0x00,0x00,0x3c,0x42,0x42,0x5c,0x40,0x3c,0x00,0x00, /* 232 */
|
|
||||||
0x08,0x30,0x00,0x00,0x3c,0x42,0x42,0x5c,0x40,0x3c,0x00,0x00, /* 233 */
|
|
||||||
0x38,0x44,0x00,0x00,0x3c,0x42,0x42,0x5c,0x40,0x3c,0x00,0x00, /* 234 */
|
|
||||||
0x6c,0x00,0x00,0x00,0x3c,0x42,0x42,0x5c,0x40,0x3c,0x00,0x00, /* 235 */
|
|
||||||
0x20,0x18,0x00,0x10,0x00,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 236 */
|
|
||||||
0x08,0x30,0x00,0x10,0x00,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 237 */
|
|
||||||
0x38,0x44,0x00,0x10,0x00,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 238 */
|
|
||||||
0x6c,0x00,0x00,0x10,0x00,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 239 */
|
|
||||||
0x00,0x14,0x08,0x14,0x02,0x3a,0x42,0x42,0x42,0x3c,0x00,0x00, /* 240 */
|
|
||||||
0x00,0x32,0x4c,0x00,0x3c,0x42,0x42,0x42,0x42,0x42,0x00,0x00, /* 241 */
|
|
||||||
0x20,0x18,0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 242 */
|
|
||||||
0x08,0x30,0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 243 */
|
|
||||||
0x38,0x44,0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 244 */
|
|
||||||
0x32,0x4c,0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 245 */
|
|
||||||
0x6c,0x00,0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 246 */
|
|
||||||
0x00,0x00,0x00,0x00,0x38,0x00,0xfe,0x00,0x38,0x00,0x00,0x00, /* 247 */
|
|
||||||
0x00,0x00,0x00,0x00,0x3a,0x44,0x4a,0x52,0x22,0x5c,0x00,0x00, /* 248 */
|
|
||||||
0x20,0x18,0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 249 */
|
|
||||||
0x08,0x30,0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 250 */
|
|
||||||
0x38,0x44,0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 251 */
|
|
||||||
0x6c,0x00,0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 252 */
|
|
||||||
0x04,0x18,0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x3a,0x02,0x3c, /* 253 */
|
|
||||||
0x00,0x80,0x80,0x9c,0xa2,0x82,0xa2,0x9c,0x80,0x80,0x00,0x00, /* 254 */
|
|
||||||
};
|
|
||||||
int radonFontMetaData[256*5]={
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,12,0,-2,12,8,12,0,-2,24,8,12,0,-2,36,8,12,0,-2,48,8,12,0,-2,60,8,12,0,-2,72,8,12,0,-2,84,8,12,0,-2,96,8,12,0,-2,108,8,12,0,-2,120,8,12,0,-2,132,8,12,0,-2,144,8,12,0,-2,156,8,12,0,-2,168,8,12,0,-2,180,8,12,0,-2,192,8,12,0,-2,204,8,12,0,-2,216,8,12,0,-2,228,8,12,0,-2,240,8,12,0,-2,252,8,12,0,-2,264,8,12,0,-2,276,8,12,0,-2,288,8,12,0,-2,300,8,12,0,-2,312,8,12,0,-2,324,8,12,0,-2,336,8,12,0,-2,348,8,12,0,-2,360,8,12,0,-2,372,8,12,0,-2,384,8,12,0,-2,396,8,12,0,-2,408,8,12,0,-2,420,8,12,0,-2,432,8,12,0,-2,444,8,12,0,-2,456,8,12,0,-2,468,8,12,0,-2,480,8,12,0,-2,492,8,12,0,-2,504,8,12,0,-2,516,8,12,0,-2,528,8,12,0,-2,540,8,12,0,-2,552,8,12,0,-2,564,8,12,0,-2,576,8,12,0,-2,588,8,12,0,-2,600,8,12,0,-2,612,8,12,0,-2,624,8,12,0,-2,636,8,12,0,-2,648,8,12,0,-2,660,8,12,0,-2,672,8,12,0,-2,684,8,12,0,-2,696,8,12,0,-2,708,8,12,0,-2,720,8,12,0,-2,732,8,12,0,-2,744,8,12,0,-2,756,8,12,0,-2,768,8,12,0,-2,780,8,12,0,-2,792,8,12,0,-2,804,8,12,0,-2,816,8,12,0,-2,828,8,12,0,-2,840,8,12,0,-2,852,8,12,0,-2,864,8,12,0,-2,876,8,12,0,-2,888,8,12,0,-2,900,8,12,0,-2,912,8,12,0,-2,924,8,12,0,-2,936,8,12,0,-2,948,8,12,0,-2,960,8,12,0,-2,972,8,12,0,-2,984,8,12,0,-2,996,8,12,0,-2,1008,8,12,0,-2,1020,8,12,0,-2,1032,8,12,0,-2,1044,8,12,0,-2,1056,8,12,0,-2,1068,8,12,0,-2,1080,8,12,0,-2,1092,8,12,0,-2,1104,8,12,0,-2,1116,8,12,0,-2,1128,8,12,0,-2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1140,8,12,0,-2,1152,8,12,0,-2,1164,8,12,0,-2,1176,8,12,0,-2,1188,8,12,0,-2,1200,8,12,0,-2,1212,8,12,0,-2,1224,8,12,0,-2,1236,8,12,0,-2,1248,8,12,0,-2,1260,8,12,0,-2,1272,8,12,0,-2,1284,8,12,0,-2,1296,8,12,0,-2,1308,8,12,0,-2,1320,8,12,0,-2,1332,8,12,0,-2,1344,8,12,0,-2,1356,8,12,0,-2,1368,8,12,0,-2,1380,8,12,0,-2,1392,8,12,0,-2,1404,8,12,0,-2,1416,8,12,0,-2,1428,8,12,0,-2,1440,8,12,0,-2,1452,8,12,0,-2,1464,8,12,0,-2,1476,8,12,0,-2,1488,8,12,0,-2,1500,8,12,0,-2,1512,8,12,0,-2,1524,8,12,0,-2,1536,8,12,0,-2,1548,8,12,0,-2,1560,8,12,0,-2,1572,8,12,0,-2,1584,8,12,0,-2,1596,8,12,0,-2,1608,8,12,0,-2,1620,8,12,0,-2,1632,8,12,0,-2,1644,8,12,0,-2,1656,8,12,0,-2,1668,8,12,0,-2,1680,8,12,0,-2,1692,8,12,0,-2,1704,8,12,0,-2,1716,8,12,0,-2,1728,8,12,0,-2,1740,8,12,0,-2,1752,8,12,0,-2,1764,8,12,0,-2,1776,8,12,0,-2,1788,8,12,0,-2,1800,8,12,0,-2,1812,8,12,0,-2,1824,8,12,0,-2,1836,8,12,0,-2,1848,8,12,0,-2,1860,8,12,0,-2,1872,8,12,0,-2,1884,8,12,0,-2,1896,8,12,0,-2,1908,8,12,0,-2,1920,8,12,0,-2,1932,8,12,0,-2,1944,8,12,0,-2,1956,8,12,0,-2,1968,8,12,0,-2,1980,8,12,0,-2,1992,8,12,0,-2,2004,8,12,0,-2,2016,8,12,0,-2,2028,8,12,0,-2,2040,8,12,0,-2,2052,8,12,0,-2,2064,8,12,0,-2,2076,8,12,0,-2,2088,8,12,0,-2,2100,8,12,0,-2,2112,8,12,0,-2,2124,8,12,0,-2,2136,8,12,0,-2,2148,8,12,0,-2,2160,8,12,0,-2,2172,8,12,0,-2,2184,8,12,0,-2,2196,8,12,0,-2,2208,8,12,0,-2,2220,8,12,0,-2,2232,8,12,0,-2,2244,8,12,0,-2,2256,8,12,0,-2,2268,8,12,0,-2,0,0,0,0,0,};
|
|
||||||
rfbFontData radonFont={radonFontData, radonFontMetaData};
|
|
@ -1,858 +0,0 @@
|
|||||||
#ifndef RFB_H
|
|
||||||
#define RFB_H
|
|
||||||
|
|
||||||
/*
|
|
||||||
* rfb.h - header file for RFB DDX implementation.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
|
|
||||||
* Original Xvnc code 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
|
||||||
* USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if(defined __cplusplus)
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <zlib.h>
|
|
||||||
#include "keysym.h"
|
|
||||||
|
|
||||||
/* TODO: this stuff has to go into autoconf */
|
|
||||||
typedef unsigned char CARD8;
|
|
||||||
typedef unsigned short CARD16;
|
|
||||||
typedef unsigned int CARD32;
|
|
||||||
typedef CARD32 Pixel;
|
|
||||||
/* typedef CARD32 KeySym; */
|
|
||||||
#ifndef __osf__
|
|
||||||
typedef unsigned long KeySym;
|
|
||||||
#endif
|
|
||||||
#define SIGNED signed
|
|
||||||
/* for some strange reason, "typedef signed char Bool;" yields a four byte
|
|
||||||
signed int on IRIX, but only for rfbserver.o!!! */
|
|
||||||
#ifdef Bool
|
|
||||||
#undef Bool
|
|
||||||
#endif
|
|
||||||
#define Bool signed char
|
|
||||||
#undef FALSE
|
|
||||||
#define FALSE 0
|
|
||||||
#undef TRUE
|
|
||||||
#define TRUE -1
|
|
||||||
|
|
||||||
#include "rfbproto.h"
|
|
||||||
|
|
||||||
#if defined(__linux__) || defined(__GLIBC__)
|
|
||||||
#include <endian.h>
|
|
||||||
#elif defined(__APPLE__) || defined(__FreeBSD__)
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <machine/endian.h>
|
|
||||||
#ifndef _BYTE_ORDER
|
|
||||||
#define _BYTE_ORDER BYTE_ORDER
|
|
||||||
#endif
|
|
||||||
#ifndef _LITTLE_ENDIAN
|
|
||||||
#define _LITTLE_ENDIAN LITTLE_ENDIAN
|
|
||||||
#endif
|
|
||||||
#elif defined (__SVR4) && defined (__sun) /* Solaris */
|
|
||||||
#include <sys/types.h>
|
|
||||||
#if defined(__sparc)
|
|
||||||
/* SPARC here (big endian) */
|
|
||||||
#define _BYTE_ORDER 4321
|
|
||||||
#elif defined(__i386)
|
|
||||||
#define _BYTE_ORDER 1234
|
|
||||||
#else
|
|
||||||
#error Solaris 2.5.1 had ppc support did it not? :-)
|
|
||||||
#endif
|
|
||||||
#undef Bool
|
|
||||||
#define Bool char
|
|
||||||
#undef SIGNED
|
|
||||||
#define SIGNED
|
|
||||||
#include <sys/types.h>
|
|
||||||
/* typedef unsigned int pthread_t; */
|
|
||||||
#elif defined(WIN32)
|
|
||||||
#define _LITTLE_ENDIAN 1234
|
|
||||||
#define _BYTE_ORDER _LITTLE_ENDIAN
|
|
||||||
#undef Bool
|
|
||||||
#define Bool int
|
|
||||||
#elif defined(_AIX)
|
|
||||||
#define _BYTE_ORDER 4321
|
|
||||||
#undef Bool
|
|
||||||
#define Bool int
|
|
||||||
#else
|
|
||||||
#ifdef __osf__
|
|
||||||
#include <machine/endian.h>
|
|
||||||
#define _BYTE_ORDER BYTE_ORDER
|
|
||||||
#else
|
|
||||||
#include <sys/endian.h>
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef _BYTE_ORDER
|
|
||||||
#define _BYTE_ORDER __BYTE_ORDER
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(_LITTLE_ENDIAN) && defined(__LITTLE_ENDIAN)
|
|
||||||
#define _LITTLE_ENDIAN __LITTLE_ENDIAN
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
#include <sys/timeb.h>
|
|
||||||
#include <winsock.h>
|
|
||||||
#undef SOCKET
|
|
||||||
#define SOCKET int
|
|
||||||
#else
|
|
||||||
#define max(a,b) (((a)>(b))?(a):(b))
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#define SOCKET int
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef INADDR_NONE
|
|
||||||
#define INADDR_NONE ((in_addr_t) 0xffffffff)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_PTHREADS
|
|
||||||
#include <pthread.h>
|
|
||||||
#if 0 /* debugging */
|
|
||||||
#define LOCK(mutex) fprintf(stderr,"%s:%d LOCK(%s,0x%x)\n",__FILE__,__LINE__,#mutex,&(mutex))
|
|
||||||
#define UNLOCK(mutex) fprintf(stderr,"%s:%d UNLOCK(%s,0x%x)\n",__FILE__,__LINE__,#mutex,&(mutex))
|
|
||||||
#define MUTEX(mutex) int mutex
|
|
||||||
#define INIT_MUTEX(mutex) fprintf(stderr,"%s:%d INIT_MUTEX(%s,0x%x)\n",__FILE__,__LINE__,#mutex,&(mutex))
|
|
||||||
#define TINI_MUTEX(mutex) fprintf(stderr,"%s:%d TINI_MUTEX(%s)\n",__FILE__,__LINE__,#mutex)
|
|
||||||
#define TSIGNAL(cond) fprintf(stderr,"%s:%d TSIGNAL(%s)\n",__FILE__,__LINE__,#cond)
|
|
||||||
#define WAIT(cond,mutex) /* fprintf(stderr,"%s:%d WAIT(%s,%s)\n",__FILE__,__LINE__,#cond,#mutex) */
|
|
||||||
#define COND(cond)
|
|
||||||
#define INIT_COND(cond) fprintf(stderr,"%s:%d INIT_COND(%s)\n",__FILE__,__LINE__,#cond)
|
|
||||||
#define TINI_COND(cond) fprintf(stderr,"%s:%d TINI_COND(%s)\n",__FILE__,__LINE__,#cond)
|
|
||||||
#define IF_PTHREADS(x)
|
|
||||||
#else
|
|
||||||
#define LOCK(mutex) pthread_mutex_lock(&(mutex));
|
|
||||||
#define UNLOCK(mutex) pthread_mutex_unlock(&(mutex));
|
|
||||||
#define MUTEX(mutex) pthread_mutex_t (mutex)
|
|
||||||
#define INIT_MUTEX(mutex) pthread_mutex_init(&(mutex),NULL)
|
|
||||||
#define TINI_MUTEX(mutex) pthread_mutex_destroy(&(mutex))
|
|
||||||
#define TSIGNAL(cond) pthread_cond_signal(&(cond))
|
|
||||||
#define WAIT(cond,mutex) pthread_cond_wait(&(cond),&(mutex))
|
|
||||||
#define TIMEDWAIT(cond,mutex,t) {struct timeval tv;\
|
|
||||||
tv.tv_sec = (t) / 1000;\
|
|
||||||
tv.tv_usec = ((t) % 1000) * 1000;\
|
|
||||||
pthread_cond_timedwait(&(cond),&(mutex),(const timespec*)(&tv));}
|
|
||||||
#define COND(cond) pthread_cond_t (cond)
|
|
||||||
#define INIT_COND(cond) pthread_cond_init(&(cond),NULL)
|
|
||||||
#define TINI_COND(cond) pthread_cond_destroy(&(cond))
|
|
||||||
#define IF_PTHREADS(x) x
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#define LOCK(mutex)
|
|
||||||
#define UNLOCK(mutex)
|
|
||||||
#define MUTEX(mutex)
|
|
||||||
#define INIT_MUTEX(mutex)
|
|
||||||
#define TINI_MUTEX(mutex)
|
|
||||||
#define TSIGNAL(cond)
|
|
||||||
#define WAIT(cond,mutex) this_is_unsupported
|
|
||||||
#define COND(cond)
|
|
||||||
#define INIT_COND(cond)
|
|
||||||
#define TINI_COND(cond)
|
|
||||||
#define IF_PTHREADS(x)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* end of stuff for autoconf */
|
|
||||||
|
|
||||||
/* if you use pthreads, but don't define HAVE_PTHREADS, the structs
|
|
||||||
get all mixed up. So this gives a linker error reminding you to compile
|
|
||||||
the library and your application (at least the parts including rfb.h)
|
|
||||||
with the same support for pthreads. */
|
|
||||||
#ifdef HAVE_PTHREADS
|
|
||||||
#define rfbInitServer rfbInitServerWithPthreads
|
|
||||||
#else
|
|
||||||
#define rfbInitServer rfbInitServerWithoutPthreads
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define MAX_ENCODINGS 10
|
|
||||||
|
|
||||||
struct _rfbClientRec;
|
|
||||||
struct _rfbScreenInfo;
|
|
||||||
struct rfbCursor;
|
|
||||||
|
|
||||||
enum rfbNewClientAction {
|
|
||||||
RFB_CLIENT_ACCEPT,
|
|
||||||
RFB_CLIENT_ON_HOLD,
|
|
||||||
RFB_CLIENT_REFUSE
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef void (*KbdAddEventProcPtr) (Bool down, KeySym keySym, struct _rfbClientRec* cl);
|
|
||||||
typedef void (*KbdReleaseAllKeysProcPtr) (struct _rfbClientRec* cl);
|
|
||||||
typedef void (*PtrAddEventProcPtr) (int buttonMask, int x, int y, struct _rfbClientRec* cl);
|
|
||||||
typedef void (*SetXCutTextProcPtr) (char* str,int len, struct _rfbClientRec* cl);
|
|
||||||
typedef struct rfbCursor* (*GetCursorProcPtr) (struct _rfbClientRec* pScreen);
|
|
||||||
typedef Bool (*SetTranslateFunctionProcPtr)(struct _rfbClientRec* cl);
|
|
||||||
typedef Bool (*PasswordCheckProcPtr)(struct _rfbClientRec* cl,const char* encryptedPassWord,int len);
|
|
||||||
typedef enum rfbNewClientAction (*NewClientHookPtr)(struct _rfbClientRec* cl);
|
|
||||||
typedef void (*DisplayHookPtr)(struct _rfbClientRec* cl);
|
|
||||||
typedef void (*InetdDisconnectPtr)();
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
CARD32 count;
|
|
||||||
Bool is16; /* is the data format short? */
|
|
||||||
union {
|
|
||||||
CARD8* bytes;
|
|
||||||
CARD16* shorts;
|
|
||||||
} data; /* there have to be count*3 entries */
|
|
||||||
} rfbColourMap;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Per-screen (framebuffer) structure. There can be as many as you wish,
|
|
||||||
* each serving different clients. However, you have to call
|
|
||||||
* rfbProcessEvents for each of these.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct _rfbScreenInfo
|
|
||||||
{
|
|
||||||
int width;
|
|
||||||
int paddedWidthInBytes;
|
|
||||||
int height;
|
|
||||||
int depth;
|
|
||||||
int bitsPerPixel;
|
|
||||||
int sizeInBytes;
|
|
||||||
|
|
||||||
Pixel blackPixel;
|
|
||||||
Pixel whitePixel;
|
|
||||||
|
|
||||||
/* some screen specific data can be put into a struct where screenData
|
|
||||||
* points to. You need this if you have more than one screen at the
|
|
||||||
* same time while using the same functions.
|
|
||||||
*/
|
|
||||||
void* screenData;
|
|
||||||
|
|
||||||
/* The following two members are used to minimise the amount of unnecessary
|
|
||||||
drawing caused by cursor movement. Whenever any drawing affects the
|
|
||||||
part of the screen where the cursor is, the cursor is removed first and
|
|
||||||
then the drawing is done (this is what the sprite routines test for).
|
|
||||||
Afterwards, however, we do not replace the cursor, even when the cursor
|
|
||||||
is logically being moved across the screen. We only draw the cursor
|
|
||||||
again just as we are about to send the client a framebuffer update.
|
|
||||||
|
|
||||||
We need to be careful when removing and drawing the cursor because of
|
|
||||||
their relationship with the normal drawing routines. The drawing
|
|
||||||
routines can invoke the cursor routines, but also the cursor routines
|
|
||||||
themselves end up invoking drawing routines.
|
|
||||||
|
|
||||||
Removing the cursor (rfbUndrawCursor) is eventually achieved by
|
|
||||||
doing a CopyArea from a pixmap to the screen, where the pixmap contains
|
|
||||||
the saved contents of the screen under the cursor. Before doing this,
|
|
||||||
however, we set cursorIsDrawn to FALSE. Then, when CopyArea is called,
|
|
||||||
it sees that cursorIsDrawn is FALSE and so doesn't feel the need to
|
|
||||||
(recursively!) remove the cursor before doing it.
|
|
||||||
|
|
||||||
Putting up the cursor (rfbDrawCursor) involves a call to
|
|
||||||
PushPixels. While this is happening, cursorIsDrawn must be FALSE so
|
|
||||||
that PushPixels doesn't think it has to remove the cursor first.
|
|
||||||
Obviously cursorIsDrawn is set to TRUE afterwards.
|
|
||||||
|
|
||||||
Another problem we face is that drawing routines sometimes cause a
|
|
||||||
framebuffer update to be sent to the RFB client. When the RFB client is
|
|
||||||
already waiting for a framebuffer update and some drawing to the
|
|
||||||
framebuffer then happens, the drawing routine sees that the client is
|
|
||||||
ready, so it calls rfbSendFramebufferUpdate. If the cursor is not drawn
|
|
||||||
at this stage, it must be put up, and so rfbSpriteRestoreCursor is
|
|
||||||
called. However, if the original drawing routine was actually called
|
|
||||||
from within rfbSpriteRestoreCursor or rfbSpriteRemoveCursor we don't
|
|
||||||
want this to happen. So both the cursor routines set
|
|
||||||
dontSendFramebufferUpdate to TRUE, and all the drawing routines check
|
|
||||||
this before calling rfbSendFramebufferUpdate. */
|
|
||||||
|
|
||||||
Bool cursorIsDrawn; /* TRUE if the cursor is currently drawn */
|
|
||||||
Bool dontSendFramebufferUpdate; /* TRUE while removing or drawing the
|
|
||||||
cursor */
|
|
||||||
|
|
||||||
/* additions by libvncserver */
|
|
||||||
|
|
||||||
rfbPixelFormat rfbServerFormat;
|
|
||||||
rfbColourMap colourMap; /* set this if rfbServerFormat.trueColour==FALSE */
|
|
||||||
const char* desktopName;
|
|
||||||
char rfbThisHost[255];
|
|
||||||
|
|
||||||
Bool autoPort;
|
|
||||||
int rfbPort;
|
|
||||||
SOCKET rfbListenSock;
|
|
||||||
int maxSock;
|
|
||||||
int maxFd;
|
|
||||||
fd_set allFds;
|
|
||||||
|
|
||||||
Bool socketInitDone;
|
|
||||||
SOCKET inetdSock;
|
|
||||||
Bool inetdInitDone;
|
|
||||||
|
|
||||||
int udpPort;
|
|
||||||
SOCKET udpSock;
|
|
||||||
struct _rfbClientRec* udpClient;
|
|
||||||
Bool udpSockConnected;
|
|
||||||
struct sockaddr_in udpRemoteAddr;
|
|
||||||
|
|
||||||
int rfbMaxClientWait;
|
|
||||||
|
|
||||||
/* http stuff */
|
|
||||||
Bool httpInitDone;
|
|
||||||
int httpPort;
|
|
||||||
char* httpDir;
|
|
||||||
SOCKET httpListenSock;
|
|
||||||
SOCKET httpSock;
|
|
||||||
FILE* httpFP;
|
|
||||||
|
|
||||||
PasswordCheckProcPtr passwordCheck;
|
|
||||||
void* rfbAuthPasswdData;
|
|
||||||
|
|
||||||
/* this is the amount of milliseconds to wait at least before sending
|
|
||||||
* an update. */
|
|
||||||
int rfbDeferUpdateTime;
|
|
||||||
char* rfbScreen;
|
|
||||||
Bool rfbAlwaysShared;
|
|
||||||
Bool rfbNeverShared;
|
|
||||||
Bool rfbDontDisconnect;
|
|
||||||
struct _rfbClientRec* rfbClientHead;
|
|
||||||
|
|
||||||
/* cursor */
|
|
||||||
int cursorX, cursorY,underCursorBufferLen;
|
|
||||||
char* underCursorBuffer;
|
|
||||||
Bool dontConvertRichCursorToXCursor;
|
|
||||||
struct rfbCursor* cursor;
|
|
||||||
|
|
||||||
/* the frameBufferhas to be supplied by the serving process.
|
|
||||||
* The buffer will not be freed by
|
|
||||||
*/
|
|
||||||
char* frameBuffer;
|
|
||||||
KbdAddEventProcPtr kbdAddEvent;
|
|
||||||
KbdReleaseAllKeysProcPtr kbdReleaseAllKeys;
|
|
||||||
PtrAddEventProcPtr ptrAddEvent;
|
|
||||||
SetXCutTextProcPtr setXCutText;
|
|
||||||
GetCursorProcPtr getCursorPtr;
|
|
||||||
SetTranslateFunctionProcPtr setTranslateFunction;
|
|
||||||
|
|
||||||
/* newClientHook is called just after a new client is created */
|
|
||||||
NewClientHookPtr newClientHook;
|
|
||||||
/* displayHook is called just before a frame buffer update */
|
|
||||||
DisplayHookPtr displayHook;
|
|
||||||
/* inetdDisconnectHook is called when the connection has been
|
|
||||||
interrupted before a client could connect. */
|
|
||||||
InetdDisconnectPtr inetdDisconnectHook;
|
|
||||||
#ifdef HAVE_PTHREADS
|
|
||||||
MUTEX(cursorMutex);
|
|
||||||
Bool backgroundLoop;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} rfbScreenInfo, *rfbScreenInfoPtr;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* rfbTranslateFnType is the type of translation functions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef void (*rfbTranslateFnType)(char *table, rfbPixelFormat *in,
|
|
||||||
rfbPixelFormat *out,
|
|
||||||
char *iptr, char *optr,
|
|
||||||
int bytesBetweenInputLines,
|
|
||||||
int width, int height);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* vncauth.h - describes the functions provided by the vncauth library.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define MAXPWLEN 8
|
|
||||||
#define CHALLENGESIZE 16
|
|
||||||
|
|
||||||
extern int vncEncryptAndStorePasswd(char *passwd, char *fname);
|
|
||||||
extern char *vncDecryptPasswdFromFile(char *fname);
|
|
||||||
extern void vncRandomBytes(unsigned char *bytes);
|
|
||||||
extern void vncEncryptBytes(unsigned char *bytes, char *passwd);
|
|
||||||
|
|
||||||
/* region stuff */
|
|
||||||
|
|
||||||
struct sraRegion;
|
|
||||||
typedef struct sraRegion* sraRegionPtr;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Per-client structure.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef void (*ClientGoneHookPtr)(struct _rfbClientRec* cl);
|
|
||||||
typedef void (*NegotiationFinishedHookPtr)(struct _rfbClientRec* cl);
|
|
||||||
|
|
||||||
typedef struct _rfbClientRec {
|
|
||||||
|
|
||||||
/* back pointer to the screen */
|
|
||||||
rfbScreenInfoPtr screen;
|
|
||||||
|
|
||||||
/* private data. You should put any application client specific data
|
|
||||||
* into a struct and let clientData point to it. Don't forget to
|
|
||||||
* free the struct via clientGoneHook!
|
|
||||||
*
|
|
||||||
* This is useful if the IO functions have to behave client specific.
|
|
||||||
*/
|
|
||||||
void* clientData;
|
|
||||||
|
|
||||||
ClientGoneHookPtr clientGoneHook;
|
|
||||||
|
|
||||||
/* negotiationFinishedHook is called when the negotiation phase has ended */
|
|
||||||
NegotiationFinishedHookPtr negotiationFinishedHook;
|
|
||||||
|
|
||||||
SOCKET sock;
|
|
||||||
char *host;
|
|
||||||
|
|
||||||
#ifdef HAVE_PTHREADS
|
|
||||||
pthread_t client_thread;
|
|
||||||
#endif
|
|
||||||
/* Possible client states: */
|
|
||||||
enum {
|
|
||||||
RFB_PROTOCOL_VERSION, /* establishing protocol version */
|
|
||||||
RFB_AUTHENTICATION, /* authenticating */
|
|
||||||
RFB_INITIALISATION, /* sending initialisation messages */
|
|
||||||
RFB_NORMAL /* normal protocol messages */
|
|
||||||
} state;
|
|
||||||
|
|
||||||
Bool reverseConnection;
|
|
||||||
Bool onHold;
|
|
||||||
Bool readyForSetColourMapEntries;
|
|
||||||
Bool useCopyRect;
|
|
||||||
int preferredEncoding;
|
|
||||||
int correMaxWidth, correMaxHeight;
|
|
||||||
|
|
||||||
/* The following member is only used during VNC authentication */
|
|
||||||
CARD8 authChallenge[CHALLENGESIZE];
|
|
||||||
|
|
||||||
/* The following members represent the update needed to get the client's
|
|
||||||
framebuffer from its present state to the current state of our
|
|
||||||
framebuffer.
|
|
||||||
|
|
||||||
If the client does not accept CopyRect encoding then the update is
|
|
||||||
simply represented as the region of the screen which has been modified
|
|
||||||
(modifiedRegion).
|
|
||||||
|
|
||||||
If the client does accept CopyRect encoding, then the update consists of
|
|
||||||
two parts. First we have a single copy from one region of the screen to
|
|
||||||
another (the destination of the copy is copyRegion), and second we have
|
|
||||||
the region of the screen which has been modified in some other way
|
|
||||||
(modifiedRegion).
|
|
||||||
|
|
||||||
Although the copy is of a single region, this region may have many
|
|
||||||
rectangles. When sending an update, the copyRegion is always sent
|
|
||||||
before the modifiedRegion. This is because the modifiedRegion may
|
|
||||||
overlap parts of the screen which are in the source of the copy.
|
|
||||||
|
|
||||||
In fact during normal processing, the modifiedRegion may even overlap
|
|
||||||
the destination copyRegion. Just before an update is sent we remove
|
|
||||||
from the copyRegion anything in the modifiedRegion. */
|
|
||||||
|
|
||||||
sraRegionPtr copyRegion; /* the destination region of the copy */
|
|
||||||
int copyDX, copyDY; /* the translation by which the copy happens */
|
|
||||||
|
|
||||||
sraRegionPtr modifiedRegion;
|
|
||||||
|
|
||||||
/* As part of the FramebufferUpdateRequest, a client can express interest
|
|
||||||
in a subrectangle of the whole framebuffer. This is stored in the
|
|
||||||
requestedRegion member. In the normal case this is the whole
|
|
||||||
framebuffer if the client is ready, empty if it's not. */
|
|
||||||
|
|
||||||
sraRegionPtr requestedRegion;
|
|
||||||
|
|
||||||
/* The following member represents the state of the "deferred update" timer
|
|
||||||
- when the framebuffer is modified and the client is ready, in most
|
|
||||||
cases it is more efficient to defer sending the update by a few
|
|
||||||
milliseconds so that several changes to the framebuffer can be combined
|
|
||||||
into a single update. */
|
|
||||||
|
|
||||||
struct timeval startDeferring;
|
|
||||||
|
|
||||||
/* translateFn points to the translation function which is used to copy
|
|
||||||
and translate a rectangle from the framebuffer to an output buffer. */
|
|
||||||
|
|
||||||
rfbTranslateFnType translateFn;
|
|
||||||
char *translateLookupTable;
|
|
||||||
rfbPixelFormat format;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* UPDATE_BUF_SIZE must be big enough to send at least one whole line of the
|
|
||||||
* framebuffer. So for a max screen width of say 2K with 32-bit pixels this
|
|
||||||
* means 8K minimum.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define UPDATE_BUF_SIZE 30000
|
|
||||||
|
|
||||||
char updateBuf[UPDATE_BUF_SIZE];
|
|
||||||
int ublen;
|
|
||||||
|
|
||||||
/* statistics */
|
|
||||||
|
|
||||||
int rfbBytesSent[MAX_ENCODINGS];
|
|
||||||
int rfbRectanglesSent[MAX_ENCODINGS];
|
|
||||||
int rfbLastRectMarkersSent;
|
|
||||||
int rfbLastRectBytesSent;
|
|
||||||
int rfbCursorBytesSent;
|
|
||||||
int rfbCursorUpdatesSent;
|
|
||||||
int rfbFramebufferUpdateMessagesSent;
|
|
||||||
int rfbRawBytesEquivalent;
|
|
||||||
int rfbKeyEventsRcvd;
|
|
||||||
int rfbPointerEventsRcvd;
|
|
||||||
|
|
||||||
/* zlib encoding -- necessary compression state info per client */
|
|
||||||
|
|
||||||
struct z_stream_s compStream;
|
|
||||||
Bool compStreamInited;
|
|
||||||
CARD32 zlibCompressLevel;
|
|
||||||
|
|
||||||
/* tight encoding -- preserve zlib streams' state for each client */
|
|
||||||
|
|
||||||
z_stream zsStruct[4];
|
|
||||||
Bool zsActive[4];
|
|
||||||
int zsLevel[4];
|
|
||||||
int tightCompressLevel;
|
|
||||||
int tightQualityLevel;
|
|
||||||
|
|
||||||
/* soft cursor images */
|
|
||||||
unsigned char *softSource;
|
|
||||||
int softSourceLen;
|
|
||||||
rfbSoftCursorSetImage *softCursorImages[rfbSoftCursorMaxImages];
|
|
||||||
int nextUnusedSoftCursorImage;
|
|
||||||
|
|
||||||
Bool enableLastRectEncoding; /* client supports LastRect encoding */
|
|
||||||
Bool enableSoftCursorUpdates; /* client supports softcursor updates */
|
|
||||||
Bool disableBackground; /* client wants to disable background */
|
|
||||||
Bool enableCursorShapeUpdates; /* client supports cursor shape updates */
|
|
||||||
Bool useRichCursorEncoding; /* rfbEncodingRichCursor is preferred */
|
|
||||||
Bool cursorWasChanged; /* cursor shape update should be sent */
|
|
||||||
Bool cursorWasMoved; /* cursor move shape update should be sent */
|
|
||||||
#ifdef BACKCHANNEL
|
|
||||||
Bool enableBackChannel;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct _rfbClientRec *prev;
|
|
||||||
struct _rfbClientRec *next;
|
|
||||||
|
|
||||||
#ifdef HAVE_PTHREADS
|
|
||||||
/* whenever a client is referenced, the refCount has to be incremented
|
|
||||||
and afterwards decremented, so that the client is not cleaned up
|
|
||||||
while being referenced.
|
|
||||||
Use the functions rfbIncrClientRef(cl) and rfbDecrClientRef(cl);
|
|
||||||
*/
|
|
||||||
int refCount;
|
|
||||||
MUTEX(refCountMutex);
|
|
||||||
COND(deleteCond);
|
|
||||||
|
|
||||||
MUTEX(outputMutex);
|
|
||||||
MUTEX(updateMutex);
|
|
||||||
COND(updateCond);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} rfbClientRec, *rfbClientPtr;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This macro is used to test whether there is a framebuffer update needing to
|
|
||||||
* be sent to the client.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define FB_UPDATE_PENDING(cl) \
|
|
||||||
((!(cl)->enableCursorShapeUpdates && !(cl)->screen->cursorIsDrawn) || \
|
|
||||||
((cl)->enableCursorShapeUpdates && (cl)->cursorWasChanged) || \
|
|
||||||
!sraRgnEmpty((cl)->copyRegion) || !sraRgnEmpty((cl)->modifiedRegion))
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Macros for endian swapping.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define Swap16(s) ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff))
|
|
||||||
|
|
||||||
#define Swap24(l) ((((l) & 0xff) << 16) | (((l) >> 16) & 0xff) | \
|
|
||||||
(((l) & 0x00ff00)))
|
|
||||||
|
|
||||||
#define Swap32(l) (((l) >> 24) | \
|
|
||||||
(((l) & 0x00ff0000) >> 8) | \
|
|
||||||
(((l) & 0x0000ff00) << 8) | \
|
|
||||||
((l) << 24))
|
|
||||||
|
|
||||||
|
|
||||||
extern char rfbEndianTest;
|
|
||||||
|
|
||||||
#define Swap16IfLE(s) (rfbEndianTest ? Swap16(s) : (s))
|
|
||||||
#define Swap24IfLE(l) (rfbEndianTest ? Swap24(l) : (l))
|
|
||||||
#define Swap32IfLE(l) (rfbEndianTest ? Swap32(l) : (l))
|
|
||||||
|
|
||||||
/* sockets.c */
|
|
||||||
|
|
||||||
extern int rfbMaxClientWait;
|
|
||||||
|
|
||||||
extern void rfbInitSockets(rfbScreenInfoPtr rfbScreen);
|
|
||||||
extern void rfbDisconnectUDPSock(rfbScreenInfoPtr rfbScreen);
|
|
||||||
extern void rfbCloseClient(rfbClientPtr cl);
|
|
||||||
extern int ReadExact(rfbClientPtr cl, char *buf, int len);
|
|
||||||
extern int ReadExactTimeout(rfbClientPtr cl, char *buf, int len,int timeout);
|
|
||||||
extern int WriteExact(rfbClientPtr cl, const char *buf, int len);
|
|
||||||
extern void rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec);
|
|
||||||
extern int rfbConnect(rfbScreenInfoPtr rfbScreen, char* host, int port);
|
|
||||||
extern int ConnectToTcpAddr(char* host, int port);
|
|
||||||
extern int ListenOnTCPPort(int port);
|
|
||||||
extern int ListenOnUDPPort(int port);
|
|
||||||
|
|
||||||
/* rfbserver.c */
|
|
||||||
|
|
||||||
extern rfbClientPtr pointerClient;
|
|
||||||
|
|
||||||
|
|
||||||
/* Routines to iterate over the client list in a thread-safe way.
|
|
||||||
Only a single iterator can be in use at a time process-wide. */
|
|
||||||
typedef struct rfbClientIterator *rfbClientIteratorPtr;
|
|
||||||
|
|
||||||
extern void rfbClientListInit(rfbScreenInfoPtr rfbScreen);
|
|
||||||
extern rfbClientIteratorPtr rfbGetClientIterator(rfbScreenInfoPtr rfbScreen);
|
|
||||||
extern rfbClientPtr rfbClientIteratorNext(rfbClientIteratorPtr iterator);
|
|
||||||
extern void rfbReleaseClientIterator(rfbClientIteratorPtr iterator);
|
|
||||||
|
|
||||||
extern void rfbNewClientConnection(rfbScreenInfoPtr rfbScreen,int sock);
|
|
||||||
extern rfbClientPtr rfbNewClient(rfbScreenInfoPtr rfbScreen,int sock);
|
|
||||||
extern rfbClientPtr rfbNewUDPClient(rfbScreenInfoPtr rfbScreen);
|
|
||||||
extern rfbClientPtr rfbReverseConnection(rfbScreenInfoPtr rfbScreen,char *host, int port);
|
|
||||||
extern void rfbClientConnectionGone(rfbClientPtr cl);
|
|
||||||
extern void rfbProcessClientMessage(rfbClientPtr cl);
|
|
||||||
extern void rfbClientConnFailed(rfbClientPtr cl, char *reason);
|
|
||||||
extern void rfbNewUDPConnection(rfbScreenInfoPtr rfbScreen,int sock);
|
|
||||||
extern void rfbProcessUDPInput(rfbScreenInfoPtr rfbScreen);
|
|
||||||
extern Bool rfbSendPing(rfbClientPtr cl);
|
|
||||||
extern Bool rfbSendFramebufferUpdate(rfbClientPtr cl, sraRegionPtr updateRegion);
|
|
||||||
extern Bool rfbSendRectEncodingRaw(rfbClientPtr cl, int x,int y,int w,int h);
|
|
||||||
extern Bool rfbSendUpdateBuf(rfbClientPtr cl);
|
|
||||||
extern void rfbSendServerCutText(rfbScreenInfoPtr rfbScreen,char *str, int len);
|
|
||||||
extern Bool rfbSendCopyRegion(rfbClientPtr cl,sraRegionPtr reg,int dx,int dy);
|
|
||||||
extern Bool rfbSendLastRectMarker(rfbClientPtr cl);
|
|
||||||
extern Bool rfbSendSetColourMapEntries(rfbClientPtr cl, int firstColour, int nColours);
|
|
||||||
extern void rfbSendBell(rfbScreenInfoPtr rfbScreen);
|
|
||||||
|
|
||||||
void rfbGotXCutText(rfbScreenInfoPtr rfbScreen, char *str, int len);
|
|
||||||
|
|
||||||
#ifdef BACKCHANNEL
|
|
||||||
extern void rfbSendBackChannel(rfbScreenInfoPtr s,char* message,int len);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* translate.c */
|
|
||||||
|
|
||||||
extern Bool rfbEconomicTranslate;
|
|
||||||
|
|
||||||
extern void rfbTranslateNone(char *table, rfbPixelFormat *in,
|
|
||||||
rfbPixelFormat *out,
|
|
||||||
char *iptr, char *optr,
|
|
||||||
int bytesBetweenInputLines,
|
|
||||||
int width, int height);
|
|
||||||
extern Bool rfbSetTranslateFunction(rfbClientPtr cl);
|
|
||||||
extern Bool rfbSetClientColourMap(rfbClientPtr cl, int firstColour, int nColours);
|
|
||||||
extern void rfbSetClientColourMaps(rfbScreenInfoPtr rfbScreen, int firstColour, int nColours);
|
|
||||||
|
|
||||||
/* httpd.c */
|
|
||||||
|
|
||||||
extern int httpPort;
|
|
||||||
extern char *httpDir;
|
|
||||||
|
|
||||||
extern void httpInitSockets(rfbScreenInfoPtr rfbScreen);
|
|
||||||
extern void httpCheckFds(rfbScreenInfoPtr rfbScreen);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* auth.c */
|
|
||||||
|
|
||||||
extern void rfbAuthNewClient(rfbClientPtr cl);
|
|
||||||
extern void rfbAuthProcessClientMessage(rfbClientPtr cl);
|
|
||||||
|
|
||||||
|
|
||||||
/* rre.c */
|
|
||||||
|
|
||||||
extern Bool rfbSendRectEncodingRRE(rfbClientPtr cl, int x,int y,int w,int h);
|
|
||||||
|
|
||||||
|
|
||||||
/* corre.c */
|
|
||||||
|
|
||||||
extern Bool rfbSendRectEncodingCoRRE(rfbClientPtr cl, int x,int y,int w,int h);
|
|
||||||
|
|
||||||
|
|
||||||
/* hextile.c */
|
|
||||||
|
|
||||||
extern Bool rfbSendRectEncodingHextile(rfbClientPtr cl, int x, int y, int w,
|
|
||||||
int h);
|
|
||||||
|
|
||||||
|
|
||||||
/* zlib.c */
|
|
||||||
|
|
||||||
/* Minimum zlib rectangle size in bytes. Anything smaller will
|
|
||||||
* not compress well due to overhead.
|
|
||||||
*/
|
|
||||||
#define VNC_ENCODE_ZLIB_MIN_COMP_SIZE (17)
|
|
||||||
|
|
||||||
/* Set maximum zlib rectangle size in pixels. Always allow at least
|
|
||||||
* two scan lines.
|
|
||||||
*/
|
|
||||||
#define ZLIB_MAX_RECT_SIZE (128*256)
|
|
||||||
#define ZLIB_MAX_SIZE(min) ((( min * 2 ) > ZLIB_MAX_RECT_SIZE ) ? \
|
|
||||||
( min * 2 ) : ZLIB_MAX_RECT_SIZE )
|
|
||||||
|
|
||||||
extern Bool rfbSendRectEncodingZlib(rfbClientPtr cl, int x, int y, int w,
|
|
||||||
int h);
|
|
||||||
|
|
||||||
|
|
||||||
/* tight.c */
|
|
||||||
|
|
||||||
#define TIGHT_DEFAULT_COMPRESSION 6
|
|
||||||
|
|
||||||
extern Bool rfbTightDisableGradient;
|
|
||||||
|
|
||||||
extern int rfbNumCodedRectsTight(rfbClientPtr cl, int x,int y,int w,int h);
|
|
||||||
extern Bool rfbSendRectEncodingTight(rfbClientPtr cl, int x,int y,int w,int h);
|
|
||||||
|
|
||||||
|
|
||||||
/* cursor.c */
|
|
||||||
|
|
||||||
typedef struct rfbCursor {
|
|
||||||
const char *source; /* points to bits */
|
|
||||||
const char *mask; /* points to bits */
|
|
||||||
unsigned short width, height, xhot, yhot; /* metrics */
|
|
||||||
unsigned short foreRed, foreGreen, foreBlue; /* device-independent colour */
|
|
||||||
unsigned short backRed, backGreen, backBlue; /* device-independent colour */
|
|
||||||
unsigned char *richSource; /* source bytes for a rich cursor */
|
|
||||||
} rfbCursor, *rfbCursorPtr;
|
|
||||||
|
|
||||||
extern Bool rfbSendCursorShape(rfbClientPtr cl/*, rfbScreenInfoPtr pScreen*/);
|
|
||||||
extern Bool rfbSendSoftCursor(rfbClientPtr cl, Bool cursorWasChanged);
|
|
||||||
extern unsigned char rfbReverseByte[0x100];
|
|
||||||
extern void rfbConvertLSBCursorBitmapOrMask(int width,int height,unsigned char* bitmap);
|
|
||||||
extern rfbCursorPtr rfbMakeXCursor(int width,int height,char* cursorString,char* maskString);
|
|
||||||
extern char* rfbMakeMaskForXCursor(int width,int height,char* cursorString);
|
|
||||||
extern void MakeXCursorFromRichCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr cursor);
|
|
||||||
extern void MakeRichCursorFromXCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr cursor);
|
|
||||||
extern void MakeSoftCursor(rfbClientPtr cl,rfbCursorPtr cursor);
|
|
||||||
extern void rfbFreeCursor(rfbCursorPtr cursor);
|
|
||||||
extern void rfbDrawCursor(rfbScreenInfoPtr rfbScreen);
|
|
||||||
extern void rfbUndrawCursor(rfbScreenInfoPtr rfbScreen);
|
|
||||||
extern void rfbSetCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr c,Bool freeOld);
|
|
||||||
|
|
||||||
/* cursor handling for the pointer */
|
|
||||||
extern void defaultPtrAddEvent(int buttonMask,int x,int y,rfbClientPtr cl);
|
|
||||||
|
|
||||||
/* stats.c */
|
|
||||||
|
|
||||||
extern void rfbResetStats(rfbClientPtr cl);
|
|
||||||
extern void rfbPrintStats(rfbClientPtr cl);
|
|
||||||
|
|
||||||
/* font.c */
|
|
||||||
|
|
||||||
typedef struct rfbFontData {
|
|
||||||
unsigned char* data;
|
|
||||||
/*
|
|
||||||
metaData is a 256*5 array:
|
|
||||||
for each character
|
|
||||||
(offset,width,height,x,y)
|
|
||||||
*/
|
|
||||||
int* metaData;
|
|
||||||
} rfbFontData,* rfbFontDataPtr;
|
|
||||||
|
|
||||||
int rfbDrawChar(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,int x,int y,unsigned char c,Pixel colour);
|
|
||||||
void rfbDrawString(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,int x,int y,const char* string,Pixel colour);
|
|
||||||
/* if colour==backColour, background is transparent */
|
|
||||||
int rfbDrawCharWithClip(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,int x,int y,unsigned char c,int x1,int y1,int x2,int y2,Pixel colour,Pixel backColour);
|
|
||||||
void rfbDrawStringWithClip(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,int x,int y,const char* string,int x1,int y1,int x2,int y2,Pixel colour,Pixel backColour);
|
|
||||||
int rfbWidthOfString(rfbFontDataPtr font,const char* string);
|
|
||||||
int rfbWidthOfChar(rfbFontDataPtr font,unsigned char c);
|
|
||||||
void rfbFontBBox(rfbFontDataPtr font,unsigned char c,int* x1,int* y1,int* x2,int* y2);
|
|
||||||
/* this returns the smallest box enclosing any character of font. */
|
|
||||||
void rfbWholeFontBBox(rfbFontDataPtr font,int *x1, int *y1, int *x2, int *y2);
|
|
||||||
|
|
||||||
/* dynamically load a linux console font (4096 bytes, 256 glyphs a 8x16 */
|
|
||||||
rfbFontDataPtr rfbLoadConsoleFont(char *filename);
|
|
||||||
/* free a dynamically loaded font */
|
|
||||||
void rfbFreeFont(rfbFontDataPtr font);
|
|
||||||
|
|
||||||
/* draw.c */
|
|
||||||
|
|
||||||
/* You have to call rfbUndrawCursor before using these functions */
|
|
||||||
void rfbFillRect(rfbScreenInfoPtr s,int x1,int y1,int x2,int y2,Pixel col);
|
|
||||||
void rfbDrawPixel(rfbScreenInfoPtr s,int x,int y,Pixel col);
|
|
||||||
void rfbDrawLine(rfbScreenInfoPtr s,int x1,int y1,int x2,int y2,Pixel col);
|
|
||||||
|
|
||||||
/* selbox.c */
|
|
||||||
|
|
||||||
/* this opens a modal select box. list is an array of strings, the end marked
|
|
||||||
with a NULL.
|
|
||||||
It returns the index in the list or -1 if cancelled or something else
|
|
||||||
wasn't kosher. */
|
|
||||||
typedef void (*SelectionChangedHookPtr)(int _index);
|
|
||||||
extern int rfbSelectBox(rfbScreenInfoPtr rfbScreen,
|
|
||||||
rfbFontDataPtr font, char** list,
|
|
||||||
int x1, int y1, int x2, int y2,
|
|
||||||
Pixel foreColour, Pixel backColour,
|
|
||||||
int border,SelectionChangedHookPtr selChangedHook);
|
|
||||||
|
|
||||||
/* cargs.c */
|
|
||||||
|
|
||||||
extern void rfbUsage(void);
|
|
||||||
extern void rfbPurgeArguments(int* argc,int* position,int count,char *argv[]);
|
|
||||||
extern void rfbProcessArguments(rfbScreenInfoPtr rfbScreen,int* argc, char *argv[]);
|
|
||||||
extern void rfbProcessSizeArguments(int* width,int* height,int* bpp,int* argc, char *argv[]);
|
|
||||||
|
|
||||||
/* main.c */
|
|
||||||
|
|
||||||
extern void rfbLogEnable(int enabled);
|
|
||||||
extern void rfbLog(const char *format, ...);
|
|
||||||
extern void rfbLogPerror(const char *str);
|
|
||||||
|
|
||||||
void rfbScheduleCopyRect(rfbScreenInfoPtr rfbScreen,int x1,int y1,int x2,int y2,int dx,int dy);
|
|
||||||
void rfbScheduleCopyRegion(rfbScreenInfoPtr rfbScreen,sraRegionPtr copyRegion,int dx,int dy);
|
|
||||||
|
|
||||||
void rfbDoCopyRect(rfbScreenInfoPtr rfbScreen,int x1,int y1,int x2,int y2,int dx,int dy);
|
|
||||||
void rfbDoCopyRegion(rfbScreenInfoPtr rfbScreen,sraRegionPtr copyRegion,int dx,int dy);
|
|
||||||
|
|
||||||
void rfbMarkRectAsModified(rfbScreenInfoPtr rfbScreen,int x1,int y1,int x2,int y2);
|
|
||||||
void rfbMarkRegionAsModified(rfbScreenInfoPtr rfbScreen,sraRegionPtr modRegion);
|
|
||||||
void doNothingWithClient(rfbClientPtr cl);
|
|
||||||
enum rfbNewClientAction defaultNewClientHook(rfbClientPtr cl);
|
|
||||||
|
|
||||||
/* to check against plain passwords */
|
|
||||||
Bool rfbCheckPasswordByList(rfbClientPtr cl,const char* response,int len);
|
|
||||||
|
|
||||||
/* functions to make a vnc server */
|
|
||||||
extern rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv,
|
|
||||||
int width,int height,int bitsPerSample,int samplesPerPixel,
|
|
||||||
int bytesPerPixel);
|
|
||||||
extern void rfbInitServer(rfbScreenInfoPtr rfbScreen);
|
|
||||||
extern void rfbScreenCleanup(rfbScreenInfoPtr screenInfo);
|
|
||||||
|
|
||||||
/* functions to accept/refuse a client that has been put on hold
|
|
||||||
by a NewClientHookPtr function. Must not be called in other
|
|
||||||
situations. */
|
|
||||||
extern void rfbStartOnHoldClient(rfbClientPtr cl);
|
|
||||||
extern void rfbRefuseOnHoldClient(rfbClientPtr cl);
|
|
||||||
|
|
||||||
/* call one of these two functions to service the vnc clients.
|
|
||||||
usec are the microseconds the select on the fds waits.
|
|
||||||
if you are using the event loop, set this to some value > 0, so the
|
|
||||||
server doesn't get a high load just by listening. */
|
|
||||||
|
|
||||||
extern void rfbRunEventLoop(rfbScreenInfoPtr screenInfo, long usec, Bool runInBackground);
|
|
||||||
extern void rfbProcessEvents(rfbScreenInfoPtr screenInfo,long usec);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if(defined __cplusplus)
|
|
||||||
}
|
|
||||||
#endif
|
|
@ -1,848 +0,0 @@
|
|||||||
#ifndef RFBPROTO_H
|
|
||||||
#define RFBPROTO_H
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2000, 2001 Const 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
|
||||||
* USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* rfbproto.h - header file for the RFB protocol version 3.3
|
|
||||||
*
|
|
||||||
* Uses types CARD<n> for an n-bit unsigned integer, INT<n> for an n-bit signed
|
|
||||||
* integer (for n = 8, 16 and 32).
|
|
||||||
*
|
|
||||||
* All multiple byte integers are in big endian (network) order (most
|
|
||||||
* significant byte first). Unless noted otherwise there is no special
|
|
||||||
* alignment of protocol structures.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Once the initial handshaking is done, all messages start with a type byte,
|
|
||||||
* (usually) followed by message-specific data. The order of definitions in
|
|
||||||
* this file is as follows:
|
|
||||||
*
|
|
||||||
* (1) Structures used in several types of message.
|
|
||||||
* (2) Structures used in the initial handshaking.
|
|
||||||
* (3) Message types.
|
|
||||||
* (4) Encoding types.
|
|
||||||
* (5) For each message type, the form of the data following the type byte.
|
|
||||||
* Sometimes this is defined by a single structure but the more complex
|
|
||||||
* messages have to be explained by comments.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
|
||||||
*
|
|
||||||
* Structures used in several messages
|
|
||||||
*
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------
|
|
||||||
* Structure used to specify a rectangle. This structure is a multiple of 4
|
|
||||||
* bytes so that it can be interspersed with 32-bit pixel data without
|
|
||||||
* affecting alignment.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
CARD16 x;
|
|
||||||
CARD16 y;
|
|
||||||
CARD16 w;
|
|
||||||
CARD16 h;
|
|
||||||
} rfbRectangle;
|
|
||||||
|
|
||||||
#define sz_rfbRectangle 8
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------
|
|
||||||
* Structure used to specify pixel format.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
|
|
||||||
CARD8 bitsPerPixel; /* 8,16,32 only */
|
|
||||||
|
|
||||||
CARD8 depth; /* 8 to 32 */
|
|
||||||
|
|
||||||
CARD8 bigEndian; /* True if multi-byte pixels are interpreted
|
|
||||||
as big endian, or if single-bit-per-pixel
|
|
||||||
has most significant bit of the byte
|
|
||||||
corresponding to first (leftmost) pixel. Of
|
|
||||||
course this is meaningless for 8 bits/pix */
|
|
||||||
|
|
||||||
CARD8 trueColour; /* If false then we need a "colour map" to
|
|
||||||
convert pixels to RGB. If true, xxxMax and
|
|
||||||
xxxShift specify bits used for red, green
|
|
||||||
and blue */
|
|
||||||
|
|
||||||
/* the following fields are only meaningful if trueColour is true */
|
|
||||||
|
|
||||||
CARD16 redMax; /* maximum red value (= 2^n - 1 where n is the
|
|
||||||
number of bits used for red). Note this
|
|
||||||
value is always in big endian order. */
|
|
||||||
|
|
||||||
CARD16 greenMax; /* similar for green */
|
|
||||||
|
|
||||||
CARD16 blueMax; /* and blue */
|
|
||||||
|
|
||||||
CARD8 redShift; /* number of shifts needed to get the red
|
|
||||||
value in a pixel to the least significant
|
|
||||||
bit. To find the red value from a given
|
|
||||||
pixel, do the following:
|
|
||||||
1) Swap pixel value according to bigEndian
|
|
||||||
(e.g. if bigEndian is false and host byte
|
|
||||||
order is big endian, then swap).
|
|
||||||
2) Shift right by redShift.
|
|
||||||
3) AND with redMax (in host byte order).
|
|
||||||
4) You now have the red value between 0 and
|
|
||||||
redMax. */
|
|
||||||
|
|
||||||
CARD8 greenShift; /* similar for green */
|
|
||||||
|
|
||||||
CARD8 blueShift; /* and blue */
|
|
||||||
|
|
||||||
CARD8 pad1;
|
|
||||||
CARD16 pad2;
|
|
||||||
|
|
||||||
} rfbPixelFormat;
|
|
||||||
|
|
||||||
#define sz_rfbPixelFormat 16
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
|
||||||
*
|
|
||||||
* Initial handshaking messages
|
|
||||||
*
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------
|
|
||||||
* Protocol Version
|
|
||||||
*
|
|
||||||
* The server always sends 12 bytes to start which identifies the latest RFB
|
|
||||||
* protocol version number which it supports. These bytes are interpreted
|
|
||||||
* as a string of 12 ASCII characters in the format "RFB xxx.yyy\n" where
|
|
||||||
* xxx and yyy are the major and minor version numbers (for version 3.3
|
|
||||||
* this is "RFB 003.003\n").
|
|
||||||
*
|
|
||||||
* The client then replies with a similar 12-byte message giving the version
|
|
||||||
* number of the protocol which should actually be used (which may be different
|
|
||||||
* to that quoted by the server).
|
|
||||||
*
|
|
||||||
* It is intended that both clients and servers may provide some level of
|
|
||||||
* backwards compatibility by this mechanism. Servers in particular should
|
|
||||||
* attempt to provide backwards compatibility, and even forwards compatibility
|
|
||||||
* to some extent. For example if a client demands version 3.1 of the
|
|
||||||
* protocol, a 3.0 server can probably assume that by ignoring requests for
|
|
||||||
* encoding types it doesn't understand, everything will still work OK. This
|
|
||||||
* will probably not be the case for changes in the major version number.
|
|
||||||
*
|
|
||||||
* The format string below can be used in sprintf or sscanf to generate or
|
|
||||||
* decode the version string respectively.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define rfbProtocolVersionFormat "RFB %03d.%03d\n"
|
|
||||||
#define rfbProtocolMajorVersion 3
|
|
||||||
#define rfbProtocolMinorVersion 3
|
|
||||||
|
|
||||||
typedef char rfbProtocolVersionMsg[13]; /* allow extra byte for null */
|
|
||||||
|
|
||||||
#define sz_rfbProtocolVersionMsg 12
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------
|
|
||||||
* Authentication
|
|
||||||
*
|
|
||||||
* Once the protocol version has been decided, the server then sends a 32-bit
|
|
||||||
* word indicating whether any authentication is needed on the connection.
|
|
||||||
* The value of this word determines the authentication scheme in use. For
|
|
||||||
* version 3.0 of the protocol this may have one of the following values:
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define rfbConnFailed 0
|
|
||||||
#define rfbNoAuth 1
|
|
||||||
#define rfbVncAuth 2
|
|
||||||
|
|
||||||
/*
|
|
||||||
* rfbConnFailed: For some reason the connection failed (e.g. the server
|
|
||||||
* cannot support the desired protocol version). This is
|
|
||||||
* followed by a string describing the reason (where a
|
|
||||||
* string is specified as a 32-bit length followed by that
|
|
||||||
* many ASCII characters).
|
|
||||||
*
|
|
||||||
* rfbNoAuth: No authentication is needed.
|
|
||||||
*
|
|
||||||
* rfbVncAuth: The VNC authentication scheme is to be used. A 16-byte
|
|
||||||
* challenge follows, which the client encrypts as
|
|
||||||
* appropriate using the password and sends the resulting
|
|
||||||
* 16-byte response. If the response is correct, the
|
|
||||||
* server sends the 32-bit word rfbVncAuthOK. If a simple
|
|
||||||
* failure happens, the server sends rfbVncAuthFailed and
|
|
||||||
* closes the connection. If the server decides that too
|
|
||||||
* many failures have occurred, it sends rfbVncAuthTooMany
|
|
||||||
* and closes the connection. In the latter case, the
|
|
||||||
* server should not allow an immediate reconnection by
|
|
||||||
* the client.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define rfbVncAuthOK 0
|
|
||||||
#define rfbVncAuthFailed 1
|
|
||||||
#define rfbVncAuthTooMany 2
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------
|
|
||||||
* Client Initialisation Message
|
|
||||||
*
|
|
||||||
* Once the client and server are sure that they're happy to talk to one
|
|
||||||
* another, the client sends an initialisation message. At present this
|
|
||||||
* message only consists of a boolean indicating whether the server should try
|
|
||||||
* to share the desktop by leaving other clients connected, or give exclusive
|
|
||||||
* access to this client by disconnecting all other clients.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
CARD8 shared;
|
|
||||||
} rfbClientInitMsg;
|
|
||||||
|
|
||||||
#define sz_rfbClientInitMsg 1
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------
|
|
||||||
* Server Initialisation Message
|
|
||||||
*
|
|
||||||
* After the client initialisation message, the server sends one of its own.
|
|
||||||
* This tells the client the width and height of the server's framebuffer,
|
|
||||||
* its pixel format and the name associated with the desktop.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
CARD16 framebufferWidth;
|
|
||||||
CARD16 framebufferHeight;
|
|
||||||
rfbPixelFormat format; /* the server's preferred pixel format */
|
|
||||||
CARD32 nameLength;
|
|
||||||
/* followed by char name[nameLength] */
|
|
||||||
} rfbServerInitMsg;
|
|
||||||
|
|
||||||
#define sz_rfbServerInitMsg (8 + sz_rfbPixelFormat)
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Following the server initialisation message it's up to the client to send
|
|
||||||
* whichever protocol messages it wants. Typically it will send a
|
|
||||||
* SetPixelFormat message and a SetEncodings message, followed by a
|
|
||||||
* FramebufferUpdateRequest. From then on the server will send
|
|
||||||
* FramebufferUpdate messages in response to the client's
|
|
||||||
* FramebufferUpdateRequest messages. The client should send
|
|
||||||
* FramebufferUpdateRequest messages with incremental set to true when it has
|
|
||||||
* finished processing one FramebufferUpdate and is ready to process another.
|
|
||||||
* With a fast client, the rate at which FramebufferUpdateRequests are sent
|
|
||||||
* should be regulated to avoid hogging the network.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
|
||||||
*
|
|
||||||
* Message types
|
|
||||||
*
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
/* server -> client */
|
|
||||||
|
|
||||||
#define rfbFramebufferUpdate 0
|
|
||||||
#define rfbSetColourMapEntries 1
|
|
||||||
#define rfbBell 2
|
|
||||||
#define rfbServerCutText 3
|
|
||||||
#ifdef BACKCHANNEL
|
|
||||||
#define rfbBackChannel 15
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* client -> server */
|
|
||||||
|
|
||||||
#define rfbSetPixelFormat 0
|
|
||||||
#define rfbFixColourMapEntries 1 /* not currently supported */
|
|
||||||
#define rfbSetEncodings 2
|
|
||||||
#define rfbFramebufferUpdateRequest 3
|
|
||||||
#define rfbKeyEvent 4
|
|
||||||
#define rfbPointerEvent 5
|
|
||||||
#define rfbClientCutText 6
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
|
||||||
*
|
|
||||||
* Encoding types
|
|
||||||
*
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
#define rfbEncodingRaw 0
|
|
||||||
#define rfbEncodingCopyRect 1
|
|
||||||
#define rfbEncodingRRE 2
|
|
||||||
#define rfbEncodingCoRRE 4
|
|
||||||
#define rfbEncodingHextile 5
|
|
||||||
#define rfbEncodingZlib 6
|
|
||||||
#define rfbEncodingTight 7
|
|
||||||
#define rfbEncodingZlibHex 8
|
|
||||||
#ifdef BACKCHANNEL
|
|
||||||
#define rfbEncodingBackChannel 15
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Special encoding numbers:
|
|
||||||
* 0xFFFFFF00 .. 0xFFFFFF0F -- encoding-specific compression levels;
|
|
||||||
* 0xFFFFFF10 .. 0xFFFFFF1F -- mouse cursor shape data;
|
|
||||||
* 0xFFFFFF20 .. 0xFFFFFF2F -- various protocol extensions;
|
|
||||||
* 0xFFFFFF30 .. 0xFFFFFFDF -- not allocated yet;
|
|
||||||
* 0xFFFFFFE0 .. 0xFFFFFFEF -- quality level for JPEG compressor;
|
|
||||||
* 0xFFFFFFF0 .. 0xFFFFFFFF -- cross-encoding compression levels.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define rfbEncodingCompressLevel0 0xFFFFFF00
|
|
||||||
#define rfbEncodingCompressLevel1 0xFFFFFF01
|
|
||||||
#define rfbEncodingCompressLevel2 0xFFFFFF02
|
|
||||||
#define rfbEncodingCompressLevel3 0xFFFFFF03
|
|
||||||
#define rfbEncodingCompressLevel4 0xFFFFFF04
|
|
||||||
#define rfbEncodingCompressLevel5 0xFFFFFF05
|
|
||||||
#define rfbEncodingCompressLevel6 0xFFFFFF06
|
|
||||||
#define rfbEncodingCompressLevel7 0xFFFFFF07
|
|
||||||
#define rfbEncodingCompressLevel8 0xFFFFFF08
|
|
||||||
#define rfbEncodingCompressLevel9 0xFFFFFF09
|
|
||||||
|
|
||||||
#define rfbEncodingXCursor 0xFFFFFF10
|
|
||||||
#define rfbEncodingRichCursor 0xFFFFFF11
|
|
||||||
#define rfbEncodingSoftCursor 0xFFFFFF12
|
|
||||||
|
|
||||||
#define rfbEncodingLastRect 0xFFFFFF20
|
|
||||||
#define rfbEncodingBackground 0xFFFFFF25
|
|
||||||
|
|
||||||
#define rfbEncodingQualityLevel0 0xFFFFFFE0
|
|
||||||
#define rfbEncodingQualityLevel1 0xFFFFFFE1
|
|
||||||
#define rfbEncodingQualityLevel2 0xFFFFFFE2
|
|
||||||
#define rfbEncodingQualityLevel3 0xFFFFFFE3
|
|
||||||
#define rfbEncodingQualityLevel4 0xFFFFFFE4
|
|
||||||
#define rfbEncodingQualityLevel5 0xFFFFFFE5
|
|
||||||
#define rfbEncodingQualityLevel6 0xFFFFFFE6
|
|
||||||
#define rfbEncodingQualityLevel7 0xFFFFFFE7
|
|
||||||
#define rfbEncodingQualityLevel8 0xFFFFFFE8
|
|
||||||
#define rfbEncodingQualityLevel9 0xFFFFFFE9
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
|
||||||
*
|
|
||||||
* Server -> client message definitions
|
|
||||||
*
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------
|
|
||||||
* FramebufferUpdate - a block of rectangles to be copied to the framebuffer.
|
|
||||||
*
|
|
||||||
* This message consists of a header giving the number of rectangles of pixel
|
|
||||||
* data followed by the rectangles themselves. The header is padded so that
|
|
||||||
* together with the type byte it is an exact multiple of 4 bytes (to help
|
|
||||||
* with alignment of 32-bit pixels):
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
CARD8 type; /* always rfbFramebufferUpdate */
|
|
||||||
CARD8 pad;
|
|
||||||
CARD16 nRects;
|
|
||||||
/* followed by nRects rectangles */
|
|
||||||
} rfbFramebufferUpdateMsg;
|
|
||||||
|
|
||||||
#define sz_rfbFramebufferUpdateMsg 4
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Each rectangle of pixel data consists of a header describing the position
|
|
||||||
* and size of the rectangle and a type word describing the encoding of the
|
|
||||||
* pixel data, followed finally by the pixel data. Note that if the client has
|
|
||||||
* not sent a SetEncodings message then it will only receive raw pixel data.
|
|
||||||
* Also note again that this structure is a multiple of 4 bytes.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
rfbRectangle r;
|
|
||||||
CARD32 encoding; /* one of the encoding types rfbEncoding... */
|
|
||||||
} rfbFramebufferUpdateRectHeader;
|
|
||||||
|
|
||||||
#define sz_rfbFramebufferUpdateRectHeader (sz_rfbRectangle + 4)
|
|
||||||
|
|
||||||
|
|
||||||
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
* Raw Encoding. Pixels are sent in top-to-bottom scanline order,
|
|
||||||
* left-to-right within a scanline with no padding in between.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
* CopyRect Encoding. The pixels are specified simply by the x and y position
|
|
||||||
* of the source rectangle.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
CARD16 srcX;
|
|
||||||
CARD16 srcY;
|
|
||||||
} rfbCopyRect;
|
|
||||||
|
|
||||||
#define sz_rfbCopyRect 4
|
|
||||||
|
|
||||||
|
|
||||||
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
* RRE - Rise-and-Run-length Encoding. We have an rfbRREHeader structure
|
|
||||||
* giving the number of subrectangles following. Finally the data follows in
|
|
||||||
* the form [<bgpixel><subrect><subrect>...] where each <subrect> is
|
|
||||||
* [<pixel><rfbRectangle>].
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
CARD32 nSubrects;
|
|
||||||
} rfbRREHeader;
|
|
||||||
|
|
||||||
#define sz_rfbRREHeader 4
|
|
||||||
|
|
||||||
|
|
||||||
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
* CoRRE - Compact RRE Encoding. We have an rfbRREHeader structure giving
|
|
||||||
* the number of subrectangles following. Finally the data follows in the form
|
|
||||||
* [<bgpixel><subrect><subrect>...] where each <subrect> is
|
|
||||||
* [<pixel><rfbCoRRERectangle>]. This means that
|
|
||||||
* the whole rectangle must be at most 255x255 pixels.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
CARD8 x;
|
|
||||||
CARD8 y;
|
|
||||||
CARD8 w;
|
|
||||||
CARD8 h;
|
|
||||||
} rfbCoRRERectangle;
|
|
||||||
|
|
||||||
#define sz_rfbCoRRERectangle 4
|
|
||||||
|
|
||||||
|
|
||||||
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
* Hextile Encoding. The rectangle is divided up into "tiles" of 16x16 pixels,
|
|
||||||
* starting at the top left going in left-to-right, top-to-bottom order. If
|
|
||||||
* the width of the rectangle is not an exact multiple of 16 then the width of
|
|
||||||
* the last tile in each row will be correspondingly smaller. Similarly if the
|
|
||||||
* height is not an exact multiple of 16 then the height of each tile in the
|
|
||||||
* final row will also be smaller. Each tile begins with a "subencoding" type
|
|
||||||
* byte, which is a mask made up of a number of bits. If the Raw bit is set
|
|
||||||
* then the other bits are irrelevant; w*h pixel values follow (where w and h
|
|
||||||
* are the width and height of the tile). Otherwise the tile is encoded in a
|
|
||||||
* similar way to RRE, except that the position and size of each subrectangle
|
|
||||||
* can be specified in just two bytes. The other bits in the mask are as
|
|
||||||
* follows:
|
|
||||||
*
|
|
||||||
* BackgroundSpecified - if set, a pixel value follows which specifies
|
|
||||||
* the background colour for this tile. The first non-raw tile in a
|
|
||||||
* rectangle must have this bit set. If this bit isn't set then the
|
|
||||||
* background is the same as the last tile.
|
|
||||||
*
|
|
||||||
* ForegroundSpecified - if set, a pixel value follows which specifies
|
|
||||||
* the foreground colour to be used for all subrectangles in this tile.
|
|
||||||
* If this bit is set then the SubrectsColoured bit must be zero.
|
|
||||||
*
|
|
||||||
* AnySubrects - if set, a single byte follows giving the number of
|
|
||||||
* subrectangles following. If not set, there are no subrectangles (i.e.
|
|
||||||
* the whole tile is just solid background colour).
|
|
||||||
*
|
|
||||||
* SubrectsColoured - if set then each subrectangle is preceded by a pixel
|
|
||||||
* value giving the colour of that subrectangle. If not set, all
|
|
||||||
* subrectangles are the same colour, the foreground colour; if the
|
|
||||||
* ForegroundSpecified bit wasn't set then the foreground is the same as
|
|
||||||
* the last tile.
|
|
||||||
*
|
|
||||||
* The position and size of each subrectangle is specified in two bytes. The
|
|
||||||
* Pack macros below can be used to generate the two bytes from x, y, w, h,
|
|
||||||
* and the Extract macros can be used to extract the x, y, w, h values from
|
|
||||||
* the two bytes.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define rfbHextileRaw (1 << 0)
|
|
||||||
#define rfbHextileBackgroundSpecified (1 << 1)
|
|
||||||
#define rfbHextileForegroundSpecified (1 << 2)
|
|
||||||
#define rfbHextileAnySubrects (1 << 3)
|
|
||||||
#define rfbHextileSubrectsColoured (1 << 4)
|
|
||||||
|
|
||||||
#define rfbHextilePackXY(x,y) (((x) << 4) | (y))
|
|
||||||
#define rfbHextilePackWH(w,h) ((((w)-1) << 4) | ((h)-1))
|
|
||||||
#define rfbHextileExtractX(byte) ((byte) >> 4)
|
|
||||||
#define rfbHextileExtractY(byte) ((byte) & 0xf)
|
|
||||||
#define rfbHextileExtractW(byte) (((byte) >> 4) + 1)
|
|
||||||
#define rfbHextileExtractH(byte) (((byte) & 0xf) + 1)
|
|
||||||
|
|
||||||
|
|
||||||
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
* zlib - zlib compressed Encoding. We have an rfbZlibHeader structure
|
|
||||||
* giving the number of bytes following. Finally the data follows is
|
|
||||||
* zlib compressed version of the raw pixel data as negotiated.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
CARD32 nBytes;
|
|
||||||
} rfbZlibHeader;
|
|
||||||
|
|
||||||
#define sz_rfbZlibHeader 4
|
|
||||||
|
|
||||||
|
|
||||||
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
* Tight Encoding. FIXME: Add more documentation.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define rfbTightExplicitFilter 0x04
|
|
||||||
#define rfbTightFill 0x08
|
|
||||||
#define rfbTightJpeg 0x09
|
|
||||||
#define rfbTightMaxSubencoding 0x09
|
|
||||||
|
|
||||||
/* Filters to improve compression efficiency */
|
|
||||||
#define rfbTightFilterCopy 0x00
|
|
||||||
#define rfbTightFilterPalette 0x01
|
|
||||||
#define rfbTightFilterGradient 0x02
|
|
||||||
|
|
||||||
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
* XCursor encoding. This is a special encoding used to transmit X-style
|
|
||||||
* cursor shapes from server to clients. Note that for this encoding,
|
|
||||||
* coordinates in rfbFramebufferUpdateRectHeader structure hold hotspot
|
|
||||||
* position (r.x, r.y) and cursor size (r.w, r.h). If (w * h != 0), two RGB
|
|
||||||
* samples are sent after header in the rfbXCursorColors structure. They
|
|
||||||
* denote foreground and background colors of the cursor. If a client
|
|
||||||
* supports only black-and-white cursors, it should ignore these colors and
|
|
||||||
* assume that foreground is black and background is white. Next, two bitmaps
|
|
||||||
* (1 bits per pixel) follow: first one with actual data (value 0 denotes
|
|
||||||
* background color, value 1 denotes foreground color), second one with
|
|
||||||
* transparency data (bits with zero value mean that these pixels are
|
|
||||||
* transparent). Both bitmaps represent cursor data in a byte stream, from
|
|
||||||
* left to right, from top to bottom, and each row is byte-aligned. Most
|
|
||||||
* significant bits correspond to leftmost pixels. The number of bytes in
|
|
||||||
* each row can be calculated as ((w + 7) / 8). If (w * h == 0), cursor
|
|
||||||
* should be hidden (or default local cursor should be set by the client).
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
CARD8 foreRed;
|
|
||||||
CARD8 foreGreen;
|
|
||||||
CARD8 foreBlue;
|
|
||||||
CARD8 backRed;
|
|
||||||
CARD8 backGreen;
|
|
||||||
CARD8 backBlue;
|
|
||||||
} rfbXCursorColors;
|
|
||||||
|
|
||||||
#define sz_rfbXCursorColors 6
|
|
||||||
|
|
||||||
|
|
||||||
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
* RichCursor encoding. This is a special encoding used to transmit cursor
|
|
||||||
* shapes from server to clients. It is similar to the XCursor encoding but
|
|
||||||
* uses client pixel format instead of two RGB colors to represent cursor
|
|
||||||
* image. For this encoding, coordinates in rfbFramebufferUpdateRectHeader
|
|
||||||
* structure hold hotspot position (r.x, r.y) and cursor size (r.w, r.h).
|
|
||||||
* After header, two pixmaps follow: first one with cursor image in current
|
|
||||||
* client pixel format (like in raw encoding), second with transparency data
|
|
||||||
* (1 bit per pixel, exactly the same format as used for transparency bitmap
|
|
||||||
* in the XCursor encoding). If (w * h == 0), cursor should be hidden (or
|
|
||||||
* default local cursor should be set by the client).
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
* SoftCursor encoding. This encoding is used to transmit image and position
|
|
||||||
* of the remote cursor. It has two sub-messages: SetImage is used to upload
|
|
||||||
* one of 16 images, and Move selects the image and sets the position of the
|
|
||||||
* cursor.
|
|
||||||
* Each SoftCursor message starts with a CARD8. If it is in the 0-15 range
|
|
||||||
* it specifies the number of the cursor image and is followed by the
|
|
||||||
* rfbSoftCursorMove message. If the given cursor has not been set yet the
|
|
||||||
* message will be ignored. If the first CARD8 is in the 128-143 range it
|
|
||||||
* specifies the cursor that will be set in the following
|
|
||||||
* rfbSoftCursorSetImage message. To hide the cursor send a SetImage
|
|
||||||
* message with width and height 0 and imageLength 0.
|
|
||||||
* SetImage transmits the hotspot coordinates in the x/y fields of the
|
|
||||||
* rfbFramebufferUpdateRectHeader, width and height of the image are in the
|
|
||||||
* header's width and height fields.
|
|
||||||
* Move transmits the pointer coordinates in the w/h fields of the
|
|
||||||
* header, x/y are always 0.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
CARD8 imageIndex;
|
|
||||||
CARD8 buttonMask; /* bits 0-7 are buttons 1-8, 0=up, 1=down */
|
|
||||||
} rfbSoftCursorMove;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
CARD8 imageIndex;
|
|
||||||
CARD8 padding;
|
|
||||||
CARD16 imageLength;
|
|
||||||
/*
|
|
||||||
* Followed by an image of the cursor in the client's image format
|
|
||||||
* with the following RLE mask compression. It begins with CARD8 that
|
|
||||||
* specifies the number of mask'ed pixels that will be NOT transmitted.
|
|
||||||
* Then follows a CARD8 that specified by the number of unmask'd pixels
|
|
||||||
* that will be transmitted next. Then a CARD8 with the number of mask'd
|
|
||||||
* pixels and so on.
|
|
||||||
*/
|
|
||||||
} rfbSoftCursorSetImage;
|
|
||||||
|
|
||||||
typedef union {
|
|
||||||
CARD8 type;
|
|
||||||
rfbSoftCursorMove move;
|
|
||||||
rfbSoftCursorSetImage setImage;
|
|
||||||
} rfbSoftCursorMsg;
|
|
||||||
|
|
||||||
#define rfbSoftCursorMaxImages 16
|
|
||||||
#define rfbSoftCursorSetIconOffset 128
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------
|
|
||||||
* SetColourMapEntries - these messages are only sent if the pixel
|
|
||||||
* format uses a "colour map" (i.e. trueColour false) and the client has not
|
|
||||||
* fixed the entire colour map using FixColourMapEntries. In addition they
|
|
||||||
* will only start being sent after the client has sent its first
|
|
||||||
* FramebufferUpdateRequest. So if the client always tells the server to use
|
|
||||||
* trueColour then it never needs to process this type of message.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
CARD8 type; /* always rfbSetColourMapEntries */
|
|
||||||
CARD8 pad;
|
|
||||||
CARD16 firstColour;
|
|
||||||
CARD16 nColours;
|
|
||||||
|
|
||||||
/* Followed by nColours * 3 * CARD16
|
|
||||||
r1, g1, b1, r2, g2, b2, r3, g3, b3, ..., rn, bn, gn */
|
|
||||||
|
|
||||||
} rfbSetColourMapEntriesMsg;
|
|
||||||
|
|
||||||
#define sz_rfbSetColourMapEntriesMsg 6
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------
|
|
||||||
* Bell - ring a bell on the client if it has one.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
CARD8 type; /* always rfbBell */
|
|
||||||
} rfbBellMsg;
|
|
||||||
|
|
||||||
#define sz_rfbBellMsg 1
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------
|
|
||||||
* ServerCutText - the server has new text in its cut buffer.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
CARD8 type; /* always rfbServerCutText */
|
|
||||||
CARD8 pad1;
|
|
||||||
CARD16 pad2;
|
|
||||||
CARD32 length;
|
|
||||||
/* followed by char text[length] */
|
|
||||||
} rfbServerCutTextMsg;
|
|
||||||
|
|
||||||
#define sz_rfbServerCutTextMsg 8
|
|
||||||
|
|
||||||
#ifdef BACKCHANNEL
|
|
||||||
typedef rfbServerCutTextMsg rfbBackChannelMsg;
|
|
||||||
#define sz_rfbBackChannelMsg 8
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------
|
|
||||||
* Union of all server->client messages.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef union {
|
|
||||||
CARD8 type;
|
|
||||||
rfbFramebufferUpdateMsg fu;
|
|
||||||
rfbSetColourMapEntriesMsg scme;
|
|
||||||
rfbBellMsg b;
|
|
||||||
rfbServerCutTextMsg sct;
|
|
||||||
} rfbServerToClientMsg;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
|
||||||
*
|
|
||||||
* Message definitions (client -> server)
|
|
||||||
*
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------
|
|
||||||
* SetPixelFormat - tell the RFB server the format in which the client wants
|
|
||||||
* pixels sent.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
CARD8 type; /* always rfbSetPixelFormat */
|
|
||||||
CARD8 pad1;
|
|
||||||
CARD16 pad2;
|
|
||||||
rfbPixelFormat format;
|
|
||||||
} rfbSetPixelFormatMsg;
|
|
||||||
|
|
||||||
#define sz_rfbSetPixelFormatMsg (sz_rfbPixelFormat + 4)
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------
|
|
||||||
* FixColourMapEntries - when the pixel format uses a "colour map", fix
|
|
||||||
* read-only colour map entries.
|
|
||||||
*
|
|
||||||
* ***************** NOT CURRENTLY SUPPORTED *****************
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
CARD8 type; /* always rfbFixColourMapEntries */
|
|
||||||
CARD8 pad;
|
|
||||||
CARD16 firstColour;
|
|
||||||
CARD16 nColours;
|
|
||||||
|
|
||||||
/* Followed by nColours * 3 * CARD16
|
|
||||||
r1, g1, b1, r2, g2, b2, r3, g3, b3, ..., rn, bn, gn */
|
|
||||||
|
|
||||||
} rfbFixColourMapEntriesMsg;
|
|
||||||
|
|
||||||
#define sz_rfbFixColourMapEntriesMsg 6
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------
|
|
||||||
* SetEncodings - tell the RFB server which encoding types we accept. Put them
|
|
||||||
* in order of preference, if we have any. We may always receive raw
|
|
||||||
* encoding, even if we don't specify it here.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
CARD8 type; /* always rfbSetEncodings */
|
|
||||||
CARD8 pad;
|
|
||||||
CARD16 nEncodings;
|
|
||||||
/* followed by nEncodings * CARD32 encoding types */
|
|
||||||
} rfbSetEncodingsMsg;
|
|
||||||
|
|
||||||
#define sz_rfbSetEncodingsMsg 4
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------
|
|
||||||
* FramebufferUpdateRequest - request for a framebuffer update. If incremental
|
|
||||||
* is true then the client just wants the changes since the last update. If
|
|
||||||
* false then it wants the whole of the specified rectangle.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
CARD8 type; /* always rfbFramebufferUpdateRequest */
|
|
||||||
CARD8 incremental;
|
|
||||||
CARD16 x;
|
|
||||||
CARD16 y;
|
|
||||||
CARD16 w;
|
|
||||||
CARD16 h;
|
|
||||||
} rfbFramebufferUpdateRequestMsg;
|
|
||||||
|
|
||||||
#define sz_rfbFramebufferUpdateRequestMsg 10
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------
|
|
||||||
* KeyEvent - key press or release
|
|
||||||
*
|
|
||||||
* Keys are specified using the "keysym" values defined by the X Window System.
|
|
||||||
* For most ordinary keys, the keysym is the same as the corresponding ASCII
|
|
||||||
* value. Other common keys are:
|
|
||||||
*
|
|
||||||
* BackSpace 0xff08
|
|
||||||
* Tab 0xff09
|
|
||||||
* Return or Enter 0xff0d
|
|
||||||
* Escape 0xff1b
|
|
||||||
* Insert 0xff63
|
|
||||||
* Delete 0xffff
|
|
||||||
* Home 0xff50
|
|
||||||
* End 0xff57
|
|
||||||
* Page Up 0xff55
|
|
||||||
* Page Down 0xff56
|
|
||||||
* Left 0xff51
|
|
||||||
* Up 0xff52
|
|
||||||
* Right 0xff53
|
|
||||||
* Down 0xff54
|
|
||||||
* F1 0xffbe
|
|
||||||
* F2 0xffbf
|
|
||||||
* ... ...
|
|
||||||
* F12 0xffc9
|
|
||||||
* Shift 0xffe1
|
|
||||||
* Control 0xffe3
|
|
||||||
* Meta 0xffe7
|
|
||||||
* Alt 0xffe9
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
CARD8 type; /* always rfbKeyEvent */
|
|
||||||
CARD8 down; /* true if down (press), false if up */
|
|
||||||
CARD16 pad;
|
|
||||||
CARD32 key; /* key is specified as an X keysym */
|
|
||||||
} rfbKeyEventMsg;
|
|
||||||
|
|
||||||
#define sz_rfbKeyEventMsg 8
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------
|
|
||||||
* PointerEvent - mouse/pen move and/or button press.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
CARD8 type; /* always rfbPointerEvent */
|
|
||||||
CARD8 buttonMask; /* bits 0-7 are buttons 1-8, 0=up, 1=down */
|
|
||||||
CARD16 x;
|
|
||||||
CARD16 y;
|
|
||||||
} rfbPointerEventMsg;
|
|
||||||
|
|
||||||
#define rfbButton1Mask 1
|
|
||||||
#define rfbButton2Mask 2
|
|
||||||
#define rfbButton3Mask 4
|
|
||||||
|
|
||||||
#define sz_rfbPointerEventMsg 6
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------
|
|
||||||
* ClientCutText - the client has new text in its cut buffer.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
CARD8 type; /* always rfbClientCutText */
|
|
||||||
CARD8 pad1;
|
|
||||||
CARD16 pad2;
|
|
||||||
CARD32 length;
|
|
||||||
/* followed by char text[length] */
|
|
||||||
} rfbClientCutTextMsg;
|
|
||||||
|
|
||||||
#define sz_rfbClientCutTextMsg 8
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------
|
|
||||||
* Union of all client->server messages.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef union {
|
|
||||||
CARD8 type;
|
|
||||||
rfbSetPixelFormatMsg spf;
|
|
||||||
rfbFixColourMapEntriesMsg fcme;
|
|
||||||
rfbSetEncodingsMsg se;
|
|
||||||
rfbFramebufferUpdateRequestMsg fur;
|
|
||||||
rfbKeyEventMsg ke;
|
|
||||||
rfbPointerEventMsg pe;
|
|
||||||
rfbClientCutTextMsg cct;
|
|
||||||
} rfbClientToServerMsg;
|
|
||||||
|
|
||||||
#endif
|
|
File diff suppressed because it is too large
Load Diff
@ -1,322 +0,0 @@
|
|||||||
/*
|
|
||||||
* rre.c
|
|
||||||
*
|
|
||||||
* Routines to implement Rise-and-Run-length Encoding (RRE). This
|
|
||||||
* code is based on krw's original javatel rfbserver.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
|
|
||||||
* Original Xvnc code 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
|
||||||
* USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "rfb.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* rreBeforeBuf contains pixel data in the client's format.
|
|
||||||
* rreAfterBuf contains the RRE encoded version. If the RRE encoded version is
|
|
||||||
* larger than the raw data or if it exceeds rreAfterBufSize then
|
|
||||||
* raw encoding is used instead.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int rreBeforeBufSize = 0;
|
|
||||||
static char *rreBeforeBuf = NULL;
|
|
||||||
|
|
||||||
static int rreAfterBufSize = 0;
|
|
||||||
static char *rreAfterBuf = NULL;
|
|
||||||
static int rreAfterBufLen;
|
|
||||||
|
|
||||||
static int subrectEncode8(CARD8 *data, int w, int h);
|
|
||||||
static int subrectEncode16(CARD16 *data, int w, int h);
|
|
||||||
static int subrectEncode32(CARD32 *data, int w, int h);
|
|
||||||
static CARD32 getBgColour(char *data, int size, int bpp);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* rfbSendRectEncodingRRE - send a given rectangle using RRE encoding.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Bool
|
|
||||||
rfbSendRectEncodingRRE(cl, x, y, w, h)
|
|
||||||
rfbClientPtr cl;
|
|
||||||
int x, y, w, h;
|
|
||||||
{
|
|
||||||
rfbFramebufferUpdateRectHeader rect;
|
|
||||||
rfbRREHeader hdr;
|
|
||||||
int nSubrects;
|
|
||||||
int i;
|
|
||||||
char *fbptr = (cl->screen->frameBuffer + (cl->screen->paddedWidthInBytes * y)
|
|
||||||
+ (x * (cl->screen->bitsPerPixel / 8)));
|
|
||||||
|
|
||||||
int maxRawSize = (cl->screen->width * cl->screen->height
|
|
||||||
* (cl->format.bitsPerPixel / 8));
|
|
||||||
|
|
||||||
if (rreBeforeBufSize < maxRawSize) {
|
|
||||||
rreBeforeBufSize = maxRawSize;
|
|
||||||
if (rreBeforeBuf == NULL)
|
|
||||||
rreBeforeBuf = (char *)malloc(rreBeforeBufSize);
|
|
||||||
else
|
|
||||||
rreBeforeBuf = (char *)realloc(rreBeforeBuf, rreBeforeBufSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rreAfterBufSize < maxRawSize) {
|
|
||||||
rreAfterBufSize = maxRawSize;
|
|
||||||
if (rreAfterBuf == NULL)
|
|
||||||
rreAfterBuf = (char *)malloc(rreAfterBufSize);
|
|
||||||
else
|
|
||||||
rreAfterBuf = (char *)realloc(rreAfterBuf, rreAfterBufSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
(*cl->translateFn)(cl->translateLookupTable,
|
|
||||||
&(cl->screen->rfbServerFormat),
|
|
||||||
&cl->format, fbptr, rreBeforeBuf,
|
|
||||||
cl->screen->paddedWidthInBytes, w, h);
|
|
||||||
|
|
||||||
switch (cl->format.bitsPerPixel) {
|
|
||||||
case 8:
|
|
||||||
nSubrects = subrectEncode8((CARD8 *)rreBeforeBuf, w, h);
|
|
||||||
break;
|
|
||||||
case 16:
|
|
||||||
nSubrects = subrectEncode16((CARD16 *)rreBeforeBuf, w, h);
|
|
||||||
break;
|
|
||||||
case 32:
|
|
||||||
nSubrects = subrectEncode32((CARD32 *)rreBeforeBuf, w, h);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
rfbLog("getBgColour: bpp %d?\n",cl->format.bitsPerPixel);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nSubrects < 0) {
|
|
||||||
|
|
||||||
/* RRE encoding was too large, use raw */
|
|
||||||
|
|
||||||
return rfbSendRectEncodingRaw(cl, x, y, w, h);
|
|
||||||
}
|
|
||||||
|
|
||||||
cl->rfbRectanglesSent[rfbEncodingRRE]++;
|
|
||||||
cl->rfbBytesSent[rfbEncodingRRE] += (sz_rfbFramebufferUpdateRectHeader
|
|
||||||
+ sz_rfbRREHeader + rreAfterBufLen);
|
|
||||||
|
|
||||||
if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbRREHeader
|
|
||||||
> UPDATE_BUF_SIZE)
|
|
||||||
{
|
|
||||||
if (!rfbSendUpdateBuf(cl))
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
rect.r.x = Swap16IfLE(x);
|
|
||||||
rect.r.y = Swap16IfLE(y);
|
|
||||||
rect.r.w = Swap16IfLE(w);
|
|
||||||
rect.r.h = Swap16IfLE(h);
|
|
||||||
rect.encoding = Swap32IfLE(rfbEncodingRRE);
|
|
||||||
|
|
||||||
memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
|
|
||||||
sz_rfbFramebufferUpdateRectHeader);
|
|
||||||
cl->ublen += sz_rfbFramebufferUpdateRectHeader;
|
|
||||||
|
|
||||||
hdr.nSubrects = Swap32IfLE(nSubrects);
|
|
||||||
|
|
||||||
memcpy(&cl->updateBuf[cl->ublen], (char *)&hdr, sz_rfbRREHeader);
|
|
||||||
cl->ublen += sz_rfbRREHeader;
|
|
||||||
|
|
||||||
for (i = 0; i < rreAfterBufLen;) {
|
|
||||||
|
|
||||||
int bytesToCopy = UPDATE_BUF_SIZE - cl->ublen;
|
|
||||||
|
|
||||||
if (i + bytesToCopy > rreAfterBufLen) {
|
|
||||||
bytesToCopy = rreAfterBufLen - i;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(&cl->updateBuf[cl->ublen], &rreAfterBuf[i], bytesToCopy);
|
|
||||||
|
|
||||||
cl->ublen += bytesToCopy;
|
|
||||||
i += bytesToCopy;
|
|
||||||
|
|
||||||
if (cl->ublen == UPDATE_BUF_SIZE) {
|
|
||||||
if (!rfbSendUpdateBuf(cl))
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* subrectEncode() encodes the given multicoloured rectangle as a background
|
|
||||||
* colour overwritten by single-coloured rectangles. It returns the number
|
|
||||||
* of subrectangles in the encoded buffer, or -1 if subrect encoding won't
|
|
||||||
* fit in the buffer. It puts the encoded rectangles in rreAfterBuf. The
|
|
||||||
* single-colour rectangle partition is not optimal, but does find the biggest
|
|
||||||
* horizontal or vertical rectangle top-left anchored to each consecutive
|
|
||||||
* coordinate position.
|
|
||||||
*
|
|
||||||
* The coding scheme is simply [<bgcolour><subrect><subrect>...] where each
|
|
||||||
* <subrect> is [<colour><x><y><w><h>].
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define DEFINE_SUBRECT_ENCODE(bpp) \
|
|
||||||
static int \
|
|
||||||
subrectEncode##bpp(data,w,h) \
|
|
||||||
CARD##bpp *data; \
|
|
||||||
int w; \
|
|
||||||
int h; \
|
|
||||||
{ \
|
|
||||||
CARD##bpp cl; \
|
|
||||||
rfbRectangle subrect; \
|
|
||||||
int x,y; \
|
|
||||||
int i,j; \
|
|
||||||
int hx=0,hy,vx=0,vy; \
|
|
||||||
int hyflag; \
|
|
||||||
CARD##bpp *seg; \
|
|
||||||
CARD##bpp *line; \
|
|
||||||
int hw,hh,vw,vh; \
|
|
||||||
int thex,they,thew,theh; \
|
|
||||||
int numsubs = 0; \
|
|
||||||
int newLen; \
|
|
||||||
CARD##bpp bg = (CARD##bpp)getBgColour((char*)data,w*h,bpp); \
|
|
||||||
\
|
|
||||||
*((CARD##bpp*)rreAfterBuf) = bg; \
|
|
||||||
\
|
|
||||||
rreAfterBufLen = (bpp/8); \
|
|
||||||
\
|
|
||||||
for (y=0; y<h; y++) { \
|
|
||||||
line = data+(y*w); \
|
|
||||||
for (x=0; x<w; x++) { \
|
|
||||||
if (line[x] != bg) { \
|
|
||||||
cl = line[x]; \
|
|
||||||
hy = y-1; \
|
|
||||||
hyflag = 1; \
|
|
||||||
for (j=y; j<h; j++) { \
|
|
||||||
seg = data+(j*w); \
|
|
||||||
if (seg[x] != cl) {break;} \
|
|
||||||
i = x; \
|
|
||||||
while ((seg[i] == cl) && (i < w)) i += 1; \
|
|
||||||
i -= 1; \
|
|
||||||
if (j == y) vx = hx = i; \
|
|
||||||
if (i < vx) vx = i; \
|
|
||||||
if ((hyflag > 0) && (i >= hx)) {hy += 1;} else {hyflag = 0;} \
|
|
||||||
} \
|
|
||||||
vy = j-1; \
|
|
||||||
\
|
|
||||||
/* We now have two possible subrects: (x,y,hx,hy) and (x,y,vx,vy) \
|
|
||||||
* We'll choose the bigger of the two. \
|
|
||||||
*/ \
|
|
||||||
hw = hx-x+1; \
|
|
||||||
hh = hy-y+1; \
|
|
||||||
vw = vx-x+1; \
|
|
||||||
vh = vy-y+1; \
|
|
||||||
\
|
|
||||||
thex = x; \
|
|
||||||
they = y; \
|
|
||||||
\
|
|
||||||
if ((hw*hh) > (vw*vh)) { \
|
|
||||||
thew = hw; \
|
|
||||||
theh = hh; \
|
|
||||||
} else { \
|
|
||||||
thew = vw; \
|
|
||||||
theh = vh; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
subrect.x = Swap16IfLE(thex); \
|
|
||||||
subrect.y = Swap16IfLE(they); \
|
|
||||||
subrect.w = Swap16IfLE(thew); \
|
|
||||||
subrect.h = Swap16IfLE(theh); \
|
|
||||||
\
|
|
||||||
newLen = rreAfterBufLen + (bpp/8) + sz_rfbRectangle; \
|
|
||||||
if ((newLen > (w * h * (bpp/8))) || (newLen > rreAfterBufSize)) \
|
|
||||||
return -1; \
|
|
||||||
\
|
|
||||||
numsubs += 1; \
|
|
||||||
*((CARD##bpp*)(rreAfterBuf + rreAfterBufLen)) = cl; \
|
|
||||||
rreAfterBufLen += (bpp/8); \
|
|
||||||
memcpy(&rreAfterBuf[rreAfterBufLen],&subrect,sz_rfbRectangle); \
|
|
||||||
rreAfterBufLen += sz_rfbRectangle; \
|
|
||||||
\
|
|
||||||
/* \
|
|
||||||
* Now mark the subrect as done. \
|
|
||||||
*/ \
|
|
||||||
for (j=they; j < (they+theh); j++) { \
|
|
||||||
for (i=thex; i < (thex+thew); i++) { \
|
|
||||||
data[j*w+i] = bg; \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
return numsubs; \
|
|
||||||
}
|
|
||||||
|
|
||||||
DEFINE_SUBRECT_ENCODE(8)
|
|
||||||
DEFINE_SUBRECT_ENCODE(16)
|
|
||||||
DEFINE_SUBRECT_ENCODE(32)
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* getBgColour() gets the most prevalent colour in a byte array.
|
|
||||||
*/
|
|
||||||
static CARD32
|
|
||||||
getBgColour(data,size,bpp)
|
|
||||||
char *data;
|
|
||||||
int size;
|
|
||||||
int bpp;
|
|
||||||
{
|
|
||||||
|
|
||||||
#define NUMCLRS 256
|
|
||||||
|
|
||||||
static int counts[NUMCLRS];
|
|
||||||
int i,j,k;
|
|
||||||
|
|
||||||
int maxcount = 0;
|
|
||||||
CARD8 maxclr = 0;
|
|
||||||
|
|
||||||
if (bpp != 8) {
|
|
||||||
if (bpp == 16) {
|
|
||||||
return ((CARD16 *)data)[0];
|
|
||||||
} else if (bpp == 32) {
|
|
||||||
return ((CARD32 *)data)[0];
|
|
||||||
} else {
|
|
||||||
rfbLog("getBgColour: bpp %d?\n",bpp);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0; i<NUMCLRS; i++) {
|
|
||||||
counts[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (j=0; j<size; j++) {
|
|
||||||
k = (int)(((CARD8 *)data)[j]);
|
|
||||||
if (k >= NUMCLRS) {
|
|
||||||
rfbLog("getBgColour: unusual colour = %d\n", k);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
counts[k] += 1;
|
|
||||||
if (counts[k] > maxcount) {
|
|
||||||
maxcount = counts[k];
|
|
||||||
maxclr = ((CARD8 *)data)[j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return maxclr;
|
|
||||||
}
|
|
@ -1,301 +0,0 @@
|
|||||||
#include <ctype.h>
|
|
||||||
#include "rfb.h"
|
|
||||||
#include "keysym.h"
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
rfbScreenInfoPtr screen;
|
|
||||||
rfbFontDataPtr font;
|
|
||||||
char** list;
|
|
||||||
int listSize;
|
|
||||||
int selected;
|
|
||||||
int displayStart;
|
|
||||||
int x1,y1,x2,y2,textH,pageH;
|
|
||||||
int xhot,yhot;
|
|
||||||
int buttonWidth,okBX,cancelBX,okX,cancelX,okY;
|
|
||||||
Bool okInverted,cancelInverted;
|
|
||||||
int lastButtons;
|
|
||||||
Pixel colour,backColour;
|
|
||||||
SelectionChangedHookPtr selChangedHook;
|
|
||||||
enum { SELECTING, OK, CANCEL } state;
|
|
||||||
} rfbSelectData;
|
|
||||||
|
|
||||||
static const char okStr[] = "OK";
|
|
||||||
static const char cancelStr[] = "Cancel";
|
|
||||||
|
|
||||||
static void selPaintButtons(rfbSelectData* m,Bool invertOk,Bool invertCancel)
|
|
||||||
{
|
|
||||||
rfbScreenInfoPtr s = m->screen;
|
|
||||||
Pixel bcolour = m->backColour;
|
|
||||||
Pixel colour = m->colour;
|
|
||||||
|
|
||||||
rfbFillRect(s,m->x1,m->okY-m->textH,m->x2,m->okY,bcolour);
|
|
||||||
|
|
||||||
if(invertOk) {
|
|
||||||
rfbFillRect(s,m->okBX,m->okY-m->textH,m->okBX+m->buttonWidth,m->okY,colour);
|
|
||||||
rfbDrawStringWithClip(s,m->font,m->okX+m->xhot,m->okY-1+m->yhot,okStr,
|
|
||||||
m->x1,m->okY-m->textH,m->x2,m->okY,
|
|
||||||
bcolour,colour);
|
|
||||||
} else
|
|
||||||
rfbDrawString(s,m->font,m->okX+m->xhot,m->okY-1+m->yhot,okStr,colour);
|
|
||||||
|
|
||||||
if(invertCancel) {
|
|
||||||
rfbFillRect(s,m->cancelBX,m->okY-m->textH,
|
|
||||||
m->cancelBX+m->buttonWidth,m->okY,colour);
|
|
||||||
rfbDrawStringWithClip(s,m->font,m->cancelX+m->xhot,m->okY-1+m->yhot,
|
|
||||||
cancelStr,m->x1,m->okY-m->textH,m->x2,m->okY,
|
|
||||||
bcolour,colour);
|
|
||||||
} else
|
|
||||||
rfbDrawString(s,m->font,m->cancelX+m->xhot,m->okY-1+m->yhot,cancelStr,colour);
|
|
||||||
|
|
||||||
m->okInverted = invertOk;
|
|
||||||
m->cancelInverted = invertCancel;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* line is relative to displayStart */
|
|
||||||
static void selPaintLine(rfbSelectData* m,int line,Bool invert)
|
|
||||||
{
|
|
||||||
int y1 = m->y1+line*m->textH, y2 = y1+m->textH;
|
|
||||||
if(y2>m->y2)
|
|
||||||
y2=m->y2;
|
|
||||||
rfbFillRect(m->screen,m->x1,y1,m->x2,y2,invert?m->colour:m->backColour);
|
|
||||||
if(m->displayStart+line<m->listSize)
|
|
||||||
rfbDrawStringWithClip(m->screen,m->font,m->x1+m->xhot,y2-1+m->yhot,
|
|
||||||
m->list[m->displayStart+line],
|
|
||||||
m->x1,y1,m->x2,y2,
|
|
||||||
invert?m->backColour:m->colour,
|
|
||||||
invert?m->backColour:m->colour);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void selSelect(rfbSelectData* m,int _index)
|
|
||||||
{
|
|
||||||
int delta;
|
|
||||||
|
|
||||||
if(_index==m->selected || _index<0 || _index>=m->listSize)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if(m->selected>=0)
|
|
||||||
selPaintLine(m,m->selected-m->displayStart,FALSE);
|
|
||||||
|
|
||||||
if(_index<m->displayStart || _index>=m->displayStart+m->pageH) {
|
|
||||||
/* targetLine is the screen line in which the selected line will
|
|
||||||
be displayed.
|
|
||||||
targetLine = m->pageH/2 doesn't look so nice */
|
|
||||||
int targetLine = m->selected-m->displayStart;
|
|
||||||
int lineStart,lineEnd;
|
|
||||||
|
|
||||||
/* scroll */
|
|
||||||
if(_index<targetLine)
|
|
||||||
targetLine = _index;
|
|
||||||
else if(_index+m->pageH-targetLine>=m->listSize)
|
|
||||||
targetLine = _index+m->pageH-m->listSize;
|
|
||||||
delta = _index-(m->displayStart+targetLine);
|
|
||||||
|
|
||||||
if(delta>-m->pageH && delta<m->pageH) {
|
|
||||||
if(delta>0) {
|
|
||||||
lineStart = m->pageH-delta;
|
|
||||||
lineEnd = m->pageH;
|
|
||||||
rfbDoCopyRect(m->screen,m->x1,m->y1,m->x2,m->y1+lineStart*m->textH,
|
|
||||||
0,-delta*m->textH);
|
|
||||||
} else {
|
|
||||||
lineStart = 0;
|
|
||||||
lineEnd = -delta;
|
|
||||||
rfbDoCopyRect(m->screen,
|
|
||||||
m->x1,m->y1+lineEnd*m->textH,m->x2,m->y2,
|
|
||||||
0,-delta*m->textH);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
lineStart = 0;
|
|
||||||
lineEnd = m->pageH;
|
|
||||||
}
|
|
||||||
m->displayStart += delta;
|
|
||||||
for(delta=lineStart;delta<lineEnd;delta++)
|
|
||||||
if(delta!=_index)
|
|
||||||
selPaintLine(m,delta,FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
m->selected = _index;
|
|
||||||
selPaintLine(m,m->selected-m->displayStart,TRUE);
|
|
||||||
|
|
||||||
if(m->selChangedHook)
|
|
||||||
m->selChangedHook(_index);
|
|
||||||
|
|
||||||
/* todo: scrollbars */
|
|
||||||
}
|
|
||||||
|
|
||||||
static void selKbdAddEvent(Bool down,KeySym keySym,rfbClientPtr cl)
|
|
||||||
{
|
|
||||||
if(down) {
|
|
||||||
if(keySym>' ' && keySym<0xff) {
|
|
||||||
int i;
|
|
||||||
rfbSelectData* m = (rfbSelectData*)cl->screen->screenData;
|
|
||||||
char c = tolower(keySym);
|
|
||||||
|
|
||||||
for(i=m->selected+1;m->list[i] && tolower(m->list[i][0])!=c;i++);
|
|
||||||
if(!m->list[i])
|
|
||||||
for(i=0;i<m->selected && tolower(m->list[i][0])!=c;i++);
|
|
||||||
selSelect(m,i);
|
|
||||||
} else if(keySym==XK_Escape) {
|
|
||||||
rfbSelectData* m = (rfbSelectData*)cl->screen->screenData;
|
|
||||||
m->state = CANCEL;
|
|
||||||
} else if(keySym==XK_Return) {
|
|
||||||
rfbSelectData* m = (rfbSelectData*)cl->screen->screenData;
|
|
||||||
m->state = OK;
|
|
||||||
} else {
|
|
||||||
rfbSelectData* m = (rfbSelectData*)cl->screen->screenData;
|
|
||||||
int curSel=m->selected;
|
|
||||||
if(keySym==XK_Up) {
|
|
||||||
if(curSel>0)
|
|
||||||
selSelect(m,curSel-1);
|
|
||||||
} else if(keySym==XK_Down) {
|
|
||||||
if(curSel+1<m->listSize)
|
|
||||||
selSelect(m,curSel+1);
|
|
||||||
} else {
|
|
||||||
if(keySym==XK_Page_Down) {
|
|
||||||
if(curSel+m->pageH<m->listSize)
|
|
||||||
selSelect(m,curSel+m->pageH);
|
|
||||||
else
|
|
||||||
selSelect(m,m->listSize-1);
|
|
||||||
} else if(keySym==XK_Page_Up) {
|
|
||||||
if(curSel-m->pageH>=0)
|
|
||||||
selSelect(m,curSel-m->pageH);
|
|
||||||
else
|
|
||||||
selSelect(m,0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void selPtrAddEvent(int buttonMask,int x,int y,rfbClientPtr cl)
|
|
||||||
{
|
|
||||||
rfbSelectData* m = (rfbSelectData*)cl->screen->screenData;
|
|
||||||
if(y<m->okY && y>=m->okY-m->textH) {
|
|
||||||
if(x>=m->okBX && x<m->okBX+m->buttonWidth) {
|
|
||||||
if(!m->okInverted)
|
|
||||||
selPaintButtons(m,TRUE,FALSE);
|
|
||||||
if(buttonMask)
|
|
||||||
m->state = OK;
|
|
||||||
} else if(x>=m->cancelBX && x<m->cancelBX+m->buttonWidth) {
|
|
||||||
if(!m->cancelInverted)
|
|
||||||
selPaintButtons(m,FALSE,TRUE);
|
|
||||||
if(buttonMask)
|
|
||||||
m->state = CANCEL;
|
|
||||||
} else if(m->okInverted || m->cancelInverted)
|
|
||||||
selPaintButtons(m,FALSE,FALSE);
|
|
||||||
} else {
|
|
||||||
if(m->okInverted || m->cancelInverted)
|
|
||||||
selPaintButtons(m,FALSE,FALSE);
|
|
||||||
if(!m->lastButtons && buttonMask) {
|
|
||||||
if(x>=m->x1 && x<m->x2 && y>=m->y1 && y<m->y2)
|
|
||||||
selSelect(m,m->displayStart+(y-m->y1)/m->textH);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m->lastButtons = buttonMask;
|
|
||||||
|
|
||||||
/* todo: scrollbars */
|
|
||||||
}
|
|
||||||
|
|
||||||
static rfbCursorPtr selGetCursorPtr(rfbClientPtr cl)
|
|
||||||
{
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int rfbSelectBox(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,
|
|
||||||
char** list,
|
|
||||||
int x1,int y1,int x2,int y2,
|
|
||||||
Pixel colour,Pixel backColour,
|
|
||||||
int border,SelectionChangedHookPtr selChangedHook)
|
|
||||||
{
|
|
||||||
int bpp = rfbScreen->bitsPerPixel/8;
|
|
||||||
char* frameBufferBackup;
|
|
||||||
void* screenDataBackup = rfbScreen->screenData;
|
|
||||||
KbdAddEventProcPtr kbdAddEventBackup = rfbScreen->kbdAddEvent;
|
|
||||||
PtrAddEventProcPtr ptrAddEventBackup = rfbScreen->ptrAddEvent;
|
|
||||||
GetCursorProcPtr getCursorPtrBackup = rfbScreen->getCursorPtr;
|
|
||||||
DisplayHookPtr displayHookBackup = rfbScreen->displayHook;
|
|
||||||
rfbSelectData selData;
|
|
||||||
int i,j,k;
|
|
||||||
int fx1,fy1,fx2,fy2; /* for font bbox */
|
|
||||||
|
|
||||||
if(list==0 || *list==0)
|
|
||||||
return(-1);
|
|
||||||
|
|
||||||
rfbWholeFontBBox(font, &fx1, &fy1, &fx2, &fy2);
|
|
||||||
selData.textH = fy2-fy1;
|
|
||||||
/* I need at least one line for the choice and one for the buttons */
|
|
||||||
if(y2-y1<selData.textH*2+3*border)
|
|
||||||
return(-1);
|
|
||||||
selData.xhot = -fx1;
|
|
||||||
selData.yhot = -fy2;
|
|
||||||
selData.x1 = x1+border;
|
|
||||||
selData.y1 = y1+border;
|
|
||||||
selData.y2 = y2-selData.textH-3*border;
|
|
||||||
selData.x2 = x2-2*border;
|
|
||||||
selData.pageH = (selData.y2-selData.y1)/selData.textH;
|
|
||||||
|
|
||||||
i = rfbWidthOfString(font,okStr);
|
|
||||||
j = rfbWidthOfString(font,cancelStr);
|
|
||||||
selData.buttonWidth= k = 4*border+(i<j)?j:i;
|
|
||||||
selData.okBX = x1+(x2-x1-2*k)/3;
|
|
||||||
if(selData.okBX<x1+border) /* too narrow! */
|
|
||||||
return(-1);
|
|
||||||
selData.cancelBX = x1+k+(x2-x1-2*k)*2/3;
|
|
||||||
selData.okX = selData.okBX+(k-i)/2;
|
|
||||||
selData.cancelX = selData.cancelBX+(k-j)/2;
|
|
||||||
selData.okY = y2-border;
|
|
||||||
|
|
||||||
rfbUndrawCursor(rfbScreen);
|
|
||||||
frameBufferBackup = (char*)malloc(bpp*(x2-x1)*(y2-y1));
|
|
||||||
|
|
||||||
selData.state = SELECTING;
|
|
||||||
selData.screen = rfbScreen;
|
|
||||||
selData.font = font;
|
|
||||||
selData.list = list;
|
|
||||||
selData.colour = colour;
|
|
||||||
selData.backColour = backColour;
|
|
||||||
for(i=0;list[i];i++);
|
|
||||||
selData.selected = i;
|
|
||||||
selData.listSize = i;
|
|
||||||
selData.displayStart = i;
|
|
||||||
selData.lastButtons = 0;
|
|
||||||
selData.selChangedHook = selChangedHook;
|
|
||||||
|
|
||||||
rfbScreen->screenData = &selData;
|
|
||||||
rfbScreen->kbdAddEvent = selKbdAddEvent;
|
|
||||||
rfbScreen->ptrAddEvent = selPtrAddEvent;
|
|
||||||
rfbScreen->getCursorPtr = selGetCursorPtr;
|
|
||||||
rfbScreen->displayHook = 0;
|
|
||||||
|
|
||||||
/* backup screen */
|
|
||||||
for(j=0;j<y2-y1;j++)
|
|
||||||
memcpy(frameBufferBackup+j*(x2-x1)*bpp,
|
|
||||||
rfbScreen->frameBuffer+j*rfbScreen->paddedWidthInBytes+x1*bpp,
|
|
||||||
(x2-x1)*bpp);
|
|
||||||
|
|
||||||
/* paint list and buttons */
|
|
||||||
rfbFillRect(rfbScreen,x1,y1,x2,y2,colour);
|
|
||||||
selPaintButtons(&selData,FALSE,FALSE);
|
|
||||||
selSelect(&selData,0);
|
|
||||||
|
|
||||||
/* modal loop */
|
|
||||||
while(selData.state == SELECTING)
|
|
||||||
rfbProcessEvents(rfbScreen,20000);
|
|
||||||
|
|
||||||
/* copy back screen data */
|
|
||||||
for(j=0;j<y2-y1;j++)
|
|
||||||
memcpy(rfbScreen->frameBuffer+j*rfbScreen->paddedWidthInBytes+x1*bpp,
|
|
||||||
frameBufferBackup+j*(x2-x1)*bpp,
|
|
||||||
(x2-x1)*bpp);
|
|
||||||
free(frameBufferBackup);
|
|
||||||
rfbMarkRectAsModified(rfbScreen,x1,y1,x2,y2);
|
|
||||||
rfbScreen->screenData = screenDataBackup;
|
|
||||||
rfbScreen->kbdAddEvent = kbdAddEventBackup;
|
|
||||||
rfbScreen->ptrAddEvent = ptrAddEventBackup;
|
|
||||||
rfbScreen->getCursorPtr = getCursorPtrBackup;
|
|
||||||
rfbScreen->displayHook = displayHookBackup;
|
|
||||||
|
|
||||||
if(selData.state==CANCEL)
|
|
||||||
selData.selected=-1;
|
|
||||||
return(selData.selected);
|
|
||||||
}
|
|
||||||
|
|
@ -1,592 +0,0 @@
|
|||||||
/*
|
|
||||||
* sockets.c - deal with TCP & UDP sockets.
|
|
||||||
*
|
|
||||||
* This code should be independent of any changes in the RFB protocol. It just
|
|
||||||
* deals with the X server scheduling stuff, calling rfbNewClientConnection and
|
|
||||||
* rfbProcessClientMessage to actually deal with the protocol. If a socket
|
|
||||||
* needs to be closed for any reason then rfbCloseClient should be called, and
|
|
||||||
* this in turn will call rfbClientConnectionGone. To make an active
|
|
||||||
* connection out, call rfbConnect - note that this does _not_ call
|
|
||||||
* rfbNewClientConnection.
|
|
||||||
*
|
|
||||||
* This file is divided into two types of function. Those beginning with
|
|
||||||
* "rfb" are specific to sockets using the RFB protocol. Those without the
|
|
||||||
* "rfb" prefix are more general socket routines (which are used by the http
|
|
||||||
* code).
|
|
||||||
*
|
|
||||||
* Thanks to Karl Hakimian for pointing out that some platforms return EAGAIN
|
|
||||||
* not EWOULDBLOCK.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
|
|
||||||
* Original Xvnc code 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
|
||||||
* USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#ifdef WIN32
|
|
||||||
#pragma warning (disable: 4018 4761)
|
|
||||||
#define close closesocket
|
|
||||||
#define read(sock,buf,len) recv(sock,buf,len,0)
|
|
||||||
#define EWOULDBLOCK WSAEWOULDBLOCK
|
|
||||||
#define ETIMEDOUT WSAETIMEDOUT
|
|
||||||
#define write(sock,buf,len) send(sock,buf,len,0)
|
|
||||||
#else
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <netinet/tcp.h>
|
|
||||||
#include <netdb.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#endif
|
|
||||||
#if defined(__osf__)
|
|
||||||
typedef int socklen_t;
|
|
||||||
#endif
|
|
||||||
#if defined(__linux__) && defined(NEED_TIMEVAL)
|
|
||||||
struct timeval
|
|
||||||
{
|
|
||||||
long int tv_sec,tv_usec;
|
|
||||||
}
|
|
||||||
;
|
|
||||||
#endif
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#ifdef USE_LIBWRAP
|
|
||||||
#include <syslog.h>
|
|
||||||
#include <tcpd.h>
|
|
||||||
int allow_severity=LOG_INFO;
|
|
||||||
int deny_severity=LOG_WARNING;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "rfb.h"
|
|
||||||
|
|
||||||
/*#ifndef WIN32
|
|
||||||
int max(int i,int j) { return(i<j?j:i); }
|
|
||||||
#endif
|
|
||||||
*/
|
|
||||||
|
|
||||||
int rfbMaxClientWait = 20000; /* time (ms) after which we decide client has
|
|
||||||
gone away - needed to stop us hanging */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* rfbInitSockets sets up the TCP and UDP sockets to listen for RFB
|
|
||||||
* connections. It does nothing if called again.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
rfbInitSockets(rfbScreenInfoPtr rfbScreen)
|
|
||||||
{
|
|
||||||
if (rfbScreen->socketInitDone)
|
|
||||||
return;
|
|
||||||
|
|
||||||
rfbScreen->socketInitDone = TRUE;
|
|
||||||
|
|
||||||
if (rfbScreen->inetdSock != -1) {
|
|
||||||
const int one = 1;
|
|
||||||
|
|
||||||
#ifndef WIN32
|
|
||||||
if (fcntl(rfbScreen->inetdSock, F_SETFL, O_NONBLOCK) < 0) {
|
|
||||||
rfbLogPerror("fcntl");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (setsockopt(rfbScreen->inetdSock, IPPROTO_TCP, TCP_NODELAY,
|
|
||||||
(char *)&one, sizeof(one)) < 0) {
|
|
||||||
rfbLogPerror("setsockopt");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
FD_ZERO(&(rfbScreen->allFds));
|
|
||||||
FD_SET(rfbScreen->inetdSock, &(rfbScreen->allFds));
|
|
||||||
rfbScreen->maxFd = rfbScreen->inetdSock;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(rfbScreen->autoPort) {
|
|
||||||
int i;
|
|
||||||
rfbLog("Autoprobing TCP port \n");
|
|
||||||
|
|
||||||
for (i = 5900; i < 6000; i++) {
|
|
||||||
if ((rfbScreen->rfbListenSock = ListenOnTCPPort(i)) >= 0) {
|
|
||||||
rfbScreen->rfbPort = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i >= 6000) {
|
|
||||||
rfbLogPerror("Failure autoprobing");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
rfbLog("Autoprobing selected port %d\n", rfbScreen->rfbPort);
|
|
||||||
FD_ZERO(&(rfbScreen->allFds));
|
|
||||||
FD_SET(rfbScreen->rfbListenSock, &(rfbScreen->allFds));
|
|
||||||
rfbScreen->maxFd = rfbScreen->rfbListenSock;
|
|
||||||
}
|
|
||||||
else if(rfbScreen->rfbPort>0) {
|
|
||||||
rfbLog("Listening for VNC connections on TCP port %d\n", rfbScreen->rfbPort);
|
|
||||||
|
|
||||||
if ((rfbScreen->rfbListenSock = ListenOnTCPPort(rfbScreen->rfbPort)) < 0) {
|
|
||||||
rfbLogPerror("ListenOnTCPPort");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
FD_ZERO(&(rfbScreen->allFds));
|
|
||||||
FD_SET(rfbScreen->rfbListenSock, &(rfbScreen->allFds));
|
|
||||||
rfbScreen->maxFd = rfbScreen->rfbListenSock;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rfbScreen->udpPort != 0) {
|
|
||||||
rfbLog("rfbInitSockets: listening for input on UDP port %d\n",rfbScreen->udpPort);
|
|
||||||
|
|
||||||
if ((rfbScreen->udpSock = ListenOnUDPPort(rfbScreen->udpPort)) < 0) {
|
|
||||||
rfbLogPerror("ListenOnUDPPort");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
FD_SET(rfbScreen->udpSock, &(rfbScreen->allFds));
|
|
||||||
rfbScreen->maxFd = max((int)rfbScreen->udpSock,rfbScreen->maxFd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* rfbCheckFds is called from ProcessInputEvents to check for input on the RFB
|
|
||||||
* socket(s). If there is input to process, the appropriate function in the
|
|
||||||
* RFB server code will be called (rfbNewClientConnection,
|
|
||||||
* rfbProcessClientMessage, etc).
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec)
|
|
||||||
{
|
|
||||||
int nfds;
|
|
||||||
fd_set fds;
|
|
||||||
struct timeval tv;
|
|
||||||
struct sockaddr_in addr;
|
|
||||||
size_t addrlen = sizeof(addr);
|
|
||||||
char buf[6];
|
|
||||||
const int one = 1;
|
|
||||||
int sock;
|
|
||||||
rfbClientIteratorPtr i;
|
|
||||||
rfbClientPtr cl;
|
|
||||||
|
|
||||||
if (!rfbScreen->inetdInitDone && rfbScreen->inetdSock != -1) {
|
|
||||||
rfbNewClientConnection(rfbScreen,rfbScreen->inetdSock);
|
|
||||||
rfbScreen->inetdInitDone = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy((char *)&fds, (char *)&(rfbScreen->allFds), sizeof(fd_set));
|
|
||||||
tv.tv_sec = 0;
|
|
||||||
tv.tv_usec = usec;
|
|
||||||
nfds = select(rfbScreen->maxFd + 1, &fds, NULL, NULL /* &fds */, &tv);
|
|
||||||
if (nfds == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (nfds < 0) {
|
|
||||||
#ifdef WIN32
|
|
||||||
errno = WSAGetLastError();
|
|
||||||
#endif
|
|
||||||
rfbLogPerror("rfbCheckFds: select");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rfbScreen->rfbListenSock != -1 && FD_ISSET(rfbScreen->rfbListenSock, &fds)) {
|
|
||||||
|
|
||||||
if ((sock = accept(rfbScreen->rfbListenSock,
|
|
||||||
(struct sockaddr *)&addr, &addrlen)) < 0) {
|
|
||||||
rfbLogPerror("rfbCheckFds: accept");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef WIN32
|
|
||||||
if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) {
|
|
||||||
rfbLogPerror("rfbCheckFds: fcntl");
|
|
||||||
close(sock);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
|
|
||||||
(char *)&one, sizeof(one)) < 0) {
|
|
||||||
rfbLogPerror("rfbCheckFds: setsockopt");
|
|
||||||
close(sock);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef USE_LIBWRAP
|
|
||||||
if(!hosts_ctl("vnc",STRING_UNKNOWN,inet_ntoa(addr.sin_addr),
|
|
||||||
STRING_UNKNOWN)) {
|
|
||||||
rfbLog("Rejected connection from client %s\n",
|
|
||||||
inet_ntoa(addr.sin_addr));
|
|
||||||
close(sock);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
rfbLog("Got connection from client %s\n", inet_ntoa(addr.sin_addr));
|
|
||||||
|
|
||||||
rfbNewClient(rfbScreen,sock);
|
|
||||||
|
|
||||||
FD_CLR(rfbScreen->rfbListenSock, &fds);
|
|
||||||
if (--nfds == 0)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((rfbScreen->udpSock != -1) && FD_ISSET(rfbScreen->udpSock, &fds)) {
|
|
||||||
if(!rfbScreen->udpClient)
|
|
||||||
rfbNewUDPClient(rfbScreen);
|
|
||||||
if (recvfrom(rfbScreen->udpSock, buf, 1, MSG_PEEK,
|
|
||||||
(struct sockaddr *)&addr, &addrlen) < 0) {
|
|
||||||
rfbLogPerror("rfbCheckFds: UDP: recvfrom");
|
|
||||||
rfbDisconnectUDPSock(rfbScreen);
|
|
||||||
rfbScreen->udpSockConnected = FALSE;
|
|
||||||
} else {
|
|
||||||
if (!rfbScreen->udpSockConnected ||
|
|
||||||
(memcmp(&addr, &rfbScreen->udpRemoteAddr, addrlen) != 0))
|
|
||||||
{
|
|
||||||
/* new remote end */
|
|
||||||
rfbLog("rfbCheckFds: UDP: got connection\n");
|
|
||||||
|
|
||||||
memcpy(&rfbScreen->udpRemoteAddr, &addr, addrlen);
|
|
||||||
rfbScreen->udpSockConnected = TRUE;
|
|
||||||
|
|
||||||
if (connect(rfbScreen->udpSock,
|
|
||||||
(struct sockaddr *)&addr, addrlen) < 0) {
|
|
||||||
rfbLogPerror("rfbCheckFds: UDP: connect");
|
|
||||||
rfbDisconnectUDPSock(rfbScreen);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rfbNewUDPConnection(rfbScreen,rfbScreen->udpSock);
|
|
||||||
}
|
|
||||||
|
|
||||||
rfbProcessUDPInput(rfbScreen);
|
|
||||||
}
|
|
||||||
|
|
||||||
FD_CLR(rfbScreen->udpSock, &fds);
|
|
||||||
if (--nfds == 0)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
i = rfbGetClientIterator(rfbScreen);
|
|
||||||
while((cl = rfbClientIteratorNext(i))) {
|
|
||||||
if (cl->onHold)
|
|
||||||
continue;
|
|
||||||
if (FD_ISSET(cl->sock, &fds) && FD_ISSET(cl->sock, &(rfbScreen->allFds)))
|
|
||||||
rfbProcessClientMessage(cl);
|
|
||||||
}
|
|
||||||
rfbReleaseClientIterator(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
rfbDisconnectUDPSock(rfbScreenInfoPtr rfbScreen)
|
|
||||||
{
|
|
||||||
rfbScreen->udpSockConnected = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
rfbCloseClient(cl)
|
|
||||||
rfbClientPtr cl;
|
|
||||||
{
|
|
||||||
LOCK(cl->updateMutex);
|
|
||||||
if (cl->sock != -1) {
|
|
||||||
FD_CLR(cl->sock,&(cl->screen->allFds));
|
|
||||||
shutdown(cl->sock,SHUT_RDWR);
|
|
||||||
close(cl->sock);
|
|
||||||
cl->sock = -1;
|
|
||||||
}
|
|
||||||
TSIGNAL(cl->updateCond);
|
|
||||||
UNLOCK(cl->updateMutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* rfbConnect is called to make a connection out to a given TCP address.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
rfbConnect(rfbScreen, host, port)
|
|
||||||
rfbScreenInfoPtr rfbScreen;
|
|
||||||
char *host;
|
|
||||||
int port;
|
|
||||||
{
|
|
||||||
int sock;
|
|
||||||
int one = 1;
|
|
||||||
|
|
||||||
rfbLog("Making connection to client on host %s port %d\n",
|
|
||||||
host,port);
|
|
||||||
|
|
||||||
if ((sock = ConnectToTcpAddr(host, port)) < 0) {
|
|
||||||
rfbLogPerror("connection failed");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef WIN32
|
|
||||||
if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) {
|
|
||||||
rfbLogPerror("fcntl failed");
|
|
||||||
close(sock);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
|
|
||||||
(char *)&one, sizeof(one)) < 0) {
|
|
||||||
rfbLogPerror("setsockopt failed");
|
|
||||||
close(sock);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* AddEnabledDevice(sock); */
|
|
||||||
FD_SET(sock, &rfbScreen->allFds);
|
|
||||||
rfbScreen->maxFd = max(sock,rfbScreen->maxFd);
|
|
||||||
|
|
||||||
return sock;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ReadExact reads an exact number of bytes from a client. Returns 1 if
|
|
||||||
* those bytes have been read, 0 if the other end has closed, or -1 if an error
|
|
||||||
* occurred (errno is set to ETIMEDOUT if it timed out).
|
|
||||||
* timeout is the timeout in ms, 0 for no timeout.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
ReadExactTimeout(rfbClientPtr cl, char* buf, int len, int timeout)
|
|
||||||
{
|
|
||||||
int sock = cl->sock;
|
|
||||||
int n;
|
|
||||||
fd_set fds;
|
|
||||||
struct timeval tv;
|
|
||||||
int to = 20000;
|
|
||||||
if (timeout)
|
|
||||||
to = timeout;
|
|
||||||
|
|
||||||
while (len > 0) {
|
|
||||||
n = read(sock, buf, len);
|
|
||||||
|
|
||||||
if (n > 0) {
|
|
||||||
|
|
||||||
buf += n;
|
|
||||||
len -= n;
|
|
||||||
|
|
||||||
} else if (n == 0) {
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
#ifdef WIN32
|
|
||||||
errno = WSAGetLastError();
|
|
||||||
#endif
|
|
||||||
if (errno != EWOULDBLOCK && errno != EAGAIN) {
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
FD_ZERO(&fds);
|
|
||||||
FD_SET(sock, &fds);
|
|
||||||
tv.tv_sec = to / 1000;
|
|
||||||
tv.tv_usec = (to % 1000) * 1000;
|
|
||||||
n = select(sock+1, &fds, NULL, &fds, &tv);
|
|
||||||
if (n < 0) {
|
|
||||||
rfbLogPerror("ReadExact: select");
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
if ((n == 0) && timeout) {
|
|
||||||
errno = ETIMEDOUT;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ReadExact(rfbClientPtr cl,char* buf,int len)
|
|
||||||
{
|
|
||||||
return ReadExactTimeout(cl, buf, len, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* WriteExact writes an exact number of bytes to a client. Returns 1 if
|
|
||||||
* those bytes have been written, or -1 if an error occurred (errno is set to
|
|
||||||
* ETIMEDOUT if it timed out).
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
WriteExact(cl, buf, len)
|
|
||||||
rfbClientPtr cl;
|
|
||||||
const char *buf;
|
|
||||||
int len;
|
|
||||||
{
|
|
||||||
int sock = cl->sock;
|
|
||||||
int n;
|
|
||||||
fd_set fds;
|
|
||||||
struct timeval tv;
|
|
||||||
int totalTimeWaited = 0;
|
|
||||||
|
|
||||||
LOCK(cl->outputMutex);
|
|
||||||
while (len > 0) {
|
|
||||||
n = write(sock, buf, len);
|
|
||||||
|
|
||||||
if (n > 0) {
|
|
||||||
|
|
||||||
buf += n;
|
|
||||||
len -= n;
|
|
||||||
|
|
||||||
} else if (n == 0) {
|
|
||||||
|
|
||||||
rfbLog("WriteExact: write returned 0?\n");
|
|
||||||
exit(1);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
#ifdef WIN32
|
|
||||||
errno = WSAGetLastError();
|
|
||||||
#endif
|
|
||||||
if (errno != EWOULDBLOCK && errno != EAGAIN) {
|
|
||||||
UNLOCK(cl->outputMutex);
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Retry every 5 seconds until we exceed rfbMaxClientWait. We
|
|
||||||
need to do this because select doesn't necessarily return
|
|
||||||
immediately when the other end has gone away */
|
|
||||||
|
|
||||||
FD_ZERO(&fds);
|
|
||||||
FD_SET(sock, &fds);
|
|
||||||
tv.tv_sec = 5;
|
|
||||||
tv.tv_usec = 0;
|
|
||||||
n = select(sock+1, NULL, &fds, NULL /* &fds */, &tv);
|
|
||||||
if (n < 0) {
|
|
||||||
rfbLogPerror("WriteExact: select");
|
|
||||||
UNLOCK(cl->outputMutex);
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
if (n == 0) {
|
|
||||||
totalTimeWaited += 5000;
|
|
||||||
if (totalTimeWaited >= rfbMaxClientWait) {
|
|
||||||
errno = ETIMEDOUT;
|
|
||||||
UNLOCK(cl->outputMutex);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
totalTimeWaited = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
UNLOCK(cl->outputMutex);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
ListenOnTCPPort(port)
|
|
||||||
int port;
|
|
||||||
{
|
|
||||||
struct sockaddr_in addr;
|
|
||||||
int sock;
|
|
||||||
int one = 1;
|
|
||||||
|
|
||||||
addr.sin_family = AF_INET;
|
|
||||||
addr.sin_port = htons(port);
|
|
||||||
/* addr.sin_addr.s_addr = interface.s_addr; */
|
|
||||||
addr.sin_addr.s_addr = INADDR_ANY;
|
|
||||||
|
|
||||||
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
|
|
||||||
(char *)&one, sizeof(one)) < 0) {
|
|
||||||
close(sock);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
|
||||||
close(sock);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (listen(sock, 5) < 0) {
|
|
||||||
close(sock);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return sock;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
ConnectToTcpAddr(host, port)
|
|
||||||
char *host;
|
|
||||||
int port;
|
|
||||||
{
|
|
||||||
struct hostent *hp;
|
|
||||||
int sock;
|
|
||||||
struct sockaddr_in addr;
|
|
||||||
|
|
||||||
addr.sin_family = AF_INET;
|
|
||||||
addr.sin_port = htons(port);
|
|
||||||
|
|
||||||
if ((addr.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE)
|
|
||||||
{
|
|
||||||
if (!(hp = gethostbyname(host))) {
|
|
||||||
errno = EINVAL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
addr.sin_addr.s_addr = *(unsigned long *)hp->h_addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (connect(sock, (struct sockaddr *)&addr, (sizeof(addr))) < 0) {
|
|
||||||
close(sock);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return sock;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
ListenOnUDPPort(port)
|
|
||||||
int port;
|
|
||||||
{
|
|
||||||
struct sockaddr_in addr;
|
|
||||||
int sock;
|
|
||||||
int one = 1;
|
|
||||||
|
|
||||||
addr.sin_family = AF_INET;
|
|
||||||
addr.sin_port = htons(port);
|
|
||||||
/* addr.sin_addr.s_addr = interface.s_addr; */
|
|
||||||
addr.sin_addr.s_addr = INADDR_ANY;
|
|
||||||
|
|
||||||
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
|
|
||||||
(char *)&one, sizeof(one)) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return sock;
|
|
||||||
}
|
|
@ -1,889 +0,0 @@
|
|||||||
/* -=- sraRegion.c
|
|
||||||
* Copyright (c) 2001 James "Wez" Weatherall, Johannes E. Schindelin
|
|
||||||
*
|
|
||||||
* A general purpose region clipping library
|
|
||||||
* Only deals with rectangular regions, though.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "rfb.h"
|
|
||||||
#include "sraRegion.h"
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
/* -=- Internal Span structure */
|
|
||||||
|
|
||||||
struct sraRegion;
|
|
||||||
|
|
||||||
typedef struct sraSpan {
|
|
||||||
struct sraSpan *_next;
|
|
||||||
struct sraSpan *_prev;
|
|
||||||
int start;
|
|
||||||
int end;
|
|
||||||
struct sraRegion *subspan;
|
|
||||||
} sraSpan;
|
|
||||||
|
|
||||||
typedef struct sraRegion {
|
|
||||||
sraSpan front;
|
|
||||||
sraSpan back;
|
|
||||||
} sraSpanList;
|
|
||||||
|
|
||||||
/* -=- Span routines */
|
|
||||||
|
|
||||||
sraSpanList *sraSpanListDup(const sraSpanList *src);
|
|
||||||
void sraSpanListDestroy(sraSpanList *list);
|
|
||||||
|
|
||||||
static sraSpan *
|
|
||||||
sraSpanCreate(int start, int end, const sraSpanList *subspan) {
|
|
||||||
sraSpan *item = (sraSpan*)malloc(sizeof(sraSpan));
|
|
||||||
item->_next = item->_prev = NULL;
|
|
||||||
item->start = start;
|
|
||||||
item->end = end;
|
|
||||||
item->subspan = sraSpanListDup(subspan);
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
|
|
||||||
static sraSpan *
|
|
||||||
sraSpanDup(const sraSpan *src) {
|
|
||||||
sraSpan *span;
|
|
||||||
if (!src) return NULL;
|
|
||||||
span = sraSpanCreate(src->start, src->end, src->subspan);
|
|
||||||
return span;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
sraSpanInsertAfter(sraSpan *newspan, sraSpan *after) {
|
|
||||||
newspan->_next = after->_next;
|
|
||||||
newspan->_prev = after;
|
|
||||||
after->_next->_prev = newspan;
|
|
||||||
after->_next = newspan;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
sraSpanInsertBefore(sraSpan *newspan, sraSpan *before) {
|
|
||||||
newspan->_next = before;
|
|
||||||
newspan->_prev = before->_prev;
|
|
||||||
before->_prev->_next = newspan;
|
|
||||||
before->_prev = newspan;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
sraSpanRemove(sraSpan *span) {
|
|
||||||
span->_prev->_next = span->_next;
|
|
||||||
span->_next->_prev = span->_prev;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
sraSpanDestroy(sraSpan *span) {
|
|
||||||
if (span->subspan) sraSpanListDestroy(span->subspan);
|
|
||||||
free(span);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
static void
|
|
||||||
sraSpanCheck(const sraSpan *span, const char *text) {
|
|
||||||
/* Check the span is valid! */
|
|
||||||
if (span->start == span->end) {
|
|
||||||
printf(text);
|
|
||||||
printf(":%d-%d\n", span->start, span->end);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* -=- SpanList routines */
|
|
||||||
|
|
||||||
static void sraSpanPrint(const sraSpan *s);
|
|
||||||
|
|
||||||
static void
|
|
||||||
sraSpanListPrint(const sraSpanList *l) {
|
|
||||||
sraSpan *curr;
|
|
||||||
if (!l) {
|
|
||||||
printf("NULL");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
curr = l->front._next;
|
|
||||||
printf("[");
|
|
||||||
while (curr != &(l->back)) {
|
|
||||||
sraSpanPrint(curr);
|
|
||||||
curr = curr->_next;
|
|
||||||
}
|
|
||||||
printf("]");
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
sraSpanPrint(const sraSpan *s) {
|
|
||||||
printf("(%d-%d)", (s->start), (s->end));
|
|
||||||
if (s->subspan)
|
|
||||||
sraSpanListPrint(s->subspan);
|
|
||||||
}
|
|
||||||
|
|
||||||
static sraSpanList *
|
|
||||||
sraSpanListCreate(void) {
|
|
||||||
sraSpanList *item = (sraSpanList*)malloc(sizeof(sraSpanList));
|
|
||||||
item->front._next = &(item->back);
|
|
||||||
item->front._prev = NULL;
|
|
||||||
item->back._prev = &(item->front);
|
|
||||||
item->back._next = NULL;
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
|
|
||||||
sraSpanList *
|
|
||||||
sraSpanListDup(const sraSpanList *src) {
|
|
||||||
sraSpanList *newlist;
|
|
||||||
sraSpan *newspan, *curr;
|
|
||||||
|
|
||||||
if (!src) return NULL;
|
|
||||||
newlist = sraSpanListCreate();
|
|
||||||
curr = src->front._next;
|
|
||||||
while (curr != &(src->back)) {
|
|
||||||
newspan = sraSpanDup(curr);
|
|
||||||
sraSpanInsertBefore(newspan, &(newlist->back));
|
|
||||||
curr = curr->_next;
|
|
||||||
}
|
|
||||||
|
|
||||||
return newlist;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
sraSpanListDestroy(sraSpanList *list) {
|
|
||||||
sraSpan *curr, *next;
|
|
||||||
while (list->front._next != &(list->back)) {
|
|
||||||
curr = list->front._next;
|
|
||||||
next = curr->_next;
|
|
||||||
sraSpanRemove(curr);
|
|
||||||
sraSpanDestroy(curr);
|
|
||||||
curr = next;
|
|
||||||
}
|
|
||||||
free(list);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
sraSpanListMakeEmpty(sraSpanList *list) {
|
|
||||||
sraSpan *curr, *next;
|
|
||||||
while (list->front._next != &(list->back)) {
|
|
||||||
curr = list->front._next;
|
|
||||||
next = curr->_next;
|
|
||||||
sraSpanRemove(curr);
|
|
||||||
sraSpanDestroy(curr);
|
|
||||||
curr = next;
|
|
||||||
}
|
|
||||||
list->front._next = &(list->back);
|
|
||||||
list->front._prev = NULL;
|
|
||||||
list->back._prev = &(list->front);
|
|
||||||
list->back._next = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Bool
|
|
||||||
sraSpanListEqual(const sraSpanList *s1, const sraSpanList *s2) {
|
|
||||||
sraSpan *sp1, *sp2;
|
|
||||||
|
|
||||||
if (!s1) {
|
|
||||||
if (!s2) {
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
printf("sraSpanListEqual:incompatible spans (only one NULL!)\n");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sp1 = s1->front._next;
|
|
||||||
sp2 = s2->front._next;
|
|
||||||
while ((sp1 != &(s1->back)) &&
|
|
||||||
(sp2 != &(s2->back))) {
|
|
||||||
if ((sp1->start != sp2->start) ||
|
|
||||||
(sp1->end != sp2->end) ||
|
|
||||||
(!sraSpanListEqual(sp1->subspan, sp2->subspan))) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
sp1 = sp1->_next;
|
|
||||||
sp2 = sp2->_next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((sp1 == &(s1->back)) && (sp2 == &(s2->back))) {
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Bool
|
|
||||||
sraSpanListEmpty(const sraSpanList *list) {
|
|
||||||
return (list->front._next == &(list->back));
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned long
|
|
||||||
sraSpanListCount(const sraSpanList *list) {
|
|
||||||
sraSpan *curr = list->front._next;
|
|
||||||
unsigned long count = 0;
|
|
||||||
while (curr != &(list->back)) {
|
|
||||||
if (curr->subspan) {
|
|
||||||
count += sraSpanListCount(curr->subspan);
|
|
||||||
} else {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
curr = curr->_next;
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
sraSpanMergePrevious(sraSpan *dest) {
|
|
||||||
sraSpan *prev = dest->_prev;
|
|
||||||
|
|
||||||
while ((prev->_prev) &&
|
|
||||||
(prev->end == dest->start) &&
|
|
||||||
(sraSpanListEqual(prev->subspan, dest->subspan))) {
|
|
||||||
/*
|
|
||||||
printf("merge_prev:");
|
|
||||||
sraSpanPrint(prev);
|
|
||||||
printf(" & ");
|
|
||||||
sraSpanPrint(dest);
|
|
||||||
printf("\n");
|
|
||||||
*/
|
|
||||||
dest->start = prev->start;
|
|
||||||
sraSpanRemove(prev);
|
|
||||||
sraSpanDestroy(prev);
|
|
||||||
prev = dest->_prev;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
sraSpanMergeNext(sraSpan *dest) {
|
|
||||||
sraSpan *next = dest->_next;
|
|
||||||
while ((next->_next) &&
|
|
||||||
(next->start == dest->end) &&
|
|
||||||
(sraSpanListEqual(next->subspan, dest->subspan))) {
|
|
||||||
/*
|
|
||||||
printf("merge_next:");
|
|
||||||
sraSpanPrint(dest);
|
|
||||||
printf(" & ");
|
|
||||||
sraSpanPrint(next);
|
|
||||||
printf("\n");
|
|
||||||
*/
|
|
||||||
dest->end = next->end;
|
|
||||||
sraSpanRemove(next);
|
|
||||||
sraSpanDestroy(next);
|
|
||||||
next = dest->_next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
sraSpanListOr(sraSpanList *dest, const sraSpanList *src) {
|
|
||||||
sraSpan *d_curr, *s_curr;
|
|
||||||
int s_start, s_end;
|
|
||||||
|
|
||||||
if (!dest) {
|
|
||||||
if (!src) {
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
printf("sraSpanListOr:incompatible spans (only one NULL!)\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
d_curr = dest->front._next;
|
|
||||||
s_curr = src->front._next;
|
|
||||||
s_start = s_curr->start;
|
|
||||||
s_end = s_curr->end;
|
|
||||||
while (s_curr != &(src->back)) {
|
|
||||||
|
|
||||||
/* - If we are at end of destination list OR
|
|
||||||
If the new span comes before the next destination one */
|
|
||||||
if ((d_curr == &(dest->back)) ||
|
|
||||||
(d_curr->start >= s_end)) {
|
|
||||||
/* - Add the span */
|
|
||||||
sraSpanInsertBefore(sraSpanCreate(s_start, s_end,
|
|
||||||
s_curr->subspan),
|
|
||||||
d_curr);
|
|
||||||
if (d_curr != &(dest->back))
|
|
||||||
sraSpanMergePrevious(d_curr);
|
|
||||||
s_curr = s_curr->_next;
|
|
||||||
s_start = s_curr->start;
|
|
||||||
s_end = s_curr->end;
|
|
||||||
} else {
|
|
||||||
|
|
||||||
/* - If the new span overlaps the existing one */
|
|
||||||
if ((s_start < d_curr->end) &&
|
|
||||||
(s_end > d_curr->start)) {
|
|
||||||
|
|
||||||
/* - Insert new span before the existing destination one? */
|
|
||||||
if (s_start < d_curr->start) {
|
|
||||||
sraSpanInsertBefore(sraSpanCreate(s_start,
|
|
||||||
d_curr->start,
|
|
||||||
s_curr->subspan),
|
|
||||||
d_curr);
|
|
||||||
sraSpanMergePrevious(d_curr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Split the existing span if necessary */
|
|
||||||
if (s_end < d_curr->end) {
|
|
||||||
sraSpanInsertAfter(sraSpanCreate(s_end,
|
|
||||||
d_curr->end,
|
|
||||||
d_curr->subspan),
|
|
||||||
d_curr);
|
|
||||||
d_curr->end = s_end;
|
|
||||||
}
|
|
||||||
if (s_start > d_curr->start) {
|
|
||||||
sraSpanInsertBefore(sraSpanCreate(d_curr->start,
|
|
||||||
s_start,
|
|
||||||
d_curr->subspan),
|
|
||||||
d_curr);
|
|
||||||
d_curr->start = s_start;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Recursively OR subspans */
|
|
||||||
sraSpanListOr(d_curr->subspan, s_curr->subspan);
|
|
||||||
|
|
||||||
/* Merge this span with previous or next? */
|
|
||||||
if (d_curr->_prev != &(dest->front))
|
|
||||||
sraSpanMergePrevious(d_curr);
|
|
||||||
if (d_curr->_next != &(dest->back))
|
|
||||||
sraSpanMergeNext(d_curr);
|
|
||||||
|
|
||||||
/* Move onto the next pair to compare */
|
|
||||||
if (s_end > d_curr->end) {
|
|
||||||
s_start = d_curr->end;
|
|
||||||
d_curr = d_curr->_next;
|
|
||||||
} else {
|
|
||||||
s_curr = s_curr->_next;
|
|
||||||
s_start = s_curr->start;
|
|
||||||
s_end = s_curr->end;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* - No overlap. Move to the next destination span */
|
|
||||||
d_curr = d_curr->_next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Bool
|
|
||||||
sraSpanListAnd(sraSpanList *dest, const sraSpanList *src) {
|
|
||||||
sraSpan *d_curr, *s_curr, *d_next;
|
|
||||||
|
|
||||||
if (!dest) {
|
|
||||||
if (!src) {
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
printf("sraSpanListAnd:incompatible spans (only one NULL!)\n");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
d_curr = dest->front._next;
|
|
||||||
s_curr = src->front._next;
|
|
||||||
while ((s_curr != &(src->back)) && (d_curr != &(dest->back))) {
|
|
||||||
|
|
||||||
/* - If we haven't reached a destination span yet then move on */
|
|
||||||
if (d_curr->start >= s_curr->end) {
|
|
||||||
s_curr = s_curr->_next;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* - If we are beyond the current destination span then remove it */
|
|
||||||
if (d_curr->end <= s_curr->start) {
|
|
||||||
sraSpan *next = d_curr->_next;
|
|
||||||
sraSpanRemove(d_curr);
|
|
||||||
sraSpanDestroy(d_curr);
|
|
||||||
d_curr = next;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* - If we partially overlap a span then split it up or remove bits */
|
|
||||||
if (s_curr->start > d_curr->start) {
|
|
||||||
/* - The top bit of the span does not match */
|
|
||||||
d_curr->start = s_curr->start;
|
|
||||||
}
|
|
||||||
if (s_curr->end < d_curr->end) {
|
|
||||||
/* - The end of the span does not match */
|
|
||||||
sraSpanInsertAfter(sraSpanCreate(s_curr->end,
|
|
||||||
d_curr->end,
|
|
||||||
d_curr->subspan),
|
|
||||||
d_curr);
|
|
||||||
d_curr->end = s_curr->end;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* - Now recursively process the affected span */
|
|
||||||
if (!sraSpanListAnd(d_curr->subspan, s_curr->subspan)) {
|
|
||||||
/* - The destination subspan is now empty, so we should remove it */
|
|
||||||
sraSpan *next = d_curr->_next;
|
|
||||||
sraSpanRemove(d_curr);
|
|
||||||
sraSpanDestroy(d_curr);
|
|
||||||
d_curr = next;
|
|
||||||
} else {
|
|
||||||
/* Merge this span with previous or next? */
|
|
||||||
if (d_curr->_prev != &(dest->front))
|
|
||||||
sraSpanMergePrevious(d_curr);
|
|
||||||
|
|
||||||
/* - Move on to the next span */
|
|
||||||
d_next = d_curr;
|
|
||||||
if (s_curr->end >= d_curr->end) {
|
|
||||||
d_next = d_curr->_next;
|
|
||||||
}
|
|
||||||
if (s_curr->end <= d_curr->end) {
|
|
||||||
s_curr = s_curr->_next;
|
|
||||||
}
|
|
||||||
d_curr = d_next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (d_curr != &(dest->back)) {
|
|
||||||
sraSpan *next = d_curr->_next;
|
|
||||||
sraSpanRemove(d_curr);
|
|
||||||
sraSpanDestroy(d_curr);
|
|
||||||
d_curr=next;
|
|
||||||
}
|
|
||||||
|
|
||||||
return !sraSpanListEmpty(dest);
|
|
||||||
}
|
|
||||||
|
|
||||||
static Bool
|
|
||||||
sraSpanListSubtract(sraSpanList *dest, const sraSpanList *src) {
|
|
||||||
sraSpan *d_curr, *s_curr;
|
|
||||||
|
|
||||||
if (!dest) {
|
|
||||||
if (!src) {
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
printf("sraSpanListSubtract:incompatible spans (only one NULL!)\n");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
d_curr = dest->front._next;
|
|
||||||
s_curr = src->front._next;
|
|
||||||
while ((s_curr != &(src->back)) && (d_curr != &(dest->back))) {
|
|
||||||
|
|
||||||
/* - If we haven't reached a destination span yet then move on */
|
|
||||||
if (d_curr->start >= s_curr->end) {
|
|
||||||
s_curr = s_curr->_next;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* - If we are beyond the current destination span then skip it */
|
|
||||||
if (d_curr->end <= s_curr->start) {
|
|
||||||
d_curr = d_curr->_next;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* - If we partially overlap the current span then split it up */
|
|
||||||
if (s_curr->start > d_curr->start) {
|
|
||||||
sraSpanInsertBefore(sraSpanCreate(d_curr->start,
|
|
||||||
s_curr->start,
|
|
||||||
d_curr->subspan),
|
|
||||||
d_curr);
|
|
||||||
d_curr->start = s_curr->start;
|
|
||||||
}
|
|
||||||
if (s_curr->end < d_curr->end) {
|
|
||||||
sraSpanInsertAfter(sraSpanCreate(s_curr->end,
|
|
||||||
d_curr->end,
|
|
||||||
d_curr->subspan),
|
|
||||||
d_curr);
|
|
||||||
d_curr->end = s_curr->end;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* - Now recursively process the affected span */
|
|
||||||
if ((!d_curr->subspan) || !sraSpanListSubtract(d_curr->subspan, s_curr->subspan)) {
|
|
||||||
/* - The destination subspan is now empty, so we should remove it */
|
|
||||||
sraSpan *next = d_curr->_next;
|
|
||||||
sraSpanRemove(d_curr);
|
|
||||||
sraSpanDestroy(d_curr);
|
|
||||||
d_curr = next;
|
|
||||||
} else {
|
|
||||||
/* Merge this span with previous or next? */
|
|
||||||
if (d_curr->_prev != &(dest->front))
|
|
||||||
sraSpanMergePrevious(d_curr);
|
|
||||||
if (d_curr->_next != &(dest->back))
|
|
||||||
sraSpanMergeNext(d_curr);
|
|
||||||
|
|
||||||
/* - Move on to the next span */
|
|
||||||
if (s_curr->end > d_curr->end) {
|
|
||||||
d_curr = d_curr->_next;
|
|
||||||
} else {
|
|
||||||
s_curr = s_curr->_next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return !sraSpanListEmpty(dest);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -=- Region routines */
|
|
||||||
|
|
||||||
sraRegion *
|
|
||||||
sraRgnCreate() {
|
|
||||||
return (sraRegion*)sraSpanListCreate();
|
|
||||||
}
|
|
||||||
|
|
||||||
sraRegion *
|
|
||||||
sraRgnCreateRect(int x1, int y1, int x2, int y2) {
|
|
||||||
sraSpanList *vlist, *hlist;
|
|
||||||
sraSpan *vspan, *hspan;
|
|
||||||
|
|
||||||
/* - Build the horizontal portion of the span */
|
|
||||||
hlist = sraSpanListCreate();
|
|
||||||
hspan = sraSpanCreate(x1, x2, NULL);
|
|
||||||
sraSpanInsertAfter(hspan, &(hlist->front));
|
|
||||||
|
|
||||||
/* - Build the vertical portion of the span */
|
|
||||||
vlist = sraSpanListCreate();
|
|
||||||
vspan = sraSpanCreate(y1, y2, hlist);
|
|
||||||
sraSpanInsertAfter(vspan, &(vlist->front));
|
|
||||||
|
|
||||||
sraSpanListDestroy(hlist);
|
|
||||||
|
|
||||||
return (sraRegion*)vlist;
|
|
||||||
}
|
|
||||||
|
|
||||||
sraRegion *
|
|
||||||
sraRgnCreateRgn(const sraRegion *src) {
|
|
||||||
return (sraRegion*)sraSpanListDup((sraSpanList*)src);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
sraRgnDestroy(sraRegion *rgn) {
|
|
||||||
sraSpanListDestroy((sraSpanList*)rgn);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
sraRgnMakeEmpty(sraRegion *rgn) {
|
|
||||||
sraSpanListMakeEmpty((sraSpanList*)rgn);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -=- Boolean Region ops */
|
|
||||||
|
|
||||||
Bool
|
|
||||||
sraRgnAnd(sraRegion *dst, const sraRegion *src) {
|
|
||||||
return sraSpanListAnd((sraSpanList*)dst, (sraSpanList*)src);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
sraRgnOr(sraRegion *dst, const sraRegion *src) {
|
|
||||||
sraSpanListOr((sraSpanList*)dst, (sraSpanList*)src);
|
|
||||||
}
|
|
||||||
|
|
||||||
Bool
|
|
||||||
sraRgnSubtract(sraRegion *dst, const sraRegion *src) {
|
|
||||||
return sraSpanListSubtract((sraSpanList*)dst, (sraSpanList*)src);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
sraRgnOffset(sraRegion *dst, int dx, int dy) {
|
|
||||||
sraSpan *vcurr, *hcurr;
|
|
||||||
|
|
||||||
vcurr = ((sraSpanList*)dst)->front._next;
|
|
||||||
while (vcurr != &(((sraSpanList*)dst)->back)) {
|
|
||||||
vcurr->start += dy;
|
|
||||||
vcurr->end += dy;
|
|
||||||
|
|
||||||
hcurr = vcurr->subspan->front._next;
|
|
||||||
while (hcurr != &(vcurr->subspan->back)) {
|
|
||||||
hcurr->start += dx;
|
|
||||||
hcurr->end += dx;
|
|
||||||
hcurr = hcurr->_next;
|
|
||||||
}
|
|
||||||
|
|
||||||
vcurr = vcurr->_next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sraRegion *sraRgnBBox(const sraRegion *src) {
|
|
||||||
int xmin=((unsigned int)(int)-1)>>1,ymin=xmin,xmax=1-xmin,ymax=xmax;
|
|
||||||
sraSpan *vcurr, *hcurr;
|
|
||||||
|
|
||||||
if(!src)
|
|
||||||
return sraRgnCreate();
|
|
||||||
|
|
||||||
vcurr = ((sraSpanList*)src)->front._next;
|
|
||||||
while (vcurr != &(((sraSpanList*)src)->back)) {
|
|
||||||
if(vcurr->start<ymin)
|
|
||||||
ymin=vcurr->start;
|
|
||||||
if(vcurr->end>ymax)
|
|
||||||
ymax=vcurr->end;
|
|
||||||
|
|
||||||
hcurr = vcurr->subspan->front._next;
|
|
||||||
while (hcurr != &(vcurr->subspan->back)) {
|
|
||||||
if(hcurr->start<xmin)
|
|
||||||
xmin=hcurr->start;
|
|
||||||
if(hcurr->end>xmax)
|
|
||||||
xmax=hcurr->end;
|
|
||||||
hcurr = hcurr->_next;
|
|
||||||
}
|
|
||||||
|
|
||||||
vcurr = vcurr->_next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(xmax<xmin || ymax<ymin)
|
|
||||||
return sraRgnCreate();
|
|
||||||
|
|
||||||
return sraRgnCreateRect(xmin,ymin,xmax,ymax);
|
|
||||||
}
|
|
||||||
|
|
||||||
Bool
|
|
||||||
sraRgnPopRect(sraRegion *rgn, sraRect *rect, unsigned long flags) {
|
|
||||||
sraSpan *vcurr, *hcurr;
|
|
||||||
sraSpan *vend, *hend;
|
|
||||||
Bool right2left = flags & 2;
|
|
||||||
Bool bottom2top = flags & 1;
|
|
||||||
|
|
||||||
/* - Pick correct order */
|
|
||||||
if (bottom2top) {
|
|
||||||
vcurr = ((sraSpanList*)rgn)->back._prev;
|
|
||||||
vend = &(((sraSpanList*)rgn)->front);
|
|
||||||
} else {
|
|
||||||
vcurr = ((sraSpanList*)rgn)->front._next;
|
|
||||||
vend = &(((sraSpanList*)rgn)->back);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vcurr != vend) {
|
|
||||||
rect->y1 = vcurr->start;
|
|
||||||
rect->y2 = vcurr->end;
|
|
||||||
|
|
||||||
/* - Pick correct order */
|
|
||||||
if (right2left) {
|
|
||||||
hcurr = vcurr->subspan->back._prev;
|
|
||||||
hend = &(vcurr->subspan->front);
|
|
||||||
} else {
|
|
||||||
hcurr = vcurr->subspan->front._next;
|
|
||||||
hend = &(vcurr->subspan->back);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hcurr != hend) {
|
|
||||||
rect->x1 = hcurr->start;
|
|
||||||
rect->x2 = hcurr->end;
|
|
||||||
|
|
||||||
sraSpanRemove(hcurr);
|
|
||||||
sraSpanDestroy(hcurr);
|
|
||||||
|
|
||||||
if (sraSpanListEmpty(vcurr->subspan)) {
|
|
||||||
sraSpanRemove(vcurr);
|
|
||||||
sraSpanDestroy(vcurr);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
printf("poprect:(%dx%d)-(%dx%d)\n",
|
|
||||||
rect->x1, rect->y1, rect->x2, rect->y2);
|
|
||||||
#endif
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned long
|
|
||||||
sraRgnCountRects(const sraRegion *rgn) {
|
|
||||||
unsigned long count = sraSpanListCount((sraSpanList*)rgn);
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
Bool
|
|
||||||
sraRgnEmpty(const sraRegion *rgn) {
|
|
||||||
return sraSpanListEmpty((sraSpanList*)rgn);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* iterator stuff */
|
|
||||||
sraRectangleIterator *sraRgnGetIterator(sraRegion *s)
|
|
||||||
{
|
|
||||||
/* these values have to be multiples of 4 */
|
|
||||||
#define DEFSIZE 4
|
|
||||||
#define DEFSTEP 8
|
|
||||||
sraRectangleIterator *i =
|
|
||||||
(sraRectangleIterator*)malloc(sizeof(sraRectangleIterator));
|
|
||||||
if(!i)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/* we have to recurse eventually. So, the first sPtr is the pointer to
|
|
||||||
the sraSpan in the first level. the second sPtr is the pointer to
|
|
||||||
the sraRegion.back. The third and fourth sPtr are for the second
|
|
||||||
recursion level and so on. */
|
|
||||||
i->sPtrs = (sraSpan**)malloc(sizeof(sraSpan*)*DEFSIZE);
|
|
||||||
if(!i->sPtrs) {
|
|
||||||
free(i);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
i->ptrSize = DEFSIZE;
|
|
||||||
i->sPtrs[0] = &(s->front);
|
|
||||||
i->sPtrs[1] = &(s->back);
|
|
||||||
i->ptrPos = 0;
|
|
||||||
i->reverseX = 0;
|
|
||||||
i->reverseY = 0;
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
sraRectangleIterator *sraRgnGetReverseIterator(sraRegion *s,Bool reverseX,Bool reverseY)
|
|
||||||
{
|
|
||||||
sraRectangleIterator *i = sraRgnGetIterator(s);
|
|
||||||
if(reverseY) {
|
|
||||||
i->sPtrs[1] = &(s->front);
|
|
||||||
i->sPtrs[0] = &(s->back);
|
|
||||||
}
|
|
||||||
i->reverseX = reverseX;
|
|
||||||
i->reverseY = reverseY;
|
|
||||||
return(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
static Bool sraReverse(sraRectangleIterator *i)
|
|
||||||
{
|
|
||||||
return( ((i->ptrPos&2) && i->reverseX) ||
|
|
||||||
(!(i->ptrPos&2) && i->reverseY));
|
|
||||||
}
|
|
||||||
|
|
||||||
static sraSpan* sraNextSpan(sraRectangleIterator *i)
|
|
||||||
{
|
|
||||||
if(sraReverse(i))
|
|
||||||
return(i->sPtrs[i->ptrPos]->_prev);
|
|
||||||
else
|
|
||||||
return(i->sPtrs[i->ptrPos]->_next);
|
|
||||||
}
|
|
||||||
|
|
||||||
Bool sraRgnIteratorNext(sraRectangleIterator* i,sraRect* r)
|
|
||||||
{
|
|
||||||
/* is the subspan finished? */
|
|
||||||
while(sraNextSpan(i) == i->sPtrs[i->ptrPos+1]) {
|
|
||||||
i->ptrPos -= 2;
|
|
||||||
if(i->ptrPos < 0) /* the end */
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
i->sPtrs[i->ptrPos] = sraNextSpan(i);
|
|
||||||
|
|
||||||
/* is this a new subspan? */
|
|
||||||
while(i->sPtrs[i->ptrPos]->subspan) {
|
|
||||||
if(i->ptrPos+2 > i->ptrSize) { /* array is too small */
|
|
||||||
i->ptrSize += DEFSTEP;
|
|
||||||
i->sPtrs = (sraSpan**)realloc(i->sPtrs, sizeof(sraSpan*)*i->ptrSize);
|
|
||||||
}
|
|
||||||
i->ptrPos =+ 2;
|
|
||||||
if(sraReverse(i)) {
|
|
||||||
i->sPtrs[i->ptrPos] = i->sPtrs[i->ptrPos-2]->subspan->back._prev;
|
|
||||||
i->sPtrs[i->ptrPos+1] = &(i->sPtrs[i->ptrPos-2]->subspan->front);
|
|
||||||
} else {
|
|
||||||
i->sPtrs[i->ptrPos] = i->sPtrs[i->ptrPos-2]->subspan->front._next;
|
|
||||||
i->sPtrs[i->ptrPos+1] = &(i->sPtrs[i->ptrPos-2]->subspan->back);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if((i->ptrPos%4)!=2) {
|
|
||||||
printf("sraRgnIteratorNext: offset is wrong (%d%%4!=2)\n",i->ptrPos);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
r->y1 = i->sPtrs[i->ptrPos-2]->start;
|
|
||||||
r->y2 = i->sPtrs[i->ptrPos-2]->end;
|
|
||||||
r->x1 = i->sPtrs[i->ptrPos]->start;
|
|
||||||
r->x2 = i->sPtrs[i->ptrPos]->end;
|
|
||||||
|
|
||||||
return(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void sraRgnReleaseIterator(sraRectangleIterator* i)
|
|
||||||
{
|
|
||||||
free(i->sPtrs);
|
|
||||||
free(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
sraRgnPrint(const sraRegion *rgn) {
|
|
||||||
sraSpanListPrint((sraSpanList*)rgn);
|
|
||||||
}
|
|
||||||
|
|
||||||
Bool
|
|
||||||
sraClipRect(int *x, int *y, int *w, int *h,
|
|
||||||
int cx, int cy, int cw, int ch) {
|
|
||||||
if (*x < cx) {
|
|
||||||
*w -= (cx-*x);
|
|
||||||
*x = cx;
|
|
||||||
}
|
|
||||||
if (*y < cy) {
|
|
||||||
*h -= (cy-*y);
|
|
||||||
*y = cy;
|
|
||||||
}
|
|
||||||
if (*x+*w > cx+cw) {
|
|
||||||
*w = (cx+cw)-*x;
|
|
||||||
}
|
|
||||||
if (*y+*h > cy+ch) {
|
|
||||||
*h = (cy+ch)-*y;
|
|
||||||
}
|
|
||||||
return (*w>0) && (*h>0);
|
|
||||||
}
|
|
||||||
|
|
||||||
Bool
|
|
||||||
sraClipRect2(int *x, int *y, int *x2, int *y2,
|
|
||||||
int cx, int cy, int cx2, int cy2) {
|
|
||||||
if (*x < cx)
|
|
||||||
*x = cx;
|
|
||||||
if (*y < cy)
|
|
||||||
*y = cy;
|
|
||||||
if (*x >= cx2)
|
|
||||||
*x = cx2-1;
|
|
||||||
if (*y >= cy2)
|
|
||||||
*y = cy2-1;
|
|
||||||
if (*x2 <= cx)
|
|
||||||
*x2 = cx+1;
|
|
||||||
if (*y2 <= cy)
|
|
||||||
*y2 = cy+1;
|
|
||||||
if (*x2 > cx2)
|
|
||||||
*x2 = cx2;
|
|
||||||
if (*y2 > cy2)
|
|
||||||
*y2 = cy2;
|
|
||||||
return (*x2>*x) && (*y2>*y);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* test */
|
|
||||||
|
|
||||||
#ifdef SRA_TEST
|
|
||||||
/* pipe the output to sort|uniq -u and you'll get the errors. */
|
|
||||||
int main(int argc, char** argv)
|
|
||||||
{
|
|
||||||
sraRegionPtr region, region1, region2;
|
|
||||||
sraRectangleIterator* i;
|
|
||||||
sraRect rect;
|
|
||||||
Bool b;
|
|
||||||
|
|
||||||
region = sraRgnCreateRect(10, 10, 600, 300);
|
|
||||||
region1 = sraRgnCreateRect(40, 50, 350, 200);
|
|
||||||
region2 = sraRgnCreateRect(0, 0, 20, 40);
|
|
||||||
|
|
||||||
sraRgnPrint(region);
|
|
||||||
printf("\n[(10-300)[(10-600)]]\n\n");
|
|
||||||
|
|
||||||
b = sraRgnSubtract(region, region1);
|
|
||||||
printf("%s ",b?"true":"false");
|
|
||||||
sraRgnPrint(region);
|
|
||||||
printf("\ntrue [(10-50)[(10-600)](50-200)[(10-40)(350-600)](200-300)[(10-600)]]\n\n");
|
|
||||||
|
|
||||||
sraRgnOr(region, region2);
|
|
||||||
printf("%ld\n6\n\n", sraRgnCountRects(region));
|
|
||||||
|
|
||||||
i = sraRgnGetIterator(region);
|
|
||||||
while(sraRgnIteratorNext(i, &rect))
|
|
||||||
printf("%dx%d+%d+%d ",
|
|
||||||
rect.x2-rect.x1,rect.y2-rect.y1,
|
|
||||||
rect.x1,rect.y1);
|
|
||||||
sraRgnReleaseIterator(i);
|
|
||||||
printf("\n20x10+0+0 600x30+0+10 590x10+10+40 30x150+10+50 250x150+350+50 590x100+10+200 \n\n");
|
|
||||||
|
|
||||||
i = sraRgnGetReverseIterator(region,1,0);
|
|
||||||
while(sraRgnIteratorNext(i, &rect))
|
|
||||||
printf("%dx%d+%d+%d ",
|
|
||||||
rect.x2-rect.x1,rect.y2-rect.y1,
|
|
||||||
rect.x1,rect.y1);
|
|
||||||
sraRgnReleaseIterator(i);
|
|
||||||
printf("\n20x10+0+0 600x30+0+10 590x10+10+40 250x150+350+50 30x150+10+50 590x100+10+200 \n\n");
|
|
||||||
|
|
||||||
i = sraRgnGetReverseIterator(region,1,1);
|
|
||||||
while(sraRgnIteratorNext(i, &rect))
|
|
||||||
printf("%dx%d+%d+%d ",
|
|
||||||
rect.x2-rect.x1,rect.y2-rect.y1,
|
|
||||||
rect.x1,rect.y1);
|
|
||||||
sraRgnReleaseIterator(i);
|
|
||||||
printf("\n590x100+10+200 250x150+350+50 30x150+10+50 590x10+10+40 600x30+0+10 20x10+0+0 \n\n");
|
|
||||||
|
|
||||||
sraRgnDestroy(region);
|
|
||||||
sraRgnDestroy(region1);
|
|
||||||
sraRgnDestroy(region2);
|
|
||||||
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
#endif
|
|
@ -1,65 +0,0 @@
|
|||||||
#ifndef SRAREGION_H
|
|
||||||
#define SRAREGION_H
|
|
||||||
|
|
||||||
/* -=- SRA - Simple Region Algorithm
|
|
||||||
* A simple rectangular region implementation.
|
|
||||||
* Copyright (c) 2001 James "Wez" Weatherall, Johannes E. Schindelin
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* -=- sraRect */
|
|
||||||
|
|
||||||
typedef struct _rect {
|
|
||||||
int x1;
|
|
||||||
int y1;
|
|
||||||
int x2;
|
|
||||||
int y2;
|
|
||||||
} sraRect;
|
|
||||||
|
|
||||||
typedef struct sraRegion sraRegion;
|
|
||||||
|
|
||||||
/* -=- Region manipulation functions */
|
|
||||||
|
|
||||||
extern sraRegion *sraRgnCreate();
|
|
||||||
extern sraRegion *sraRgnCreateRect(int x1, int y1, int x2, int y2);
|
|
||||||
extern sraRegion *sraRgnCreateRgn(const sraRegion *src);
|
|
||||||
|
|
||||||
extern void sraRgnDestroy(sraRegion *rgn);
|
|
||||||
extern void sraRgnMakeEmpty(sraRegion *rgn);
|
|
||||||
extern Bool sraRgnAnd(sraRegion *dst, const sraRegion *src);
|
|
||||||
extern void sraRgnOr(sraRegion *dst, const sraRegion *src);
|
|
||||||
extern Bool sraRgnSubtract(sraRegion *dst, const sraRegion *src);
|
|
||||||
|
|
||||||
extern void sraRgnOffset(sraRegion *dst, int dx, int dy);
|
|
||||||
|
|
||||||
extern Bool sraRgnPopRect(sraRegion *region, sraRect *rect,
|
|
||||||
unsigned long flags);
|
|
||||||
|
|
||||||
extern unsigned long sraRgnCountRects(const sraRegion *rgn);
|
|
||||||
extern Bool sraRgnEmpty(const sraRegion *rgn);
|
|
||||||
|
|
||||||
extern sraRegion *sraRgnBBox(const sraRegion *src);
|
|
||||||
|
|
||||||
/* -=- rectangle iterator */
|
|
||||||
|
|
||||||
typedef struct sraRectangleIterator {
|
|
||||||
Bool reverseX,reverseY;
|
|
||||||
int ptrSize,ptrPos;
|
|
||||||
struct sraSpan** sPtrs;
|
|
||||||
} sraRectangleIterator;
|
|
||||||
|
|
||||||
extern sraRectangleIterator *sraRgnGetIterator(sraRegion *s);
|
|
||||||
extern sraRectangleIterator *sraRgnGetReverseIterator(sraRegion *s,Bool reverseX,Bool reverseY);
|
|
||||||
extern Bool sraRgnIteratorNext(sraRectangleIterator *i,sraRect *r);
|
|
||||||
extern void sraRgnReleaseIterator(sraRectangleIterator *i);
|
|
||||||
|
|
||||||
void sraRgnPrint(const sraRegion *s);
|
|
||||||
|
|
||||||
/* -=- Rectangle clipper (for speed) */
|
|
||||||
|
|
||||||
extern Bool sraClipRect(int *x, int *y, int *w, int *h,
|
|
||||||
int cx, int cy, int cw, int ch);
|
|
||||||
|
|
||||||
extern Bool sraClipRect2(int *x, int *y, int *x2, int *y2,
|
|
||||||
int cx, int cy, int cx2, int cy2);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,103 +0,0 @@
|
|||||||
/*
|
|
||||||
* stats.c
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
|
|
||||||
* Original Xvnc code 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
|
||||||
* USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include "rfb.h"
|
|
||||||
|
|
||||||
static const char* encNames[] = {
|
|
||||||
"raw", "copyRect", "RRE", "[encoding 3]", "CoRRE", "hextile",
|
|
||||||
"zlib", "tight", "[encoding 8]", "[encoding 9]"
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
rfbResetStats(rfbClientPtr cl)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < MAX_ENCODINGS; i++) {
|
|
||||||
cl->rfbBytesSent[i] = 0;
|
|
||||||
cl->rfbRectanglesSent[i] = 0;
|
|
||||||
}
|
|
||||||
cl->rfbLastRectMarkersSent = 0;
|
|
||||||
cl->rfbLastRectBytesSent = 0;
|
|
||||||
cl->rfbCursorBytesSent = 0;
|
|
||||||
cl->rfbCursorUpdatesSent = 0;
|
|
||||||
cl->rfbFramebufferUpdateMessagesSent = 0;
|
|
||||||
cl->rfbRawBytesEquivalent = 0;
|
|
||||||
cl->rfbKeyEventsRcvd = 0;
|
|
||||||
cl->rfbPointerEventsRcvd = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
rfbPrintStats(rfbClientPtr cl)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
int totalRectanglesSent = 0;
|
|
||||||
int totalBytesSent = 0;
|
|
||||||
|
|
||||||
rfbLog("Statistics:\n");
|
|
||||||
|
|
||||||
if ((cl->rfbKeyEventsRcvd != 0) || (cl->rfbPointerEventsRcvd != 0))
|
|
||||||
rfbLog(" key events received %d, pointer events %d\n",
|
|
||||||
cl->rfbKeyEventsRcvd, cl->rfbPointerEventsRcvd);
|
|
||||||
|
|
||||||
for (i = 0; i < MAX_ENCODINGS; i++) {
|
|
||||||
totalRectanglesSent += cl->rfbRectanglesSent[i];
|
|
||||||
totalBytesSent += cl->rfbBytesSent[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
totalRectanglesSent += (cl->rfbCursorUpdatesSent +
|
|
||||||
cl->rfbLastRectMarkersSent);
|
|
||||||
totalBytesSent += (cl->rfbCursorBytesSent + cl->rfbLastRectBytesSent);
|
|
||||||
|
|
||||||
rfbLog(" framebuffer updates %d, rectangles %d, bytes %d\n",
|
|
||||||
cl->rfbFramebufferUpdateMessagesSent, totalRectanglesSent,
|
|
||||||
totalBytesSent);
|
|
||||||
|
|
||||||
if (cl->rfbLastRectMarkersSent != 0)
|
|
||||||
rfbLog(" LastRect markers %d, bytes %d\n",
|
|
||||||
cl->rfbLastRectMarkersSent, cl->rfbLastRectBytesSent);
|
|
||||||
|
|
||||||
if (cl->rfbCursorUpdatesSent != 0)
|
|
||||||
rfbLog(" cursor shape updates %d, bytes %d\n",
|
|
||||||
cl->rfbCursorUpdatesSent, cl->rfbCursorBytesSent);
|
|
||||||
|
|
||||||
for (i = 0; i < MAX_ENCODINGS; i++) {
|
|
||||||
if (cl->rfbRectanglesSent[i] != 0)
|
|
||||||
rfbLog(" %s rectangles %d, bytes %d\n",
|
|
||||||
encNames[i], cl->rfbRectanglesSent[i], cl->rfbBytesSent[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((totalBytesSent - cl->rfbBytesSent[rfbEncodingCopyRect]) != 0) {
|
|
||||||
rfbLog(" raw bytes equivalent %d, compression ratio %f\n",
|
|
||||||
cl->rfbRawBytesEquivalent,
|
|
||||||
(double)cl->rfbRawBytesEquivalent
|
|
||||||
/ (double)(totalBytesSent
|
|
||||||
- cl->rfbBytesSent[rfbEncodingCopyRect]-
|
|
||||||
cl->rfbCursorBytesSent -
|
|
||||||
cl->rfbLastRectBytesSent));
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,46 +0,0 @@
|
|||||||
/*
|
|
||||||
* OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
|
|
||||||
* Original Xvnc code 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
|
||||||
* USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "rfb.h"
|
|
||||||
|
|
||||||
void usage(void)
|
|
||||||
{
|
|
||||||
printf("\nusage: storepasswd <password> <filename>\n\n");
|
|
||||||
|
|
||||||
printf("Stores a password in encrypted format.\n");
|
|
||||||
printf("The resulting file can be used with the -rfbauth argument to OSXvnc.\n\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
if (argc != 3)
|
|
||||||
usage();
|
|
||||||
|
|
||||||
if (vncEncryptAndStorePasswd(argv[1], argv[2]) != 0) {
|
|
||||||
printf("storing password failed.\n");
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
printf("storing password succeeded.\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,157 +0,0 @@
|
|||||||
/*
|
|
||||||
24 bit
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
|
|
||||||
* Original Xvnc code 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
|
||||||
* USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void
|
|
||||||
rfbInitOneRGBTable24 (CARD8 *table, int inMax, int outMax, int outShift,int swap);
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
rfbInitColourMapSingleTable24(char **table, rfbPixelFormat *in,
|
|
||||||
rfbPixelFormat *out,rfbColourMap* colourMap)
|
|
||||||
{
|
|
||||||
CARD32 i, r, g, b, outValue;
|
|
||||||
CARD8 *t;
|
|
||||||
CARD8 c;
|
|
||||||
unsigned int nEntries = 1 << in->bitsPerPixel;
|
|
||||||
int shift = colourMap->is16?16:8;
|
|
||||||
|
|
||||||
if (*table) free(*table);
|
|
||||||
*table = (char *)malloc(nEntries * 3 + 1);
|
|
||||||
t = (CARD8 *)*table;
|
|
||||||
|
|
||||||
for (i = 0; i < nEntries; i++) {
|
|
||||||
r = g = b = 0;
|
|
||||||
if(i < colourMap->count) {
|
|
||||||
if(colourMap->is16) {
|
|
||||||
r = colourMap->data.shorts[3*i+0];
|
|
||||||
g = colourMap->data.shorts[3*i+1];
|
|
||||||
b = colourMap->data.shorts[3*i+2];
|
|
||||||
} else {
|
|
||||||
r = colourMap->data.bytes[3*i+0];
|
|
||||||
g = colourMap->data.bytes[3*i+1];
|
|
||||||
b = colourMap->data.bytes[3*i+2];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
outValue = ((((r * (1 + out->redMax)) >> shift) << out->redShift) |
|
|
||||||
(((g * (1 + out->greenMax)) >> shift) << out->greenShift) |
|
|
||||||
(((b * (1 + out->blueMax)) >> shift) << out->blueShift));
|
|
||||||
*(CARD32*)&t[3*i] = outValue;
|
|
||||||
if(!rfbEndianTest)
|
|
||||||
memmove(t+3*i,t+3*i+1,3);
|
|
||||||
if (out->bigEndian != in->bigEndian) {
|
|
||||||
c = t[3*i]; t[3*i] = t[3*i+2]; t[3*i+2] = c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* rfbInitTrueColourSingleTable sets up a single lookup table for truecolour
|
|
||||||
* translation.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void
|
|
||||||
rfbInitTrueColourSingleTable24 (char **table, rfbPixelFormat *in,
|
|
||||||
rfbPixelFormat *out)
|
|
||||||
{
|
|
||||||
int i,outValue;
|
|
||||||
int inRed, inGreen, inBlue, outRed, outGreen, outBlue;
|
|
||||||
CARD8 *t;
|
|
||||||
CARD8 c;
|
|
||||||
int nEntries = 1 << in->bitsPerPixel;
|
|
||||||
|
|
||||||
if (*table) free(*table);
|
|
||||||
*table = (char *)malloc(nEntries * 3 + 1);
|
|
||||||
t = (CARD8 *)*table;
|
|
||||||
|
|
||||||
for (i = 0; i < nEntries; i++) {
|
|
||||||
inRed = (i >> in->redShift) & in->redMax;
|
|
||||||
inGreen = (i >> in->greenShift) & in->greenMax;
|
|
||||||
inBlue = (i >> in->blueShift) & in->blueMax;
|
|
||||||
|
|
||||||
outRed = (inRed * out->redMax + in->redMax / 2) / in->redMax;
|
|
||||||
outGreen = (inGreen * out->greenMax + in->greenMax / 2) / in->greenMax;
|
|
||||||
outBlue = (inBlue * out->blueMax + in->blueMax / 2) / in->blueMax;
|
|
||||||
|
|
||||||
outValue = ((outRed << out->redShift) |
|
|
||||||
(outGreen << out->greenShift) |
|
|
||||||
(outBlue << out->blueShift));
|
|
||||||
*(CARD32*)&t[3*i] = outValue;
|
|
||||||
if(!rfbEndianTest)
|
|
||||||
memmove(t+3*i,t+3*i+1,3);
|
|
||||||
if (out->bigEndian != in->bigEndian) {
|
|
||||||
c = t[3*i]; t[3*i] = t[3*i+2]; t[3*i+2] = c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* rfbInitTrueColourRGBTables sets up three separate lookup tables for the
|
|
||||||
* red, green and blue values.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void
|
|
||||||
rfbInitTrueColourRGBTables24 (char **table, rfbPixelFormat *in,
|
|
||||||
rfbPixelFormat *out)
|
|
||||||
{
|
|
||||||
CARD8 *redTable;
|
|
||||||
CARD8 *greenTable;
|
|
||||||
CARD8 *blueTable;
|
|
||||||
|
|
||||||
if (*table) free(*table);
|
|
||||||
*table = (char *)malloc((in->redMax + in->greenMax + in->blueMax + 3)
|
|
||||||
* 3 + 1);
|
|
||||||
redTable = (CARD8 *)*table;
|
|
||||||
greenTable = redTable + 3*(in->redMax + 1);
|
|
||||||
blueTable = greenTable + 3*(in->greenMax + 1);
|
|
||||||
|
|
||||||
rfbInitOneRGBTable24 (redTable, in->redMax, out->redMax,
|
|
||||||
out->redShift, (out->bigEndian != in->bigEndian));
|
|
||||||
rfbInitOneRGBTable24 (greenTable, in->greenMax, out->greenMax,
|
|
||||||
out->greenShift, (out->bigEndian != in->bigEndian));
|
|
||||||
rfbInitOneRGBTable24 (blueTable, in->blueMax, out->blueMax,
|
|
||||||
out->blueShift, (out->bigEndian != in->bigEndian));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
rfbInitOneRGBTable24 (CARD8 *table, int inMax, int outMax, int outShift,
|
|
||||||
int swap)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
int nEntries = inMax + 1;
|
|
||||||
CARD32 outValue;
|
|
||||||
CARD8 c;
|
|
||||||
|
|
||||||
for (i = 0; i < nEntries; i++) {
|
|
||||||
outValue = ((i * outMax + inMax / 2) / inMax) << outShift;
|
|
||||||
*(CARD32 *)&table[3*i] = outValue;
|
|
||||||
if(!rfbEndianTest)
|
|
||||||
memmove(table+3*i,table+3*i+1,3);
|
|
||||||
if (swap) {
|
|
||||||
c = table[3*i]; table[3*i] = table[3*i+2];
|
|
||||||
table[3*i+2] = c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,84 +0,0 @@
|
|||||||
/*
|
|
||||||
* tableinitcmtemplate.c - template for initialising lookup tables for
|
|
||||||
* translation from a colour map to true colour.
|
|
||||||
*
|
|
||||||
* This file shouldn't be compiled. It is included multiple times by
|
|
||||||
* translate.c, each time with a different definition of the macro OUT.
|
|
||||||
* For each value of OUT, this file defines a function which allocates an
|
|
||||||
* appropriately sized lookup table and initialises it.
|
|
||||||
*
|
|
||||||
* I know this code isn't nice to read because of all the macros, but
|
|
||||||
* efficiency is important here.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
|
|
||||||
* Original Xvnc code 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
|
||||||
* USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if !defined(OUT)
|
|
||||||
#error "This file shouldn't be compiled."
|
|
||||||
#error "It is included as part of translate.c"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define OUT_T CONCAT2E(CARD,OUT)
|
|
||||||
#define SwapOUT(x) CONCAT2E(Swap,OUT(x))
|
|
||||||
#define rfbInitColourMapSingleTableOUT \
|
|
||||||
CONCAT2E(rfbInitColourMapSingleTable,OUT)
|
|
||||||
|
|
||||||
static void
|
|
||||||
rfbInitColourMapSingleTableOUT(char **table, rfbPixelFormat *in,
|
|
||||||
rfbPixelFormat *out,rfbColourMap* colourMap)
|
|
||||||
{
|
|
||||||
CARD32 i, r, g, b;
|
|
||||||
OUT_T *t;
|
|
||||||
CARD32 nEntries = 1 << in->bitsPerPixel;
|
|
||||||
int shift = colourMap->is16?16:8;
|
|
||||||
|
|
||||||
if (*table) free(*table);
|
|
||||||
*table = (char *)malloc(nEntries * sizeof(OUT_T));
|
|
||||||
t = (OUT_T *)*table;
|
|
||||||
|
|
||||||
for (i = 0; i < nEntries; i++) {
|
|
||||||
r = g = b = 0;
|
|
||||||
if(i < colourMap->count) {
|
|
||||||
if(colourMap->is16) {
|
|
||||||
r = colourMap->data.shorts[3*i+0];
|
|
||||||
g = colourMap->data.shorts[3*i+1];
|
|
||||||
b = colourMap->data.shorts[3*i+2];
|
|
||||||
} else {
|
|
||||||
r = colourMap->data.bytes[3*i+0];
|
|
||||||
g = colourMap->data.bytes[3*i+1];
|
|
||||||
b = colourMap->data.bytes[3*i+2];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
t[i] = ((((r * (1 + out->redMax)) >> shift) << out->redShift) |
|
|
||||||
(((g * (1 + out->greenMax)) >> shift) << out->greenShift) |
|
|
||||||
(((b * (1 + out->blueMax)) >> shift) << out->blueShift));
|
|
||||||
#if (OUT != 8)
|
|
||||||
if (out->bigEndian != in->bigEndian) {
|
|
||||||
t[i] = SwapOUT(t[i]);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef OUT_T
|
|
||||||
#undef SwapOUT
|
|
||||||
#undef rfbInitColourMapSingleTableOUT
|
|
@ -1,142 +0,0 @@
|
|||||||
/*
|
|
||||||
* tableinittctemplate.c - template for initialising lookup tables for
|
|
||||||
* truecolour to truecolour translation.
|
|
||||||
*
|
|
||||||
* This file shouldn't be compiled. It is included multiple times by
|
|
||||||
* translate.c, each time with a different definition of the macro OUT.
|
|
||||||
* For each value of OUT, this file defines two functions for initialising
|
|
||||||
* lookup tables. One is for truecolour translation using a single lookup
|
|
||||||
* table, the other is for truecolour translation using three separate
|
|
||||||
* lookup tables for the red, green and blue values.
|
|
||||||
*
|
|
||||||
* I know this code isn't nice to read because of all the macros, but
|
|
||||||
* efficiency is important here.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
|
|
||||||
* Original Xvnc code 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
|
||||||
* USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if !defined(OUT)
|
|
||||||
#error "This file shouldn't be compiled."
|
|
||||||
#error "It is included as part of translate.c"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define OUT_T CONCAT2E(CARD,OUT)
|
|
||||||
#define SwapOUT(x) CONCAT2E(Swap,OUT(x))
|
|
||||||
#define rfbInitTrueColourSingleTableOUT \
|
|
||||||
CONCAT2E(rfbInitTrueColourSingleTable,OUT)
|
|
||||||
#define rfbInitTrueColourRGBTablesOUT CONCAT2E(rfbInitTrueColourRGBTables,OUT)
|
|
||||||
#define rfbInitOneRGBTableOUT CONCAT2E(rfbInitOneRGBTable,OUT)
|
|
||||||
|
|
||||||
static void
|
|
||||||
rfbInitOneRGBTableOUT (OUT_T *table, int inMax, int outMax, int outShift,
|
|
||||||
int swap);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* rfbInitTrueColourSingleTable sets up a single lookup table for truecolour
|
|
||||||
* translation.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void
|
|
||||||
rfbInitTrueColourSingleTableOUT (char **table, rfbPixelFormat *in,
|
|
||||||
rfbPixelFormat *out)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
int inRed, inGreen, inBlue, outRed, outGreen, outBlue;
|
|
||||||
OUT_T *t;
|
|
||||||
int nEntries = 1 << in->bitsPerPixel;
|
|
||||||
|
|
||||||
if (*table) free(*table);
|
|
||||||
*table = (char *)malloc(nEntries * sizeof(OUT_T));
|
|
||||||
t = (OUT_T *)*table;
|
|
||||||
|
|
||||||
for (i = 0; i < nEntries; i++) {
|
|
||||||
inRed = (i >> in->redShift) & in->redMax;
|
|
||||||
inGreen = (i >> in->greenShift) & in->greenMax;
|
|
||||||
inBlue = (i >> in->blueShift) & in->blueMax;
|
|
||||||
|
|
||||||
outRed = (inRed * out->redMax + in->redMax / 2) / in->redMax;
|
|
||||||
outGreen = (inGreen * out->greenMax + in->greenMax / 2) / in->greenMax;
|
|
||||||
outBlue = (inBlue * out->blueMax + in->blueMax / 2) / in->blueMax;
|
|
||||||
|
|
||||||
t[i] = ((outRed << out->redShift) |
|
|
||||||
(outGreen << out->greenShift) |
|
|
||||||
(outBlue << out->blueShift));
|
|
||||||
#if (OUT != 8)
|
|
||||||
if (out->bigEndian != in->bigEndian) {
|
|
||||||
t[i] = SwapOUT(t[i]);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* rfbInitTrueColourRGBTables sets up three separate lookup tables for the
|
|
||||||
* red, green and blue values.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void
|
|
||||||
rfbInitTrueColourRGBTablesOUT (char **table, rfbPixelFormat *in,
|
|
||||||
rfbPixelFormat *out)
|
|
||||||
{
|
|
||||||
OUT_T *redTable;
|
|
||||||
OUT_T *greenTable;
|
|
||||||
OUT_T *blueTable;
|
|
||||||
|
|
||||||
if (*table) free(*table);
|
|
||||||
*table = (char *)malloc((in->redMax + in->greenMax + in->blueMax + 3)
|
|
||||||
* sizeof(OUT_T));
|
|
||||||
redTable = (OUT_T *)*table;
|
|
||||||
greenTable = redTable + in->redMax + 1;
|
|
||||||
blueTable = greenTable + in->greenMax + 1;
|
|
||||||
|
|
||||||
rfbInitOneRGBTableOUT (redTable, in->redMax, out->redMax,
|
|
||||||
out->redShift, (out->bigEndian != in->bigEndian));
|
|
||||||
rfbInitOneRGBTableOUT (greenTable, in->greenMax, out->greenMax,
|
|
||||||
out->greenShift, (out->bigEndian != in->bigEndian));
|
|
||||||
rfbInitOneRGBTableOUT (blueTable, in->blueMax, out->blueMax,
|
|
||||||
out->blueShift, (out->bigEndian != in->bigEndian));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
rfbInitOneRGBTableOUT (OUT_T *table, int inMax, int outMax, int outShift,
|
|
||||||
int swap)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
int nEntries = inMax + 1;
|
|
||||||
|
|
||||||
for (i = 0; i < nEntries; i++) {
|
|
||||||
table[i] = ((i * outMax + inMax / 2) / inMax) << outShift;
|
|
||||||
#if (OUT != 8)
|
|
||||||
if (swap) {
|
|
||||||
table[i] = SwapOUT(table[i]);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef OUT_T
|
|
||||||
#undef SwapOUT
|
|
||||||
#undef rfbInitTrueColourSingleTableOUT
|
|
||||||
#undef rfbInitTrueColourRGBTablesOUT
|
|
||||||
#undef rfbInitOneRGBTableOUT
|
|
@ -1,281 +0,0 @@
|
|||||||
/*
|
|
||||||
* tabletranstemplate.c - template for translation using lookup tables.
|
|
||||||
*
|
|
||||||
* This file shouldn't be compiled. It is included multiple times by
|
|
||||||
* translate.c, each time with different definitions of the macros IN and OUT.
|
|
||||||
*
|
|
||||||
* For each pair of values IN and OUT, this file defines two functions for
|
|
||||||
* translating a given rectangle of pixel data. One uses a single lookup
|
|
||||||
* table, and the other uses three separate lookup tables for the red, green
|
|
||||||
* and blue values.
|
|
||||||
*
|
|
||||||
* I know this code isn't nice to read because of all the macros, but
|
|
||||||
* efficiency is important here.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
|
|
||||||
* Original Xvnc code 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
|
||||||
* USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if !defined(BPP)
|
|
||||||
#error "This file shouldn't be compiled."
|
|
||||||
#error "It is included as part of translate.c"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if BPP == 24
|
|
||||||
|
|
||||||
/*
|
|
||||||
* rfbTranslateWithSingleTableINtoOUT translates a rectangle of pixel data
|
|
||||||
* using a single lookup table.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void
|
|
||||||
rfbTranslateWithSingleTable24to24 (char *table, rfbPixelFormat *in,
|
|
||||||
rfbPixelFormat *out,
|
|
||||||
char *iptr, char *optr,
|
|
||||||
int bytesBetweenInputLines,
|
|
||||||
int width, int height)
|
|
||||||
{
|
|
||||||
CARD8 *ip = (CARD8 *)iptr;
|
|
||||||
CARD8 *op = (CARD8 *)optr;
|
|
||||||
int ipextra = bytesBetweenInputLines - width * 3;
|
|
||||||
CARD8 *opLineEnd;
|
|
||||||
CARD8 *t = (CARD8 *)table;
|
|
||||||
int shift = rfbEndianTest?0:8;
|
|
||||||
CARD8 c;
|
|
||||||
|
|
||||||
while (height > 0) {
|
|
||||||
opLineEnd = op + width*3;
|
|
||||||
|
|
||||||
while (op < opLineEnd) {
|
|
||||||
*(CARD32*)op = t[((*(CARD32 *)ip)>>shift)&0x00ffffff];
|
|
||||||
if(!rfbEndianTest)
|
|
||||||
memmove(op,op+1,3);
|
|
||||||
if (out->bigEndian != in->bigEndian) {
|
|
||||||
c = op[0]; op[0] = op[2]; op[2] = c;
|
|
||||||
}
|
|
||||||
op += 3;
|
|
||||||
ip += 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
ip += ipextra;
|
|
||||||
height--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* rfbTranslateWithRGBTablesINtoOUT translates a rectangle of pixel data
|
|
||||||
* using three separate lookup tables for the red, green and blue values.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void
|
|
||||||
rfbTranslateWithRGBTables24to24 (char *table, rfbPixelFormat *in,
|
|
||||||
rfbPixelFormat *out,
|
|
||||||
char *iptr, char *optr,
|
|
||||||
int bytesBetweenInputLines,
|
|
||||||
int width, int height)
|
|
||||||
{
|
|
||||||
CARD8 *ip = (CARD8 *)iptr;
|
|
||||||
CARD8 *op = (CARD8 *)optr;
|
|
||||||
int ipextra = bytesBetweenInputLines - width*3;
|
|
||||||
CARD8 *opLineEnd;
|
|
||||||
CARD8 *redTable = (CARD8 *)table;
|
|
||||||
CARD8 *greenTable = redTable + 3*(in->redMax + 1);
|
|
||||||
CARD8 *blueTable = greenTable + 3*(in->greenMax + 1);
|
|
||||||
CARD32 outValue,inValue;
|
|
||||||
int shift = rfbEndianTest?0:8;
|
|
||||||
|
|
||||||
while (height > 0) {
|
|
||||||
opLineEnd = op+3*width;
|
|
||||||
|
|
||||||
while (op < opLineEnd) {
|
|
||||||
inValue = ((*(CARD32 *)ip)>>shift)&0x00ffffff;
|
|
||||||
outValue = (redTable[(inValue >> in->redShift) & in->redMax] |
|
|
||||||
greenTable[(inValue >> in->greenShift) & in->greenMax] |
|
|
||||||
blueTable[(inValue >> in->blueShift) & in->blueMax]);
|
|
||||||
memcpy(op,&outValue,3);
|
|
||||||
op += 3;
|
|
||||||
ip+=3;
|
|
||||||
}
|
|
||||||
ip += ipextra;
|
|
||||||
height--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#define IN_T CONCAT2E(CARD,BPP)
|
|
||||||
#define OUT_T CONCAT2E(CARD,BPP)
|
|
||||||
#define rfbTranslateWithSingleTable24toOUT \
|
|
||||||
CONCAT4E(rfbTranslateWithSingleTable,24,to,BPP)
|
|
||||||
#define rfbTranslateWithSingleTableINto24 \
|
|
||||||
CONCAT4E(rfbTranslateWithSingleTable,BPP,to,24)
|
|
||||||
#define rfbTranslateWithRGBTables24toOUT \
|
|
||||||
CONCAT4E(rfbTranslateWithRGBTables,24,to,BPP)
|
|
||||||
#define rfbTranslateWithRGBTablesINto24 \
|
|
||||||
CONCAT4E(rfbTranslateWithRGBTables,BPP,to,24)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* rfbTranslateWithSingleTableINtoOUT translates a rectangle of pixel data
|
|
||||||
* using a single lookup table.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void
|
|
||||||
rfbTranslateWithSingleTable24toOUT (char *table, rfbPixelFormat *in,
|
|
||||||
rfbPixelFormat *out,
|
|
||||||
char *iptr, char *optr,
|
|
||||||
int bytesBetweenInputLines,
|
|
||||||
int width, int height)
|
|
||||||
{
|
|
||||||
CARD8 *ip = (CARD8 *)iptr;
|
|
||||||
OUT_T *op = (OUT_T *)optr;
|
|
||||||
int ipextra = bytesBetweenInputLines - width*3;
|
|
||||||
OUT_T *opLineEnd;
|
|
||||||
OUT_T *t = (OUT_T *)table;
|
|
||||||
int shift = rfbEndianTest?0:8;
|
|
||||||
|
|
||||||
while (height > 0) {
|
|
||||||
opLineEnd = op + width;
|
|
||||||
|
|
||||||
while (op < opLineEnd) {
|
|
||||||
*(op++) = t[((*(CARD32 *)ip)>>shift)&0x00ffffff];
|
|
||||||
ip+=3;
|
|
||||||
}
|
|
||||||
|
|
||||||
ip += ipextra;
|
|
||||||
height--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* rfbTranslateWithRGBTablesINtoOUT translates a rectangle of pixel data
|
|
||||||
* using three separate lookup tables for the red, green and blue values.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void
|
|
||||||
rfbTranslateWithRGBTables24toOUT (char *table, rfbPixelFormat *in,
|
|
||||||
rfbPixelFormat *out,
|
|
||||||
char *iptr, char *optr,
|
|
||||||
int bytesBetweenInputLines,
|
|
||||||
int width, int height)
|
|
||||||
{
|
|
||||||
CARD8 *ip = (CARD8 *)iptr;
|
|
||||||
OUT_T *op = (OUT_T *)optr;
|
|
||||||
int ipextra = bytesBetweenInputLines - width*3;
|
|
||||||
OUT_T *opLineEnd;
|
|
||||||
OUT_T *redTable = (OUT_T *)table;
|
|
||||||
OUT_T *greenTable = redTable + in->redMax + 1;
|
|
||||||
OUT_T *blueTable = greenTable + in->greenMax + 1;
|
|
||||||
CARD32 inValue;
|
|
||||||
int shift = rfbEndianTest?0:8;
|
|
||||||
|
|
||||||
while (height > 0) {
|
|
||||||
opLineEnd = &op[width];
|
|
||||||
|
|
||||||
while (op < opLineEnd) {
|
|
||||||
inValue = ((*(CARD32 *)ip)>>shift)&0x00ffffff;
|
|
||||||
*(op++) = (redTable[(inValue >> in->redShift) & in->redMax] |
|
|
||||||
greenTable[(inValue >> in->greenShift) & in->greenMax] |
|
|
||||||
blueTable[(inValue >> in->blueShift) & in->blueMax]);
|
|
||||||
ip+=3;
|
|
||||||
}
|
|
||||||
ip += ipextra;
|
|
||||||
height--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* rfbTranslateWithSingleTableINto24 translates a rectangle of pixel data
|
|
||||||
* using a single lookup table.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void
|
|
||||||
rfbTranslateWithSingleTableINto24 (char *table, rfbPixelFormat *in,
|
|
||||||
rfbPixelFormat *out,
|
|
||||||
char *iptr, char *optr,
|
|
||||||
int bytesBetweenInputLines,
|
|
||||||
int width, int height)
|
|
||||||
{
|
|
||||||
IN_T *ip = (IN_T *)iptr;
|
|
||||||
CARD8 *op = (CARD8 *)optr;
|
|
||||||
int ipextra = bytesBetweenInputLines / sizeof(IN_T) - width;
|
|
||||||
CARD8 *opLineEnd;
|
|
||||||
CARD8 *t = (CARD8 *)table;
|
|
||||||
|
|
||||||
while (height > 0) {
|
|
||||||
opLineEnd = op + width * 3;
|
|
||||||
|
|
||||||
while (op < opLineEnd) {
|
|
||||||
memcpy(op,&t[3*(*(ip++))],3);
|
|
||||||
op += 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
ip += ipextra;
|
|
||||||
height--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* rfbTranslateWithRGBTablesINto24 translates a rectangle of pixel data
|
|
||||||
* using three separate lookup tables for the red, green and blue values.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void
|
|
||||||
rfbTranslateWithRGBTablesINto24 (char *table, rfbPixelFormat *in,
|
|
||||||
rfbPixelFormat *out,
|
|
||||||
char *iptr, char *optr,
|
|
||||||
int bytesBetweenInputLines,
|
|
||||||
int width, int height)
|
|
||||||
{
|
|
||||||
IN_T *ip = (IN_T *)iptr;
|
|
||||||
CARD8 *op = (CARD8 *)optr;
|
|
||||||
int ipextra = bytesBetweenInputLines / sizeof(IN_T) - width;
|
|
||||||
CARD8 *opLineEnd;
|
|
||||||
CARD8 *redTable = (CARD8 *)table;
|
|
||||||
CARD8 *greenTable = redTable + 3*(in->redMax + 1);
|
|
||||||
CARD8 *blueTable = greenTable + 3*(in->greenMax + 1);
|
|
||||||
CARD32 outValue;
|
|
||||||
|
|
||||||
while (height > 0) {
|
|
||||||
opLineEnd = op+3*width;
|
|
||||||
|
|
||||||
while (op < opLineEnd) {
|
|
||||||
outValue = (redTable[(*ip >> in->redShift) & in->redMax] |
|
|
||||||
greenTable[(*ip >> in->greenShift) & in->greenMax] |
|
|
||||||
blueTable[(*ip >> in->blueShift) & in->blueMax]);
|
|
||||||
memcpy(op,&outValue,3);
|
|
||||||
op += 3;
|
|
||||||
ip++;
|
|
||||||
}
|
|
||||||
ip += ipextra;
|
|
||||||
height--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef IN_T
|
|
||||||
#undef OUT_T
|
|
||||||
#undef rfbTranslateWithSingleTable24toOUT
|
|
||||||
#undef rfbTranslateWithRGBTables24toOUT
|
|
||||||
#undef rfbTranslateWithSingleTableINto24
|
|
||||||
#undef rfbTranslateWithRGBTablesINto24
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,117 +0,0 @@
|
|||||||
/*
|
|
||||||
* tabletranstemplate.c - template for translation using lookup tables.
|
|
||||||
*
|
|
||||||
* This file shouldn't be compiled. It is included multiple times by
|
|
||||||
* translate.c, each time with different definitions of the macros IN and OUT.
|
|
||||||
*
|
|
||||||
* For each pair of values IN and OUT, this file defines two functions for
|
|
||||||
* translating a given rectangle of pixel data. One uses a single lookup
|
|
||||||
* table, and the other uses three separate lookup tables for the red, green
|
|
||||||
* and blue values.
|
|
||||||
*
|
|
||||||
* I know this code isn't nice to read because of all the macros, but
|
|
||||||
* efficiency is important here.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
|
|
||||||
* Original Xvnc code 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
|
||||||
* USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if !defined(IN) || !defined(OUT)
|
|
||||||
#error "This file shouldn't be compiled."
|
|
||||||
#error "It is included as part of translate.c"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define IN_T CONCAT2E(CARD,IN)
|
|
||||||
#define OUT_T CONCAT2E(CARD,OUT)
|
|
||||||
#define rfbTranslateWithSingleTableINtoOUT \
|
|
||||||
CONCAT4E(rfbTranslateWithSingleTable,IN,to,OUT)
|
|
||||||
#define rfbTranslateWithRGBTablesINtoOUT \
|
|
||||||
CONCAT4E(rfbTranslateWithRGBTables,IN,to,OUT)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* rfbTranslateWithSingleTableINtoOUT translates a rectangle of pixel data
|
|
||||||
* using a single lookup table.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void
|
|
||||||
rfbTranslateWithSingleTableINtoOUT (char *table, rfbPixelFormat *in,
|
|
||||||
rfbPixelFormat *out,
|
|
||||||
char *iptr, char *optr,
|
|
||||||
int bytesBetweenInputLines,
|
|
||||||
int width, int height)
|
|
||||||
{
|
|
||||||
IN_T *ip = (IN_T *)iptr;
|
|
||||||
OUT_T *op = (OUT_T *)optr;
|
|
||||||
int ipextra = bytesBetweenInputLines / sizeof(IN_T) - width;
|
|
||||||
OUT_T *opLineEnd;
|
|
||||||
OUT_T *t = (OUT_T *)table;
|
|
||||||
|
|
||||||
while (height > 0) {
|
|
||||||
opLineEnd = op + width;
|
|
||||||
|
|
||||||
while (op < opLineEnd) {
|
|
||||||
*(op++) = t[*(ip++)];
|
|
||||||
}
|
|
||||||
|
|
||||||
ip += ipextra;
|
|
||||||
height--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* rfbTranslateWithRGBTablesINtoOUT translates a rectangle of pixel data
|
|
||||||
* using three separate lookup tables for the red, green and blue values.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void
|
|
||||||
rfbTranslateWithRGBTablesINtoOUT (char *table, rfbPixelFormat *in,
|
|
||||||
rfbPixelFormat *out,
|
|
||||||
char *iptr, char *optr,
|
|
||||||
int bytesBetweenInputLines,
|
|
||||||
int width, int height)
|
|
||||||
{
|
|
||||||
IN_T *ip = (IN_T *)iptr;
|
|
||||||
OUT_T *op = (OUT_T *)optr;
|
|
||||||
int ipextra = bytesBetweenInputLines / sizeof(IN_T) - width;
|
|
||||||
OUT_T *opLineEnd;
|
|
||||||
OUT_T *redTable = (OUT_T *)table;
|
|
||||||
OUT_T *greenTable = redTable + in->redMax + 1;
|
|
||||||
OUT_T *blueTable = greenTable + in->greenMax + 1;
|
|
||||||
|
|
||||||
while (height > 0) {
|
|
||||||
opLineEnd = &op[width];
|
|
||||||
|
|
||||||
while (op < opLineEnd) {
|
|
||||||
*(op++) = (redTable[(*ip >> in->redShift) & in->redMax] |
|
|
||||||
greenTable[(*ip >> in->greenShift) & in->greenMax] |
|
|
||||||
blueTable[(*ip >> in->blueShift) & in->blueMax]);
|
|
||||||
ip++;
|
|
||||||
}
|
|
||||||
ip += ipextra;
|
|
||||||
height--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef IN_T
|
|
||||||
#undef OUT_T
|
|
||||||
#undef rfbTranslateWithSingleTableINtoOUT
|
|
||||||
#undef rfbTranslateWithRGBTablesINtoOUT
|
|
File diff suppressed because it is too large
Load Diff
@ -1,484 +0,0 @@
|
|||||||
/*
|
|
||||||
* translate.c - translate between different pixel formats
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
|
|
||||||
* Original Xvnc code 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
|
||||||
* USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include "rfb.h"
|
|
||||||
#include "sraRegion.h"
|
|
||||||
|
|
||||||
static void PrintPixelFormat(rfbPixelFormat *pf);
|
|
||||||
static Bool rfbSetClientColourMapBGR233(rfbClientPtr cl);
|
|
||||||
|
|
||||||
Bool rfbEconomicTranslate = FALSE;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Some standard pixel formats.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static const rfbPixelFormat BGR233Format = {
|
|
||||||
8, 8, 0, 1, 7, 7, 3, 0, 3, 6, 0, 0
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Macro to compare pixel formats.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define PF_EQ(x,y) \
|
|
||||||
((x.bitsPerPixel == y.bitsPerPixel) && \
|
|
||||||
(x.depth == y.depth) && \
|
|
||||||
((x.bigEndian == y.bigEndian) || (x.bitsPerPixel == 8)) && \
|
|
||||||
(x.trueColour == y.trueColour) && \
|
|
||||||
(!x.trueColour || ((x.redMax == y.redMax) && \
|
|
||||||
(x.greenMax == y.greenMax) && \
|
|
||||||
(x.blueMax == y.blueMax) && \
|
|
||||||
(x.redShift == y.redShift) && \
|
|
||||||
(x.greenShift == y.greenShift) && \
|
|
||||||
(x.blueShift == y.blueShift))))
|
|
||||||
|
|
||||||
#define CONCAT2(a,b) a##b
|
|
||||||
#define CONCAT2E(a,b) CONCAT2(a,b)
|
|
||||||
#define CONCAT4(a,b,c,d) a##b##c##d
|
|
||||||
#define CONCAT4E(a,b,c,d) CONCAT4(a,b,c,d)
|
|
||||||
|
|
||||||
#undef OUT
|
|
||||||
#undef IN
|
|
||||||
|
|
||||||
#define OUT 8
|
|
||||||
#include "tableinitcmtemplate.c"
|
|
||||||
#include "tableinittctemplate.c"
|
|
||||||
#define IN 8
|
|
||||||
#include "tabletranstemplate.c"
|
|
||||||
#undef IN
|
|
||||||
#define IN 16
|
|
||||||
#include "tabletranstemplate.c"
|
|
||||||
#undef IN
|
|
||||||
#define IN 32
|
|
||||||
#include "tabletranstemplate.c"
|
|
||||||
#undef IN
|
|
||||||
#undef OUT
|
|
||||||
|
|
||||||
#define OUT 16
|
|
||||||
#include "tableinitcmtemplate.c"
|
|
||||||
#include "tableinittctemplate.c"
|
|
||||||
#define IN 8
|
|
||||||
#include "tabletranstemplate.c"
|
|
||||||
#undef IN
|
|
||||||
#define IN 16
|
|
||||||
#include "tabletranstemplate.c"
|
|
||||||
#undef IN
|
|
||||||
#define IN 32
|
|
||||||
#include "tabletranstemplate.c"
|
|
||||||
#undef IN
|
|
||||||
#undef OUT
|
|
||||||
|
|
||||||
#define OUT 32
|
|
||||||
#include "tableinitcmtemplate.c"
|
|
||||||
#include "tableinittctemplate.c"
|
|
||||||
#define IN 8
|
|
||||||
#include "tabletranstemplate.c"
|
|
||||||
#undef IN
|
|
||||||
#define IN 16
|
|
||||||
#include "tabletranstemplate.c"
|
|
||||||
#undef IN
|
|
||||||
#define IN 32
|
|
||||||
#include "tabletranstemplate.c"
|
|
||||||
#undef IN
|
|
||||||
#undef OUT
|
|
||||||
|
|
||||||
#ifdef ALLOW24BPP
|
|
||||||
#define COUNT_OFFSETS 4
|
|
||||||
#define BPP2OFFSET(bpp) ((bpp)/8-1)
|
|
||||||
#include "tableinit24.c"
|
|
||||||
#define BPP 8
|
|
||||||
#include "tabletrans24template.c"
|
|
||||||
#undef BPP
|
|
||||||
#define BPP 16
|
|
||||||
#include "tabletrans24template.c"
|
|
||||||
#undef BPP
|
|
||||||
#define BPP 24
|
|
||||||
#include "tabletrans24template.c"
|
|
||||||
#undef BPP
|
|
||||||
#define BPP 32
|
|
||||||
#include "tabletrans24template.c"
|
|
||||||
#undef BPP
|
|
||||||
#else
|
|
||||||
#define COUNT_OFFSETS 3
|
|
||||||
#define BPP2OFFSET(bpp) ((int)(bpp)/16)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef void (*rfbInitCMTableFnType)(char **table, rfbPixelFormat *in,
|
|
||||||
rfbPixelFormat *out,rfbColourMap* cm);
|
|
||||||
typedef void (*rfbInitTableFnType)(char **table, rfbPixelFormat *in,
|
|
||||||
rfbPixelFormat *out);
|
|
||||||
|
|
||||||
rfbInitCMTableFnType rfbInitColourMapSingleTableFns[COUNT_OFFSETS] = {
|
|
||||||
rfbInitColourMapSingleTable8,
|
|
||||||
rfbInitColourMapSingleTable16,
|
|
||||||
#ifdef ALLOW24BPP
|
|
||||||
rfbInitColourMapSingleTable24,
|
|
||||||
#endif
|
|
||||||
rfbInitColourMapSingleTable32
|
|
||||||
};
|
|
||||||
|
|
||||||
rfbInitTableFnType rfbInitTrueColourSingleTableFns[COUNT_OFFSETS] = {
|
|
||||||
rfbInitTrueColourSingleTable8,
|
|
||||||
rfbInitTrueColourSingleTable16,
|
|
||||||
#ifdef ALLOW24BPP
|
|
||||||
rfbInitTrueColourSingleTable24,
|
|
||||||
#endif
|
|
||||||
rfbInitTrueColourSingleTable32
|
|
||||||
};
|
|
||||||
|
|
||||||
rfbInitTableFnType rfbInitTrueColourRGBTablesFns[COUNT_OFFSETS] = {
|
|
||||||
rfbInitTrueColourRGBTables8,
|
|
||||||
rfbInitTrueColourRGBTables16,
|
|
||||||
#ifdef ALLOW24BPP
|
|
||||||
rfbInitTrueColourRGBTables24,
|
|
||||||
#endif
|
|
||||||
rfbInitTrueColourRGBTables32
|
|
||||||
};
|
|
||||||
|
|
||||||
rfbTranslateFnType rfbTranslateWithSingleTableFns[COUNT_OFFSETS][COUNT_OFFSETS] = {
|
|
||||||
{ rfbTranslateWithSingleTable8to8,
|
|
||||||
rfbTranslateWithSingleTable8to16,
|
|
||||||
#ifdef ALLOW24BPP
|
|
||||||
rfbTranslateWithSingleTable8to24,
|
|
||||||
#endif
|
|
||||||
rfbTranslateWithSingleTable8to32 },
|
|
||||||
{ rfbTranslateWithSingleTable16to8,
|
|
||||||
rfbTranslateWithSingleTable16to16,
|
|
||||||
#ifdef ALLOW24BPP
|
|
||||||
rfbTranslateWithSingleTable16to24,
|
|
||||||
#endif
|
|
||||||
rfbTranslateWithSingleTable16to32 },
|
|
||||||
#ifdef ALLOW24BPP
|
|
||||||
{ rfbTranslateWithSingleTable24to8,
|
|
||||||
rfbTranslateWithSingleTable24to16,
|
|
||||||
rfbTranslateWithSingleTable24to24,
|
|
||||||
rfbTranslateWithSingleTable24to32 },
|
|
||||||
#endif
|
|
||||||
{ rfbTranslateWithSingleTable32to8,
|
|
||||||
rfbTranslateWithSingleTable32to16,
|
|
||||||
#ifdef ALLOW24BPP
|
|
||||||
rfbTranslateWithSingleTable32to24,
|
|
||||||
#endif
|
|
||||||
rfbTranslateWithSingleTable32to32 }
|
|
||||||
};
|
|
||||||
|
|
||||||
rfbTranslateFnType rfbTranslateWithRGBTablesFns[COUNT_OFFSETS][COUNT_OFFSETS] = {
|
|
||||||
{ rfbTranslateWithRGBTables8to8,
|
|
||||||
rfbTranslateWithRGBTables8to16,
|
|
||||||
#ifdef ALLOW24BPP
|
|
||||||
rfbTranslateWithRGBTables8to24,
|
|
||||||
#endif
|
|
||||||
rfbTranslateWithRGBTables8to32 },
|
|
||||||
{ rfbTranslateWithRGBTables16to8,
|
|
||||||
rfbTranslateWithRGBTables16to16,
|
|
||||||
#ifdef ALLOW24BPP
|
|
||||||
rfbTranslateWithRGBTables16to24,
|
|
||||||
#endif
|
|
||||||
rfbTranslateWithRGBTables16to32 },
|
|
||||||
#ifdef ALLOW24BPP
|
|
||||||
{ rfbTranslateWithRGBTables24to8,
|
|
||||||
rfbTranslateWithRGBTables24to16,
|
|
||||||
rfbTranslateWithRGBTables24to24,
|
|
||||||
rfbTranslateWithRGBTables24to32 },
|
|
||||||
#endif
|
|
||||||
{ rfbTranslateWithRGBTables32to8,
|
|
||||||
rfbTranslateWithRGBTables32to16,
|
|
||||||
#ifdef ALLOW24BPP
|
|
||||||
rfbTranslateWithRGBTables32to24,
|
|
||||||
#endif
|
|
||||||
rfbTranslateWithRGBTables32to32 }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* rfbTranslateNone is used when no translation is required.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
rfbTranslateNone(char *table, rfbPixelFormat *in, rfbPixelFormat *out,
|
|
||||||
char *iptr, char *optr, int bytesBetweenInputLines,
|
|
||||||
int width, int height)
|
|
||||||
{
|
|
||||||
int bytesPerOutputLine = width * (out->bitsPerPixel / 8);
|
|
||||||
|
|
||||||
while (height > 0) {
|
|
||||||
memcpy(optr, iptr, bytesPerOutputLine);
|
|
||||||
iptr += bytesBetweenInputLines;
|
|
||||||
optr += bytesPerOutputLine;
|
|
||||||
height--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* rfbSetTranslateFunction sets the translation function.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Bool
|
|
||||||
rfbSetTranslateFunction(cl)
|
|
||||||
rfbClientPtr cl;
|
|
||||||
{
|
|
||||||
rfbLog("Pixel format for client %s:\n",cl->host);
|
|
||||||
PrintPixelFormat(&cl->format);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check that bits per pixel values are valid
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ((cl->screen->rfbServerFormat.bitsPerPixel != 8) &&
|
|
||||||
(cl->screen->rfbServerFormat.bitsPerPixel != 16) &&
|
|
||||||
#ifdef ALLOW24BPP
|
|
||||||
(cl->screen->rfbServerFormat.bitsPerPixel != 24) &&
|
|
||||||
#endif
|
|
||||||
(cl->screen->rfbServerFormat.bitsPerPixel != 32))
|
|
||||||
{
|
|
||||||
rfbLog("%s: server bits per pixel not 8, 16 or 32 (is %d)\n",
|
|
||||||
"rfbSetTranslateFunction",
|
|
||||||
cl->screen->rfbServerFormat.bitsPerPixel);
|
|
||||||
rfbCloseClient(cl);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((cl->format.bitsPerPixel != 8) &&
|
|
||||||
(cl->format.bitsPerPixel != 16) &&
|
|
||||||
#ifdef ALLOW24BPP
|
|
||||||
(cl->format.bitsPerPixel != 24) &&
|
|
||||||
#endif
|
|
||||||
(cl->format.bitsPerPixel != 32))
|
|
||||||
{
|
|
||||||
rfbLog("%s: client bits per pixel not 8, 16 or 32\n",
|
|
||||||
"rfbSetTranslateFunction");
|
|
||||||
rfbCloseClient(cl);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!cl->format.trueColour && (cl->format.bitsPerPixel != 8)) {
|
|
||||||
rfbLog("rfbSetTranslateFunction: client has colour map "
|
|
||||||
"but %d-bit - can only cope with 8-bit colour maps\n",
|
|
||||||
cl->format.bitsPerPixel);
|
|
||||||
rfbCloseClient(cl);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* bpp is valid, now work out how to translate
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!cl->format.trueColour) {
|
|
||||||
/*
|
|
||||||
* truecolour -> colour map
|
|
||||||
*
|
|
||||||
* Set client's colour map to BGR233, then effectively it's
|
|
||||||
* truecolour as well
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!rfbSetClientColourMapBGR233(cl))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
cl->format = BGR233Format;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* truecolour -> truecolour */
|
|
||||||
|
|
||||||
if (PF_EQ(cl->format,cl->screen->rfbServerFormat)) {
|
|
||||||
|
|
||||||
/* client & server the same */
|
|
||||||
|
|
||||||
rfbLog("no translation needed\n");
|
|
||||||
cl->translateFn = rfbTranslateNone;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((cl->screen->rfbServerFormat.bitsPerPixel < 16) ||
|
|
||||||
((!cl->screen->rfbServerFormat.trueColour || !rfbEconomicTranslate) &&
|
|
||||||
(cl->screen->rfbServerFormat.bitsPerPixel == 16))) {
|
|
||||||
|
|
||||||
/* we can use a single lookup table for <= 16 bpp */
|
|
||||||
|
|
||||||
cl->translateFn = rfbTranslateWithSingleTableFns
|
|
||||||
[BPP2OFFSET(cl->screen->rfbServerFormat.bitsPerPixel)]
|
|
||||||
[BPP2OFFSET(cl->format.bitsPerPixel)];
|
|
||||||
|
|
||||||
if(cl->screen->rfbServerFormat.trueColour)
|
|
||||||
(*rfbInitTrueColourSingleTableFns
|
|
||||||
[BPP2OFFSET(cl->format.bitsPerPixel)]) (&cl->translateLookupTable,
|
|
||||||
&(cl->screen->rfbServerFormat), &cl->format);
|
|
||||||
else
|
|
||||||
(*rfbInitColourMapSingleTableFns
|
|
||||||
[BPP2OFFSET(cl->format.bitsPerPixel)]) (&cl->translateLookupTable,
|
|
||||||
&(cl->screen->rfbServerFormat), &cl->format,&cl->screen->colourMap);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
/* otherwise we use three separate tables for red, green and blue */
|
|
||||||
|
|
||||||
cl->translateFn = rfbTranslateWithRGBTablesFns
|
|
||||||
[BPP2OFFSET(cl->screen->rfbServerFormat.bitsPerPixel)]
|
|
||||||
[BPP2OFFSET(cl->format.bitsPerPixel)];
|
|
||||||
|
|
||||||
(*rfbInitTrueColourRGBTablesFns
|
|
||||||
[BPP2OFFSET(cl->format.bitsPerPixel)]) (&cl->translateLookupTable,
|
|
||||||
&(cl->screen->rfbServerFormat), &cl->format);
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* rfbSetClientColourMapBGR233 sets the client's colour map so that it's
|
|
||||||
* just like an 8-bit BGR233 true colour client.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static Bool
|
|
||||||
rfbSetClientColourMapBGR233(cl)
|
|
||||||
rfbClientPtr cl;
|
|
||||||
{
|
|
||||||
char buf[sz_rfbSetColourMapEntriesMsg + 256 * 3 * 2];
|
|
||||||
rfbSetColourMapEntriesMsg *scme = (rfbSetColourMapEntriesMsg *)buf;
|
|
||||||
CARD16 *rgb = (CARD16 *)(&buf[sz_rfbSetColourMapEntriesMsg]);
|
|
||||||
int i, len;
|
|
||||||
int r, g, b;
|
|
||||||
|
|
||||||
if (cl->format.bitsPerPixel != 8 ) {
|
|
||||||
rfbLog("%s: client not 8 bits per pixel\n",
|
|
||||||
"rfbSetClientColourMapBGR233");
|
|
||||||
rfbCloseClient(cl);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
scme->type = rfbSetColourMapEntries;
|
|
||||||
|
|
||||||
scme->firstColour = Swap16IfLE(0);
|
|
||||||
scme->nColours = Swap16IfLE(256);
|
|
||||||
|
|
||||||
len = sz_rfbSetColourMapEntriesMsg;
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
|
|
||||||
for (b = 0; b < 4; b++) {
|
|
||||||
for (g = 0; g < 8; g++) {
|
|
||||||
for (r = 0; r < 8; r++) {
|
|
||||||
rgb[i++] = Swap16IfLE(r * 65535 / 7);
|
|
||||||
rgb[i++] = Swap16IfLE(g * 65535 / 7);
|
|
||||||
rgb[i++] = Swap16IfLE(b * 65535 / 3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
len += 256 * 3 * 2;
|
|
||||||
|
|
||||||
if (WriteExact(cl, buf, len) < 0) {
|
|
||||||
rfbLogPerror("rfbSetClientColourMapBGR233: write");
|
|
||||||
rfbCloseClient(cl);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* this function is not called very often, so it needn't be
|
|
||||||
efficient. */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* rfbSetClientColourMap is called to set the client's colour map. If the
|
|
||||||
* client is a true colour client, we simply update our own translation table
|
|
||||||
* and mark the whole screen as having been modified.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Bool
|
|
||||||
rfbSetClientColourMap(cl, firstColour, nColours)
|
|
||||||
rfbClientPtr cl;
|
|
||||||
int firstColour;
|
|
||||||
int nColours;
|
|
||||||
{
|
|
||||||
if (cl->screen->rfbServerFormat.trueColour || !cl->readyForSetColourMapEntries) {
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nColours == 0) {
|
|
||||||
nColours = cl->screen->colourMap.count;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cl->format.trueColour) {
|
|
||||||
(*rfbInitColourMapSingleTableFns
|
|
||||||
[BPP2OFFSET(cl->format.bitsPerPixel)]) (&cl->translateLookupTable,
|
|
||||||
&cl->screen->rfbServerFormat, &cl->format,&cl->screen->colourMap);
|
|
||||||
|
|
||||||
sraRgnDestroy(cl->modifiedRegion);
|
|
||||||
cl->modifiedRegion =
|
|
||||||
sraRgnCreateRect(0,0,cl->screen->width,cl->screen->height);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rfbSendSetColourMapEntries(cl, firstColour, nColours);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* rfbSetClientColourMaps sets the colour map for each RFB client.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
rfbSetClientColourMaps(rfbScreen, firstColour, nColours)
|
|
||||||
rfbScreenInfoPtr rfbScreen;
|
|
||||||
int firstColour;
|
|
||||||
int nColours;
|
|
||||||
{
|
|
||||||
rfbClientIteratorPtr i;
|
|
||||||
rfbClientPtr cl;
|
|
||||||
|
|
||||||
i = rfbGetClientIterator(rfbScreen);
|
|
||||||
while((cl = rfbClientIteratorNext(i)))
|
|
||||||
rfbSetClientColourMap(cl, firstColour, nColours);
|
|
||||||
rfbReleaseClientIterator(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
PrintPixelFormat(pf)
|
|
||||||
rfbPixelFormat *pf;
|
|
||||||
{
|
|
||||||
if (pf->bitsPerPixel == 1) {
|
|
||||||
rfbLog(" 1 bpp, %s sig bit in each byte is leftmost on the screen.\n",
|
|
||||||
(pf->bigEndian ? "most" : "least"));
|
|
||||||
} else {
|
|
||||||
rfbLog(" %d bpp, depth %d%s\n",pf->bitsPerPixel,pf->depth,
|
|
||||||
((pf->bitsPerPixel == 8) ? ""
|
|
||||||
: (pf->bigEndian ? ", big endian" : ", little endian")));
|
|
||||||
if (pf->trueColour) {
|
|
||||||
rfbLog(" true colour: max r %d g %d b %d, shift r %d g %d b %d\n",
|
|
||||||
pf->redMax, pf->greenMax, pf->blueMax,
|
|
||||||
pf->redShift, pf->greenShift, pf->blueShift);
|
|
||||||
} else {
|
|
||||||
rfbLog(" uses a colour map (not true colour).\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,171 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
|
||||||
* USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* vncauth.c - Functions for VNC password management and authentication.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <time.h>
|
|
||||||
#ifdef WIN32
|
|
||||||
#define srandom srand
|
|
||||||
#define random rand
|
|
||||||
#else
|
|
||||||
#include <sys/time.h>
|
|
||||||
#endif
|
|
||||||
#include "rfb.h"
|
|
||||||
#include "d3des.h"
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We use a fixed key to store passwords, since we assume that our local
|
|
||||||
* file system is secure but nonetheless don't want to store passwords
|
|
||||||
* as plaintext.
|
|
||||||
*/
|
|
||||||
|
|
||||||
unsigned char fixedkey[8] = {23,82,107,6,35,78,88,7};
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Encrypt a password and store it in a file. Returns 0 if successful,
|
|
||||||
* 1 if the file could not be written.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
vncEncryptAndStorePasswd(char *passwd, char *fname)
|
|
||||||
{
|
|
||||||
FILE *fp;
|
|
||||||
unsigned int i;
|
|
||||||
unsigned char encryptedPasswd[8];
|
|
||||||
|
|
||||||
if ((fp = fopen(fname,"w")) == NULL) return 1;
|
|
||||||
|
|
||||||
/* windows security sux */
|
|
||||||
#ifndef WIN32
|
|
||||||
chmod(fname, S_IRUSR|S_IWUSR);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* pad password with nulls */
|
|
||||||
|
|
||||||
for (i = 0; i < 8; i++) {
|
|
||||||
if (i < strlen(passwd)) {
|
|
||||||
encryptedPasswd[i] = passwd[i];
|
|
||||||
} else {
|
|
||||||
encryptedPasswd[i] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Do encryption in-place - this way we overwrite our copy of the plaintext
|
|
||||||
password */
|
|
||||||
|
|
||||||
deskey(fixedkey, EN0);
|
|
||||||
des(encryptedPasswd, encryptedPasswd);
|
|
||||||
|
|
||||||
for (i = 0; i < 8; i++) {
|
|
||||||
putc(encryptedPasswd[i], fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Decrypt a password from a file. Returns a pointer to a newly allocated
|
|
||||||
* string containing the password or a null pointer if the password could
|
|
||||||
* not be retrieved for some reason.
|
|
||||||
*/
|
|
||||||
|
|
||||||
char *
|
|
||||||
vncDecryptPasswdFromFile(char *fname)
|
|
||||||
{
|
|
||||||
FILE *fp;
|
|
||||||
int i, ch;
|
|
||||||
unsigned char *passwd = (unsigned char *)malloc(9);
|
|
||||||
|
|
||||||
if ((fp = fopen(fname,"r")) == NULL) return NULL;
|
|
||||||
|
|
||||||
for (i = 0; i < 8; i++) {
|
|
||||||
ch = getc(fp);
|
|
||||||
if (ch == EOF) {
|
|
||||||
fclose(fp);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
passwd[i] = ch;
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
deskey(fixedkey, DE1);
|
|
||||||
des(passwd, passwd);
|
|
||||||
|
|
||||||
passwd[8] = 0;
|
|
||||||
|
|
||||||
return (char *)passwd;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Generate CHALLENGESIZE random bytes for use in challenge-response
|
|
||||||
* authentication.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
vncRandomBytes(unsigned char *bytes)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
unsigned int seed = (unsigned int) time(0);
|
|
||||||
|
|
||||||
srandom(seed);
|
|
||||||
for (i = 0; i < CHALLENGESIZE; i++) {
|
|
||||||
bytes[i] = (unsigned char)(random() & 255);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Encrypt CHALLENGESIZE bytes in memory using a password.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
vncEncryptBytes(unsigned char *bytes, char *passwd)
|
|
||||||
{
|
|
||||||
unsigned char key[8];
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
/* key is simply password padded with nulls */
|
|
||||||
|
|
||||||
for (i = 0; i < 8; i++) {
|
|
||||||
if (i < strlen(passwd)) {
|
|
||||||
key[i] = passwd[i];
|
|
||||||
} else {
|
|
||||||
key[i] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
deskey(key, EN0);
|
|
||||||
|
|
||||||
for (i = 0; i < CHALLENGESIZE; i += 8) {
|
|
||||||
des(bytes+i, bytes+i);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,119 +0,0 @@
|
|||||||
/* This program is a simple server to show events coming from the client */
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include "rfb.h"
|
|
||||||
#include "default8x16.h"
|
|
||||||
|
|
||||||
char f[640*480];
|
|
||||||
char* keys[0x400];
|
|
||||||
|
|
||||||
int hex2number(unsigned char c)
|
|
||||||
{
|
|
||||||
if(c>'f') return(-1);
|
|
||||||
else if(c>'F')
|
|
||||||
return(10+c-'a');
|
|
||||||
else if(c>'9')
|
|
||||||
return(10+c-'A');
|
|
||||||
else
|
|
||||||
return(c-'0');
|
|
||||||
}
|
|
||||||
|
|
||||||
void read_keys()
|
|
||||||
{
|
|
||||||
int i,j,k;
|
|
||||||
char buffer[1024];
|
|
||||||
FILE* keysyms=fopen("keysym.h","r");
|
|
||||||
|
|
||||||
memset(keys,0,0x400*sizeof(char*));
|
|
||||||
|
|
||||||
if(!keysyms)
|
|
||||||
return;
|
|
||||||
|
|
||||||
while(!feof(keysyms)) {
|
|
||||||
fgets(buffer,1024,keysyms);
|
|
||||||
if(!strncmp(buffer,"#define XK_",strlen("#define XK_"))) {
|
|
||||||
for(i=strlen("#define XK_");buffer[i] && buffer[i]!=' '
|
|
||||||
&& buffer[i]!='\t';i++);
|
|
||||||
if(buffer[i]==0) /* don't support wrapped lines */
|
|
||||||
continue;
|
|
||||||
buffer[i]=0;
|
|
||||||
for(i++;buffer[i] && buffer[i]!='0';i++);
|
|
||||||
if(buffer[i]==0 || buffer[i+1]!='x') continue;
|
|
||||||
for(j=0,i+=2;(k=hex2number(buffer[i]))>=0;i++)
|
|
||||||
j=j*16+k;
|
|
||||||
if(keys[j&0x3ff]) {
|
|
||||||
char* x=malloc(1+strlen(keys[j&0x3ff])+1+strlen(buffer+strlen("#define ")));
|
|
||||||
strcpy(x,keys[j&0x3ff]);
|
|
||||||
strcat(x,",");
|
|
||||||
strcat(x,buffer+strlen("#define "));
|
|
||||||
free(keys[j&0x3ff]);
|
|
||||||
keys[j&0x3ff]=x;
|
|
||||||
} else
|
|
||||||
keys[j&0x3ff] = strdup(buffer+strlen("#define "));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
fclose(keysyms);
|
|
||||||
}
|
|
||||||
|
|
||||||
int lineHeight=16,lineY=480-16;
|
|
||||||
void output(rfbScreenInfoPtr s,char* line)
|
|
||||||
{
|
|
||||||
rfbDoCopyRect(s,0,0,640,480-lineHeight,0,-lineHeight);
|
|
||||||
rfbDrawString(s,&default8x16Font,10,lineY,line,0x01);
|
|
||||||
fprintf(stderr,"%s\n",line);
|
|
||||||
}
|
|
||||||
|
|
||||||
void dokey(Bool down,KeySym k,rfbClientPtr cl)
|
|
||||||
{
|
|
||||||
char buffer[1024];
|
|
||||||
|
|
||||||
sprintf(buffer,"%s: %s (0x%x)",
|
|
||||||
down?"down":"up",keys[k&0x3ff]?keys[k&0x3ff]:"",k);
|
|
||||||
output(cl->screen,buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void doptr(int buttonMask,int x,int y,rfbClientPtr cl)
|
|
||||||
{
|
|
||||||
char buffer[1024];
|
|
||||||
if(buttonMask) {
|
|
||||||
sprintf(buffer,"Ptr: mouse button mask 0x%x at %d,%d",buttonMask,x,y);
|
|
||||||
output(cl->screen,buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void newclient(rfbClientPtr cl)
|
|
||||||
{
|
|
||||||
char buffer[1024];
|
|
||||||
struct sockaddr_in addr;
|
|
||||||
int len=sizeof(addr),ip;
|
|
||||||
|
|
||||||
getpeername(cl->sock,&addr,&len);
|
|
||||||
ip=ntohl(addr.sin_addr.s_addr);
|
|
||||||
sprintf(buffer,"Client connected from ip %d.%d.%d.%d",
|
|
||||||
(ip>>24)&0xff,(ip>>16)&0xff,(ip>>8)&0xff,ip&0xff);
|
|
||||||
output(cl->screen,buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc,char** argv)
|
|
||||||
{
|
|
||||||
rfbScreenInfoPtr s=rfbGetScreen(&argc,argv,640,480,8,1,1);
|
|
||||||
s->colourMap.is16=FALSE;
|
|
||||||
s->colourMap.count=2;
|
|
||||||
s->colourMap.data.bytes="\xd0\xd0\xd0\x30\x01\xe0";
|
|
||||||
s->rfbServerFormat.trueColour=FALSE;
|
|
||||||
s->frameBuffer=f;
|
|
||||||
s->kbdAddEvent=dokey;
|
|
||||||
s->ptrAddEvent=doptr;
|
|
||||||
s->newClientHook=newclient;
|
|
||||||
|
|
||||||
memset(f,0,640*480);
|
|
||||||
read_keys();
|
|
||||||
rfbInitServer(s);
|
|
||||||
|
|
||||||
while(1) {
|
|
||||||
rfbProcessEvents(s,999999);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,578 +0,0 @@
|
|||||||
/* This file (x11vnc.c) is part of LibVNCServer.
|
|
||||||
It is a small clone of x0rfbserver by HexoNet, demonstrating the
|
|
||||||
capabilities of LibVNCServer.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <X11/Xlib.h>
|
|
||||||
#include <X11/keysym.h>
|
|
||||||
#include <X11/extensions/XTest.h>
|
|
||||||
#ifndef NO_SHM
|
|
||||||
#include <X11/extensions/XShm.h>
|
|
||||||
#include <sys/shm.h>
|
|
||||||
#endif
|
|
||||||
#define KEYSYM_H
|
|
||||||
#undef Bool
|
|
||||||
#define KeySym RFBKeySym
|
|
||||||
#include "rfb.h"
|
|
||||||
|
|
||||||
Display *dpy = 0;
|
|
||||||
int window;
|
|
||||||
int c=0,blockLength = 32;
|
|
||||||
int tileX=0,tileY=0,tileWidth=32,tileHeight=32*2,dontTile=TRUE;
|
|
||||||
Bool gotInput = FALSE;
|
|
||||||
Bool viewOnly = FALSE;
|
|
||||||
Bool sharedMode = FALSE;
|
|
||||||
|
|
||||||
Bool disconnectAfterFirstClient = TRUE;
|
|
||||||
|
|
||||||
/* keyboard handling */
|
|
||||||
#define KBDDEBUG
|
|
||||||
|
|
||||||
char modifiers[0x100];
|
|
||||||
KeyCode keycodes[0x100],leftShiftCode,rightShiftCode,altGrCode;
|
|
||||||
|
|
||||||
void init_keycodes()
|
|
||||||
{
|
|
||||||
KeySym key,*keymap;
|
|
||||||
int i,j,minkey,maxkey,syms_per_keycode;
|
|
||||||
|
|
||||||
memset(modifiers,-1,sizeof(modifiers));
|
|
||||||
|
|
||||||
XDisplayKeycodes(dpy,&minkey,&maxkey);
|
|
||||||
keymap=XGetKeyboardMapping(dpy,minkey,(maxkey - minkey + 1),&syms_per_keycode);
|
|
||||||
|
|
||||||
#ifdef KBDDEBUG
|
|
||||||
fprintf(stderr,"minkey=%d, maxkey=%d, syms_per_keycode=%d\n",
|
|
||||||
minkey,maxkey,syms_per_keycode);
|
|
||||||
#endif
|
|
||||||
for (i = minkey; i <= maxkey; i++)
|
|
||||||
for(j=0;j<syms_per_keycode;j++) {
|
|
||||||
key=keymap[(i-minkey)*syms_per_keycode+j];
|
|
||||||
#ifdef KBDDEBUG
|
|
||||||
fprintf(stderr,"keymap(i=0x%x,j=%d)==0x%lx\n",i,j,key);
|
|
||||||
#endif
|
|
||||||
if(key>=' ' && key<0x100 && i==XKeysymToKeycode(dpy,key)) {
|
|
||||||
keycodes[key]=i;
|
|
||||||
modifiers[key]=j;
|
|
||||||
#ifdef KBDDEBUG
|
|
||||||
fprintf(stderr,"key 0x%lx (%c): keycode=0x%x, modifier=%d\n",
|
|
||||||
key,(char)key,i,j);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
leftShiftCode=XKeysymToKeycode(dpy,XK_Shift_L);
|
|
||||||
rightShiftCode=XKeysymToKeycode(dpy,XK_Shift_R);
|
|
||||||
altGrCode=XKeysymToKeycode(dpy,XK_Mode_switch);
|
|
||||||
|
|
||||||
#ifdef KBDDEBUG
|
|
||||||
fprintf(stderr,"leftShift=0x%x, rightShift=0x%x, altGr=0x%x\n",
|
|
||||||
leftShiftCode,rightShiftCode,altGrCode);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
XFree ((char *) keymap);
|
|
||||||
}
|
|
||||||
|
|
||||||
static Bool shutDownServer=0;
|
|
||||||
|
|
||||||
/* the hooks */
|
|
||||||
|
|
||||||
void clientGone(rfbClientPtr cl)
|
|
||||||
{
|
|
||||||
shutDownServer=-1;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum rfbNewClientAction newClient(rfbClientPtr cl)
|
|
||||||
{
|
|
||||||
if(disconnectAfterFirstClient)
|
|
||||||
cl->clientGoneHook = clientGone;
|
|
||||||
if(viewOnly)
|
|
||||||
cl->clientData = (void*)-1;
|
|
||||||
else
|
|
||||||
cl->clientData = (void*)0;
|
|
||||||
return(RFB_CLIENT_ACCEPT);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define LEFTSHIFT 1
|
|
||||||
#define RIGHTSHIFT 2
|
|
||||||
#define ALTGR 4
|
|
||||||
char ModifierState = 0;
|
|
||||||
|
|
||||||
/* this function adjusts the modifiers according to mod (as from modifiers) and ModifierState */
|
|
||||||
|
|
||||||
void tweakModifiers(char mod,Bool down)
|
|
||||||
{
|
|
||||||
Bool isShift=ModifierState&(LEFTSHIFT|RIGHTSHIFT);
|
|
||||||
#ifdef KBDDEBUG
|
|
||||||
fprintf(stderr,"tweakModifiers: 0x%x %s\n",
|
|
||||||
mod,down?"down":"up");
|
|
||||||
#endif
|
|
||||||
if(mod<0) return;
|
|
||||||
if(isShift && mod!=1) {
|
|
||||||
if(ModifierState&LEFTSHIFT)
|
|
||||||
XTestFakeKeyEvent(dpy,leftShiftCode,!down,CurrentTime);
|
|
||||||
if(ModifierState&RIGHTSHIFT)
|
|
||||||
XTestFakeKeyEvent(dpy,rightShiftCode,!down,CurrentTime);
|
|
||||||
}
|
|
||||||
if(!isShift && mod==1)
|
|
||||||
XTestFakeKeyEvent(dpy,leftShiftCode,down,CurrentTime);
|
|
||||||
|
|
||||||
if(ModifierState&ALTGR && mod!=2)
|
|
||||||
XTestFakeKeyEvent(dpy,altGrCode,!down,CurrentTime);
|
|
||||||
if(!(ModifierState&ALTGR) && mod==2)
|
|
||||||
XTestFakeKeyEvent(dpy,altGrCode,down,CurrentTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
void keyboard(Bool down,KeySym keySym,rfbClientPtr cl)
|
|
||||||
{
|
|
||||||
if(((int)cl->clientData)==-1) return; /* viewOnly */
|
|
||||||
|
|
||||||
#define ADJUSTMOD(sym,state) \
|
|
||||||
if(keySym==sym) { if(down) ModifierState|=state; else ModifierState&=~state; }
|
|
||||||
|
|
||||||
ADJUSTMOD(XK_Shift_L,LEFTSHIFT)
|
|
||||||
ADJUSTMOD(XK_Shift_R,RIGHTSHIFT)
|
|
||||||
ADJUSTMOD(XK_Mode_switch,ALTGR)
|
|
||||||
|
|
||||||
#ifdef KBDDEBUG
|
|
||||||
fprintf(stderr,"keyboard: down=%s, keySym=0x%lx (%s), ModState=0x%x\n",
|
|
||||||
down?"down":"up",keySym,XKeysymToString(keySym),ModifierState);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(keySym>=' ' && keySym<0x100) {
|
|
||||||
KeyCode k;
|
|
||||||
if(down)
|
|
||||||
tweakModifiers(modifiers[keySym],True);
|
|
||||||
//tweakModifiers(modifiers[keySym],down);
|
|
||||||
//k = XKeysymToKeycode( dpy,keySym );
|
|
||||||
k = keycodes[keySym];
|
|
||||||
if(k!=NoSymbol) {
|
|
||||||
XTestFakeKeyEvent(dpy,k,down,CurrentTime);
|
|
||||||
gotInput = TRUE;
|
|
||||||
}
|
|
||||||
if(down)
|
|
||||||
tweakModifiers(modifiers[keySym],False);
|
|
||||||
gotInput = TRUE;
|
|
||||||
} else {
|
|
||||||
KeyCode k = XKeysymToKeycode( dpy,keySym );
|
|
||||||
if(k!=NoSymbol) {
|
|
||||||
XTestFakeKeyEvent(dpy,k,down,CurrentTime);
|
|
||||||
gotInput = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int oldButtonMask = 0;
|
|
||||||
|
|
||||||
void mouse(int buttonMask,int x,int y,rfbClientPtr cl)
|
|
||||||
{
|
|
||||||
int i=0;
|
|
||||||
|
|
||||||
if(((int)cl->clientData)==-1) return; /* viewOnly */
|
|
||||||
|
|
||||||
XTestFakeMotionEvent(dpy,0,x,y,CurrentTime );
|
|
||||||
while(i<5) {
|
|
||||||
if ((oldButtonMask&(1<<i))!=(buttonMask&(1<<i)))
|
|
||||||
XTestFakeButtonEvent(dpy,i+1,(buttonMask&(1<<i))?True:False,CurrentTime);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
oldButtonMask = buttonMask;
|
|
||||||
//fprintf(stderr,"-");
|
|
||||||
gotInput = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* the X11 interaction */
|
|
||||||
|
|
||||||
#ifndef NO_SHM
|
|
||||||
Bool useSHM = TRUE;
|
|
||||||
XShmSegmentInfo shminfo;
|
|
||||||
#else
|
|
||||||
Bool useSHM = FALSE;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void getImage(int bpp,Display *dpy,int xscreen,XImage **i,int x,int y,int width,int height)
|
|
||||||
{
|
|
||||||
if(width<=0) width=DisplayWidth(dpy,xscreen);
|
|
||||||
if(height<=0) height=DisplayHeight(dpy,xscreen);
|
|
||||||
if(useSHM && bpp>0) {
|
|
||||||
static Bool firstTime = TRUE;
|
|
||||||
if(firstTime) {
|
|
||||||
firstTime = FALSE;
|
|
||||||
*i = XShmCreateImage(dpy,
|
|
||||||
DefaultVisual( dpy, xscreen ),
|
|
||||||
bpp,
|
|
||||||
ZPixmap,
|
|
||||||
NULL,
|
|
||||||
&shminfo,
|
|
||||||
width,height);
|
|
||||||
|
|
||||||
if(*i == 0) {
|
|
||||||
useSHM = FALSE;
|
|
||||||
getImage(bpp,dpy,xscreen,i,x,y,width,height);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
shminfo.shmid = shmget( IPC_PRIVATE,
|
|
||||||
(*i)->bytes_per_line * (*i)->height,
|
|
||||||
IPC_CREAT | 0777 );
|
|
||||||
shminfo.shmaddr = (*i)->data = (char *) shmat( shminfo.shmid, 0, 0 );
|
|
||||||
shminfo.readOnly = False;
|
|
||||||
XShmAttach( dpy, &shminfo );
|
|
||||||
}
|
|
||||||
|
|
||||||
if(x==0 && y==0 && width==DisplayWidth(dpy,xscreen) && height==DisplayHeight(dpy,xscreen))
|
|
||||||
XShmGetImage(dpy,window,*i,0,0,AllPlanes);
|
|
||||||
else
|
|
||||||
XGetSubImage(dpy,window,x,y,width,height,AllPlanes,ZPixmap,*i,0,0);
|
|
||||||
} else {
|
|
||||||
*i = XGetImage(dpy,window,x,y,width,height,AllPlanes,ZPixmap );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void checkForImageUpdates(rfbScreenInfoPtr s,char *b,int rowstride,int x,int y,int width,int height)
|
|
||||||
{
|
|
||||||
Bool changed;
|
|
||||||
int i,j,k,l1,l2,x1,y1;
|
|
||||||
int bpp=s->bitsPerPixel/8;
|
|
||||||
|
|
||||||
for(j=0;j<height;j+=blockLength)
|
|
||||||
for(i=0;i<width;i+=blockLength) {
|
|
||||||
y1=j+blockLength; if(y1>height) y1=height;
|
|
||||||
x1=i+blockLength; if(x1>width) x1=width;
|
|
||||||
y1*=rowstride;
|
|
||||||
x1*=bpp;
|
|
||||||
changed=FALSE;
|
|
||||||
for(l1=j*rowstride,l2=(j+y)*s->paddedWidthInBytes+x*bpp;l1<y1;l1+=rowstride,l2+=s->paddedWidthInBytes)
|
|
||||||
for(k=i*bpp;k<x1;k++)
|
|
||||||
if(s->frameBuffer[l2+k]!=b[l1+k]) {
|
|
||||||
// fprintf(stderr,"changed: %d, %d\n",k,l);
|
|
||||||
changed=TRUE;
|
|
||||||
goto changed_p;
|
|
||||||
}
|
|
||||||
if(changed) {
|
|
||||||
changed_p:
|
|
||||||
for(l1+=i*bpp,l2+=i*bpp;l1<y1;l1+=rowstride,l2+=s->paddedWidthInBytes)
|
|
||||||
memcpy(/*b+l,*/s->frameBuffer+l2,b+l1,x1-i*bpp);
|
|
||||||
rfbMarkRectAsModified(s,x+i,y+j,x+i+blockLength,y+j+blockLength);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int probeX=0,probeY=0;
|
|
||||||
|
|
||||||
void probeScreen(rfbScreenInfoPtr s,int xscreen)
|
|
||||||
{
|
|
||||||
int i,j,/*pixel,i1,*/j1,
|
|
||||||
bpp=s->rfbServerFormat.bitsPerPixel/8,/*mask=(1<<bpp)-1,*/
|
|
||||||
rstride=s->paddedWidthInBytes;
|
|
||||||
XImage* im;
|
|
||||||
//fprintf(stderr,"/%d,%d",probeX,probeY);
|
|
||||||
#if 0
|
|
||||||
probeX++;
|
|
||||||
if(probeX>=tileWidth) {
|
|
||||||
probeX=0;
|
|
||||||
probeY++;
|
|
||||||
if(probeY>=tileHeight)
|
|
||||||
probeY=0;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
probeX=(rand()%tileWidth);
|
|
||||||
probeY=(rand()%tileHeight);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for(j=probeY;j<s->height;j+=tileHeight)
|
|
||||||
for(i=0/*probeX*/;i<s->width;i+=tileWidth) {
|
|
||||||
im=XGetImage(dpy,window,i,j,tileWidth/*1*/,1,AllPlanes,ZPixmap);
|
|
||||||
/* for(i1=0;i1<bpp && im->data[i1]==(s->frameBuffer+i*bpp+j*rstride)[i1];i1++);
|
|
||||||
if(i1<bpp) { */
|
|
||||||
if(memcmp(im->data,s->frameBuffer+i*bpp+j*rstride,tileWidth*bpp)) {
|
|
||||||
/* do update */
|
|
||||||
int x=i/*-probeX*/,w=(x+tileWidth>s->width)?s->width-x:tileWidth,
|
|
||||||
y=j-probeY,h=(y+tileHeight>s->height)?s->height-y:tileHeight;
|
|
||||||
|
|
||||||
XDestroyImage(im);
|
|
||||||
//getImage(bpp,dpy,xscreen,&im,x,y,w,h);
|
|
||||||
//fprintf(stderr,"GetImage(%d,%d,%d,%d)",x,y,w,h);
|
|
||||||
im = XGetImage(dpy,window,x,y,w,h,AllPlanes,ZPixmap );
|
|
||||||
for(j1=0;j1<h;j1++)
|
|
||||||
memcpy(s->frameBuffer+x*bpp+(y+j1)*rstride,
|
|
||||||
im->data+j1*im->bytes_per_line,bpp*w);
|
|
||||||
//checkForImageUpdates(s,im->data,rstride,x,y,w,h);
|
|
||||||
//if(0 && !useSHM)
|
|
||||||
XDestroyImage(im);
|
|
||||||
//memcpy(s->frameBuffer+i*bpp+j*rstride,&pixel,bpp);
|
|
||||||
rfbMarkRectAsModified(s,x,y,x+w,y+h);
|
|
||||||
//fprintf(stderr,"%d:%d:%x\n",i,j,pixel);
|
|
||||||
//fprintf(stderr,"*");
|
|
||||||
} else
|
|
||||||
XDestroyImage(im);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define LOCAL_CONTROL
|
|
||||||
|
|
||||||
#ifdef LOCAL_CONTROL
|
|
||||||
#include "1instance.c"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* the main program */
|
|
||||||
|
|
||||||
int main(int argc,char** argv)
|
|
||||||
{
|
|
||||||
//Screen *sc;
|
|
||||||
//Colormap cm;
|
|
||||||
XImage *framebufferImage;
|
|
||||||
char *backupImage;
|
|
||||||
int xscreen,i;
|
|
||||||
rfbScreenInfoPtr screen;
|
|
||||||
int maxMsecsToConnect = 5000; /* a maximum of 5 seconds to connect */
|
|
||||||
int updateCounter; /* about every 50 ms a screen update should be made. */
|
|
||||||
|
|
||||||
#ifdef LOCAL_CONTROL
|
|
||||||
char message[1024];
|
|
||||||
single_instance_struct single_instance = { "/tmp/x11vnc_control" };
|
|
||||||
|
|
||||||
open_control_file(&single_instance);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for(i=argc-1;i>0;i--)
|
|
||||||
#ifdef LOCAL_CONTROL
|
|
||||||
if(i<argc-1 && !strcmp(argv[i],"-toggleviewonly")) {
|
|
||||||
snprintf(message, sizeof(message), "t%s",argv[i+1]);
|
|
||||||
send_message(&single_instance,message);
|
|
||||||
exit(0);
|
|
||||||
} else if(!strcmp(argv[i],"-listclients")) {
|
|
||||||
fprintf(stderr,"list clients\n");
|
|
||||||
send_message(&single_instance,"l");
|
|
||||||
exit(0);
|
|
||||||
} else
|
|
||||||
#ifdef BACKCHANNEL
|
|
||||||
if(i<argc-1 && !strcmp(argv[i],"-backchannel")) {
|
|
||||||
snprintf(message, sizeof(message), "b%s",argv[i+1]);
|
|
||||||
send_message(&single_instance,message);
|
|
||||||
exit(0);
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
if(i<argc-1 && strcmp(argv[i],"-display")==0) {
|
|
||||||
fprintf(stderr,"Using display %s\n",argv[i+1]);
|
|
||||||
dpy = XOpenDisplay(argv[i+1]);
|
|
||||||
if(dpy==0) {
|
|
||||||
fprintf(stderr,"Couldn't connect to display \"%s\".\n",argv[i+1]);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
} else if(i<argc-1 && strcmp(argv[i],"-wait4client")==0) {
|
|
||||||
maxMsecsToConnect = atoi(argv[i+1]);
|
|
||||||
} else if(i<argc-1 && strcmp(argv[i],"-update")==0) {
|
|
||||||
updateCounter = atoi(argv[i+1]);
|
|
||||||
} else if(strcmp(argv[i],"-noshm")==0) {
|
|
||||||
useSHM = FALSE;
|
|
||||||
} else if(strcmp(argv[i],"-runforever")==0) {
|
|
||||||
disconnectAfterFirstClient = FALSE;
|
|
||||||
} else if(strcmp(argv[i],"-tile")==0) {
|
|
||||||
dontTile=FALSE;
|
|
||||||
} else if(strcmp(argv[i],"-viewonly")==0) {
|
|
||||||
viewOnly=TRUE;
|
|
||||||
} else if(strcmp(argv[i],"-shared")==0) {
|
|
||||||
sharedMode=TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
updateCounter = dontTile?20:1;
|
|
||||||
|
|
||||||
if(dpy==0)
|
|
||||||
dpy = XOpenDisplay("");
|
|
||||||
if(dpy==0) {
|
|
||||||
fprintf(stderr,"Couldn't open display!\n");
|
|
||||||
exit(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
xscreen = DefaultScreen(dpy);
|
|
||||||
window = RootWindow(dpy,xscreen);
|
|
||||||
//XTestGrabControl(dpy,True);
|
|
||||||
|
|
||||||
init_keycodes();
|
|
||||||
|
|
||||||
getImage(0,dpy,xscreen,&framebufferImage,0,0,-1,-1);
|
|
||||||
|
|
||||||
screen = rfbGetScreen(&argc,argv,framebufferImage->width,
|
|
||||||
framebufferImage->height,
|
|
||||||
framebufferImage->bits_per_pixel,
|
|
||||||
8,
|
|
||||||
framebufferImage->bits_per_pixel/8);
|
|
||||||
|
|
||||||
screen->paddedWidthInBytes = framebufferImage->bytes_per_line;
|
|
||||||
|
|
||||||
screen->rfbServerFormat.bitsPerPixel = framebufferImage->bits_per_pixel;
|
|
||||||
screen->rfbServerFormat.depth = framebufferImage->depth;
|
|
||||||
//rfbEndianTest = framebufferImage->bitmap_bit_order != MSBFirst;
|
|
||||||
screen->rfbServerFormat.trueColour = TRUE;
|
|
||||||
|
|
||||||
if ( screen->rfbServerFormat.bitsPerPixel == 8 ) {
|
|
||||||
if(CellsOfScreen(ScreenOfDisplay(dpy,xscreen))) {
|
|
||||||
XColor color[256];
|
|
||||||
int i;
|
|
||||||
screen->colourMap.count = 256;
|
|
||||||
screen->rfbServerFormat.trueColour = FALSE;
|
|
||||||
screen->colourMap.is16 = TRUE;
|
|
||||||
for(i=0;i<256;i++)
|
|
||||||
color[i].pixel=i;
|
|
||||||
XQueryColors(dpy,DefaultColormap(dpy,xscreen),color,256);
|
|
||||||
screen->colourMap.data.shorts = (short*)malloc(3*sizeof(short)*screen->colourMap.count);
|
|
||||||
for(i=0;i<screen->colourMap.count;i++) {
|
|
||||||
screen->colourMap.data.shorts[i*3+0] = color[i].red;
|
|
||||||
screen->colourMap.data.shorts[i*3+1] = color[i].green;
|
|
||||||
screen->colourMap.data.shorts[i*3+2] = color[i].blue;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
screen->rfbServerFormat.redShift = 0;
|
|
||||||
screen->rfbServerFormat.greenShift = 2;
|
|
||||||
screen->rfbServerFormat.blueShift = 5;
|
|
||||||
screen->rfbServerFormat.redMax = 3;
|
|
||||||
screen->rfbServerFormat.greenMax = 7;
|
|
||||||
screen->rfbServerFormat.blueMax = 3;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
screen->rfbServerFormat.redShift = 0;
|
|
||||||
if ( framebufferImage->red_mask )
|
|
||||||
while ( ! ( framebufferImage->red_mask & (1 << screen->rfbServerFormat.redShift) ) )
|
|
||||||
screen->rfbServerFormat.redShift++;
|
|
||||||
screen->rfbServerFormat.greenShift = 0;
|
|
||||||
if ( framebufferImage->green_mask )
|
|
||||||
while ( ! ( framebufferImage->green_mask & (1 << screen->rfbServerFormat.greenShift) ) )
|
|
||||||
screen->rfbServerFormat.greenShift++;
|
|
||||||
screen->rfbServerFormat.blueShift = 0;
|
|
||||||
if ( framebufferImage->blue_mask )
|
|
||||||
while ( ! ( framebufferImage->blue_mask & (1 << screen->rfbServerFormat.blueShift) ) )
|
|
||||||
screen->rfbServerFormat.blueShift++;
|
|
||||||
screen->rfbServerFormat.redMax = framebufferImage->red_mask >> screen->rfbServerFormat.redShift;
|
|
||||||
screen->rfbServerFormat.greenMax = framebufferImage->green_mask >> screen->rfbServerFormat.greenShift;
|
|
||||||
screen->rfbServerFormat.blueMax = framebufferImage->blue_mask >> screen->rfbServerFormat.blueShift;
|
|
||||||
}
|
|
||||||
|
|
||||||
backupImage = malloc(screen->height*screen->paddedWidthInBytes);
|
|
||||||
memcpy(backupImage,framebufferImage->data,screen->height*screen->paddedWidthInBytes);
|
|
||||||
|
|
||||||
screen->frameBuffer = backupImage;
|
|
||||||
screen->cursor = 0;
|
|
||||||
screen->newClientHook = newClient;
|
|
||||||
|
|
||||||
screen->kbdAddEvent = keyboard;
|
|
||||||
screen->ptrAddEvent = mouse;
|
|
||||||
|
|
||||||
if(sharedMode) {
|
|
||||||
screen->rfbAlwaysShared = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
screen->rfbDeferUpdateTime = 1;
|
|
||||||
updateCounter /= screen->rfbDeferUpdateTime;
|
|
||||||
|
|
||||||
rfbInitServer(screen);
|
|
||||||
|
|
||||||
c=0;
|
|
||||||
while(1) {
|
|
||||||
if(screen->rfbClientHead)
|
|
||||||
maxMsecsToConnect = 1<<16;
|
|
||||||
else {
|
|
||||||
maxMsecsToConnect -= screen->rfbDeferUpdateTime;
|
|
||||||
if(maxMsecsToConnect<0) {
|
|
||||||
fprintf(stderr,"Maximum time to connect reached. Exiting.\n");
|
|
||||||
XTestDiscard(dpy);
|
|
||||||
exit(2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef LOCAL_CONTROL
|
|
||||||
if(get_next_message(message,1024,&single_instance,50)) {
|
|
||||||
if(message[0]=='l' && message[1]==0) {
|
|
||||||
rfbClientPtr cl;
|
|
||||||
int i;
|
|
||||||
for(i=0,cl=screen->rfbClientHead;cl;cl=cl->next,i++)
|
|
||||||
fprintf(stderr,"%02d: %s\n",i,cl->host);
|
|
||||||
} else if(message[0]=='t') {
|
|
||||||
rfbClientPtr cl;
|
|
||||||
for(cl=screen->rfbClientHead;cl;cl=cl->next)
|
|
||||||
if(!strcmp(message+1,cl->host)) {
|
|
||||||
cl->clientData=(void*)((cl->clientData==0)?-1:0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifdef BACKCHANNEL
|
|
||||||
else if(message[0]=='b')
|
|
||||||
rfbSendBackChannel(screen,message+1,strlen(message+1));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
rfbProcessEvents(screen,-1);
|
|
||||||
if(shutDownServer) {
|
|
||||||
free(backupImage);
|
|
||||||
rfbScreenCleanup(screen);
|
|
||||||
XFree(dpy);
|
|
||||||
#ifndef NO_SHM
|
|
||||||
XShmDetach(dpy,framebufferImage);
|
|
||||||
#endif
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(dontTile) {
|
|
||||||
if(gotInput) {
|
|
||||||
gotInput = FALSE;
|
|
||||||
c=updateCounter;
|
|
||||||
} else if(screen->rfbClientHead && c++>updateCounter) {
|
|
||||||
c=0;
|
|
||||||
//fprintf(stderr,"*");
|
|
||||||
if(!useSHM)
|
|
||||||
framebufferImage->f.destroy_image(framebufferImage);
|
|
||||||
if(dontTile) {
|
|
||||||
getImage(screen->rfbServerFormat.bitsPerPixel,dpy,xscreen,&framebufferImage,0,0,screen->width,screen->height);
|
|
||||||
checkForImageUpdates(screen,framebufferImage->data,framebufferImage->bytes_per_line,
|
|
||||||
0,0,screen->width,screen->height);
|
|
||||||
} else {
|
|
||||||
/* old tile code. Eventually to be removed (TODO) */
|
|
||||||
char isRightEdge = tileX+tileWidth>=screen->width;
|
|
||||||
char isLowerEdge = tileY+tileHeight>=screen->height;
|
|
||||||
getImage(screen->rfbServerFormat.bitsPerPixel,dpy,xscreen,&framebufferImage,tileX,tileY,
|
|
||||||
isRightEdge?screen->width-tileX:tileWidth,
|
|
||||||
isLowerEdge?screen->height-tileY:tileHeight);
|
|
||||||
checkForImageUpdates(screen,framebufferImage->data,framebufferImage->bytes_per_line,
|
|
||||||
tileX,tileY,
|
|
||||||
isRightEdge?screen->width-tileX:tileWidth,
|
|
||||||
isLowerEdge?screen->height-tileY:tileHeight);
|
|
||||||
if(isRightEdge) {
|
|
||||||
tileX=0;
|
|
||||||
if(isLowerEdge)
|
|
||||||
tileY=0;
|
|
||||||
else
|
|
||||||
tileY+=tileHeight;
|
|
||||||
} else
|
|
||||||
tileX+=tileWidth;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if(c++>updateCounter) {
|
|
||||||
c=0;
|
|
||||||
probeScreen(screen,xscreen);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef WRITE_SNAPS
|
|
||||||
{
|
|
||||||
int i,j,r,g,b;
|
|
||||||
FILE* f=fopen("test.pnm","wb");
|
|
||||||
fprintf(f,"P6\n%d %d\n255\n",screen->width,screen->height);
|
|
||||||
for(j=0;j<screen->height;j++)
|
|
||||||
for(i=0;i<screen->width;i++) {
|
|
||||||
//r=screen->frameBuffer[j*screen->paddedWidthInBytes+i*2];
|
|
||||||
r=framebufferImage->data[j*screen->paddedWidthInBytes+i*2];
|
|
||||||
fputc(((r>>screen->rfbServerFormat.redShift)&screen->rfbServerFormat.redMax)*255/screen->rfbServerFormat.redMax,f);
|
|
||||||
fputc(((r>>screen->rfbServerFormat.greenShift)&screen->rfbServerFormat.greenMax)*255/screen->rfbServerFormat.greenMax,f);
|
|
||||||
fputc(((r>>screen->rfbServerFormat.blueShift)&screen->rfbServerFormat.blueMax)*255/screen->rfbServerFormat.blueMax,f);
|
|
||||||
}
|
|
||||||
fclose(f);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#ifndef NO_SHM
|
|
||||||
//XShmDetach(dpy,framebufferImage);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return(0);
|
|
||||||
}
|
|
@ -1,182 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <rfb.h>
|
|
||||||
#include <keysym.h>
|
|
||||||
#include "radon.h"
|
|
||||||
|
|
||||||
int maxx=400, maxy=400, bpp=4;
|
|
||||||
/* odd maxx doesn't work (vncviewer bug) */
|
|
||||||
|
|
||||||
/* Here we create a structure so that every client has it's own pointer */
|
|
||||||
|
|
||||||
/* turns the framebuffer black */
|
|
||||||
void blank_framebuffer(char* frame_buffer, int x1, int y1, int x2, int y2);
|
|
||||||
/* displays a red bar, a green bar, and a blue bar */
|
|
||||||
void draw_primary_colors (char* frame_buffer, int x1, int y1, int x2, int y2);
|
|
||||||
void linecount (char* frame_buffer);
|
|
||||||
/* handles mouse events */
|
|
||||||
void on_mouse_event (int buttonMask,int x,int y,rfbClientPtr cl);
|
|
||||||
/* handles keyboard events */
|
|
||||||
void on_key_press (Bool down,KeySym key,rfbClientPtr cl);
|
|
||||||
|
|
||||||
int main (int argc, char **argv)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
rfbScreenInfoPtr server;
|
|
||||||
|
|
||||||
rfbProcessSizeArguments(&maxx,&maxy,&bpp,&argc,argv);
|
|
||||||
|
|
||||||
server = rfbGetScreen (&argc, argv, maxx, maxy, 8, 3, bpp);
|
|
||||||
server->desktopName = "Zippy das wundersquirrel\'s VNC server";
|
|
||||||
server->frameBuffer = (char*)malloc(maxx*maxy*bpp);
|
|
||||||
server->rfbAlwaysShared = TRUE;
|
|
||||||
server->kbdAddEvent = on_key_press;
|
|
||||||
server->ptrAddEvent = on_mouse_event;
|
|
||||||
|
|
||||||
rfbInitServer (server);
|
|
||||||
|
|
||||||
blank_framebuffer(server->frameBuffer, 0, 0, maxx, maxy);
|
|
||||||
rfbRunEventLoop (server, -1, FALSE);
|
|
||||||
free(server->frameBuffer);
|
|
||||||
rfbScreenCleanup (server);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void blank_framebuffer(char* frame_buffer, int x1, int y1, int x2, int y2)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for (i=0; i < maxx * maxy * bpp; i++) frame_buffer[i]=(char) 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void draw_primary_colors (char* frame_buffer, int x1, int y1, int x2, int y2)
|
|
||||||
{
|
|
||||||
int i, j, current_pixel;
|
|
||||||
for (i=y1; i < y2; i++){
|
|
||||||
for (j=x1; j < x2; j++) {
|
|
||||||
current_pixel = (i*x2 + j) * bpp;
|
|
||||||
if (i < y2 ) {
|
|
||||||
frame_buffer[current_pixel+0] = (char) 128;
|
|
||||||
frame_buffer[current_pixel+1] = (char) 0;
|
|
||||||
frame_buffer[current_pixel+2] = (char) 0;
|
|
||||||
}
|
|
||||||
if (i < y2/3*2) {
|
|
||||||
frame_buffer[current_pixel+0] = (char) 0;
|
|
||||||
frame_buffer[current_pixel+1] = (char) 128;
|
|
||||||
frame_buffer[current_pixel+2] = (char) 0;
|
|
||||||
}
|
|
||||||
if (i < y2/3) {
|
|
||||||
frame_buffer[current_pixel+0] = (char) 0;
|
|
||||||
frame_buffer[current_pixel+1] = (char) 0;
|
|
||||||
frame_buffer[current_pixel+2] = (char) 128;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Dscho's versions (slower, but works for bpp != 3 or 4) */
|
|
||||||
void draw_primary_colours_generic(rfbScreenInfoPtr s,int x1,int y1,int x2,int y2)
|
|
||||||
{
|
|
||||||
rfbPixelFormat f=s->rfbServerFormat;
|
|
||||||
int i,j;
|
|
||||||
for(j=y1;j<y2;j++)
|
|
||||||
for(i=x1;i<x2;i++)
|
|
||||||
if(j<y1*2/3+y2/3)
|
|
||||||
rfbDrawPixel(s,i,j,f.redMax<<f.redShift);
|
|
||||||
else if(j<y1/3+y2*2/3)
|
|
||||||
rfbDrawPixel(s,i,j,f.greenMax<<f.greenShift);
|
|
||||||
else
|
|
||||||
rfbDrawPixel(s,i,j,f.blueMax<<f.blueShift);
|
|
||||||
}
|
|
||||||
|
|
||||||
void draw_primary_colours_generic_fast(rfbScreenInfoPtr s,int x1,int y1,int x2,int y2)
|
|
||||||
{
|
|
||||||
rfbPixelFormat f=s->rfbServerFormat;
|
|
||||||
int i,j,y3=(y1*2+y2)/3,y4=(y1+y2*2)/3;
|
|
||||||
/* draw first pixel */
|
|
||||||
rfbDrawPixel(s,x1,y1,f.redMax<<f.redShift);
|
|
||||||
rfbDrawPixel(s,x1,y3,f.greenMax<<f.greenShift);
|
|
||||||
rfbDrawPixel(s,x1,y4,f.blueMax<<f.blueShift);
|
|
||||||
/* then copy stripes */
|
|
||||||
for(j=0;j<y2-y4;j++)
|
|
||||||
for(i=x1;i<x2;i++) {
|
|
||||||
#define ADDR(x,y) s->frameBuffer+(x)*bpp+(y)*s->paddedWidthInBytes
|
|
||||||
memcpy(ADDR(i,j+y1),ADDR(x1,y1),bpp);
|
|
||||||
memcpy(ADDR(i,j+y3),ADDR(x1,y3),bpp);
|
|
||||||
memcpy(ADDR(i,j+y4),ADDR(x1,y4),bpp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void draw_primary_colours_generic_ultrafast(rfbScreenInfoPtr s,int x1,int y1,int x2,int y2)
|
|
||||||
{
|
|
||||||
rfbPixelFormat f=s->rfbServerFormat;
|
|
||||||
int i,j,y3=(y1*2+y2)/3,y4=(y1+y2*2)/3;
|
|
||||||
/* fill rectangles */
|
|
||||||
rfbFillRect(s,x1,y1,x2,y3,f.redMax<<f.redShift);
|
|
||||||
rfbFillRect(s,x1,y3,x2,y4,f.greenMax<<f.greenShift);
|
|
||||||
rfbFillRect(s,x1,y4,x2,y2,f.blueMax<<f.blueShift);
|
|
||||||
}
|
|
||||||
|
|
||||||
void linecount (char* frame_buffer)
|
|
||||||
{
|
|
||||||
int i,j,k, current_pixel;
|
|
||||||
for (i=maxy-4; i>maxy-20; i-=4)
|
|
||||||
for (j=0; j<4; j++) for (k=0; k < maxx; k++) {
|
|
||||||
current_pixel = (i*j*maxx + k) * bpp;
|
|
||||||
if (i%2 == 0) {
|
|
||||||
frame_buffer[current_pixel+0] = (char) 0;
|
|
||||||
frame_buffer[current_pixel+1] = (char) 0;
|
|
||||||
frame_buffer[current_pixel+2] = (char) 128;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i%2 == 1) {
|
|
||||||
frame_buffer[current_pixel+0] = (char) 128;
|
|
||||||
frame_buffer[current_pixel+1] = (char) 0;
|
|
||||||
frame_buffer[current_pixel+2] = (char) 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void on_key_press (Bool down,KeySym key,rfbClientPtr cl)
|
|
||||||
{
|
|
||||||
if (down) //or else the action occurs on both the press and depress
|
|
||||||
switch (key) {
|
|
||||||
|
|
||||||
case XK_b:
|
|
||||||
case XK_B:
|
|
||||||
rfbUndrawCursor(cl->screen);
|
|
||||||
blank_framebuffer(cl->screen->frameBuffer, 0, 0, maxx, maxy);
|
|
||||||
rfbDrawString(cl->screen,&radonFont,20,maxy-20,"Hello, World!",0xffffff);
|
|
||||||
rfbMarkRectAsModified(cl->screen,0, 0,maxx,maxy);
|
|
||||||
fprintf (stderr, "Framebuffer blanked\n");
|
|
||||||
break;
|
|
||||||
case XK_p:
|
|
||||||
case XK_P:
|
|
||||||
rfbUndrawCursor(cl->screen);
|
|
||||||
/* draw_primary_colors (cl->screen->frameBuffer, 0, 0, maxx, maxy); */
|
|
||||||
draw_primary_colours_generic_ultrafast (cl->screen, 0, 0, maxx, maxy);
|
|
||||||
rfbMarkRectAsModified(cl->screen,0, 0,maxx,maxy);
|
|
||||||
fprintf (stderr, "Primary colors displayed\n");
|
|
||||||
break;
|
|
||||||
case XK_Q:
|
|
||||||
case XK_q:
|
|
||||||
fprintf (stderr, "Exiting now\n");
|
|
||||||
exit(0);
|
|
||||||
case XK_C:
|
|
||||||
case XK_c:
|
|
||||||
rfbUndrawCursor(cl->screen);
|
|
||||||
rfbDrawString(cl->screen,&radonFont,20,100,"Hello, World!",0xffffff);
|
|
||||||
rfbMarkRectAsModified(cl->screen,0, 0,maxx,maxy);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
fprintf (stderr, "The %c key was pressed\n", (char) key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void on_mouse_event (int buttonMask,int x,int y,rfbClientPtr cl)
|
|
||||||
{
|
|
||||||
printf("buttonMask: %i\n"
|
|
||||||
"x: %i\n" "y: %i\n", buttonMask, x, y);
|
|
||||||
}
|
|
@ -1,304 +0,0 @@
|
|||||||
/*
|
|
||||||
* zlib.c
|
|
||||||
*
|
|
||||||
* Routines to implement zlib based encoding (deflate).
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
|
||||||
* USA.
|
|
||||||
*
|
|
||||||
* For the latest source code, please check:
|
|
||||||
*
|
|
||||||
* http://www.developVNC.org/
|
|
||||||
*
|
|
||||||
* or send email to feedback@developvnc.org.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "rfb.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* zlibBeforeBuf contains pixel data in the client's format.
|
|
||||||
* zlibAfterBuf contains the zlib (deflated) encoding version.
|
|
||||||
* If the zlib compressed/encoded version is
|
|
||||||
* larger than the raw data or if it exceeds zlibAfterBufSize then
|
|
||||||
* raw encoding is used instead.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int zlibBeforeBufSize = 0;
|
|
||||||
static char *zlibBeforeBuf = NULL;
|
|
||||||
|
|
||||||
static int zlibAfterBufSize = 0;
|
|
||||||
static char *zlibAfterBuf = NULL;
|
|
||||||
static int zlibAfterBufLen;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* rfbSendOneRectEncodingZlib - send a given rectangle using one Zlib
|
|
||||||
* rectangle encoding.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Bool
|
|
||||||
rfbSendOneRectEncodingZlib(cl, x, y, w, h)
|
|
||||||
rfbClientPtr cl;
|
|
||||||
int x, y, w, h;
|
|
||||||
{
|
|
||||||
rfbFramebufferUpdateRectHeader rect;
|
|
||||||
rfbZlibHeader hdr;
|
|
||||||
int deflateResult;
|
|
||||||
int previousOut;
|
|
||||||
int i;
|
|
||||||
char *fbptr = (cl->screen->frameBuffer + (cl->screen->paddedWidthInBytes * y)
|
|
||||||
+ (x * (cl->screen->bitsPerPixel / 8)));
|
|
||||||
|
|
||||||
int maxRawSize;
|
|
||||||
int maxCompSize;
|
|
||||||
|
|
||||||
maxRawSize = (cl->screen->width * cl->screen->height
|
|
||||||
* (cl->format.bitsPerPixel / 8));
|
|
||||||
|
|
||||||
if (zlibBeforeBufSize < maxRawSize) {
|
|
||||||
zlibBeforeBufSize = maxRawSize;
|
|
||||||
if (zlibBeforeBuf == NULL)
|
|
||||||
zlibBeforeBuf = (char *)malloc(zlibBeforeBufSize);
|
|
||||||
else
|
|
||||||
zlibBeforeBuf = (char *)realloc(zlibBeforeBuf, zlibBeforeBufSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* zlib compression is not useful for very small data sets.
|
|
||||||
* So, we just send these raw without any compression.
|
|
||||||
*/
|
|
||||||
if (( w * h * (cl->screen->bitsPerPixel / 8)) <
|
|
||||||
VNC_ENCODE_ZLIB_MIN_COMP_SIZE ) {
|
|
||||||
|
|
||||||
int result;
|
|
||||||
|
|
||||||
/* The translation function (used also by the in raw encoding)
|
|
||||||
* requires 4/2/1 byte alignment in the output buffer (which is
|
|
||||||
* updateBuf for the raw encoding) based on the bitsPerPixel of
|
|
||||||
* the viewer/client. This prevents SIGBUS errors on some
|
|
||||||
* architectures like SPARC, PARISC...
|
|
||||||
*/
|
|
||||||
if (( cl->format.bitsPerPixel > 8 ) &&
|
|
||||||
( cl->ublen % ( cl->format.bitsPerPixel / 8 )) != 0 ) {
|
|
||||||
if (!rfbSendUpdateBuf(cl))
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = rfbSendRectEncodingRaw(cl, x, y, w, h);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* zlib requires output buffer to be slightly larger than the input
|
|
||||||
* buffer, in the worst case.
|
|
||||||
*/
|
|
||||||
maxCompSize = maxRawSize + (( maxRawSize + 99 ) / 100 ) + 12;
|
|
||||||
|
|
||||||
if (zlibAfterBufSize < maxCompSize) {
|
|
||||||
zlibAfterBufSize = maxCompSize;
|
|
||||||
if (zlibAfterBuf == NULL)
|
|
||||||
zlibAfterBuf = (char *)malloc(zlibAfterBufSize);
|
|
||||||
else
|
|
||||||
zlibAfterBuf = (char *)realloc(zlibAfterBuf, zlibAfterBufSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Convert pixel data to client format.
|
|
||||||
*/
|
|
||||||
(*cl->translateFn)(cl->translateLookupTable, &cl->screen->rfbServerFormat,
|
|
||||||
&cl->format, fbptr, zlibBeforeBuf,
|
|
||||||
cl->screen->paddedWidthInBytes, w, h);
|
|
||||||
|
|
||||||
cl->compStream.next_in = ( Bytef * )zlibBeforeBuf;
|
|
||||||
cl->compStream.avail_in = w * h * (cl->format.bitsPerPixel / 8);
|
|
||||||
cl->compStream.next_out = ( Bytef * )zlibAfterBuf;
|
|
||||||
cl->compStream.avail_out = maxCompSize;
|
|
||||||
cl->compStream.data_type = Z_BINARY;
|
|
||||||
|
|
||||||
/* Initialize the deflation state. */
|
|
||||||
if ( cl->compStreamInited == FALSE ) {
|
|
||||||
|
|
||||||
cl->compStream.total_in = 0;
|
|
||||||
cl->compStream.total_out = 0;
|
|
||||||
cl->compStream.zalloc = Z_NULL;
|
|
||||||
cl->compStream.zfree = Z_NULL;
|
|
||||||
cl->compStream.opaque = Z_NULL;
|
|
||||||
|
|
||||||
deflateInit2( &(cl->compStream),
|
|
||||||
cl->zlibCompressLevel,
|
|
||||||
Z_DEFLATED,
|
|
||||||
MAX_WBITS,
|
|
||||||
MAX_MEM_LEVEL,
|
|
||||||
Z_DEFAULT_STRATEGY );
|
|
||||||
/* deflateInit( &(cl->compStream), Z_BEST_COMPRESSION ); */
|
|
||||||
/* deflateInit( &(cl->compStream), Z_BEST_SPEED ); */
|
|
||||||
cl->compStreamInited = TRUE;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
previousOut = cl->compStream.total_out;
|
|
||||||
|
|
||||||
/* Perform the compression here. */
|
|
||||||
deflateResult = deflate( &(cl->compStream), Z_SYNC_FLUSH );
|
|
||||||
|
|
||||||
/* Find the total size of the resulting compressed data. */
|
|
||||||
zlibAfterBufLen = cl->compStream.total_out - previousOut;
|
|
||||||
|
|
||||||
if ( deflateResult != Z_OK ) {
|
|
||||||
rfbLog("zlib deflation error: %s\n", cl->compStream.msg);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Note that it is not possible to switch zlib parameters based on
|
|
||||||
* the results of the compression pass. The reason is
|
|
||||||
* that we rely on the compressor and decompressor states being
|
|
||||||
* in sync. Compressing and then discarding the results would
|
|
||||||
* cause lose of synchronization.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Update statics */
|
|
||||||
cl->rfbRectanglesSent[rfbEncodingZlib]++;
|
|
||||||
cl->rfbBytesSent[rfbEncodingZlib] += (sz_rfbFramebufferUpdateRectHeader
|
|
||||||
+ sz_rfbZlibHeader + zlibAfterBufLen);
|
|
||||||
|
|
||||||
if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbZlibHeader
|
|
||||||
> UPDATE_BUF_SIZE)
|
|
||||||
{
|
|
||||||
if (!rfbSendUpdateBuf(cl))
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
rect.r.x = Swap16IfLE(x);
|
|
||||||
rect.r.y = Swap16IfLE(y);
|
|
||||||
rect.r.w = Swap16IfLE(w);
|
|
||||||
rect.r.h = Swap16IfLE(h);
|
|
||||||
rect.encoding = Swap32IfLE(rfbEncodingZlib);
|
|
||||||
|
|
||||||
memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
|
|
||||||
sz_rfbFramebufferUpdateRectHeader);
|
|
||||||
cl->ublen += sz_rfbFramebufferUpdateRectHeader;
|
|
||||||
|
|
||||||
hdr.nBytes = Swap32IfLE(zlibAfterBufLen);
|
|
||||||
|
|
||||||
memcpy(&cl->updateBuf[cl->ublen], (char *)&hdr, sz_rfbZlibHeader);
|
|
||||||
cl->ublen += sz_rfbZlibHeader;
|
|
||||||
|
|
||||||
for (i = 0; i < zlibAfterBufLen;) {
|
|
||||||
|
|
||||||
int bytesToCopy = UPDATE_BUF_SIZE - cl->ublen;
|
|
||||||
|
|
||||||
if (i + bytesToCopy > zlibAfterBufLen) {
|
|
||||||
bytesToCopy = zlibAfterBufLen - i;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(&cl->updateBuf[cl->ublen], &zlibAfterBuf[i], bytesToCopy);
|
|
||||||
|
|
||||||
cl->ublen += bytesToCopy;
|
|
||||||
i += bytesToCopy;
|
|
||||||
|
|
||||||
if (cl->ublen == UPDATE_BUF_SIZE) {
|
|
||||||
if (!rfbSendUpdateBuf(cl))
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* rfbSendRectEncodingZlib - send a given rectangle using one or more
|
|
||||||
* Zlib encoding rectangles.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Bool
|
|
||||||
rfbSendRectEncodingZlib(cl, x, y, w, h)
|
|
||||||
rfbClientPtr cl;
|
|
||||||
int x, y, w, h;
|
|
||||||
{
|
|
||||||
int maxLines;
|
|
||||||
int linesRemaining;
|
|
||||||
rfbRectangle partialRect;
|
|
||||||
|
|
||||||
partialRect.x = x;
|
|
||||||
partialRect.y = y;
|
|
||||||
partialRect.w = w;
|
|
||||||
partialRect.h = h;
|
|
||||||
|
|
||||||
/* Determine maximum pixel/scan lines allowed per rectangle. */
|
|
||||||
maxLines = ( ZLIB_MAX_SIZE(w) / w );
|
|
||||||
|
|
||||||
/* Initialize number of scan lines left to do. */
|
|
||||||
linesRemaining = h;
|
|
||||||
|
|
||||||
/* Loop until all work is done. */
|
|
||||||
while ( linesRemaining > 0 ) {
|
|
||||||
|
|
||||||
int linesToComp;
|
|
||||||
|
|
||||||
if ( maxLines < linesRemaining )
|
|
||||||
linesToComp = maxLines;
|
|
||||||
else
|
|
||||||
linesToComp = linesRemaining;
|
|
||||||
|
|
||||||
partialRect.h = linesToComp;
|
|
||||||
|
|
||||||
/* Encode (compress) and send the next rectangle. */
|
|
||||||
if ( ! rfbSendOneRectEncodingZlib( cl,
|
|
||||||
partialRect.x,
|
|
||||||
partialRect.y,
|
|
||||||
partialRect.w,
|
|
||||||
partialRect.h )) {
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Technically, flushing the buffer here is not extrememly
|
|
||||||
* efficient. However, this improves the overall throughput
|
|
||||||
* of the system over very slow networks. By flushing
|
|
||||||
* the buffer with every maximum size zlib rectangle, we
|
|
||||||
* improve the pipelining usage of the server CPU, network,
|
|
||||||
* and viewer CPU components. Insuring that these components
|
|
||||||
* are working in parallel actually improves the performance
|
|
||||||
* seen by the user.
|
|
||||||
* Since, zlib is most useful for slow networks, this flush
|
|
||||||
* is appropriate for the desired behavior of the zlib encoding.
|
|
||||||
*/
|
|
||||||
if (( cl->ublen > 0 ) &&
|
|
||||||
( linesToComp == maxLines )) {
|
|
||||||
if (!rfbSendUpdateBuf(cl)) {
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Update remaining and incremental rectangle location. */
|
|
||||||
linesRemaining -= linesToComp;
|
|
||||||
partialRect.y += linesToComp;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in new issue