2 * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
4 * This is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This software is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this software; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
21 * vncviewer.c - the Xt-based VNC viewer.
24 #ifdef __STRICT_ANSI__
32 #include <rfb/rfbclient.h>
34 static void Dummy(rfbClient* client) {
36 static rfbBool DummyPoint(rfbClient* client, int x, int y) {
39 static void DummyRect(rfbClient* client, int x, int y, int w, int h) {
43 static char* NoPassword(rfbClient* client) {
51 static char* ReadPassword(rfbClient* client) {
54 rfbClientErr("ReadPassword on MinGW32 NOT IMPLEMENTED\n");
55 return NoPassword(client);
59 struct termios save,noecho;
61 if(tcgetattr(fileno(stdin),&save)!=0) return p;
62 noecho=save; noecho.c_lflag &= ~ECHO;
63 if(tcsetattr(fileno(stdin),TCSAFLUSH,&noecho)!=0) return p;
64 fprintf(stderr,"Password: ");
76 tcsetattr(fileno(stdin),TCSAFLUSH,&save);
80 static rfbBool MallocFrameBuffer(rfbClient* client) {
81 if(client->frameBuffer)
82 free(client->frameBuffer);
83 client->frameBuffer=malloc(client->width*client->height*client->format.bitsPerPixel/8);
84 return client->frameBuffer?TRUE:FALSE;
87 static void initAppData(AppData* data) {
88 data->shareDesktop=TRUE;
90 data->encodingsString="tight zrle ultra copyrect hextile zlib corre rre raw";
91 data->useBGR233=FALSE;
93 data->forceOwnCmap=FALSE;
94 data->forceTrueColour=FALSE;
95 data->requestedDepth=0;
96 data->compressLevel=3;
98 #ifdef LIBVNCSERVER_HAVE_LIBJPEG
99 data->enableJPEG=TRUE;
101 data->enableJPEG=FALSE;
103 data->useRemoteCursor=FALSE;
106 rfbClient* rfbGetClient(int bitsPerSample,int samplesPerPixel,
108 rfbClient* client=(rfbClient*)calloc(sizeof(rfbClient),1);
110 rfbClientErr("Couldn't allocate client structure!\n");
113 initAppData(&client->appData);
114 client->programName = NULL;
115 client->endianTest = 1;
116 client->programName="";
117 client->serverHost="";
118 client->serverPort=5900;
120 client->CurrentKeyboardLedState = 0;
121 client->HandleKeyboardLedState = (HandleKeyboardLedStateProc)DummyPoint;
123 /* default: use complete frame buffer */
124 client->updateRect.x = -1;
126 client->format.bitsPerPixel = bytesPerPixel*8;
127 client->format.depth = bitsPerSample*samplesPerPixel;
128 client->appData.requestedDepth=client->format.depth;
129 client->format.bigEndian = *(char *)&client->endianTest?FALSE:TRUE;
130 client->format.trueColour = TRUE;
132 if (client->format.bitsPerPixel == 8) {
133 client->format.redMax = 7;
134 client->format.greenMax = 7;
135 client->format.blueMax = 3;
136 client->format.redShift = 0;
137 client->format.greenShift = 3;
138 client->format.blueShift = 6;
140 client->format.redMax = (1 << bitsPerSample) - 1;
141 client->format.greenMax = (1 << bitsPerSample) - 1;
142 client->format.blueMax = (1 << bitsPerSample) - 1;
143 if(!client->format.bigEndian) {
144 client->format.redShift = 0;
145 client->format.greenShift = bitsPerSample;
146 client->format.blueShift = bitsPerSample * 2;
148 if(client->format.bitsPerPixel==8*3) {
149 client->format.redShift = bitsPerSample*2;
150 client->format.greenShift = bitsPerSample*1;
151 client->format.blueShift = 0;
153 client->format.redShift = bitsPerSample*3;
154 client->format.greenShift = bitsPerSample*2;
155 client->format.blueShift = bitsPerSample;
160 client->bufoutptr=client->buf;
163 #ifdef LIBVNCSERVER_HAVE_LIBZ
164 client->raw_buffer_size = -1;
165 client->decompStreamInited = FALSE;
167 #ifdef LIBVNCSERVER_HAVE_LIBJPEG
168 memset(client->zlibStreamActive,0,sizeof(rfbBool)*4);
169 client->jpegSrcManager = NULL;
173 client->HandleCursorPos = DummyPoint;
174 client->SoftCursorLockArea = DummyRect;
175 client->SoftCursorUnlockScreen = Dummy;
176 client->GotFrameBufferUpdate = DummyRect;
177 client->GetPassword = ReadPassword;
178 client->MallocFrameBuffer = MallocFrameBuffer;
179 client->Bell = Dummy;
180 client->CurrentKeyboardLedState = 0;
181 client->HandleKeyboardLedState = (HandleKeyboardLedStateProc)DummyPoint;
186 static rfbBool rfbInitConnection(rfbClient* client)
188 /* Unless we accepted an incoming connection, make a TCP connection to the
191 if (!client->listenSpecified) {
192 if (!client->serverHost || !ConnectToRFBServer(client,client->serverHost,client->serverPort))
196 /* Initialise the VNC connection, including reading the password */
198 if (!InitialiseRFBConnection(client))
201 if (!SetFormatAndEncodings(client))
204 client->width=client->si.framebufferWidth;
205 client->height=client->si.framebufferHeight;
206 client->MallocFrameBuffer(client);
208 if (client->updateRect.x < 0) {
209 client->updateRect.x = client->updateRect.y = 0;
210 client->updateRect.w = client->width;
211 client->updateRect.h = client->height;
214 if (client->appData.scaleSetting>1)
216 if (!SendScaleSetting(client, client->appData.scaleSetting))
218 if (!SendFramebufferUpdateRequest(client,
219 client->updateRect.x / client->appData.scaleSetting,
220 client->updateRect.y / client->appData.scaleSetting,
221 client->updateRect.w / client->appData.scaleSetting,
222 client->updateRect.h / client->appData.scaleSetting,
228 if (!SendFramebufferUpdateRequest(client,
229 client->updateRect.x, client->updateRect.y,
230 client->updateRect.w, client->updateRect.h,
238 rfbBool rfbInitClient(rfbClient* client,int* argc,char** argv) {
241 if(argv && argc && *argc) {
242 if(client->programName==0)
243 client->programName=argv[0];
245 for (i = 1; i < *argc; i++) {
247 if (strcmp(argv[i], "-listen") == 0) {
248 listenForIncomingConnections(client);
250 } else if (strcmp(argv[i], "-play") == 0) {
251 client->serverPort = -1;
253 } else if (i+1<*argc && strcmp(argv[i], "-encodings") == 0) {
254 client->appData.encodingsString = argv[i+1];
256 } else if (i+1<*argc && strcmp(argv[i], "-compress") == 0) {
257 client->appData.compressLevel = atoi(argv[i+1]);
259 } else if (i+1<*argc && strcmp(argv[i], "-quality") == 0) {
260 client->appData.qualityLevel = atoi(argv[i+1]);
262 } else if (i+1<*argc && strcmp(argv[i], "-scale") == 0) {
263 client->appData.scaleSetting = atoi(argv[i+1]);
266 char* colon=strchr(argv[i],':');
269 client->serverHost=strdup(argv[i]);
270 client->serverHost[(int)(colon-argv[i])]='\0';
271 client->serverPort=atoi(colon+1);
273 client->serverHost=strdup(argv[i]);
275 if(client->serverPort>=0 && client->serverPort<5900)
276 client->serverPort+=5900;
278 /* purge arguments */
281 memmove(argv+i,argv+j,(*argc-i)*sizeof(char*));
285 } else if(client->listenSpecified) {
286 listenForIncomingConnections(client);
289 if(!rfbInitConnection(client)) {
290 rfbClientCleanup(client);
297 void rfbClientCleanup(rfbClient* client) {
298 #ifdef LIBVNCSERVER_HAVE_LIBZ
299 #ifdef LIBVNCSERVER_HAVE_LIBJPEG
302 for ( i = 0; i < 4; i++ ) {
303 if (client->zlibStreamActive[i] == TRUE ) {
304 if (inflateEnd (&client->zlibStream[i]) != Z_OK &&
305 client->zlibStream[i].msg != NULL)
306 rfbClientLog("inflateEnd: %s\n", client->zlibStream[i].msg);
310 if ( client->decompStreamInited == TRUE ) {
311 if (inflateEnd (&client->decompStream) != Z_OK &&
312 client->decompStream.msg != NULL)
313 rfbClientLog("inflateEnd: %s\n", client->decompStream.msg );
316 if (client->jpegSrcManager)
317 free(client->jpegSrcManager);
322 if (client->sock >= 0)
325 free(client->desktopName);
326 free(client->serverHost);