1 /*
2 * browser.c - win32 interface to web browser
3 *
4 * Copyright (C) 2000 Stephen F. White
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program (see the file "COPYING" for details); if
18 * not, write to the Free Software Foundation, Inc., 675 Mass Ave,
19 * Cambridge, MA 02139, USA.
20 */
21
22 #include <swt.h>
23 #include <windows.h>
24 #include <stdio.h>
25 #include <fcntl.h>
26 #include "WriteFlags.h"
27 #include "../../config.h"
28 #include "../../mysnprintf.h"
29
30 #define DEFAULT_BROWSER "\"C:\\Program Files\\Internet Explorer\\IExplore.exe\""
31 #define DEFAULT_FIREFOX "\"C:\\Program Files\\Mozilla Firefox\\firefox.exe\""
32 #define DEFAULT_EDGE "\"C:\\Program Files\\C:\Windows\System32\cmd.exe start edge:\""
33
34 #define STARTUP_TIMEOUT 10000
35
36 typedef struct SBrowser {
37 STABLE prefs;
38 char *command;
39 char *application;
40 int vrmlLevel;
41 int useRemote;
42 int xtypExecute;
43 char *remoteCommand;
44 char *topic;
45
46 DWORD DDEInst;
47 HSZ ourService;
48 HSZ theirService;
49 HSZ topicSZ;
50 HSZ exitSZ;
51 HANDLE hProcess;
52 } SBrowser;
53
54 static int browserLaunch(char* command , HANDLE* hProcess,
55 const char *path, SWND wnd);
56 static int browserConnect(SBROWSER browser);
57 static int browserGoTo(SBROWSER browser, const char *path);
58 static int bringToFront(SBROWSER browser);
59 static char *fmtMsg(LPCTSTR lpszFormat, ...);
60 static int getShellOpenCommand(SBROWSER browser, const char *extension);
61 static void saveBrowserPreferences(SBROWSER browser);
62
63 /*******************/
64 /* browser preview */
65 /*******************/
66
67 SBROWSER
swBrowserInit(STABLE prefs)68 swBrowserInit(STABLE prefs)
69 {
70 SBrowser *browser = malloc(sizeof(SBrowser));
71 browser->prefs = prefs;
72 browser->command = mystrdup(swGetPreference(prefs, "PreviewCommand", ""));
73 browser->useRemote = swGetIntPreference(prefs, "PreviewUseRemote", FALSE);
74 browser->vrmlLevel = swGetIntPreference(prefs, "PreviewVrmlLevel", X3DOM);
75 browser->xtypExecute = swGetIntPreference(prefs, "XtypExecuteDDE", FALSE);
76 browser->remoteCommand = mystrdup(swGetPreference(prefs,
77 "PreviewRemoteCommand", ""));
78 browser->application = mystrdup(swGetPreference(prefs,
79 "PreviewApplication", ""));
80 browser->topic = mystrdup(swGetPreference(prefs, "PreviewTopic", ""));
81
82 if (!browser->command[0])
83 getShellOpenCommand(browser, ".wrl");
84 if (!browser->command[0])
85 browser->command = strdup(DEFAULT_BROWSER);
86 if (!browser->remoteCommand[0])
87 browser->useRemote = FALSE;
88
89 browser->hProcess = NULL;
90 browser->DDEInst = 0L;
91
92 return browser;
93 }
94
95 int
swBrowserGetVrmlLevel(SBROWSER browser)96 swBrowserGetVrmlLevel(SBROWSER browser)
97 {
98 return browser->vrmlLevel;
99 }
100
101 int
swBrowserGetRemote(SBROWSER browser)102 swBrowserGetRemote(SBROWSER browser)
103 {
104 return browser->useRemote;
105 }
106
107 void
swBrowserSetRemote(SBROWSER browser,int remote)108 swBrowserSetRemote(SBROWSER browser, int remote)
109 {
110 browser->useRemote = remote;
111 }
112
113 void
swBrowserGetSettings(SBROWSER browser,const char ** command,int * vrmlLevel,int * useRemote,int * xtypExecute,const char ** remoteCommand,const char ** application,const char ** topic)114 swBrowserGetSettings(SBROWSER browser, const char **command,
115 int* vrmlLevel, int *useRemote, int *xtypExecute,
116 const char **remoteCommand, const char **application,
117 const char **topic)
118 {
119 *command = browser->command;
120 *vrmlLevel = browser->vrmlLevel;
121 *xtypExecute = browser->xtypExecute;
122 *useRemote = browser->useRemote;
123 *remoteCommand = browser->remoteCommand;
124 *application = browser->application;
125 *topic = browser->topic;
126 }
127
128 void
swBrowserSetSettings(SBROWSER browser,const char * command,int vrmlLevel,int useRemote,int xtypExecute,const char * remoteCommand,const char * application,const char * topic)129 swBrowserSetSettings(SBROWSER browser, const char *command,
130 int vrmlLevel, int useRemote, int xtypExecute,
131 const char *remoteCommand, const char *application,
132 const char *topic)
133 {
134 char *oldCommand = strdup(command);
135 char *oldRemoteCommand = strdup(remoteCommand);
136 free(browser->command);
137 free(browser->remoteCommand);
138 free(browser->application);
139 free(browser->topic);
140
141 browser->command = oldCommand;
142 browser->vrmlLevel = vrmlLevel;
143 browser->useRemote = useRemote;
144 browser->xtypExecute = xtypExecute;
145 browser->remoteCommand = oldRemoteCommand;
146 browser->application = mystrdup(application);
147 browser->topic = mystrdup(topic);
148
149 saveBrowserPreferences(browser);
150 }
151
152 static void
saveBrowserPreferences(SBROWSER browser)153 saveBrowserPreferences(SBROWSER browser)
154 {
155 swSetPreference(browser->prefs, "PreviewCommand", browser->command);
156 swSetIntPreference(browser->prefs, "PreviewVrmlLevel", browser->vrmlLevel);
157 swSetIntPreference(browser->prefs, "PreviewUseRemote", browser->useRemote);
158 swSetIntPreference(browser->prefs, "XtypExecuteDDE", browser->xtypExecute);
159 swSetPreference(browser->prefs, "PreviewRemoteCommand", browser->remoteCommand);
160 swSetPreference(browser->prefs, "PreviewApplication", browser->application);
161 swSetPreference(browser->prefs, "PreviewTopic", browser->topic);
162 }
163
164 void
swBrowserSetDefault(SBROWSER browser)165 swBrowserSetDefault(SBROWSER browser)
166 {
167 browser->command = mystrdup("");
168 browser->useRemote = TRUE;
169 browser->vrmlLevel = X3DOM;
170 browser->xtypExecute = FALSE;
171 browser->remoteCommand = mystrdup("");
172 browser->application = mystrdup("");
173 browser->topic = mystrdup("");
174
175 if (!browser->command[0])
176 getShellOpenCommand(browser, ".wrl");
177 if (!browser->command[0])
178 browser->command = strdup(DEFAULT_BROWSER);
179 if (!browser->remoteCommand[0])
180 browser->useRemote = FALSE;
181 browser->hProcess = NULL;
182 browser->DDEInst = 0L;
183 }
184
185 void
swBrowserPreview(SBROWSER browser,const char * path,SWND wnd)186 swBrowserPreview(SBROWSER browser, const char *path, SWND wnd)
187 {
188 if (browser->useRemote != 0) {
189 if (browserLaunch(browser->remoteCommand,browser->hProcess, path, wnd))
190 browserGoTo(browser, path);
191 } else {
192 browserLaunch(browser->command,browser->hProcess, path, wnd);
193 }
194 }
195
196 void
swBrowserShutdown(SBROWSER browser)197 swBrowserShutdown(SBROWSER browser)
198 {
199 saveBrowserPreferences(browser);
200 if (browser->hProcess) {
201 TerminateProcess(browser->hProcess, 1);
202 CloseHandle(browser->hProcess);
203 }
204 free(browser->command);
205 free(browser->remoteCommand);
206 free(browser->application);
207 free(browser->topic);
208
209 if (browser->DDEInst != 0) {
210 DdeNameService( browser->DDEInst, NULL, NULL, DNS_UNREGISTER);
211 DdeFreeStringHandle( browser->DDEInst, browser->theirService);
212 DdeFreeStringHandle( browser->DDEInst, browser->ourService);
213 DdeFreeStringHandle( browser->DDEInst, browser->topicSZ);
214 DdeUninitialize( browser->DDEInst );
215 }
216 free(browser);
217 }
218
219 static char *
fmtMsg(LPCTSTR lpszFormat,...)220 fmtMsg(LPCTSTR lpszFormat, ...)
221 {
222 char *buf;
223 LPTSTR lpszTemp;
224
225 // format message into temporary buffer lpszTemp
226 va_list argList;
227 va_start(argList, lpszFormat);
228
229 FormatMessage(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER,
230 lpszFormat, 0, 0, (LPTSTR)&lpszTemp, 0, &argList);
231
232 // assign lpszTemp into the resulting string and free the temporary
233 buf = mystrdup(lpszTemp);
234 LocalFree(lpszTemp);
235 va_end(argList);
236 return buf;
237 }
238
browserLaunch(char * command,HANDLE * hProcess,const char * path,SWND wnd)239 static int browserLaunch(char* command, HANDLE* hProcess, const char *path,
240 SWND wnd)
241 {
242 STARTUPINFO startInfo;
243 PROCESS_INFORMATION processInfo;
244 int rc;
245 char *s, *cmdline;
246
247 if (path && path[0]) {
248 if (strstr(command,"%s") == NULL)
249 cmdline = fmtMsg(command, path);
250 else {
251 // expand %s to path
252 char buf[1024];
253 mysnprintf(buf, 1023, command, path);
254 cmdline = mystrdup(buf);
255 }
256 } else {
257 cmdline = mystrdup(command);
258 if (cmdline[0] == '"') {
259 s = strchr(cmdline+1, '"');
260 if (s) (*(s+1)) = 0;
261 } else {
262 s = strchr(cmdline, ' ');
263 if (s) *s = 0;
264 }
265 }
266
267 memset(&startInfo, 0, sizeof(startInfo));
268
269 startInfo.cb = sizeof(STARTUPINFO);
270 startInfo.dwFlags = STARTF_USESHOWWINDOW;
271 startInfo.wShowWindow = SW_SHOWNA;
272
273 if (CreateProcess(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL,
274 &startInfo, &processInfo) != 0) {
275 WaitForInputIdle( processInfo.hProcess, STARTUP_TIMEOUT );
276 CloseHandle(processInfo.hThread);
277 hProcess = processInfo.hProcess;
278 rc = TRUE;
279 } else {
280 rc = FALSE;
281 }
282 free(cmdline);
283 return rc;
284 }
285
DDECallback(UINT type,UINT fmt,HCONV hconv,HSZ hsz1,HSZ hsz2,HDDEDATA hData,DWORD dwData1,DWORD dwData2)286 static HDDEDATA DDECallback(
287 UINT type, /* transaction type */
288 UINT fmt, /* clipboard data format */
289 HCONV hconv, /* handle of conversation */
290 HSZ hsz1, /* handle of string */
291 HSZ hsz2, /* handle of string */
292 HDDEDATA hData, /* handle of global memory object */
293 DWORD dwData1, /* transaction-specific data */
294 DWORD dwData2 /* transaction-specific data */ )
295 {
296 return (HDDEDATA) 1;
297 }
298
browserGoTo(SBROWSER browser,const char * path)299 static int browserGoTo(SBROWSER browser, const char *path)
300 {
301 char *buf;
302
303 HSZ data;
304 HCONV conv;
305 HDDEDATA res;
306 int timeout = 120;
307 int rc = FALSE;
308
309 if (browser->DDEInst == 0) {
310 if (!browserConnect(browser)) return FALSE;
311 }
312 conv = DdeConnect( browser->DDEInst, browser->theirService,
313 browser->topicSZ, NULL );
314 if (conv != NULL) {
315 buf = fmtMsg( browser->remoteCommand, path );
316 data = DdeCreateStringHandle( browser->DDEInst, buf, CP_WINANSI );
317
318 if (browser->xtypExecute)
319 res = DdeClientTransaction(buf, strlen(buf)+1, conv, 0L, 0,
320 XTYP_EXECUTE, TIMEOUT_ASYNC, NULL);
321 else
322 res = DdeClientTransaction(NULL, 0, conv, data, CF_TEXT,
323 XTYP_REQUEST, TIMEOUT_ASYNC, NULL);
324
325 DdeDisconnect( conv);
326 DdeFreeStringHandle( browser->DDEInst, data);
327 free(buf);
328 if (!browser->xtypExecute)
329 bringToFront(browser);
330 rc = TRUE;
331 }
332 return rc;
333 }
334
queryValue(HKEY key,const char * subKey,char ** result)335 LONG queryValue(HKEY key, const char *subKey, char **result)
336 {
337 LONG size, rc;
338
339 rc = RegQueryValue(key, subKey, NULL, &size);
340 if (rc == ERROR_SUCCESS) {
341 *result = (char *) malloc(size + 1);
342 RegQueryValue(key, subKey, *result, &size);
343 } else {
344 *result = mystrdup("");
345 }
346 return rc;
347 }
348
349 static int
getShellOpenCommand(SBROWSER browser,const char * extension)350 getShellOpenCommand(SBROWSER browser, const char *extension)
351 {
352 HKEY key;
353 char *info;
354
355 if (queryValue(HKEY_CLASSES_ROOT, extension, &info) != ERROR_SUCCESS) {
356 return FALSE;
357 }
358
359 if (RegOpenKey(HKEY_CLASSES_ROOT, info, &key) != ERROR_SUCCESS) {
360 free(info);
361 return FALSE;
362 }
363
364 free(browser->command);
365 free(browser->remoteCommand);
366 free(browser->application);
367 free(browser->topic);
368 queryValue(key, "Shell\\Open\\command", &browser->command);
369 queryValue(key, "Shell\\Open\\ddeexec", &browser->remoteCommand);
370 browser->useRemote = browser->remoteCommand[0];
371 queryValue(key, "Shell\\Open\\ddeexec\\Application", &browser->application);
372 queryValue(key, "Shell\\Open\\ddeexec\\Topic", &browser->topic);
373
374 RegCloseKey(key);
375 free(info);
376 return TRUE;
377 }
378
379 static int
browserConnect(SBROWSER browser)380 browserConnect(SBROWSER browser)
381 {
382 int rc = FALSE;
383
384 UINT initRes = DdeInitialize(&browser->DDEInst,
385 (PFNCALLBACK) DDECallback,
386 APPCLASS_STANDARD |
387 CBF_FAIL_CONNECTIONS |
388 CBF_SKIP_DISCONNECTS,
389 0);
390
391 if (initRes == DMLERR_NO_ERROR) {
392 browser->theirService = DdeCreateStringHandle(browser->DDEInst, browser->application, CP_WINANSI );
393 browser->ourService = DdeCreateStringHandle(browser->DDEInst, "Dune", CP_WINANSI );
394 browser->topicSZ = DdeCreateStringHandle(browser->DDEInst, browser->topic, CP_WINANSI );
395
396 DdeNameService(browser->DDEInst, browser->ourService, NULL, DNS_REGISTER);
397 rc = TRUE;
398 }
399 return rc;
400 }
401
bringToFront(SBROWSER browser)402 static int bringToFront(SBROWSER browser)
403 {
404 HSZ data, activate;
405 HCONV conv;
406 int timeout = 120;
407 int rc = FALSE;
408
409 activate = DdeCreateStringHandle(browser->DDEInst, "WWW_Activate", CP_WINANSI );
410 conv = DdeConnect(browser->DDEInst, browser->theirService, activate, NULL );
411 if (conv != NULL) {
412 data = DdeCreateStringHandle(browser->DDEInst, "0xFFFFFFFF", CP_WINANSI );
413
414 DdeClientTransaction(NULL, 0, conv, data, CF_TEXT, XTYP_REQUEST,
415 TIMEOUT_ASYNC, NULL);
416
417 DdeFreeStringHandle( browser->DDEInst, data);
418 DdeDisconnect( conv);
419 rc = TRUE;
420 }
421 DdeFreeStringHandle( browser->DDEInst, activate);
422 return rc;
423 }
424
swRemoveFile(const char * filename)425 void swRemoveFile(const char* filename)
426 {
427 unlink(filename);
428 }
429
430
431 /**********/
432 /* upload */
433 /**********/
434
435 typedef struct SUpload {
436 STABLE prefs;
437 char *commandline;
438 char *htmlTag;
439 char *password;
440 } SUpload;
441
442 SUPLOAD
swUploadInit(STABLE prefs)443 swUploadInit(STABLE prefs)
444 {
445 SUpload *upload = malloc(sizeof(SUpload));
446 upload->prefs = prefs;
447 upload->commandline = mystrdup(swGetPreference(prefs, "UploadCommandLine",
448 ""));
449 upload->htmlTag = mystrdup(swGetPreference(prefs, "UploadHtmlTags",
450 ""));
451 /* do not read/store password for security reasons */
452 upload->password = malloc(1024);
453 upload->password[0] = 0;
454 VirtualLock(upload->password, 1024);
455
456 return upload;
457 }
458
459 void
swUploadGetSettings(SUPLOAD upload,const char ** commandline,const char ** htmlTag,const char ** password)460 swUploadGetSettings(SUPLOAD upload,
461 const char **commandline,
462 const char **htmlTag,
463 const char **password)
464 {
465 *commandline = upload->commandline;
466 *htmlTag = upload->htmlTag;
467 *password = upload->password;
468 }
469
470 void
swUploadSetSettings(SUPLOAD upload,const char * commandline,const char * htmlTag,const char * password)471 swUploadSetSettings(SUPLOAD upload,
472 const char *commandline,
473 const char *htmlTag,
474 const char *password)
475 {
476 free(upload->commandline);
477 free(upload->htmlTag);
478
479 upload->commandline = mystrdup(commandline);
480 upload->htmlTag = mystrdup(htmlTag);
481 if (password != NULL)
482 mystrncpy_secure(upload->password, password, 1023);
483 else
484 upload->password[0] = 0;
485
486 swSetPreference(upload->prefs, "UploadCommandLine", upload->commandline);
487 swSetPreference(upload->prefs, "UploadHtmlTags", upload->htmlTag);
488 /* do not read/store password for security reasons */
489 }
490
491 int
swHasUpload(SUPLOAD upload)492 swHasUpload(SUPLOAD upload)
493 {
494 if (strlen(upload->commandline) > 0)
495 return 1;
496 else
497 return 0;
498 }
499
500 char*
swUpload(SUPLOAD upload,char * fileToUpload,SHBROWSER browser,SWND wnd)501 swUpload(SUPLOAD upload, char *fileToUpload, SHBROWSER browser, SWND wnd)
502 {
503 static char uploadCommand[1024];
504 FILE *cmd;
505 HANDLE f;
506 struct _SECURITY_ATTRIBUTES security_attrib = {
507 sizeof(SECURITY_ATTRIBUTES),
508 NULL, // default security descriptor of the calling process
509 FALSE
510 };
511 DWORD bytesWritten;
512 static char htmlTags[1024];
513 int needPassword = 0;
514 char *htmlpath = (char *) malloc(1024);
515 htmlpath[0] = 0;
516
517 if ((upload->password != NULL) && (strlen(upload->password) != 0))
518 if (strstr(upload->commandline, "%s") != NULL)
519 if (strstr(strstr(upload->commandline, "%s") + 2, "%s") != NULL)
520 needPassword = 1; // if commandline has two %s
521 VirtualLock(uploadCommand, 1024);
522 if (needPassword)
523 mysnprintf(uploadCommand, 1023, upload->commandline, upload->password,
524 fileToUpload);
525 else
526 mysnprintf(uploadCommand, 1023, upload->commandline, fileToUpload, "");
527
528 if (system(uploadCommand) != 0) {
529 swMessageBox(wnd, "upload failed", "Upload failed",
530 SW_MB_OK, SW_MB_WARNING);
531 htmlpath[0] = 0;
532 VirtualUnlock(uploadCommand, 1024);
533 return htmlpath;
534 } else
535 VirtualUnlock(uploadCommand, 1024);
536
537 swGetTempPath(htmlpath, ".dune_upload_reload", ".html", 1024);
538
539 f = CreateFile(htmlpath,
540 GENERIC_WRITE, // open for writing
541 0, // do not share
542 &security_attrib, // security attributes
543 CREATE_NEW, // do not overwrite existing
544 FILE_ATTRIBUTE_NORMAL, // normal file
545 NULL); // no attr. template
546
547 if (f == NULL) {
548 char msg[1024];
549 mysnprintf(msg, 1023, "creation of new html file %s failed", htmlpath);
550 swMessageBox(wnd, msg, "Upload reload error", SW_MB_OK, SW_MB_WARNING);
551 htmlpath[0] = 0;
552 return htmlpath;
553 }
554 if ((upload->password != NULL) && (strlen(upload->password) != 0))
555 mysnprintf(htmlTags, 1023, upload->htmlTag, upload->password);
556 else
557 mysnprintf(htmlTags, 1023, upload->htmlTag, "");
558 if (WriteFile(f, htmlTags, sizeof(htmlTags), &bytesWritten,NULL) ==0) {
559 char msg[1024];
560 mysnprintf(msg, 1023, "write to html file %s failed", htmlpath);
561 swMessageBox(wnd, msg, "Upload reload error", SW_MB_OK, SW_MB_WARNING);
562 return htmlpath;
563 }
564 CloseHandle(f);
565 helpBrowserGoTo(browser, htmlpath);
566 return htmlpath;
567 }
568
569 void
swUploadCleanupPasswd(SUPLOAD upload)570 swUploadCleanupPasswd(SUPLOAD upload)
571 {
572 int i;
573 for (i = 0; i < strlen(upload->password); i++)
574 upload->password[i] = (char) 0;
575 VirtualUnlock(upload->password, 1024);
576 }
577
578 /* help browser */
579
580 static void saveHelpBrowserPreferences(SHBROWSER browser);
581 static int getShellOpenHelpCommand(SHBROWSER browser, const char *extension);
582 static int helpBrowserGoTo(SHBROWSER browser, const char *path);
583 static int helpBringToFront(SHBROWSER browser);
584 static int helpBrowserConnect(SHBROWSER browser);
585
586 typedef struct SHelpBrowser {
587 STABLE prefs;
588 char *helpCommand;
589 char *helpRemoteCommand;
590 char *helpApplication;
591 char *helpTopic;
592 char *helpUrl;
593 char *vrmlUrl;
594 char *x3dUrl;
595 DWORD DDEInst;
596 HSZ ourService;
597 HSZ theirService;
598 HSZ topicSZ;
599 HSZ exitSZ;
600 HANDLE hProcess;
601 } SHBrowser;
602
603
swHelpBrowserInit(STABLE prefs)604 SHBROWSER swHelpBrowserInit(STABLE prefs)
605 {
606 SHBrowser *browser = malloc(sizeof(SHBrowser));
607 char *url;
608 const char *index = "index.html";
609 const char *helpDir = HELP_URL;
610
611 browser->prefs = prefs;
612 browser->helpCommand = mystrdup(swGetPreference(prefs, "HelpCommand", ""));
613 browser->helpRemoteCommand = mystrdup(swGetPreference(prefs,
614 "HelpRemoteCommand",""));
615 browser->helpApplication = mystrdup(swGetPreference(prefs,
616 #ifdef _WIN32
617 "HelpApplication", DEFAULT_BROWSER));
618 #else
619 "HelpApplication", ""));
620 #endif
621 browser->helpTopic = mystrdup(swGetPreference(prefs, "HelpTopic", ""));
622 url = (char *) malloc(strlen(HELP_URL) + strlen(index) + 2);
623 strcpy(url, HELP_URL);
624 if (helpDir[strlen(helpDir - 1)] != '/')
625 strcat(url, "/");
626 strcat(url, index);
627 browser->helpUrl = mystrdup(swGetPreference(prefs, "HelpURL", url));
628 free(url);
629 browser->vrmlUrl = mystrdup(swGetPreference(prefs, "HelpVrml",
630 VRML_NODES_URL));
631 browser->x3dUrl = mystrdup(swGetPreference(prefs, "HelpX3D",
632 X3D_URL));
633
634 if (browser->helpCommand[0]==' ') {
635 getShellOpenHelpCommand(browser, ".htm");
636 } else if (!browser->helpCommand[0]) {
637 getShellOpenHelpCommand(browser, ".htm");
638 }
639
640 browser->hProcess = NULL;
641 browser->DDEInst = 0L;
642
643 return browser;
644 }
645
646 void
swHelpBrowserSetDefaults(SHBROWSER browser)647 swHelpBrowserSetDefaults(SHBROWSER browser)
648 {
649 char *dunedocs = NULL;
650
651 browser->helpCommand = mystrdup(WWW_BROWSER);
652 dunedocs = getenv("DUNEDOCS");
653 if (dunedocs != NULL) {
654 char *url;
655 url = (char *) malloc(strlen(dunedocs) + /* strlen(html) */ + 1);
656 strcpy(url, dunedocs);
657 browser->helpUrl = mystrdup(url);
658 free(url);
659 } else
660 browser->helpUrl = mystrdup(HELP_URL);
661 browser->vrmlUrl = mystrdup(VRML_NODES_URL);
662 browser->x3dUrl = mystrdup(X3D_URL);
663 }
664
665
swHelpBrowserGetSettings(SHBROWSER browser,const char ** helpCommand,const char ** helpRemoteCommand,const char ** helpUrl,const char ** vrmlUrl,const char ** x3dUrl,const char ** helpApplication,const char ** helpTopic)666 void swHelpBrowserGetSettings(SHBROWSER browser,
667 const char **helpCommand,
668 const char **helpRemoteCommand,
669 const char **helpUrl,
670 const char **vrmlUrl, const char **x3dUrl,
671 const char **helpApplication,
672 const char **helpTopic)
673 {
674 *helpCommand = browser->helpCommand;
675 *helpRemoteCommand = browser->helpRemoteCommand;
676 *helpUrl = browser->helpUrl;
677 *vrmlUrl = browser->vrmlUrl;
678 *x3dUrl = browser->x3dUrl;
679 *helpApplication = browser->helpApplication;
680 *helpTopic = browser->helpTopic;
681 }
682
swHelpBrowserSetSettings(SHBROWSER browser,const char * helpCommand,const char * helpRemoteCommand,const char * helpUrl,const char * vrmlUrl,const char * x3dUrl,const char * helpApplication,const char * helpTopic)683 void swHelpBrowserSetSettings(SHBROWSER browser,
684 const char *helpCommand,
685 const char *helpRemoteCommand,
686 const char *helpUrl,
687 const char *vrmlUrl, const char *x3dUrl,
688 const char *helpApplication,
689 const char *helpTopic)
690 {
691 free(browser->helpCommand);
692 free(browser->helpRemoteCommand);
693 free(browser->helpUrl);
694 free(browser->vrmlUrl);
695 free(browser->x3dUrl);
696 free(browser->helpApplication);
697 free(browser->helpTopic);
698
699 browser->helpCommand = mystrdup(helpCommand);
700 browser->helpRemoteCommand = mystrdup(helpRemoteCommand);
701 browser->helpUrl = mystrdup(helpUrl);
702 browser->vrmlUrl = mystrdup(vrmlUrl);
703 browser->x3dUrl = mystrdup(vrmlUrl);
704 browser->helpApplication = mystrdup(helpApplication);
705 browser->helpTopic = mystrdup(helpTopic);
706
707 saveHelpBrowserPreferences(browser);
708 }
709
710 void
swHelpBrowserX3d(SHBROWSER browser,const char * string,SWND wnd)711 swHelpBrowserX3d(SHBROWSER browser, const char* string, SWND wnd)
712 {
713 int pathLen=strlen(browser->x3dUrl);
714 char *path=malloc(pathLen+strlen(string)+2);
715 strcpy(path,browser->x3dUrl);
716 strcat(path,string);
717 helpBrowserGoTo(browser, path);
718 free(path);
719 }
720
721 static void
saveHelpBrowserPreferences(SHBROWSER browser)722 saveHelpBrowserPreferences(SHBROWSER browser)
723 {
724 swSetPreference(browser->prefs, "HelpCommand", browser->helpCommand);
725 swSetPreference(browser->prefs, "HelpRemoteCommand", browser->helpRemoteCommand);
726 swSetPreference(browser->prefs, "HelpUrl", browser->helpUrl);
727 swSetPreference(browser->prefs, "HelpVrml", browser->vrmlUrl);
728 swSetPreference(browser->prefs, "HelpX3d", browser->x3dUrl);
729 swSetPreference(browser->prefs, "HelpApplication", browser->helpApplication);
730 swSetPreference(browser->prefs, "HelpTopic", browser->helpTopic);
731 }
732
swHelpBrowserHTML(SHBROWSER browser,SWND wnd)733 void swHelpBrowserHTML(SHBROWSER browser, SWND wnd)
734 {
735 swHelpBrowserPath(browser, browser->helpUrl, wnd);
736 }
737
738 void
swHelpBrowserPath(SHBROWSER browser,const char * path,SWND wnd)739 swHelpBrowserPath(SHBROWSER browser, const char* path, SWND wnd)
740 {
741 if ((strstr(browser->helpCommand, "%s") != NULL) ||
742 (strstr(browser->helpCommand, "%1") != NULL)) {
743 char buf[4096];
744 mysnprintf(buf,4096, browser->helpCommand, path);
745 browserLaunch(buf, browser->hProcess, " ", wnd);
746 } else if (!helpBrowserGoTo(browser, path))
747 if (browserLaunch(browser->helpCommand, browser->hProcess, NULL, wnd)) {
748 helpBrowserGoTo(browser, path);
749 }
750 }
751
swGetHelpUrl(SHBROWSER browser)752 char *swGetHelpUrl(SHBROWSER browser)
753 {
754 return browser->helpUrl;
755 }
756
757 void
swHelpBrowserVRML(SHBROWSER browser,const char * selection_string,int isCover,SWND wnd)758 swHelpBrowserVRML(SHBROWSER browser, const char* selection_string,
759 int isCover, SWND wnd)
760 {
761 int pathLen=strlen(browser->vrmlUrl);
762 const char *coverFile="/coverNodes/nodesRef.html";
763 char* path;
764 if (isCover)
765 pathLen=strlen(browser->helpUrl)+strlen(coverFile)+1;
766 path=malloc(pathLen+strlen(selection_string)+2);
767 if (isCover) {
768 strcpy(path, browser->helpUrl);
769 strcat(path, coverFile);
770 } else
771 strcpy(path,browser->vrmlUrl);
772 strcat(path,"#");
773 strcat(path,selection_string);
774 if (strstr(browser->helpCommand, "%s") != NULL) {
775 char buf[4096];
776 mysnprintf(buf,4096, browser->helpCommand, path);
777 browserLaunch(buf, browser->hProcess, " ", wnd);
778 } else if (!helpBrowserGoTo(browser, path))
779 if (browserLaunch(browser->helpCommand, browser->hProcess, NULL, wnd)) {
780 helpBrowserGoTo(browser, path);
781 }
782 free(path);
783 }
784
swHelpBrowserShutdown(SHBROWSER browser)785 void swHelpBrowserShutdown(SHBROWSER browser)
786 {
787 saveHelpBrowserPreferences(browser);
788 if (browser->hProcess) {
789 TerminateProcess(browser->hProcess, 1);
790 CloseHandle(browser->hProcess);
791 }
792 free(browser->helpCommand);
793 free(browser->helpRemoteCommand);
794 free(browser->helpUrl);
795 free(browser->vrmlUrl);
796 free(browser->helpApplication);
797 free(browser->helpTopic);
798
799 if (browser->DDEInst != 0) {
800 DdeNameService(browser->DDEInst, NULL, NULL, DNS_UNREGISTER);
801 DdeFreeStringHandle(browser->DDEInst, browser->theirService);
802 DdeFreeStringHandle(browser->DDEInst, browser->ourService);
803 DdeFreeStringHandle(browser->DDEInst, browser->topicSZ);
804 DdeUninitialize(browser->DDEInst );
805 }
806 free(browser);
807 }
808
809 static int
getShellOpenHelpCommand(SHBROWSER browser,const char * extension)810 getShellOpenHelpCommand(SHBROWSER browser, const char *extension)
811 {
812 HKEY key;
813 char *info;
814
815 if (queryValue(HKEY_CLASSES_ROOT, extension, &info) != ERROR_SUCCESS) {
816 return FALSE;
817 }
818
819 if (RegOpenKey(HKEY_CLASSES_ROOT, info, &key) != ERROR_SUCCESS) {
820 free(info);
821 return FALSE;
822 }
823
824 free(browser->helpCommand);
825 free(browser->helpApplication);
826 free(browser->helpTopic);
827
828 queryValue(key, "Shell\\Open\\command", &browser->helpCommand);
829 // queryValue(key, "Shell\\Open\\ddeexec", &browser->helpRemoteCommand);
830 browser->helpRemoteCommand = mystrdup("%1");
831 queryValue(key, "Shell\\Open\\ddeexec\\Application", &browser->helpApplication);
832 queryValue(key, "Shell\\Open\\ddeexec\\Topic", &browser->helpTopic);
833
834 RegCloseKey(key);
835 free(info);
836 return TRUE;
837 }
838
helpBrowserGoTo(SHBROWSER browser,const char * path)839 static int helpBrowserGoTo(SHBROWSER browser, const char *path)
840 {
841 char *buf;
842
843 HSZ data;
844 HCONV conv;
845 HDDEDATA res;
846 int timeout = 120;
847 int rc = FALSE;
848
849 if (browser->DDEInst == 0) {
850 if (!helpBrowserConnect(browser)) return FALSE;
851 }
852 conv = DdeConnect(browser->DDEInst, browser->theirService,
853 browser->topicSZ, NULL );
854 if (conv != NULL) {
855 buf = fmtMsg( browser->helpRemoteCommand, path );
856 data = DdeCreateStringHandle( browser->DDEInst, buf, CP_WINANSI );
857
858 res = DdeClientTransaction(NULL, 0, conv, data, CF_TEXT,
859 XTYP_REQUEST, TIMEOUT_ASYNC, NULL);
860
861 DdeDisconnect( conv);
862 DdeFreeStringHandle( browser->DDEInst, data);
863 free(buf);
864 helpBringToFront(browser);
865 rc = TRUE;
866 }
867 return rc;
868 }
869
870
helpBringToFront(SHBROWSER browser)871 static int helpBringToFront(SHBROWSER browser)
872 {
873 HSZ data, activate;
874 HCONV conv;
875 int timeout = 120;
876 int rc = FALSE;
877
878 activate = DdeCreateStringHandle(browser->DDEInst, "WWW_Activate", CP_WINANSI );
879 conv = DdeConnect( browser->DDEInst, browser->theirService, activate, NULL );
880 if (conv != NULL) {
881 data = DdeCreateStringHandle(browser->DDEInst, "0xFFFFFFFF", CP_WINANSI );
882
883 DdeClientTransaction(NULL, 0, conv, data, CF_TEXT, XTYP_REQUEST,
884 TIMEOUT_ASYNC, NULL);
885
886 DdeFreeStringHandle(browser->DDEInst, data);
887 DdeDisconnect( conv);
888 rc = TRUE;
889 }
890 DdeFreeStringHandle(browser->DDEInst, activate);
891 return rc;
892 }
893
894 static int
helpBrowserConnect(SHBROWSER browser)895 helpBrowserConnect(SHBROWSER browser)
896 {
897 int rc = FALSE;
898
899 UINT initRes = DdeInitialize(&browser->DDEInst,
900 (PFNCALLBACK) DDECallback,
901 APPCLASS_STANDARD |
902 CBF_FAIL_CONNECTIONS |
903 CBF_SKIP_DISCONNECTS,
904 0);
905
906 if (initRes == DMLERR_NO_ERROR) {
907 browser->theirService = DdeCreateStringHandle( browser->DDEInst, browser->helpApplication, CP_WINANSI );
908 browser->ourService = DdeCreateStringHandle( browser->DDEInst, "Dune", CP_WINANSI );
909 browser->topicSZ = DdeCreateStringHandle( browser->DDEInst, browser->helpTopic, CP_WINANSI );
910
911 DdeNameService( browser->DDEInst, browser->ourService, NULL, DNS_REGISTER);
912 rc = TRUE;
913 }
914 return rc;
915 }
916
917
918 /****************/
919 /* text editor */
920 /**************/
921
922 HANDLE hProcess;
923
924 int
swCheckRunningProcess(void)925 swCheckRunningProcess(void)
926 {
927 DWORD ExitCode;
928 if (GetExitCodeProcess(hProcess, &ExitCode))
929 if (ExitCode == STILL_ACTIVE)
930 return 1;
931 else {
932 CloseHandle(hProcess);
933 return 0;
934 }
935 else
936 return 0;
937
938 }
939
940 int
swCreateCheckableProcess(const char * cmdline)941 swCreateCheckableProcess(const char *cmdline)
942 {
943 STARTUPINFO startInfo;
944 PROCESS_INFORMATION processInfo;
945 SECURITY_ATTRIBUTES securityAttributes;
946 int rc;
947
948 memset(&startInfo, 0, sizeof(startInfo));
949
950 startInfo.cb = sizeof(STARTUPINFO);
951 startInfo.dwFlags = STARTF_USESHOWWINDOW;
952 startInfo.wShowWindow = SW_SHOWNA;
953
954 memset(&securityAttributes, 0, sizeof(securityAttributes));
955
956 securityAttributes.nLength = sizeof(securityAttributes);
957 securityAttributes.lpSecurityDescriptor = (void*)PROCESS_QUERY_INFORMATION;
958 securityAttributes.bInheritHandle = TRUE;
959
960 if (CreateProcess(NULL, cmdline, &securityAttributes, NULL, TRUE, 0,
961 NULL, NULL,
962 &startInfo, &processInfo) != 0) {
963 WaitForInputIdle(processInfo.hProcess, STARTUP_TIMEOUT );
964 CloseHandle(processInfo.hThread);
965 hProcess = processInfo.hProcess;
966 rc = 0;
967 } else {
968 rc = GetLastError();
969 }
970 return rc;
971 }
972
973 typedef struct STextedit {
974 STABLE prefs;
975 char *textEditCommand;
976 char *textEditLinenumberOption;
977 int textEditUseExtensionTxt;
978 char *imageEditCommand;
979 char *imageEdit4KidsCommand;
980 char *soundEditCommand;
981 char *movieEditCommand;
982 } STextedit;
983
984
985 STEXTEDIT
swTextEditInit(STABLE prefs)986 swTextEditInit(STABLE prefs)
987 {
988 STextedit *textEdit = malloc(sizeof(STextedit));
989 textEdit->prefs = prefs;
990 if (getenv("WINEDITOR") != NULL) {
991 textEdit->textEditCommand = mystrdup(swGetPreference(
992 prefs, "TextEditCommand", getenv("WINEDITOR")));
993 textEdit->textEditLinenumberOption = mystrdup(swGetPreference(
994 prefs, "TextEditLinenumberOption", ""));
995 } else {
996 textEdit->textEditCommand = mystrdup(swGetPreference(
997 prefs, "TextEditCommand",
998 "\"C:\\Program Files\\Windows NT\\Accessories\\Wordpad.exe\""));
999 textEdit->textEditLinenumberOption = mystrdup(swGetPreference(
1000 prefs, "TextEditLinenumberOption", " "));
1001 }
1002 textEdit->textEditUseExtensionTxt = swGetIntPreference(
1003 prefs, "TextEditUseExtensionTxt", 1);
1004 textEdit->imageEditCommand = mystrdup(swGetPreference(
1005 prefs, "ImageEditCommand", "C:\\Windows\\system32\\mspaint.exe"));
1006 textEdit->imageEdit4KidsCommand = mystrdup(swGetPreference(
1007 prefs, "ImageEdit4KidsCommand", "C:\\Windows\\system32\\mspaint.exe"));
1008 textEdit->soundEditCommand = mystrdup(swGetPreference(
1009 prefs, "SoundEditCommand", HAVE_SOUND_EDITOR));
1010 textEdit->movieEditCommand = mystrdup(swGetPreference(
1011 prefs, "MovieEditCommand", HAVE_MOVIE_EDITOR));
1012
1013 return textEdit;
1014 }
1015
swTextEditGetSettingsUseExtensionTxt(STEXTEDIT textEdit,int * textEditUseExtensionTxt)1016 void swTextEditGetSettingsUseExtensionTxt(STEXTEDIT textEdit,
1017 int *textEditUseExtensionTxt)
1018 {
1019 *textEditUseExtensionTxt = textEdit->textEditUseExtensionTxt;
1020 }
1021
1022 void
swTextEditGetSettings(STEXTEDIT textEdit,const char ** textEditCommand,const char ** textEditLinenumberOption,int * textEditUseExtensionTxt)1023 swTextEditGetSettings(STEXTEDIT textEdit,
1024 const char **textEditCommand,
1025 const char **textEditLinenumberOption,
1026 int *textEditUseExtensionTxt)
1027 {
1028 *textEditCommand = textEdit->textEditCommand;
1029 *textEditLinenumberOption = textEdit->textEditLinenumberOption;
1030 *textEditUseExtensionTxt = textEdit->textEditUseExtensionTxt;
1031 }
1032
swTextEditGetCommand(STEXTEDIT textEdit)1033 char *swTextEditGetCommand(STEXTEDIT textEdit)
1034 {
1035 return textEdit->textEditCommand;
1036 }
1037
swImageEditGetSettings(STEXTEDIT textEdit)1038 char *swImageEditGetSettings(STEXTEDIT textEdit)
1039 {
1040 return textEdit->imageEditCommand;
1041 }
1042
swImageEdit4KidsGetSettings(STEXTEDIT textEdit)1043 char *swImageEdit4KidsGetSettings(STEXTEDIT textEdit)
1044 {
1045 return textEdit->imageEdit4KidsCommand;
1046 }
1047
swSoundEditGetSettings(STEXTEDIT textEdit)1048 char *swSoundEditGetSettings(STEXTEDIT textEdit)
1049 {
1050 return textEdit->soundEditCommand;
1051 }
1052
swMovieEditGetSettings(STEXTEDIT textEdit)1053 char *swMovieEditGetSettings(STEXTEDIT textEdit)
1054 {
1055 return textEdit->movieEditCommand;
1056 }
1057
1058 void
swTextEditSetSettings(STEXTEDIT textEdit,const char * textEditCommand,const char * textEditLinenumberOption,int textEditUseExtensionTxt)1059 swTextEditSetSettings(STEXTEDIT textEdit,
1060 const char *textEditCommand,
1061 const char *textEditLinenumberOption,
1062 int textEditUseExtensionTxt)
1063 {
1064 free(textEdit->textEditCommand);
1065 textEdit->textEditCommand = mystrdup(textEditCommand);
1066
1067 free(textEdit->textEditLinenumberOption);
1068 textEdit->textEditLinenumberOption = mystrdup(textEditLinenumberOption);
1069
1070 textEdit->textEditUseExtensionTxt = textEditUseExtensionTxt;
1071
1072 swSetPreference(textEdit->prefs, "TextEditCommand",
1073 textEdit->textEditCommand);
1074 swSetPreference(textEdit->prefs, "TextEditLinenumberOption",
1075 textEdit->textEditLinenumberOption);
1076 swSetIntPreference(textEdit->prefs, "TextEditUseExtensionTxt",
1077 textEdit->textEditUseExtensionTxt);
1078
1079 textEdit->imageEditCommand = mystrdup(swGetPreference(
1080 textEdit->prefs, "ImageEditCommand", HAVE_IMAGE_EDITOR));
1081 textEdit->imageEdit4KidsCommand = mystrdup(swGetPreference(
1082 textEdit->prefs, "ImageEdit4KidsCommand", HAVE_IMAGE_EDITOR4KIDS));
1083 textEdit->soundEditCommand = mystrdup(swGetPreference(
1084 textEdit->prefs, "C:\\usr\\bin\\SoundEditCommand.exe", ""));
1085 textEdit->movieEditCommand = mystrdup(swGetPreference(
1086 textEdit->prefs, "C:\\usr\\bin\\movieEditCommand.exe", ""));
1087 }
1088
1089 void
swImageEditSetSettings(STEXTEDIT textEdit,const char * imageEditCommand)1090 swImageEditSetSettings(STEXTEDIT textEdit,
1091 const char *imageEditCommand)
1092 {
1093 free(textEdit->imageEditCommand);
1094 textEdit->imageEditCommand = mystrdup(imageEditCommand);
1095 swSetPreference(textEdit->prefs, "ImageEditCommand",
1096 textEdit->imageEditCommand);
1097 }
1098
1099 void
swImageEdit4KidsSetSettings(STEXTEDIT textEdit,const char * imageEditCommand)1100 swImageEdit4KidsSetSettings(STEXTEDIT textEdit,
1101 const char *imageEditCommand)
1102 {
1103 free(textEdit->imageEdit4KidsCommand);
1104 textEdit->imageEdit4KidsCommand = mystrdup(imageEditCommand);
1105 swSetPreference(textEdit->prefs, "ImageEdit4KidsCommand",
1106 textEdit->imageEdit4KidsCommand);
1107 }
1108
1109 void
swSoundEditSetSettings(STEXTEDIT textEdit,const char * soundEditCommand)1110 swSoundEditSetSettings(STEXTEDIT textEdit,
1111 const char *soundEditCommand)
1112 {
1113 free(textEdit->soundEditCommand);
1114 textEdit->soundEditCommand = mystrdup(soundEditCommand);
1115 swSetPreference(textEdit->prefs, "SoundEditCommand",
1116 textEdit->soundEditCommand);
1117 }
1118
1119 void
swMovieEditSetSettings(STEXTEDIT textEdit,const char * movieEditCommand)1120 swMovieEditSetSettings(STEXTEDIT textEdit,
1121 const char *movieEditCommand)
1122 {
1123 free(textEdit->movieEditCommand);
1124 textEdit->movieEditCommand = mystrdup(movieEditCommand);
1125 swSetPreference(textEdit->prefs, "MovieEditCommand",
1126 textEdit->movieEditCommand);
1127 }
1128
1129
1130