blob: ac1dab37ad746756d1e7d70b600d3583b5b69aea [file] [log] [blame]
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved.
2 *
3 * This is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This software is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
16 * USA.
17 */
18#include <stdio.h>
19
20#define NEED_REPLIES
21#include <X11/Xlibint.h>
22#define _VNCEXT_PROTO_
23#include "vncExt.h"
24
25static Bool XVncExtClientCutTextNotifyWireToEvent(Display* dpy, XEvent* e,
26 xEvent* w);
27static Bool XVncExtSelectionChangeNotifyWireToEvent(Display* dpy, XEvent* e,
28 xEvent* w);
29
30static Bool extensionInited = False;
31static XExtCodes* codes = 0;
32
33static Bool checkExtension(Display* dpy)
34{
35 if (!extensionInited) {
36 extensionInited = True;
37 codes = XInitExtension(dpy, VNCEXTNAME);
38 if (!codes) return False;
39 XESetWireToEvent(dpy, codes->first_event + VncExtClientCutTextNotify,
40 XVncExtClientCutTextNotifyWireToEvent);
41 XESetWireToEvent(dpy, codes->first_event + VncExtSelectionChangeNotify,
42 XVncExtSelectionChangeNotifyWireToEvent);
43 }
44 return codes != 0;
45}
46
47Bool XVncExtQueryExtension(Display* dpy, int* event_basep, int* error_basep)
48{
49 if (!checkExtension(dpy)) return False;
50 *event_basep = codes->first_event;
51 *error_basep = codes->first_error;
52 return True;
53}
54
55Bool XVncExtSetParam(Display* dpy, const char* param)
56{
57 xVncExtSetParamReq* req;
58 xVncExtSetParamReply rep;
59
60 int paramLen = strlen(param);
61 if (paramLen > 255) return False;
62 if (!checkExtension(dpy)) return False;
63
64 LockDisplay(dpy);
65 GetReq(VncExtSetParam, req);
66 req->reqType = codes->major_opcode;
67 req->vncExtReqType = X_VncExtSetParam;
68 req->length += (paramLen + 3) >> 2;
69 req->paramLen = paramLen;
70 Data(dpy, param, paramLen);
71 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
72 UnlockDisplay(dpy);
73 SyncHandle();
74 return False;
75 }
76 UnlockDisplay(dpy);
77 SyncHandle();
78 return rep.success;
79}
80
81Bool XVncExtGetParam(Display* dpy, const char* param, char** value, int* len)
82{
83 xVncExtGetParamReq* req;
84 xVncExtGetParamReply rep;
85
86 int paramLen = strlen(param);
87 *value = 0;
88 *len = 0;
89 if (paramLen > 255) return False;
90 if (!checkExtension(dpy)) return False;
91
92 LockDisplay(dpy);
93 GetReq(VncExtGetParam, req);
94 req->reqType = codes->major_opcode;
95 req->vncExtReqType = X_VncExtGetParam;
96 req->length += (paramLen + 3) >> 2;
97 req->paramLen = paramLen;
98 Data(dpy, param, paramLen);
99 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
100 UnlockDisplay(dpy);
101 SyncHandle();
102 return False;
103 }
104 if (rep.success) {
105 *len = rep.valueLen;
106 *value = (char*) Xmalloc (*len+1);
107 _XReadPad(dpy, *value, *len);
108 (*value)[*len] = 0;
109 }
110 UnlockDisplay(dpy);
111 SyncHandle();
112 return rep.success;
113}
114
115char* XVncExtGetParamDesc(Display* dpy, const char* param)
116{
117 xVncExtGetParamDescReq* req;
118 xVncExtGetParamDescReply rep;
119 char* desc = 0;
120
121 int paramLen = strlen(param);
122 if (paramLen > 255) return False;
123 if (!checkExtension(dpy)) return False;
124
125 LockDisplay(dpy);
126 GetReq(VncExtGetParamDesc, req);
127 req->reqType = codes->major_opcode;
128 req->vncExtReqType = X_VncExtGetParamDesc;
129 req->length += (paramLen + 3) >> 2;
130 req->paramLen = paramLen;
131 Data(dpy, param, paramLen);
132 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
133 UnlockDisplay(dpy);
134 SyncHandle();
135 return False;
136 }
137 if (rep.success) {
138 desc = (char*)Xmalloc(rep.descLen+1);
139 _XReadPad(dpy, desc, rep.descLen);
140 desc[rep.descLen] = 0;
141 }
142 UnlockDisplay(dpy);
143 SyncHandle();
144 return desc;
145}
146
147char** XVncExtListParams(Display* dpy, int* nParams)
148{
149 xVncExtListParamsReq* req;
150 xVncExtListParamsReply rep;
151 char** list = 0;
152 char* ch;
153 int rlen, paramLen, i;
154
155 if (!checkExtension(dpy)) return False;
156
157 LockDisplay(dpy);
158 GetReq(VncExtListParams, req);
159 req->reqType = codes->major_opcode;
160 req->vncExtReqType = X_VncExtListParams;
161 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
162 UnlockDisplay(dpy);
163 SyncHandle();
164 return False;
165 }
166 UnlockDisplay(dpy);
167 SyncHandle();
168 if (rep.nParams) {
169 list = (char**)Xmalloc(rep.nParams * sizeof(char*));
170 rlen = rep.length << 2;
171 ch = (char*)Xmalloc(rlen + 1);
172 if (!list || !ch) {
173 if (list) Xfree((char*)list);
174 if (ch) Xfree(ch);
175 _XEatData(dpy, rlen);
176 UnlockDisplay(dpy);
177 SyncHandle();
178 return 0;
179 }
180 _XReadPad(dpy, ch, rlen);
181 paramLen = *ch++;
182 for (i = 0; i < rep.nParams; i++) {
183 list[i] = ch;
184 ch += paramLen;
185 paramLen = *ch;
186 *ch++ = 0;
187 }
188 }
189 *nParams = rep.nParams;
190 UnlockDisplay(dpy);
191 SyncHandle();
192 return list;
193}
194
195void XVncExtFreeParamList(char** list)
196{
197 if (list) {
198 Xfree(list[0]-1);
199 Xfree((char*)list);
200 }
201}
202
203Bool XVncExtSetServerCutText(Display* dpy, const char* str, int len)
204{
205 xVncExtSetServerCutTextReq* req;
206
207 if (!checkExtension(dpy)) return False;
208
209 LockDisplay(dpy);
210 GetReq(VncExtSetServerCutText, req);
211 req->reqType = codes->major_opcode;
212 req->vncExtReqType = X_VncExtSetServerCutText;
213 req->length += (len + 3) >> 2;
214 req->textLen = len;
215 Data(dpy, str, len);
216 UnlockDisplay(dpy);
217 SyncHandle();
218 return True;
219}
220
221Bool XVncExtGetClientCutText(Display* dpy, char** str, int* len)
222{
223 xVncExtGetClientCutTextReq* req;
224 xVncExtGetClientCutTextReply rep;
225
226 if (!checkExtension(dpy)) return False;
227
228 LockDisplay(dpy);
229 GetReq(VncExtGetClientCutText, req);
230 req->reqType = codes->major_opcode;
231 req->vncExtReqType = X_VncExtGetClientCutText;
232 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
233 UnlockDisplay(dpy);
234 SyncHandle();
235 return False;
236 }
237 UnlockDisplay(dpy);
238 SyncHandle();
239 *len = rep.textLen;
240 *str = (char*) Xmalloc (*len+1);
241 _XReadPad(dpy, *str, *len);
242 (*str)[*len] = 0;
243 return True;
244}
245
246Bool XVncExtSelectInput(Display* dpy, Window w, int mask)
247{
248 xVncExtSelectInputReq* req;
249
250 if (!checkExtension(dpy)) return False;
251
252 LockDisplay(dpy);
253 GetReq(VncExtSelectInput, req);
254 req->reqType = codes->major_opcode;
255 req->vncExtReqType = X_VncExtSelectInput;
256 req->window = w;
257 req->mask = mask;
258 UnlockDisplay(dpy);
259 SyncHandle();
260 return True;
261}
262
263Bool XVncExtConnect(Display* dpy, char* hostAndPort)
264{
265 xVncExtConnectReq* req;
266 xVncExtConnectReply rep;
267
268 int strLen = strlen(hostAndPort);
269 if (strLen > 255) return False;
270 if (!checkExtension(dpy)) return False;
271
272 LockDisplay(dpy);
273 GetReq(VncExtConnect, req);
274 req->reqType = codes->major_opcode;
275 req->vncExtReqType = X_VncExtConnect;
276 req->length += (strLen + 3) >> 2;
277 req->strLen = strLen;
278 Data(dpy, hostAndPort, strLen);
279 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
280 UnlockDisplay(dpy);
281 SyncHandle();
282 return False;
283 }
284 UnlockDisplay(dpy);
285 SyncHandle();
286 return rep.success;
287}
288
289static Bool XVncExtClientCutTextNotifyWireToEvent(Display* dpy, XEvent* e,
290 xEvent* w)
291{
292 XVncExtClientCutTextEvent* ev = (XVncExtClientCutTextEvent*)e;
293 xVncExtClientCutTextNotifyEvent* wire = (xVncExtClientCutTextNotifyEvent*)w;
294 ev->type = wire->type & 0x7f;
295 ev->serial = _XSetLastRequestRead(dpy,(xGenericReply*)wire);
296 ev->send_event = (wire->type & 0x80) != 0;
297 ev->display = dpy;
298 ev->window = wire->window;
299 ev->time = wire->time;
300 return True;
301}
302
303static Bool XVncExtSelectionChangeNotifyWireToEvent(Display* dpy, XEvent* e,
304 xEvent* w)
305{
306 XVncExtSelectionChangeEvent* ev = (XVncExtSelectionChangeEvent*)e;
307 xVncExtSelectionChangeNotifyEvent* wire
308 = (xVncExtSelectionChangeNotifyEvent*)w;
309 ev->type = wire->type & 0x7f;
310 ev->serial = _XSetLastRequestRead(dpy,(xGenericReply*)wire);
311 ev->send_event = (wire->type & 0x80) != 0;
312 ev->display = dpy;
313 ev->window = wire->window;
314 ev->selection = wire->selection;
315 return True;
316}