Mercurial > hg > xemacs-beta
comparison lib-src/winclient.c @ 5030:422b4b4fb2a6
Winclient updates
author | Vin Shelton <acs@xemacs.org> |
---|---|
date | Thu, 11 Feb 2010 19:33:50 -0500 |
parents | 61aff09a7589 |
children | 308d34e9f07d |
comparison
equal
deleted
inserted
replaced
5029:acf7d1bc0490 | 5030:422b4b4fb2a6 |
---|---|
30 #include <stdlib.h> | 30 #include <stdlib.h> |
31 #include <stdio.h> | 31 #include <stdio.h> |
32 #include <ctype.h> | 32 #include <ctype.h> |
33 #include <errno.h> | 33 #include <errno.h> |
34 | 34 |
35 #ifdef __CYGWIN__ | |
36 #include <stdlib.h> | |
37 #include <unistd.h> | |
38 #endif | |
39 | |
35 static void error (const char* s1, const char* s2); | 40 static void error (const char* s1, const char* s2); |
36 static void fatal (const char *s1, const char *s2); | 41 static void fatal (const char *s1, const char *s2); |
37 static void * xmalloc (size_t size); | 42 static void * xmalloc (size_t size); |
38 static char * getNextArg (const char **ptr, unsigned *len); | 43 static char * getNextArg (const char **ptr, unsigned *len); |
39 | 44 |
40 /* -- Post-Include Defines -------------------------------------------------- */ | 45 /* -- Post-Include Defines -------------------------------------------------- */ |
41 | 46 |
42 /* Timeouts & delays */ | 47 /* Timeouts & delays */ |
43 #define CONNECT_RETRIES 10 | 48 #define CONNECT_RETRIES 20 |
44 #define CONNECT_DELAY 500 /* ms */ | 49 #define CONNECT_DELAY 500 /* ms */ |
45 #define TRANSACTION_TIMEOUT 5000 /* ms */ | 50 #define TRANSACTION_TIMEOUT 5000 /* ms */ |
46 #define MAX_INPUT_IDLE_WAIT INFINITE /* ms */ | 51 #define MAX_INPUT_IDLE_WAIT INFINITE /* ms */ |
47 | 52 |
48 /* DDE Strings */ | 53 /* DDE Strings */ |
49 #define SERVICE_NAME "XEmacs" | 54 #define SERVICE_NAME "XEmacs" |
50 #define TOPIC_NAME "System" | 55 #define TOPIC_NAME "System" |
51 #define COMMAND_FORMAT "[open(\"%s%s\")]" | 56 #define COMMAND_FORMAT "[open(\"%s%s\")]" |
52 | 57 |
53 /* XEmacs program name */ | 58 /* XEmacs program name */ |
54 #define PROGRAM_TO_RUN "xemacs.exe" | 59 #define GENERIC_PROGRAM EMACS_PROGNAME ".exe" |
60 #define VERSIONED_PROGRAM EMACS_PROGNAME "-" EMACS_VERSION ".exe" | |
55 | 61 |
56 /* -- Constants ------------------------------------------------------------- */ | 62 /* -- Constants ------------------------------------------------------------- */ |
57 | 63 |
58 /* -- Global Variables ------------------------------------------------------ */ | 64 /* -- Global Variables ------------------------------------------------------ */ |
59 | 65 |
105 int nCmdShow) | 111 int nCmdShow) |
106 { | 112 { |
107 HCONV hConv; | 113 HCONV hConv; |
108 int ret = 0; | 114 int ret = 0; |
109 UINT uiRet; | 115 UINT uiRet; |
110 | 116 |
111 /* Initialise the DDEML library */ | 117 /* Initialise the DDEML library */ |
112 uiRet = DdeInitialize (&idInst, | 118 uiRet = DdeInitialize (&idInst, |
113 (PFNCALLBACK) ddeCallback, | 119 (PFNCALLBACK) ddeCallback, |
114 APPCMD_CLIENTONLY | 120 APPCMD_CLIENTONLY |
115 |CBF_FAIL_ALLSVRXACTIONS, | 121 |CBF_FAIL_ALLSVRXACTIONS, |
132 ret = parseCommandLine (hConv, lpCmdLine); | 138 ret = parseCommandLine (hConv, lpCmdLine); |
133 | 139 |
134 /* Close the conversation */ | 140 /* Close the conversation */ |
135 closeConversation (hConv); | 141 closeConversation (hConv); |
136 } | 142 } |
137 | 143 |
138 DdeUninitialize (idInst); | 144 DdeUninitialize (idInst); |
139 | 145 |
140 return ret; | 146 return ret; |
141 } | 147 } |
142 | 148 |
162 MessageBox (NULL, "Could not create string handle for service.", | 168 MessageBox (NULL, "Could not create string handle for service.", |
163 "winclient", MB_ICONEXCLAMATION | MB_OK); | 169 "winclient", MB_ICONEXCLAMATION | MB_OK); |
164 | 170 |
165 goto error; | 171 goto error; |
166 } | 172 } |
167 | 173 |
168 /* Get the topic name */ | 174 /* Get the topic name */ |
169 hszTopic = DdeCreateStringHandle (idInst, | 175 hszTopic = DdeCreateStringHandle (idInst, |
170 TOPIC_NAME, | 176 TOPIC_NAME, |
171 CP_WINANSI); | 177 CP_WINANSI); |
172 | 178 |
184 if (!hConv) | 190 if (!hConv) |
185 { | 191 { |
186 STARTUPINFO sti; | 192 STARTUPINFO sti; |
187 PROCESS_INFORMATION pi; | 193 PROCESS_INFORMATION pi; |
188 int n; | 194 int n; |
189 | 195 |
190 /* Try to start the program */ | 196 /* Try to start the program */ |
191 ZeroMemory (&sti, sizeof (sti)); | 197 ZeroMemory (&sti, sizeof (sti)); |
192 sti.cb = sizeof (sti); | 198 sti.cb = sizeof (sti); |
193 if (!CreateProcess (NULL, PROGRAM_TO_RUN, NULL, NULL, FALSE, 0, | 199 if (!CreateProcess (NULL, GENERIC_PROGRAM, NULL, NULL, FALSE, 0, |
200 NULL, NULL, &sti, &pi) && | |
201 !CreateProcess (NULL, VERSIONED_PROGRAM, NULL, NULL, FALSE, 0, | |
194 NULL, NULL, &sti, &pi)) | 202 NULL, NULL, &sti, &pi)) |
195 { | 203 { |
196 MessageBox (NULL, "Could not start process.", | 204 MessageBox (NULL, "Could not start process.", |
197 "winclient", MB_ICONEXCLAMATION | MB_OK); | 205 "winclient", MB_ICONEXCLAMATION | MB_OK); |
198 | 206 |
203 WaitForInputIdle (pi.hProcess, MAX_INPUT_IDLE_WAIT); | 211 WaitForInputIdle (pi.hProcess, MAX_INPUT_IDLE_WAIT); |
204 | 212 |
205 /* Close the handles */ | 213 /* Close the handles */ |
206 CloseHandle (pi.hThread); | 214 CloseHandle (pi.hThread); |
207 CloseHandle (pi.hProcess); | 215 CloseHandle (pi.hProcess); |
208 | 216 |
209 /* Try to connect */ | 217 /* Try to connect */ |
210 for (n = 0; n < CONNECT_RETRIES; n++) | 218 for (n = 0; n < CONNECT_RETRIES; n++) |
211 { | 219 { |
212 Sleep (CONNECT_DELAY); | 220 Sleep (CONNECT_DELAY); |
213 | 221 |
214 hConv = DdeConnect (idInst, hszService, hszTopic, NULL); | 222 hConv = DdeConnect (idInst, hszService, hszTopic, NULL); |
215 | 223 |
216 if (hConv) | 224 if (hConv) |
217 break; | 225 break; |
218 } | 226 } |
230 /* Release the string handles */ | 238 /* Release the string handles */ |
231 DdeFreeStringHandle (idInst, hszService); | 239 DdeFreeStringHandle (idInst, hszService); |
232 DdeFreeStringHandle (idInst, hszTopic); | 240 DdeFreeStringHandle (idInst, hszTopic); |
233 | 241 |
234 return hConv; | 242 return hConv; |
235 | 243 |
236 error: | 244 error: |
237 if (hConv) | 245 if (hConv) |
238 DdeDisconnect (hConv); | 246 DdeDisconnect (hConv); |
239 if (hszService) | 247 if (hszService) |
240 DdeFreeStringHandle (idInst, hszService); | 248 DdeFreeStringHandle (idInst, hszService); |
266 int | 274 int |
267 doFile (HCONV hConv, LPSTR lpszFileName1, LPSTR lpszFileName2) | 275 doFile (HCONV hConv, LPSTR lpszFileName1, LPSTR lpszFileName2) |
268 { | 276 { |
269 char *buf = NULL; | 277 char *buf = NULL; |
270 unsigned len; | 278 unsigned len; |
271 | 279 |
272 /* Calculate the buffer length */ | 280 /* Calculate the buffer length */ |
273 len = strlen (lpszFileName1) + strlen (lpszFileName2) | 281 len = strlen (lpszFileName1) + strlen (lpszFileName2) |
274 + strlen (COMMAND_FORMAT); | 282 + strlen (COMMAND_FORMAT); |
275 | 283 |
276 /* Allocate a buffer */ | 284 /* Allocate a buffer */ |
277 buf = (char *) xmalloc (len); | 285 buf = (char *) xmalloc (len); |
278 | 286 |
279 if (!buf) | 287 if (!buf) |
280 { | 288 { |
284 return 1; | 292 return 1; |
285 } | 293 } |
286 | 294 |
287 /* Build the command */ | 295 /* Build the command */ |
288 len = wsprintf (buf, COMMAND_FORMAT, lpszFileName1, lpszFileName2); | 296 len = wsprintf (buf, COMMAND_FORMAT, lpszFileName1, lpszFileName2); |
289 | |
290 len++; | 297 len++; |
291 | 298 |
292 /* OK. We're connected. Send the message. */ | 299 /* OK. We're connected. Send the message. */ |
293 DdeClientTransaction (buf, len, hConv, NULL, | 300 DdeClientTransaction (buf, len, hConv, NULL, |
294 0, XTYP_EXECUTE, TRANSACTION_TIMEOUT, NULL); | 301 0, XTYP_EXECUTE, TRANSACTION_TIMEOUT, NULL); |
295 | 302 |
296 free (buf); | 303 free (buf); |
297 | 304 |
298 return 0; | 305 return 0; |
299 } | 306 } |
300 | 307 |
301 /* | 308 /* |
302 * Name : getNextArg | 309 * Name : getNextArg |
317 p++; | 324 p++; |
318 | 325 |
319 /* If this is the end, return NULL */ | 326 /* If this is the end, return NULL */ |
320 if (!*p) | 327 if (!*p) |
321 return NULL; | 328 return NULL; |
322 | 329 |
323 /* Remember where we are */ | 330 /* Remember where we are */ |
324 start = p; | 331 start = p; |
325 | 332 |
326 /* Find the next whitespace character outside quotes */ | 333 /* Find the next whitespace character outside quotes */ |
327 if (*p == '"') | 334 if (*p == '"') |
328 all_in_quotes = 1; | 335 all_in_quotes = 1; |
329 | 336 |
330 while (*p && !quit) | 337 while (*p && !quit) |
331 { | 338 { |
332 switch (*p) | 339 switch (*p) |
333 { | 340 { |
334 case '"': | 341 case '"': |
337 break; | 344 break; |
338 | 345 |
339 case '\\': | 346 case '\\': |
340 if (!in_quotes) | 347 if (!in_quotes) |
341 all_in_quotes = 0; | 348 all_in_quotes = 0; |
342 | 349 |
343 p++; | 350 p++; |
344 | 351 |
345 if (!*p) | 352 if (!*p) |
346 break; | 353 break; |
347 | 354 |
366 if (all_in_quotes) | 373 if (all_in_quotes) |
367 { | 374 { |
368 start++; | 375 start++; |
369 length -= 2; | 376 length -= 2; |
370 } | 377 } |
371 | 378 |
372 /* Copy */ | 379 /* Copy */ |
373 buf = (char *) xmalloc (length + 1); | 380 buf = (char *) xmalloc (length + 1); |
374 | 381 |
375 if (!buf) | 382 if (!buf) |
376 return NULL; | 383 return NULL; |
377 | 384 |
378 strncpy (buf, start, length); | 385 strncpy (buf, start, length); |
379 buf[length] = '\0'; | 386 buf[length] = '\0'; |
380 | 387 |
381 /* Return the pointer and length */ | 388 /* Return the pointer and length */ |
382 *ptr = p; | 389 *ptr = p; |
403 WIN32_FIND_DATA wfd; | 410 WIN32_FIND_DATA wfd; |
404 | 411 |
405 /* Retrieve arguments */ | 412 /* Retrieve arguments */ |
406 while ((arg = getNextArg ((const char**)&lpszCommandLine, &len)) != NULL) | 413 while ((arg = getNextArg ((const char**)&lpszCommandLine, &len)) != NULL) |
407 { | 414 { |
415 fullpath = NULL; | |
416 #ifdef __CYGWIN__ | |
417 /* If the filename is not an absolute path, | |
418 add the current directory to the pathname */ | |
419 if (*arg != '/') | |
420 { | |
421 len = pathconf(".", _PC_PATH_MAX); | |
422 fullpath = (char *) xmalloc (len+1); | |
423 if (!fullpath) | |
424 { | |
425 MessageBox (NULL, "Not enough memory.", "winclient", | |
426 MB_ICONEXCLAMATION | MB_OK); | |
427 ret = 1; | |
428 break; | |
429 } | |
430 if (!getcwd(fullpath, (size_t)len)) | |
431 { | |
432 MessageBox (NULL, "Could not retrieve current directory.", | |
433 "winclient", MB_ICONEXCLAMATION | MB_OK); | |
434 ret = 1; | |
435 break; | |
436 } | |
437 /* Append trailing slash */ | |
438 strcat(fullpath, "/"); | |
439 ret = doFile (hConv, fullpath, arg); | |
440 } | |
441 else | |
442 { | |
443 /* The arg has already been expanded, so pass it as it is */ | |
444 ret = doFile (hConv, "", arg); | |
445 } | |
446 #else | |
408 /* First find the canonical path name */ | 447 /* First find the canonical path name */ |
409 fullpath = filepart = NULL; | 448 fullpath = filepart = NULL; |
410 pathlen = GetFullPathName (arg, 0, fullpath, &filepart); | 449 pathlen = GetFullPathName (arg, 0, fullpath, &filepart); |
411 | 450 |
412 fullpath = (char *) xmalloc (pathlen); | 451 fullpath = (char *) xmalloc (pathlen); |
413 | 452 |
414 if (!fullpath) | 453 if (!fullpath) |
415 { | 454 { |
416 MessageBox (NULL, "Not enough memory.", "winclient", | 455 MessageBox (NULL, "Not enough memory.", "winclient", |
417 MB_ICONEXCLAMATION | MB_OK); | 456 MB_ICONEXCLAMATION | MB_OK); |
418 | |
419 ret = 1; | 457 ret = 1; |
420 free (arg); | |
421 | |
422 break; | 458 break; |
423 } | 459 } |
424 | 460 |
425 GetFullPathName (arg, pathlen, fullpath, &filepart); | 461 GetFullPathName (arg, pathlen, fullpath, &filepart); |
426 | 462 |
446 } | 482 } |
447 while (FindNextFile (hFindFile, &wfd)); | 483 while (FindNextFile (hFindFile, &wfd)); |
448 | 484 |
449 FindClose (hFindFile); | 485 FindClose (hFindFile); |
450 } | 486 } |
451 | 487 #endif |
452 /* Release the path name buffers */ | 488 /* Release the path name buffers */ |
453 free (fullpath); | 489 if (fullpath) |
490 free (fullpath); | |
454 free (arg); | 491 free (arg); |
455 | 492 |
456 if (ret) | 493 if (ret) |
457 break; | 494 break; |
458 } | 495 } |