1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 #ifdef HAVE_CONFIG_H
30 #include "../config.h"
31 #endif
32
33 #include "server.h"
34 #include "textBuf.h"
35 #include "nedit.h"
36 #include "window.h"
37 #include "file.h"
38 #include "selection.h"
39 #include "macro.h"
40 #include "menu.h"
41 #include "preferences.h"
42 #include "server_common.h"
43 #include "filter.h"
44 #include "../util/fileUtils.h"
45 #include "../util/utils.h"
46 #include "../util/misc.h"
47 #include "../util/nedit_malloc.h"
48
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <string.h>
52 #include <limits.h>
53 #include <sys/types.h>
54 #include <sys/utsname.h>
55 #include <sys/param.h>
56 #include <unistd.h>
57 #include <pwd.h>
58
59 #include <Xm/Xm.h>
60 #include <Xm/XmP.h>
61
62 #ifdef HAVE_DEBUG_H
63 #include "../debug.h"
64 #endif
65
66
67 static void processServerCommand(
void);
68 static void cleanUpServerCommunication(
void);
69 static void processServerCommandString(
char *string);
70 static void getFileClosedProperty(WindowInfo *window);
71 static int isLocatedOnDesktop(WindowInfo *window,
long currentDesktop);
72 static WindowInfo *findWindowOnDesktop(
int tabbed,
long currentDesktop);
73
74 static Atom ServerRequestAtom =
0;
75 static Atom ServerExistsAtom =
0;
76
77
78
79
80
81 void InitServerCommunication(
void)
82 {
83 Window rootWindow = RootWindow(TheDisplay, DefaultScreen(TheDisplay));
84
85
86 CreateServerPropertyAtoms(GetPrefServerName(),
87 &ServerExistsAtom,
88 &ServerRequestAtom);
89
90
91
92
93
94 XSelectInput(TheDisplay, rootWindow, PropertyChangeMask);
95
96
97
98
99 XChangeProperty(TheDisplay, rootWindow, ServerExistsAtom,
XA_STRING,
8,
100 PropModeReplace, (
unsigned char *)
"True",
4);
101
102
103 atexit(cleanUpServerCommunication);
104 }
105
106 static void deleteProperty(Atom* atom)
107 {
108 if (!IsServer) {
109 *atom = None;
110 return;
111 }
112
113 if (*atom != None) {
114 XDeleteProperty(TheDisplay,
115 RootWindow(TheDisplay, DefaultScreen(TheDisplay)),
116 *atom);
117 *atom = None;
118 }
119 }
120
121
122
123
124 static void cleanUpServerCommunication(
void)
125 {
126 WindowInfo *w;
127
128
129
130
131 for (w = WindowList; w; w = w->next) {
132 DeleteFileClosedProperty(w);
133 }
134
135
136
137
138 DeleteServerFileAtoms(GetPrefServerName(),
139 RootWindow(TheDisplay, DefaultScreen(TheDisplay)));
140
141
142
143
144 deleteProperty(&ServerExistsAtom);
145 XSync(TheDisplay, False);
146 }
147
148
149
150
151
152
153
154
155
156 void ServerMainLoop(XtAppContext context)
157 {
158 while (
TRUE) {
159 XEvent event;
160 XtAppNextEvent(context, &event);
161 ServerDispatchEvent(&event);
162 }
163 }
164
165 static void processServerCommand(
void)
166 {
167 Atom dummyAtom;
168 unsigned long nItems, dummyULong;
169 unsigned char *propValue;
170 int getFmt;
171
172
173 if (XGetWindowProperty(TheDisplay, RootWindow(TheDisplay,
174 DefaultScreen(TheDisplay)), ServerRequestAtom,
0,
INT_MAX, True,
175 XA_STRING, &dummyAtom, &getFmt, &nItems, &dummyULong, &propValue)
176 != Success || getFmt !=
8)
177 return;
178
179
180 processServerCommandString((
char *)propValue);
181 XFree(propValue);
182 }
183
184 Boolean ServerDispatchEvent(XEvent *event)
185 {
186 if (IsServer) {
187 Window rootWindow = RootWindow(TheDisplay, DefaultScreen(TheDisplay));
188 if (event->xany.window == rootWindow && event->xany.type == PropertyNotify) {
189 const XPropertyEvent* e = &event->xproperty;
190
191 if (e->type == PropertyNotify && e->window == rootWindow) {
192 if (e->atom == ServerRequestAtom && e->state == PropertyNewValue)
193 processServerCommand();
194 else if (e->atom == ServerExistsAtom && e->state == PropertyDelete)
195 XChangeProperty(TheDisplay,
196 rootWindow,
197 ServerExistsAtom,
XA_STRING,
198 8, PropModeReplace,
199 (
unsigned char *)
"True",
4);
200 }
201 }
202 }
203 return XtDispatchEvent(event);
204 }
205
206
207 static Atom findFileOpenProperty(
const char* filename,
208 const char* pathname) {
209 char path[
MAXPATHLEN];
210 Atom atom;
211
212 if (!IsServer)
return(None);
213
214 strcpy(path, pathname);
215 strcat(path, filename);
216 atom = CreateServerFileOpenAtom(GetPrefServerName(), path);
217 return(atom);
218 }
219
220
221
222
223 static void deleteFileOpenProperty(WindowInfo *window)
224 {
225 if (window->filenameSet) {
226 Atom atom = findFileOpenProperty(window->filename, window->path);
227 deleteProperty(&atom);
228 }
229 }
230
231 static void deleteFileOpenProperty2(
const char* filename,
232 const char* pathname)
233 {
234 Atom atom = findFileOpenProperty(filename, pathname);
235 deleteProperty(&atom);
236 }
237
238
239
240
241 static Atom findFileClosedProperty(
const char* filename,
242 const char* pathname)
243 {
244 char path[
MAXPATHLEN];
245 Atom atom;
246
247 if (!IsServer)
return(None);
248
249 strcpy(path, pathname);
250 strcat(path, filename);
251 atom = CreateServerFileClosedAtom(GetPrefServerName(),
252 path,
253 True);
254 return(atom);
255 }
256
257
258 static void getFileClosedProperty(WindowInfo *window)
259 {
260 if (window->filenameSet) {
261 window->fileClosedAtom = findFileClosedProperty(window->filename,
262 window->path);
263 }
264 }
265
266
267
268
269 void DeleteFileClosedProperty(WindowInfo *window)
270 {
271 if (window->filenameSet) {
272 deleteProperty(&window->fileClosedAtom);
273 }
274 }
275
276 static void deleteFileClosedProperty2(
const char* filename,
277 const char* pathname)
278 {
279 Atom atom = findFileClosedProperty(filename, pathname);
280 deleteProperty(&atom);
281 }
282
283 static int isLocatedOnDesktop(WindowInfo *window,
long currentDesktop)
284 {
285 long windowDesktop;
286 if (currentDesktop == -
1)
287 return True;
288
289 windowDesktop = QueryDesktop(TheDisplay, window->shell);
290
291 if (windowDesktop == currentDesktop || windowDesktop == 0xFFFFFFFFL)
292 return True;
293
294 return False;
295 }
296
297 static WindowInfo *findWindowOnDesktop(
int tabbed,
long currentDesktop)
298 {
299 WindowInfo *window;
300
301 if (tabbed ==
0 || (tabbed == -
1 && GetPrefOpenInTab() ==
0)) {
302
303
304 for (window=WindowList; window!=
NULL; window=window->next) {
305 if (window->filenameSet || window->fileChanged ||
306 window->macroCmdData !=
NULL) {
307 continue;
308 }
309
310 if (isLocatedOnDesktop(window, currentDesktop)) {
311 return window;
312 }
313 }
314 }
else {
315
316 for (window=WindowList; window!=
NULL; window=window->next) {
317
318 if (!IsTopDocument(window)) {
319 continue;
320 }
321 if (isLocatedOnDesktop(window, currentDesktop)) {
322 return window;
323 }
324 }
325 }
326
327 return NULL;
328 }
329
330 static void processServerCommandString(
char *string)
331 {
332 char *fullname, filename[
MAXPATHLEN], pathname[
MAXPATHLEN];
333 char *doCommand, *geometry, *langMode, *inPtr;
334 int editFlags, stringLen = strlen(string);
335 int lineNum, createFlag, readFlag, iconicFlag, lastIconic =
0, tabbed = -
1;
336 int fileLen, doLen, lmLen, geomLen, charsRead, itemsRead;
337 WindowInfo *window, *lastFile =
NULL;
338 long currentDesktop = QueryCurrentDesktop(TheDisplay,
339 RootWindow(TheDisplay, DefaultScreen(TheDisplay)));
340
341
342
343 if (string[
0] ==
'\0') {
344 for (window=WindowList; window!=
NULL; window=window->next)
345 if (!window->filenameSet && !window->fileChanged &&
346 isLocatedOnDesktop(window, currentDesktop))
347 break;
348 if (window ==
NULL) {
349 EditNewFile(findWindowOnDesktop(tabbed, currentDesktop),
NULL,
350 False,
NULL,
NULL);
351 CheckCloseDim();
352 }
353 else {
354 RaiseDocument(window);
355 WmClientMsg(TheDisplay, XtWindow(window->shell),
356 "_NET_ACTIVE_WINDOW",
0,
0,
0,
0,
0);
357 XMapRaised(TheDisplay, XtWindow(window->shell));
358 }
359 return;
360 }
361
362
363
364
365 inPtr = string;
366 while (
TRUE) {
367
368 if (*inPtr ==
'\0')
369 break;
370
371
372
373
374
375
376 itemsRead = sscanf(inPtr,
"%d %d %d %d %d %d %d %d %d%n", &lineNum,
377 &readFlag, &createFlag, &iconicFlag, &tabbed, &fileLen,
378 &doLen, &lmLen, &geomLen, &charsRead);
379 if (itemsRead !=
9)
380 goto readError;
381 inPtr += charsRead +
1;
382 if (inPtr - string + fileLen > stringLen)
383 goto readError;
384 fullname = inPtr;
385 inPtr += fileLen;
386 *inPtr++ =
'\0';
387 if (inPtr - string + doLen > stringLen)
388 goto readError;
389 doCommand = inPtr;
390 inPtr += doLen;
391 *inPtr++ =
'\0';
392 if (inPtr - string + lmLen > stringLen)
393 goto readError;
394 langMode = inPtr;
395 inPtr += lmLen;
396 *inPtr++ =
'\0';
397 if (inPtr - string + geomLen > stringLen)
398 goto readError;
399 geometry = inPtr;
400 inPtr += geomLen;
401 *inPtr++ =
'\0';
402
403
404
405
406
407 if (fileLen <=
0) {
408 for (window=WindowList; window!=
NULL; window=window->next) {
409 if(!window->filenameSet && !window->fileChanged &&
410 (isLocatedOnDesktop(window, currentDesktop))) {
411 break;
412 }
413 }
414
415 if (*doCommand ==
'\0') {
416 if (window ==
NULL) {
417 EditNewFile(findWindowOnDesktop(tabbed, currentDesktop),
418 NULL, iconicFlag, lmLen==
0?
NULL:langMode,
NULL);
419 }
else {
420 if (iconicFlag)
421 RaiseDocument(window);
422 else
423 RaiseDocumentWindow(window);
424 }
425 }
else {
426 WindowInfo *win = WindowList;
427
428
429 while (win !=
NULL && win->macroCmdData !=
NULL) {
430 win = win->next;
431 }
432
433 if (!win) {
434 XBell(TheDisplay,
0);
435 }
else {
436
437 if (iconicFlag)
438 RaiseDocument(win);
439 else
440 RaiseDocumentWindow(win);
441 DoMacro(win, doCommand,
"-do macro");
442 }
443 }
444 CheckCloseDim();
445 return;
446 }
447
448
449
450 editFlags = (readFlag ?
PREF_READ_ONLY :
0) |
CREATE |
451 (createFlag ?
SUPPRESS_CREATE_WARN :
0);
452 if (ParseFilename(fullname, filename, pathname) !=
0) {
453 fprintf(stderr,
"XNEdit: invalid file name\n");
454 deleteFileClosedProperty2(filename, pathname);
455 break;
456 }
457
458 window = FindWindowWithFile(filename, pathname);
459 if (window ==
NULL) {
460
461 size_t pathlen = strlen(pathname);
462 size_t namelen = strlen(filename);
463 char *fullpath = NEditMalloc(pathlen + namelen +
1);
464 memcpy(fullpath, pathname, pathlen);
465 memcpy(fullpath+pathlen, filename, namelen);
466 fullpath[pathlen+namelen] =
'\0';
467 IOFilter *filter = GetFilterForPath(fullpath);
468 const char *filter_name = filter ? filter->name :
NULL;
469 NEditFree(fullpath);
470
471
472
473
474
475
476
477 window = EditExistingFile(findWindowOnDesktop(tabbed, currentDesktop),
478 filename, pathname,
NULL, filter_name, editFlags, geometry, iconicFlag,
479 lmLen ==
0 ?
NULL : langMode,
480 tabbed == -
1? GetPrefOpenInTab() : tabbed, True);
481
482 if (window) {
483 CleanUpTabBarExposeQueue(window);
484 if (lastFile && window->shell != lastFile->shell) {
485 CleanUpTabBarExposeQueue(lastFile);
486 RaiseDocument(lastFile);
487 }
488 }
489
490 }
491
492
493
494 if (window !=
NULL) {
495 deleteFileOpenProperty(window);
496 getFileClosedProperty(window);
497
498 if (lineNum >
0)
499 SelectNumberedLine(window, lineNum);
500
501 if (*doCommand !=
'\0') {
502 RaiseDocument(window);
503
504 if (!iconicFlag) {
505 WmClientMsg(TheDisplay, XtWindow(window->shell),
506 "_NET_ACTIVE_WINDOW",
0,
0,
0,
0,
0);
507 XMapRaised(TheDisplay, XtWindow(window->shell));
508 }
509
510
511
512 if (window->macroCmdData !=
NULL) {
513 XBell(TheDisplay,
0);
514 }
else {
515 DoMacro(window, doCommand,
"-do macro");
516
517
518 if (!IsValidWindow(window))
519 window =
NULL;
520 if (lastFile && !IsValidWindow(lastFile))
521 lastFile =
NULL;
522 }
523 }
524
525
526 if (window) {
527 lastFile = window;
528 lastIconic = iconicFlag;
529 }
530 }
else {
531 deleteFileOpenProperty2(filename, pathname);
532 deleteFileClosedProperty2(filename, pathname);
533 }
534 }
535
536
537 if (lastFile) {
538 CleanUpTabBarExposeQueue(lastFile);
539 if (lastIconic)
540 RaiseDocument(lastFile);
541 else
542 RaiseDocumentWindow(lastFile);
543 CheckCloseDim();
544 }
545 return;
546
547 readError:
548 fprintf(stderr,
"XNEdit: error processing server request\n");
549 return;
550 }
551