source: trunk/dll/worker.c@ 1880

Last change on this file since 1880 was 1880, checked in by Gregg Young, 10 years ago

Remove dead code and comments from remaining c files. #if 0 and #if NEVER were not addressed

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 53.2 KB
Line 
1
2/***********************************************************************
3
4 $Id: worker.c 1880 2015-10-12 18:26:16Z gyoung $
5
6 Worker thread
7
8 Copyright (c) 1993-98 M. Kimes
9 Copyright (c) 2001, 2014 Steven H. Levine
10
11 16 Oct 02 SHL Comments
12 18 Oct 02 SHL MassAction:Archive - force extension so file found
13 06 Jun 05 SHL Indent -i2
14 06 Jun 05 SHL Rework Action for VAC3.65 compat
15 27 Jul 05 SHL IDM_DOITYOURSELF - avoid need to strip in ExecOnList
16 22 Jul 06 SHL Comments
17 22 Jul 06 SHL Check more run time errors
18 03 Nov 06 SHL Renames
19 03 Nov 06 SHL Count thread usage
20 21 Apr 07 GKY Find FM2Utils by path or utils directory
21 16 Jun 07 SHL Update for OpenWatcom
22 06 Aug 07 GKY Reduce DosSleep times (ticket 148)
23 07 Aug 07 SHL Use BldQuotedFileName
24 20 Aug 07 GKY Move #pragma alloc_text to end for OpenWatcom compat
25 26 Aug 07 SHL Revert to DosSleep(0)
26 29 Feb 08 GKY Refactor global command line variables to notebook.h
27 22 Jun 08 GKY Made Felete move to xworkplace trash can on systems that have it
28 16 JUL 08 GKY Use TMP directory for temp files
29 20 Jul 08 GKY Add save/append filename to clipboard.
30 02 Aug 08 GKY Limit use of "trash can" to local writable fixed drives or to trash can supported
31 drives list if it exists. Fix ability to deselect use of trash can.
32 01 Sep 08 GKY Add code to retry on Netdrives "pipe error"
33 04 Dec 08 GKY Add a DosSleep to allow file extract to complete before rescan
34 04 Dec 08 GKY Add mutex semaphore and disable fSyncUpdates for file deletes to prevent the creation
35 on dead CNRITEMS.
36 10 Dec 08 SHL Integrate exception handler support
37 25 Dec 08 GKY Add code to allow write verify to be turned off on a per drive basis
38 25 Dec 08 GKY Add DRIVE_RSCANNED flag to monitor for the first recursive drive scan per session
39 to prevent duplicate directory names in tree following a copy before initial scan.
40 07 Feb 09 GKY Allow user to turn off alert and/or error beeps in settings notebook.
41 08 Mar 09 GKY Removed variable aurguments from docopyf and unlinkf (not used)
42 08 Mar 09 GKY Additional strings move to PCSZs
43 28 Jun 09 GKY Added AddBackslashToPath() to remove repeatative code.
44 26 Jul 09 GKY Fix failure of containers to update when Tree container isn't open in FM2 lite
45 13 Dec 09 GKY Attempt to fix container update issues with FM/2 lite
46 17 JAN 10 GKY Changes to get working with Watcom 1.9 Beta (1/16/10).
47 Mostly cast CHAR CONSTANT * as CHAR *.
48 20 Nov 10 GKY Check that pTmpDir IsValid and recreate if not found; Fixes hangs caused
49 by temp file creation failures.
50 12 Nov 11 GKY Fixed extract failure caused by spaces in the arc file name.
51 04 Aug 12 GKY Changes to use Unlock to unlock files if Unlock.exe is in path both from menu/toolbar and as part of
52 copy, move and delete operations
53 04 Aug 12 GKY Changes to allow copy and move over readonly files with a warning dialog; also added a warning dialog
54 for delete of readonly files
55 10 Mar 13 GKY Improvrd readonly check on delete to allow cancel and don't ask again options
56 Added saymsg2 for this purpose
57 09 Feb 14 GKY Modified wipeallf to allow suppression of the readonly warning on delete
58 of temporary files
59 16 Feb 14 GKY Fixed move to trashcan to work when the trashcan::drives key hadn't been
60 written to OS2.INI. INI check is now only if fTrashCan is TRUE.
61 16 Feb 14 GKY Rework readonly check on delete code so it actually works in a logical way
62 and so it works with move to trashcan inabled.
63 22 Feb 14 GKY Cleanup of readonly check code suppress spurious error on blocked directory
64 delete and eliminated the check on additional temp file deletes
65 22 Feb 14 GKY Fix warn readonly yes don't ask to work when recursing directories.
66 02 May 15 GKY Changes to allow a JAVA executable object to be created using "Real object"
67 menu item on a jar file.
68 24 Jun 15 GKY Corrected failure to show error message when locked non-exe/dll file fails
69 delete
70 12 Aug 15 JBS Ticket #522: Ensure no "highmem-unsafe" functions are called directly
71 Calls to unsafe Dos... functions have been changed to call the wrapped xDos... functions
72 22 Aug 15 GKY Remove recurse scan code.
73
74***********************************************************************/
75
76#include <stdlib.h>
77#include <string.h>
78#include <ctype.h>
79#include <share.h>
80#include <process.h> // _beginthread // 10 Dec 08 SHL
81#include <time.h>
82
83#define INCL_DOS
84#define INCL_DOSERRORS
85#define INCL_LONGLONG
86#define INCL_WINPOINTERS // WinSetFileIcon
87#define INCL_WINSHELLDATA // PrfQueryProfileData
88
89#include "fm3dll.h"
90#include "fm3dll2.h" // #define's for UM_*, control id's, etc.
91#include "mainwnd2.h" // Data declaration(s)
92#include "arccnrs.h" // Data declaration(s)
93#include "init.h" // Data declaration(s)
94#include "defview.h" // Data declaration(s)
95#include "newview.h" // Data declarations
96#include "fm3dlg.h"
97#include "fm3str.h"
98#include "comp.h" // FCOMPARE
99#include "pathutil.h" // BldQuotedFileName
100#include "makelist.h" // AddToList
101#include "errutil.h" // Dos_Error...
102#include "strutil.h" // GetPString
103#include "notebook.h" // External viewers
104#include "worker.h" // Action
105#include "notify.h" // AddNote
106#include "copyf.h" // AdjustWildcardName, make_deleteable
107#include "attribs.h" // AttrListDlgProc
108#include "chklist.h" // CheckListProc
109#include "info.h" // DrvInfoProc
110#include "extract.h" // ExtractDlgProc
111#include "info.h" // FileInfoProc
112#include "valid.h" // GetDesktopName, IsNewer
113#include "saveclip.h" // ListToClipboardHab
114#include "shadow.h" // MakeShadows
115#include "mkdir.h" // MassMkdir
116#include "uudecode.h" // MergeDlgProc
117#include "objcnr.h" // ObjCnrDlgProc
118#include "printer.h" // PrintDlgProc, PrintListThread
119#include "rename.h" // RenameProc
120#include "srchpath.h" // RunFM2Util
121#include "mainwnd.h" // TopWindowName
122#include "uudecode.h" // UUD
123#include "walkem.h" // WalkCopyDlgProc, WalkDlgProc, WalkMoveDlgProc
124#include "archive.h" // ArchiveDlgProc
125#include "misc.h" // Broadcast
126#include "common.h" // DecrThreadUsage, IncrThreadUsage
127#include "eas.h" // DisplayEAsProc
128#include "systemf.h" // ExecOnList
129#include "avl.h" // SBoxDlgProc
130#include "subj.h" // Subject
131#include "stristr.h" // stristr
132#include "wrappers.h" // xfopen
133#include "fortify.h"
134#include "excputil.h" // 06 May 08 SHL added
135#include "getnames.h" // insert_filename
136
137// Data definitions
138#pragma data_seg(GLOBAL2)
139FILE *LogFileHandle;
140BOOL fUnlock;
141
142#pragma data_seg(DATA2)
143
144static PSZ pszSrcFile = __FILE__;
145
146#ifdef UNDO
147
148static VOID LINFO undo;
149
150VOID FreeUndo(VOID)
151{
152 if (undo->list)
153 FreeList(undo->list);
154 memset(&undo, 0, sizeof(undo));
155}
156
157VOID Undo(HWND hwndCnr, HWND hwndFrame, HWND hwndClient, HWND hwndParent)
158{
159 LISTINFO *li;
160 WORKER *wk;
161
162 if (undo->type && undo->list && undo->list[0]) {
163 switch (undo->type) {
164 case IDM_MOVE:
165 case IDM_COPY:
166 case IDM_EXTRACT:
167 {
168# ifdef FORTIFY
169 Fortify_EnterScope();
170# endif
171 li = xmallocz(sizeof(LISTINFO), pszSrcFile, __LINE__);
172 if (li) {
173 wk = xmallocz(sizeof(WORKER), pszSrcFile, __LINE__);
174 if (wk) {
175 wk->size = sizeof(WORKER);
176 wk->hwndCnr = hwndCnr;
177 wk->hwndParent = hwndParent;
178 wk->hwndFrame = hwndFrame;
179 wk->hwndClient = hwndClient;
180 wk->li = li;
181 *wk->li = *undo;
182 switch (undo->type) {
183 case IDM_COPY:
184 case IDM_EXTRACT:
185 li->type = IDM_PERMDELETE;
186 break;
187 }
188 if (xbeginthread(MassAction,
189 122880,
190 wk,
191 pszSrcFile,
192 __LINE__) == -1)
193 {
194 FreeListInfo(wk->li);
195 free(wk);
196# ifdef FORTIFY
197 Fortify_LeaveScope();
198# endif
199 }
200 }
201 else
202 FreeListInfo(li);
203 }
204 }
205 break;
206 } // switch
207 }
208 FreeUndo();
209# ifdef FORTIFY
210 Fortify_LeaveScope();
211# endif
212}
213
214#endif // defined(UNDO)
215
216/**
217 * Apply action to file list
218 * Action repeated for each item in list
219 */
220
221VOID Action(VOID * args)
222{
223 WORKER *wk = (WORKER *)args;
224 HAB hab2;
225 HMQ hmq2;
226 CHAR **files = NULL;
227 INT plen = 0;
228 CHAR *p, *pp;
229 CHAR szQuotedDirName[CCHMAXPATH];
230 CHAR szQuotedFileName[CCHMAXPATH];
231
232
233 if (wk) {
234# ifdef FORTIFY
235 Fortify_EnterScope();
236# endif
237 if (wk->li && wk->li->list && wk->li->list[0]) {
238 hab2 = WinInitialize(0);
239 if (hab2) {
240 hmq2 = WinCreateMsgQueue(hab2, 0);
241 if (hmq2) {
242 CHAR message[(CCHMAXPATH * 2) + 80], wildname[CCHMAXPATH];
243 UINT x;
244 BOOL dontask = FALSE, wildcarding = FALSE, overold = FALSE;
245 BOOL overnew = FALSE, usedtarget;
246 BOOL noreadonlywarn = FALSE;
247
248 WinCancelShutdown(hmq2, TRUE);
249 IncrThreadUsage();
250 *wildname = 0;
251 // Do action specific preprocessing
252 switch (wk->li->type) {
253 case IDM_MERGE:
254 if (wk->li->type == IDM_MERGE) {
255 if (TestBinary(wk->li->list[0]))
256 wk->li->type = IDM_MERGEBINARY;
257 else
258 wk->li->type = IDM_MERGETEXT;
259 }
260 strcpy(wk->li->targetpath, wk->li->list[0]);
261 p = strrchr(wk->li->targetpath, '\\');
262 if (p) {
263 p++;
264 *p = 0;
265 }
266 else
267 strcat(wk->li->targetpath, PCSZ_BACKSLASH);
268 sprintf(wk->li->targetpath + strlen(wk->li->targetpath),
269 "MERGE.%03x", (clock() & 4095L));
270 if (!WinDlgBox(HWND_DESKTOP,
271 wk->hwndFrame,
272 MergeDlgProc, FM3ModHandle, MRG_FRAME, (PVOID) wk))
273 goto Abort;
274 if (!wk->li->type ||
275 !*wk->li->targetpath || !wk->li->list || !wk->li->list[0])
276 goto Abort;
277 if (IsFile(wk->li->targetpath) != 1 && !wk->li->list[1]) {
278 saymsg(MB_CANCEL | MB_ICONEXCLAMATION,
279 wk->hwndFrame,
280 GetPString(IDS_AHEMTEXT),
281 GetPString(IDS_SILLYMERGETEXT));
282 goto Abort;
283 }
284 break;
285 case IDM_WILDMOVE:
286 wildcarding = TRUE;
287 wk->li->type = IDM_MOVE;
288 break;
289 case IDM_WILDRENAME:
290 wildcarding = TRUE;
291 wk->li->type = IDM_RENAME;
292 break;
293 case IDM_WILDCOPY:
294 wildcarding = TRUE;
295 wk->li->type = IDM_COPY;
296 break;
297 case IDM_MOVEPRESERVE:
298 {
299 CHAR preserve[CCHMAXPATH], *end;
300
301 wk->li->type = IDM_MOVE;
302 strcpy(preserve, wk->li->list[0] + 2);
303 end = strrchr(preserve, '\\');
304 if (end) {
305 end++;
306 for (x = 1; wk->li->list[x]; x++) {
307 p = preserve;
308 pp = wk->li->list[x] + 2;
309 while (p < end && toupper(*p) == toupper(*pp)) {
310 p++;
311 pp++;
312 }
313 if (*p == '\\')
314 p++;
315 if (p < end)
316 end = p;
317 }
318 *end = 0;
319 }
320 else
321 *preserve = 0;
322 plen = strlen(preserve);
323 if (plen)
324 plen += 2;
325 }
326 break;
327 case IDM_COPYPRESERVE:
328 {
329 CHAR preserve[CCHMAXPATH], *end;
330
331 wk->li->type = IDM_COPY;
332 strcpy(preserve, wk->li->list[0] + 2);
333 end = strrchr(preserve, '\\');
334 if (end) {
335 end++;
336 for (x = 1; wk->li->list[x]; x++) {
337 p = preserve;
338 pp = wk->li->list[x] + 2;
339 while (p < end && toupper(*p) == toupper(*pp)) {
340 p++;
341 pp++;
342 }
343 if (*p == '\\')
344 p++;
345 if (p < end)
346 end = p;
347 }
348 *end = 0;
349 }
350 else
351 *preserve = 0;
352 plen = strlen(preserve);
353 if (plen)
354 plen += 2;
355 }
356 break;
357 }
358 // Process each list item
359 if (wk->li && wk->li->list && wk->li->list[0]) {
360 UINT cFilesModified = 0; // Required for AddToList
361 UINT cItemsAllocated = 0; // Required for AddToList
362 UINT cItemsInList;
363 for (cItemsInList = 0; wk->li->list[cItemsInList]; cItemsInList++); // Count
364 for (x = 0; wk->li->list[x]; x++) {
365 switch (wk->li->type) {
366 case IDM_COLLECTFROMFILE:
367 if (Collector) {
368
369 CHAR *temp = xstrdup(wk->li->list[x], pszSrcFile, __LINE__);
370
371 if (temp) {
372 if (!PostMsg(Collector,
373 UM_COLLECTFROMFILE, MPFROMP(temp), MPVOID))
374 free(temp);
375 }
376 }
377 break;
378
379 case IDM_MERGEBINARY:
380 case IDM_MERGETEXT:
381 case IDM_MERGEBINARYAPPEND:
382 case IDM_MERGETEXTAPPEND:
383 {
384 FILE *in, *out;
385 CHAR *moder, *modew;
386 int c;
387
388 switch (wk->li->type) {
389 case IDM_MERGEBINARY:
390 moder = "rb";
391 modew = "wb";
392 break;
393 case IDM_MERGEBINARYAPPEND:
394 moder = "rb";
395 modew = "a+b";
396 break;
397 case IDM_MERGETEXTAPPEND:
398 moder = "r";
399 modew = "a+";
400 break;
401 default:
402 moder = "r";
403 modew = "w";
404 break;
405 }
406 in = xfsopen(wk->li->list[x], moder, SH_DENYWR, pszSrcFile, __LINE__, TRUE);
407 if (!in) {
408 if (saymsg(MB_ENTERCANCEL,
409 HWND_DESKTOP,
410 GetPString(IDS_MERGEERRORTEXT),
411 GetPString(IDS_CANTOPENINPUTTEXT),
412 wk->li->list[x]) == MBID_CANCEL)
413 goto Abort;
414 }
415 else {
416 out = xfsopen(wk->li->targetpath, modew, SH_DENYWR,
417 pszSrcFile, __LINE__, TRUE);
418 if (out) {
419 fseek(out, 0L, SEEK_END);
420 switch (wk->li->type) {
421 case IDM_MERGEBINARY:
422 wk->li->type = IDM_MERGEBINARYAPPEND;
423 break;
424 default:
425 wk->li->type = IDM_MERGETEXTAPPEND;
426 break;
427 }
428 sprintf(message,
429 GetPString(IDS_MERGINGTEXT),
430 wk->li->list[x], wk->li->targetpath);
431 AddNote(message);
432 while ((c = fgetc(in)) != EOF)
433 fputc(c, out);
434 fclose(out);
435 sprintf(message,
436 GetPString(IDS_MERGECOMPLETETEXT),
437 wk->li->list[x], wk->li->targetpath);
438 AddNote(message);
439 }
440 else {
441 saymsg(MB_CANCEL,
442 HWND_DESKTOP,
443 GetPString(IDS_MERGEERRORTEXT),
444 GetPString(IDS_CANTOPENOUTPUTTEXT),
445 wk->li->targetpath);
446 fclose(in);
447 goto Abort;
448 }
449 fclose(in);
450 }
451 }
452 break;
453
454 case IDM_UUDECODE:
455 {
456 CHAR outname[CCHMAXPATH + 2];
457
458 sprintf(message,
459 GetPString(IDS_UUDECODINGTEXT), wk->li->list[x]);
460 AddNote(message);
461 if (UUD(wk->li->list[x], outname) && *outname) {
462 sprintf(message,
463 GetPString(IDS_UUDECODECOMPLETETEXT),
464 wk->li->list[x]);
465 AddNote(message);
466 if (AddToList(outname, &files, &cFilesModified, &cItemsAllocated))
467 Broadcast(hab2,
468 wk->hwndCnr,
469 UM_UPDATERECORD, MPFROMP(outname), MPVOID);
470 }
471 else {
472 sprintf(message,
473 GetPString(IDS_UUDECODEABORTEDTEXT),
474 wk->li->list[x]);
475 AddNote(message);
476 }
477 }
478 break;
479
480 case IDM_UNLOCKFILE:
481 if (IsFile(wk->li->list[x]) > 0 && fUnlock) {
482 runemf2(SEPARATE | INVISIBLE | BACKGROUND | WAIT,
483 HWND_DESKTOP, pszSrcFile, __LINE__,
484 NULL, NULL, "%s %s", PCSZ_UNLOCKEXE, wk->li->list[x]);
485 }
486 break;
487
488 case IDM_VIEWARCHIVE:
489 if (IsFile(wk->li->list[x]) > 0) {
490
491 ARC_TYPE *info = NULL; // Say calling for editing - fixme to know why?
492
493 if (WinDlgBox(HWND_DESKTOP,
494 wk->hwndFrame,
495 SBoxDlgProc,
496 FM3ModHandle,
497 ASEL_FRAME, (PVOID) & info) && info) {
498 WinSendMsg(wk->hwndCnr,
499 UM_OPENWINDOWFORME,
500 MPFROMP(wk->li->list[x]), MPFROMP(info));
501 }
502 }
503 break;
504
505 case IDM_EXTRACT:
506 {
507 EXTRDATA ex;
508 BOOL maskspaces = FALSE;
509 CHAR arcname[CCHMAXPATH];
510
511 memset(&ex, 0, sizeof(EXTRDATA));
512 ex.info = find_type(wk->li->list[x], NULL);
513 if (!ex.info || (!ex.info->extract && !ex.info->exwdirs))
514 break;
515 ex.size = sizeof(EXTRDATA);
516 BldQuotedFileName(arcname, wk->li->list[x]);
517 ex.arcname = arcname;
518 if (!*ex.masks)
519 strcpy(ex.masks, "*");
520 strcpy(ex.extractdir, wk->li->targetpath);
521 if (!WinDlgBox(HWND_DESKTOP,
522 wk->hwndFrame,
523 ExtractDlgProc,
524 FM3ModHandle,
525 EXT_FRAME,
526 (PVOID) & ex) ||
527 !ex.ret ||
528 !*ex.command || !*ex.arcname || !*ex.extractdir)
529 goto Abort;
530 {
531 FILESTATUS3 fsa;
532
533 DosError(FERR_DISABLEHARDERR);
534 if (DosQueryPathInfo(ex.extractdir,
535 FIL_STANDARD,
536 &fsa,
537 (ULONG) sizeof(FILESTATUS3)) ||
538 !(fsa.attrFile & FILE_DIRECTORY))
539 goto Abort;
540 }
541 if (needs_quoting(ex.masks) && !strchr(ex.masks, '\"'))
542 maskspaces = TRUE;
543 if (!runemf2(SEPARATE | WINDOWED | WAIT |
544 fArcStuffVisible ? 0 : (BACKGROUND | MINIMIZED),
545 HWND_DESKTOP, pszSrcFile, __LINE__, ex.extractdir, NULL,
546 "%s %s %s%s%s",
547 ex.command,
548 ex.arcname,
549 maskspaces ? "\"" : NullStr,
550 *ex.masks ? ex.masks : "\"*\"",
551 maskspaces ? "\"" : NullStr) &&
552 !stricmp(ex.extractdir, wk->directory)) {
553 DosSleep(100); // wait for runemf2 to complete so rescan will actually show something
554 if (WinIsWindow((HAB) 0, wk->hwndCnr))
555 WinSendMsg(wk->hwndCnr,
556 WM_COMMAND,
557 MPFROM2SHORT(IDM_RESCAN, 0), MPVOID);
558 }
559 }
560 break;
561
562 case IDM_SUBJECT:
563 {
564 INT ret;
565
566 ret = Subject(wk->hwndFrame, wk->li->list[x]);
567 if (!ret)
568 goto Abort;
569 if (ret == 1) {
570 if (AddToList(wk->li->list[x],
571 &files, &cFilesModified, &cItemsAllocated))
572 Broadcast(hab2,
573 wk->hwndCnr,
574 UM_UPDATERECORD,
575 MPFROMP(wk->li->list[x]), MPVOID);
576 }
577 }
578 break;
579
580 case IDM_INFO:
581 if (IsFullName(wk->li->list[x]) &&
582 !(driveflags[toupper(*wk->li->list[x]) - 'A'] &
583 DRIVE_INVALID)) {
584 if (!IsRoot(wk->li->list[x])) {
585
586 CHAR *list[2];
587
588 list[0] = wk->li->list[x];
589 list[1] = NULL;
590 if (!WinDlgBox(HWND_DESKTOP,
591 HWND_DESKTOP,
592 FileInfoProc,
593 FM3ModHandle, FLE_FRAME, (PVOID) list)) {
594 goto Abort;
595 }
596 }
597 else {
598 if (!WinDlgBox(HWND_DESKTOP,
599 HWND_DESKTOP,
600 DrvInfoProc,
601 FM3ModHandle,
602 INFO_FRAME, (PVOID) wk->li->list[x]))
603 goto Abort;
604 }
605 }
606 break;
607
608 case IDM_OPENWINDOW:
609 if (!IsFile(wk->li->list[x]) &&
610 WinIsWindow(hab2, wk->hwndCnr))
611 WinSendMsg(wk->hwndCnr,
612 UM_OPENWINDOWFORME,
613 MPFROMP(wk->li->list[x]), MPVOID);
614 break;
615
616 case IDM_OPENICON:
617 case IDM_OPENDETAILS:
618 case IDM_OPENTREE:
619 {
620 FILESTATUS3 fsa;
621
622 DosError(FERR_DISABLEHARDERR);
623 if (DosQueryPathInfo(wk->li->list[x],
624 FIL_STANDARD,
625 &fsa,
626 (ULONG) sizeof(FILESTATUS3)) ||
627 !(fsa.attrFile & FILE_DIRECTORY))
628 break;
629 }
630 // else intentional fallthru
631 case IDM_OPENDEFAULT:
632 case IDM_OPENSETTINGS:
633 {
634 CHAR *s;
635
636 switch (wk->li->type) {
637 case IDM_OPENICON:
638 s = (PSZ) PCSZ_ICON;
639 break;
640 case IDM_OPENDETAILS:
641 s = (PSZ) Details;
642 break;
643 case IDM_OPENTREE:
644 s = (PSZ) PCSZ_TREE;
645 break;
646 case IDM_OPENSETTINGS:
647 s = (PSZ) Settings;
648 break;
649 default:
650 s = (PSZ) Default;
651 break;
652 }
653 OpenObject(wk->li->list[x], s, wk->hwndFrame);
654 }
655 break;
656
657 case IDM_WPSMOVE:
658 case IDM_WPSCOPY:
659 case IDM_MOVE:
660 case IDM_COPY:
661 case IDM_RENAME:
662 {
663
664 // Select target
665 if (!*wk->li->targetpath && (wk->li->type == IDM_MOVE ||
666 wk->li->type == IDM_COPY ||
667 wk->li->type == IDM_WPSMOVE ||
668 wk->li->type == IDM_WPSCOPY)) {
669
670 APIRET rc = 1;
671 usedtarget = FALSE;
672 if (hwndMain) {
673 if (!*targetdir)
674 TopWindowName(hwndMain,
675 wk->hwndFrame, wk->li->targetpath);
676 else {
677 strcpy(wk->li->targetpath, targetdir);
678 usedtarget = TRUE;
679 }
680 }
681 if (!*wk->li->targetpath)
682 strcpy(wk->li->targetpath, wk->directory);
683 if (!*wk->li->targetpath) {
684 strcpy(wk->li->targetpath, wk->li->list[0]);
685 p = strrchr(wk->li->targetpath, '\\');
686 if (p) {
687 if (*(p - 1) == ':')
688 p++;
689 *p = 0;
690 }
691 }
692 MakeValidDir(wk->li->targetpath);
693 if (fConfirmTarget ||
694 (!*targetdir && strcmp(realappname, "FM/4"))) {
695 RetryPath:
696 // Confirm target
697 usedtarget = FALSE;
698 if (wk->li->type == IDM_MOVE ||
699 wk->li->type == IDM_WPSMOVE) {
700 rc = WinDlgBox(HWND_DESKTOP,
701 wk->hwndFrame,
702 WalkMoveDlgProc,
703 FM3ModHandle,
704 WALK_FRAME, MPFROMP(wk->li->targetpath));
705 }
706 else if (wk->li->type == IDM_COPY ||
707 wk->li->type == IDM_WPSCOPY) {
708 rc = WinDlgBox(HWND_DESKTOP,
709 wk->hwndFrame,
710 WalkCopyDlgProc,
711 FM3ModHandle,
712 WALK_FRAME, MPFROMP(wk->li->targetpath));
713 }
714 else
715 rc = WinDlgBox(HWND_DESKTOP,
716 wk->hwndFrame,
717 WalkDlgProc,
718 FM3ModHandle,
719 WALK_FRAME, MPFROMP(wk->li->targetpath));
720 }
721 if (!rc || !*wk->li->targetpath)
722 goto Abort;
723 // Check target OK
724 if (driveflags[toupper(*wk->li->targetpath) - 'A'] &
725 DRIVE_NOTWRITEABLE) {
726 saymsg(MB_CANCEL,
727 wk->hwndFrame,
728 GetPString(IDS_ERRORTEXT),
729 GetPString(IDS_NOTWRITENOTARGETTEXT));
730 goto RetryPath;
731 }
732 }
733 Retry:
734 {
735 // Target OK so far
736 CHAR newname[CCHMAXPATH];
737 APIRET rc;
738 INT ret;
739 FILESTATUS4L fs4;
740 BOOL isnewer;
741 BOOL existed;
742 BOOL fResetVerify = FALSE;
743 INT type = wk->li->type == IDM_RENAME ?
744 MOVE :
745 wk->li->type == IDM_MOVE ?
746 MOVE : (wk->li->type == IDM_WPSMOVE) ?
747 WPSMOVE : wk->li->type == IDM_WPSCOPY ?
748 WPSCOPY : COPY;
749 PCSZ moving = wk->li->type == IDM_RENAME ?
750 GetPString(IDS_RENAMINGTEXT) :
751 wk->li->type == IDM_MOVE || wk->li->type == IDM_WPSMOVE ?
752 GetPString(IDS_MOVINGTEXT) : GetPString(IDS_COPYINGTEXT);
753 PCSZ move = wk->li->type == IDM_RENAME ?
754 GetPString(IDS_RENAMETEXT) :
755 wk->li->type == IDM_MOVE ||
756 wk->li->type == IDM_WPSMOVE ?
757 GetPString(IDS_MOVETEXT) : GetPString(IDS_COPYTEXT);
758 PCSZ moved = wk->li->type == IDM_RENAME ?
759 GetPString(IDS_RENAMEDTEXT) :
760 wk->li->type == IDM_MOVE || wk->li->type == IDM_WPSMOVE ?
761 GetPString(IDS_MOVEDTEXT) : GetPString(IDS_COPIEDTEXT);
762
763 if (*wk->li->targetpath) {
764 strcpy(newname, wk->li->targetpath);
765 AddBackslashToPath(newname);
766 if (plen)
767 p = wk->li->list[x] + plen;
768 else {
769 p = strrchr(wk->li->list[x], '\\');
770 if (p)
771 p++;
772 else
773 p = wk->li->list[x];
774 }
775 strcat(newname, p);
776 }
777 else
778 strcpy(newname, wk->li->list[x]);
779 if ((wildcarding || wk->li->type == IDM_RENAME) &&
780 *wildname)
781 {
782 CHAR testname[CCHMAXPATH];
783 strcpy(testname, wildname);
784 if (AdjustWildcardName(newname, testname))
785 strcpy(newname, testname);
786 }
787 existed = IsFile(newname) != -1;
788 isnewer = IsNewer(wk->li->list[x], newname);
789 if (existed && wk->li->type != IDM_RENAME && dontask) {
790 if (!overold && !overnew)
791 break;
792 if (!overold && !isnewer)
793 break;
794 if (!overnew && isnewer)
795 break;
796 }
797 // Confirm overwrite unless bypassed
798 if ((wk->li->type == IDM_RENAME &&
799 (!dontask || !*wildname)) ||
800 (!dontask && existed) ||
801 (!dontask && wildcarding) ||
802 (IsFile(newname) == 0 && IsFile(wk->li->list[x]) > 0))
803 {
804 MOVEIT mv;
805 memset(&mv, 0, sizeof(MOVEIT));
806 mv.rename = (wk->li->type == IDM_RENAME);
807 mv.source = wk->li->list[x];
808 strcpy(mv.target, newname);
809 rc = WinDlgBox(HWND_DESKTOP,
810 wk->hwndFrame,
811 RenameProc,
812 FM3ModHandle, REN_FRAME, (PVOID) & mv);
813 if (!rc)
814 goto Abort;
815
816 DosSleep(1);
817 if (mv.skip || !*mv.target)
818 break;
819 if (mv.dontask)
820 dontask = TRUE;
821 if (mv.overold)
822 overold = TRUE;
823 if (mv.overnew)
824 overnew = TRUE;
825 if (mv.noreadonlywarn)
826 noreadonlywarn = TRUE;
827 if (wildcarding || wk->li->type == IDM_RENAME) {
828 p = strrchr(mv.target, '\\');
829 if (p && (strchr(p, '*') || strchr(p, '?'))) {
830 strcpy(wildname, mv.target);
831 AdjustWildcardName(wk->li->list[x], mv.target);
832 }
833 else
834 *wildname = 0;
835 }
836 strcpy(newname, mv.target);
837 existed = (IsFile(newname) != -1);
838 isnewer = IsNewer(wk->li->list[x], newname);
839 if (!mv.overwrite) {
840 if (existed && wk->li->type != IDM_RENAME && dontask) {
841 if (!overold && !overnew)
842 break;
843 if (!overold && !isnewer)
844 break;
845 if (!overnew && isnewer)
846 break;
847 }
848 }
849 }
850 if (!strcmp(wk->li->list[x], newname) ||
851 (wk->li->type == IDM_COPY &&
852 !stricmp(wk->li->list[x], newname)))
853 break;
854 sprintf(message,
855 " %s \"%s\" %s\"%s\"%s [%u %s%u]",
856 moving,
857 wk->li->list[x],
858 GetPString(IDS_TOTEXT), // Has trailing space
859 newname,
860 usedtarget ?
861 GetPString(IDS_TOTARGETTEXT) :
862 NullStr,
863 x + 1,
864 GetPString(IDS_OFTEXT), // Has trailing space
865 cItemsInList);
866 AddNote(message);
867 if (fVerify && (driveflags[toupper(*wk->li->targetpath) - 'A'] & DRIVE_WRITEVERIFYOFF) |
868 (driveflags[toupper(*wk->li->list[x]) - 'A'] & DRIVE_WRITEVERIFYOFF)) {
869 DosSetVerify(FALSE);
870 fResetVerify = TRUE;
871 }
872 if (plen) {
873 // make directory/ies, if required
874
875 CHAR dirpart[CCHMAXPATH];
876
877 strcpy(dirpart, newname);
878 p = strrchr(dirpart, '\\');
879 if (p) {
880 *p = 0;
881 if (p > dirpart + 3)
882 MassMkdir((hwndMain) ? hwndMain : wk->hwndCnr,
883 dirpart);
884 }
885 }
886 if (fRealIdle)
887 priority_idle();
888
889 rc = docopyf(type, wk->li->list[x], newname);
890 if (rc == ERROR_ACCESS_DENIED || rc == ERROR_SHARING_VIOLATION) {
891 ret = make_deleteable(newname, rc, noreadonlywarn);
892 if (ret == SM2_CANCEL)
893 break;
894 if (ret == SM2_DONTASK)
895 noreadonlywarn = TRUE;
896 if (ret == SM2_NO)
897 continue;
898 rc = docopyf(type, wk->li->list[x], newname);
899 }
900 if (rc == ERROR_ACCESS_DENIED || (rc == ERROR_SHARING_VIOLATION && fUnlock))
901 rc = NO_ERROR;
902 if (fResetVerify) {
903 DosSetVerify(fVerify);
904 fResetVerify = FALSE;
905 }
906 priority_normal();
907 if (rc) {
908 if ((rc == ERROR_DISK_FULL ||
909 rc == ERROR_HANDLE_DISK_FULL) &&
910 isalpha(*newname) &&
911 (driveflags[toupper(*newname) - 'A'] &
912 DRIVE_REMOVABLE)
913 && !(driveflags[toupper(*newname) - 'A'] &
914 DRIVE_NOTWRITEABLE)
915 && toupper(*newname) != toupper(*wk->li->list[x])
916 && !DosQueryPathInfo(wk->li->list[x], FIL_QUERYEASIZEL,
917 &fs4, sizeof(fs4))
918 && !(fs4.attrFile & FILE_DIRECTORY)) {
919
920 FSALLOCATE fsa;
921 ULONGLONG ullFreeBytes;
922 CHAR *ptr;
923 INT cntr;
924
925 Notify(GetPString(IDS_FITTINGTEXT));
926 DosError(FERR_DISABLEHARDERR);
927 if (!DosQueryFSInfo(toupper(*newname) - '@',
928 FSIL_ALLOC,
929 &fsa, sizeof(FSALLOCATE))) {
930 // Assume large file support
931 ullFreeBytes = (ULONGLONG) fsa.cUnitAvail * fsa.cSectorUnit *
932 fsa.cbSector;
933 if (ullFreeBytes) {
934 // Find item that will fit in available space
935 for (cntr = x + 1; wk->li->list[cntr]; cntr++) {
936 DosError(FERR_DISABLEHARDERR);
937 if (!DosQueryPathInfo(wk->li->list[cntr],
938 FIL_QUERYEASIZEL,
939 &fs4,
940 sizeof(fs4)) &&
941 !(fs4.attrFile & FILE_DIRECTORY) &&
942 // fixme to use CBLIST_TO_EASIZE?
943 fs4.cbFile + fs4.cbList <= ullFreeBytes) {
944 // Swap with failing item
945 ptr = wk->li->list[x];
946 wk->li->list[x] = wk->li->list[cntr];
947 wk->li->list[cntr] = ptr;
948 goto Retry;
949 }
950 }
951 Notify(GetPString(IDS_COULDNTFITTEXT));
952 }
953 }
954 rc = saymsg(MB_ABORTRETRYIGNORE | MB_ICONEXCLAMATION,
955 wk->hwndFrame,
956 GetPString(IDS_DISKFULLTEXT),
957 GetPString(IDS_ANOTHERDISKTEXT));
958 if (rc == MBID_RETRY)
959 goto Retry;
960 if (rc == MBID_ABORT)
961 goto Abort;
962 }
963 else {
964 if (LogFileHandle) {
965 fprintf(LogFileHandle,
966 GetPString(IDS_LOGTOFAILEDTEXT),
967 move, wk->li->list[x], newname, rc);
968 }
969 rc = Dos_Error(MB_ENTERCANCEL,
970 rc,
971 wk->hwndFrame,
972 pszSrcFile,
973 __LINE__,
974 "%s %s\"%s\" %s\"%s\" %s.",
975 move, // move, copy, rename etc.
976 GetPString(IDS_OFTEXT), // "of " - note trailing space
977 wk->li->list[x],
978 GetPString(IDS_TOTEXT), // "to "
979 newname, GetPString(IDS_FAILEDTEXT)); // "failed"
980 if (rc == MBID_CANCEL)
981 goto Abort;
982 }
983 }
984 else {
985 if (LogFileHandle) {
986 fprintf(LogFileHandle,
987 "%s \"%s\" %s\"%s\"\n",
988 moved,
989 wk->li->list[x],
990 GetPString(IDS_TOTEXT), newname);
991 }
992 if (!strcmp(realappname, "FM/4") || !strcmp(realappname, "FM/3") ||
993 AddToList(wk->li->list[x], &files, &cFilesModified,
994 &cItemsAllocated))
995 Broadcast(hab2,
996 wk->li->type == IDM_RENAME ? wk->hwndParent : wk->hwndCnr,
997 UM_UPDATERECORD,
998 MPFROMP(wk->li->list[x]), MPVOID);
999 if (!strcmp(realappname, "FM/4") || !strcmp(realappname, "FM/3") ||
1000 AddToList(newname, &files, &cFilesModified, &cItemsAllocated))
1001 Broadcast(hab2,
1002 wk->li->type == IDM_RENAME ? wk->hwndParent : wk->hwndCnr,
1003 UM_UPDATERECORD, MPFROMP(newname), MPVOID);
1004 }
1005 }
1006 break;
1007 }
1008
1009 case IDM_COMPARE:
1010 if ((!IsFile(wk->li->targetpath) ||
1011 IsRoot(wk->li->targetpath)) &&
1012 (!IsFile(wk->li->list[x]) || IsRoot(wk->li->list[x]))) {
1013 if (!*dircompare && WinIsWindow(hab2, wk->hwndCnr))
1014 WinSendMsg(wk->hwndCnr,
1015 UM_COMPARE,
1016 MPFROMP(wk->li->targetpath),
1017 MPFROMP(wk->li->list[x]));
1018 else {
1019 runemf2(SEPARATE,
1020 HWND_DESKTOP, pszSrcFile, __LINE__,
1021 NULL, NULL,
1022 "%s %s %s",
1023 dircompare,
1024 BldQuotedFileName(szQuotedDirName, wk->li->targetpath),
1025 BldQuotedFileName(szQuotedFileName, wk->li->list[x]));
1026 }
1027 }
1028 else if (*compare) {
1029 CHAR *fakelist[3];
1030
1031 fakelist[0] = wk->li->list[x];
1032 fakelist[1] = wk->li->targetpath;
1033 fakelist[2] = NULL;
1034 ExecOnList(wk->hwndFrame,
1035 compare,
1036 WINDOWED | SEPARATEKEEP, NULL, NULL, fakelist, NULL,
1037 pszSrcFile, __LINE__);
1038 }
1039 else {
1040 FCOMPARE fc;
1041
1042 memset(&fc, 0, sizeof(fc));
1043 fc.size = sizeof(fc);
1044 fc.hwndParent = wk->hwndParent;
1045 strcpy(fc.file1, wk->li->list[x]);
1046 strcpy(fc.file2, wk->li->targetpath);
1047 if (WinDlgBox(HWND_DESKTOP,
1048 wk->hwndFrame,
1049 CFileDlgProc,
1050 FM3ModHandle, FCMP_FRAME, (PVOID) & fc))
1051 goto Abort;
1052 }
1053 break;
1054 } // switch
1055 DosSleep(0);
1056 } // for list
1057
1058 // Do action specific post-processing
1059 switch (wk->li->type) {
1060 case IDM_MOVE:
1061 case IDM_COPY:
1062 case IDM_WPSMOVE:
1063 case IDM_WPSCOPY:
1064 case IDM_RENAME:
1065 sprintf(message,
1066 GetPString(IDS_OPSCOMPLETETEXT),
1067 wk->li->type == IDM_MOVE ?
1068 GetPString(IDS_MOVETEXT) :
1069 wk->li->type == IDM_COPY ?
1070 GetPString(IDS_COPYTEXT) :
1071 wk->li->type == IDM_WPSMOVE ?
1072 GetPString(IDS_WPSMOVETEXT) :
1073 wk->li->type == IDM_WPSCOPY ?
1074 GetPString(IDS_WPSCOPYTEXT) :
1075 GetPString(IDS_RENAMETEXT),
1076 &"s"[x == 1], // s or nul
1077 (wk->li->type == IDM_MOVE ||
1078 wk->li->type == IDM_COPY ||
1079 wk->li->type == IDM_WPSMOVE ||
1080 wk->li->type == IDM_WPSCOPY) ?
1081 GetPString(IDS_TOTEXT) : NullStr,
1082 (wk->li->type == IDM_MOVE ||
1083 wk->li->type == IDM_COPY ||
1084 wk->li->type == IDM_WPSMOVE ||
1085 wk->li->type == IDM_WPSCOPY) ?
1086 wk->li->targetpath : NullStr,
1087 GetPString(x != 1 ? IDS_ARETEXT : IDS_ISTEXT));
1088 Notify(message);
1089 if (toupper(*wk->li->targetpath) < 'C' && !fAlertBeepOff)
1090 DosBeep(1000, 25); // Wake up user
1091 DosSleep(16);
1092 if (wk->li->type == IDM_WPSMOVE || wk->li->type == IDM_WPSCOPY)
1093 DosSleep(48);
1094 break;
1095 default:
1096 break;
1097 }
1098 } // if have non-empty list
1099
1100 Abort:
1101
1102 if (files) {
1103 if (!strcmp(realappname, "FM/4") || !hwndTree ||
1104 (driveflags[*wk->li->targetpath - 'A'] & DRIVE_RSCANNED))
1105 Broadcast(hab2,
1106 wk->hwndCnr,
1107 UM_UPDATERECORDLIST, MPFROMP(files), MPVOID);
1108 FreeList(files);
1109 }
1110
1111 if (WinIsWindow(hab2, wk->hwndCnr))
1112 PostMsg(wk->hwndCnr, UM_RESCAN, MPVOID, MPVOID);
1113
1114 WinDestroyMsgQueue(hmq2);
1115 } // if queue
1116 DecrThreadUsage();
1117 WinTerminate(hab2);
1118 } // if hab2
1119 } // if list not empty
1120
1121 if (wk->li)
1122 FreeListInfo(wk->li);
1123 free(wk);
1124# ifdef FORTIFY
1125 Fortify_LeaveScope();
1126# endif
1127 DosPostEventSem(CompactSem);
1128 }
1129}
1130
1131/**
1132 * Apply file list to action
1133 * All items in list processed as a group, if possible
1134 */
1135
1136VOID MassAction(VOID * args)
1137{
1138 WORKER *wk = (WORKER *) args;
1139 HAB hab2;
1140 HMQ hmq2;
1141 CHAR **files = NULL;
1142 CHAR *p, *pp;
1143 UINT numfiles = 0, numalloc = 0;
1144
1145
1146 if (wk) {
1147# ifdef FORTIFY
1148 // Fortify_BecomeOwner(wk);
1149 Fortify_EnterScope();
1150# endif
1151 if (wk->li && wk->li->list && wk->li->list[0]) {
1152 hab2 = WinInitialize(0);
1153 if (hab2) {
1154 hmq2 = WinCreateMsgQueue(hab2, 0);
1155 if (hmq2) {
1156 WinCancelShutdown(hmq2, TRUE);
1157 IncrThreadUsage();
1158 DosError(FERR_DISABLEHARDERR);
1159 if (IsRoot(wk->li->list[0]) || !IsFile(wk->li->list[0])) {
1160 if (wk->li->type == IDM_VIEW)
1161 wk->li->type = IDM_INFO;
1162 if (wk->li->type == IDM_EDIT)
1163 wk->li->type = IDM_EAS;
1164 }
1165 switch (wk->li->type) {
1166 case IDM_INFO:
1167 if (WinDlgBox(HWND_DESKTOP,
1168 wk->hwndFrame,
1169 FileInfoProc,
1170 FM3ModHandle, FLE_FRAME, (PVOID) wk->li->list) != 2)
1171 {
1172 break;
1173 }
1174 // else intentional fallthru
1175 case IDM_UPDATE:
1176 Broadcast(hab2,
1177 wk->hwndCnr,
1178 UM_UPDATERECORDLIST, MPFROMP(wk->li->list), MPVOID);
1179 break;
1180
1181 case IDM_EAS:
1182 if (WinDlgBox(HWND_DESKTOP,
1183 wk->hwndFrame,
1184 DisplayEAsProc,
1185 FM3ModHandle, EA_FRAME, (PVOID) wk->li->list))
1186 Broadcast(hab2,
1187 wk->hwndCnr,
1188 UM_UPDATERECORDLIST, MPFROMP(wk->li->list), MPVOID);
1189 break;
1190
1191 case IDM_DOITYOURSELF:
1192 ExecOnList(wk->hwndFrame,
1193 "%a",
1194 WINDOWED | SEPARATE | PROMPT, NULL,
1195 NULL, wk->li->list, GetPString(IDS_DOITYOURSELFTEXT),
1196 pszSrcFile, __LINE__);
1197 break;
1198
1199 case IDM_MCIPLAY:
1200 {
1201 UINT x;
1202 UINT MaxFM2playStrLen = 24;
1203 ULONG total;
1204 CHAR fbuf[CCHMAXPATH];
1205
1206 if (DosSearchPath(SEARCH_IGNORENETERRS | SEARCH_ENVIRONMENT |
1207 SEARCH_CUR_DIRECTORY,
1208 (CHAR *) PCSZ_PATH, (CHAR *) PCSZ_FM2PLAYEXE, (PBYTE)fbuf, CCHMAXPATH - 1))
1209 total = MaxFM2playStrLen;
1210 else
1211 total = strlen(fbuf);
1212 for (x = 0; wk->li->list[x]; x++)
1213 total += (strlen(wk->li->list[x]) + 1 +
1214 (needs_quoting(wk->li->list[x]) * 2));
1215 if (total > 1000) {
1216
1217 FILE *fp;
1218 CHAR szTempFile[CCHMAXPATH];
1219 CHAR *modew = "w";
1220
1221 if (pTmpDir && !IsValidDir(pTmpDir))
1222 DosCreateDir(pTmpDir, 0);
1223 BldFullPathName(szTempFile, pTmpDir, PCSZ_FM2PLAYTEMP);
1224 fp = xfopen(szTempFile, modew, pszSrcFile, __LINE__, FALSE);
1225 if (fp) {
1226 fprintf(fp, "%s", ";AV/2-built FM2Play listfile\n");
1227 for (x = 0; wk->li->list[x]; x++)
1228 fprintf(fp, "%s\n", wk->li->list[x]);
1229 fprintf(fp, ";end\n");
1230 fclose(fp);
1231 strrev(szTempFile);
1232 strcat(szTempFile, "@/");
1233 strrev(szTempFile);
1234 RunFM2Util(PCSZ_FM2PLAYEXE, szTempFile);
1235 }
1236 }
1237 }
1238 // intentional fallthru
1239 case IDM_FAKEEXTRACT:
1240 case IDM_FAKEEXTRACTM:
1241 if (wk->li->type == IDM_MCIPLAY ||
1242 (*wk->li->arcname && wk->li->info &&
1243 wk->li->info->extract && *wk->li->targetpath)) {
1244
1245 CHAR szBuffer[1025];
1246 CHAR fbuf[CCHMAXPATH];
1247 UINT x;
1248
1249 if (wk->li->type == IDM_FAKEEXTRACT ||
1250 wk->li->type == IDM_FAKEEXTRACTM) {
1251 strcpy(szBuffer,
1252 (wk->li->info->exwdirs) ?
1253 wk->li->info->exwdirs : wk->li->info->extract);
1254 strcat(szBuffer, " ");
1255 BldQuotedFileName(szBuffer + strlen(szBuffer), wk->li->arcname);
1256 }
1257 else {
1258 if (DosSearchPath(SEARCH_IGNORENETERRS | SEARCH_ENVIRONMENT |
1259 SEARCH_CUR_DIRECTORY,
1260 (CHAR *) PCSZ_PATH, (CHAR *) PCSZ_FM2PLAYEXE, (PBYTE)fbuf, CCHMAXPATH - 1))
1261 strcpy(szBuffer, "UTILS\\FM2PLAY.EXE");
1262 else
1263 strcpy(szBuffer, PCSZ_FM2PLAYEXE);
1264 }
1265 p = &szBuffer[strlen(szBuffer)];
1266 strcat(szBuffer, " ");
1267 x = 0;
1268 while (wk->li->list[x]) {
1269 pp = wk->li->list[x];
1270 while (*pp) {
1271 if (*pp == '/')
1272 *pp = '\\';
1273 pp++;
1274 }
1275 BldQuotedFileName(szBuffer + strlen(szBuffer), wk->li->list[x]);
1276 x++;
1277 if (!wk->li->list[x] || strlen(szBuffer) +
1278 strlen(wk->li->list[x]) + 5 > 1024) {
1279 runemf2(SEPARATE | WINDOWED | BACKGROUND | MINIMIZED | WAIT,
1280 HWND_DESKTOP, pszSrcFile, __LINE__,
1281 (wk->li->type == IDM_FAKEEXTRACT ||
1282 wk->li->type == IDM_FAKEEXTRACTM) ?
1283 wk->li->targetpath : NULL,
1284 NULL,
1285 "%s", szBuffer);
1286 DosSleep(1);
1287 *p = 0;
1288 }
1289 strcat(szBuffer, " ");
1290 }
1291 if (wk->li->type == IDM_MCIPLAY)
1292 break;
1293 strcpy(szBuffer, wk->li->targetpath);
1294 AddBackslashToPath(wk->li->targetpath);
1295 p = szBuffer + strlen(szBuffer);
1296 for (x = 0; wk->li->list[x]; x++) {
1297 strcpy(p, wk->li->list[x]);
1298 free(wk->li->list[x]);
1299 wk->li->list[x] = xstrdup(szBuffer, pszSrcFile, __LINE__);
1300 }
1301 if (wk->li->list[0])
1302 Broadcast(hab2,
1303 wk->hwndCnr,
1304 UM_UPDATERECORDLIST, MPFROMP(wk->li->list), MPVOID);
1305 }
1306 break;
1307
1308 case IDM_SETICON:
1309 if (*wk->li->targetpath) {
1310
1311 ICONINFO ici;
1312
1313 memset(&ici, 0, sizeof(ICONINFO));
1314 ici.cb = sizeof(ICONINFO);
1315 ici.fFormat = ICON_FILE;
1316 ici.pszFileName = wk->li->list[0];
1317 if (!WinSetFileIcon((PSZ) wk->li->targetpath,
1318 (PICONINFO) & ici)) {
1319 ici.fFormat = ICON_CLEAR;
1320 WinSetFileIcon((PSZ) wk->li->targetpath, (PICONINFO) & ici);
1321 }
1322 Broadcast(hab2,
1323 wk->hwndCnr,
1324 UM_UPDATERECORD, MPFROMP(wk->li->targetpath), MPVOID);
1325 }
1326 break;
1327
1328 case IDM_APPENDTOCLIP:
1329 case IDM_SAVETOCLIP:
1330 case IDM_SAVETOCLIPFILENAME:
1331 case IDM_APPENDTOCLIPFILENAME:
1332 ListToClipboardHab(hab2,
1333 wk->li->list,
1334 wk->li->type);
1335 break;
1336
1337 case IDM_ARCHIVEM:
1338 case IDM_ARCHIVE:
1339 {
1340 DIRCNRDATA ad;
1341 CHAR szBuffer[1025];
1342 ARC_TYPE *info = NULL;
1343 char *pch;
1344 UINT x;
1345
1346 memset(&ad, 0, sizeof(DIRCNRDATA));
1347 strcpy(ad.arcname, wk->li->targetpath);
1348 if (*wk->li->targetpath && IsFile(wk->li->targetpath) > 0) {
1349 info = find_type(wk->li->targetpath, NULL);
1350 ad.namecanchange = 0;
1351 }
1352 else {
1353 if (*wk->li->targetpath && !IsFile(wk->li->targetpath))
1354 AddBackslashToPath(wk->li->targetpath);
1355 ad.namecanchange = 1;
1356 }
1357 strcpy(ad.arcname, wk->li->targetpath);
1358 if (wk->li->type == IDM_ARCHIVEM)
1359 ad.fmoving = TRUE;
1360 if (!info) {
1361 ad.info = arcsighead; // Hide dups
1362 if (!WinDlgBox(HWND_DESKTOP,
1363 wk->hwndFrame,
1364 SBoxDlgProc,
1365 FM3ModHandle,
1366 ASEL_FRAME, (PVOID) & ad.info) || !ad.info) {
1367 break; // we blew it
1368 }
1369 }
1370 else
1371 ad.info = info;
1372 if (!ad.info || (!ad.info->create &&
1373 !ad.info->move &&
1374 !ad.info->createwdirs &&
1375 !ad.info->movewdirs &&
1376 !ad.info->createrecurse))
1377 break;
1378 if (!*wk->li->targetpath && *wk->directory) {
1379 strcpy(ad.arcname, wk->directory);
1380 AddBackslashToPath(ad.arcname);
1381 }
1382 if (!WinDlgBox(HWND_DESKTOP, wk->hwndFrame, ArchiveDlgProc, FM3ModHandle,
1383 ARCH_FRAME, (PVOID) & ad) || !*ad.arcname || !*ad.command) // we blew it
1384 break;
1385 // Provide extension so containers work
1386 pch = strrchr(ad.arcname, '\\');
1387 if (pch)
1388 pch = strrchr(pch, '.');
1389 else
1390 pch = strrchr(ad.arcname, '.');
1391 if (!pch && ad.info->ext) {
1392 strcat(ad.arcname, ".");
1393 strcat(ad.arcname, ad.info->ext);
1394 }
1395 // build the sucker
1396 strcpy(szBuffer, ad.command);
1397 strcat(szBuffer, " ");
1398 BldQuotedFileName(szBuffer + strlen(szBuffer), ad.arcname);
1399 p = &szBuffer[strlen(szBuffer)];
1400 if (ad.mask.szMask) {
1401 strcat(szBuffer, " ");
1402 strcat(szBuffer, ad.mask.szMask);
1403 }
1404 strcat(szBuffer, " ");
1405 x = 0;
1406 while (wk->li->list[x]) {
1407 FILESTATUS3 fsa;
1408 memset(&fsa, 0, sizeof(FILESTATUS3));
1409 DosError(FERR_DISABLEHARDERR);
1410 DosQueryPathInfo(wk->li->list[x],
1411 FIL_STANDARD,
1412 &fsa, (ULONG) sizeof(FILESTATUS3));
1413 if (fsa.attrFile & FILE_DIRECTORY) {
1414 BldQuotedFullPathName(szBuffer + strlen(szBuffer), wk->li->list[x], "*");
1415 }
1416 else
1417 BldQuotedFileName(szBuffer + strlen(szBuffer), wk->li->list[x]);
1418 x++;
1419 if (!wk->li->list[x] ||
1420 strlen(szBuffer) + strlen(wk->li->list[x]) + 5 > 1024) {
1421 runemf2(SEPARATE | WINDOWED | WAIT |
1422 (fArcStuffVisible ? 0 : (BACKGROUND | MINIMIZED)),
1423 HWND_DESKTOP, pszSrcFile, __LINE__, NULL, NULL,
1424 "%s", szBuffer);
1425 DosSleep(1);
1426 *p = 0;
1427 }
1428 strcat(szBuffer, " ");
1429 }
1430 Broadcast(hab2,
1431 wk->hwndCnr,
1432 UM_UPDATERECORDLIST, MPFROMP(wk->li->list), MPVOID);
1433 Broadcast(hab2,
1434 wk->hwndCnr,
1435 UM_UPDATERECORD, MPFROMP(ad.arcname), MPVOID);
1436 }
1437 break;
1438
1439 case IDM_VIEW:
1440 if (!TestBinary(wk->li->list[0])) {
1441 wk->li->type = IDM_VIEWTEXT;
1442 goto SkipViewing;
1443 }
1444 else
1445 wk->li->type = IDM_VIEWBINARY;
1446 // intentional fallthru
1447 case IDM_VIEWBINARY:
1448 if (*binview) {
1449 ExecOnList((HWND) 0,
1450 binview,
1451 WINDOWED | SEPARATE, NULL, NULL, wk->li->list, NULL,
1452 pszSrcFile, __LINE__);
1453 break;
1454 }
1455 // else intentional fallthru
1456 case IDM_VIEWTEXT:
1457 SkipViewing:
1458 if (*viewer)
1459 ExecOnList((HWND) 0, viewer,
1460 WINDOWED | SEPARATE |
1461 ((fViewChild) ? CHILD : 0),
1462 NULL, NULL, wk->li->list, NULL,
1463 pszSrcFile, __LINE__);
1464 else {
1465
1466 CHAR *temp;
1467 UINT x;
1468 ULONG viewtype;
1469
1470 viewtype = (wk->li->type == IDM_VIEWTEXT) ? 8 :
1471 (wk->li->type == IDM_VIEWBINARY) ? 16 : 0;
1472 for (x = 0; wk->li->list[x]; x++) {
1473 temp = xstrdup(wk->li->list[x], pszSrcFile, __LINE__);
1474 if (temp && WinIsWindow(hab2, wk->hwndCnr)) {
1475 if (!PostMsg(wk->hwndCnr,
1476 UM_LOADFILE,
1477 MPFROMLONG(5 + viewtype), MPFROMP(temp)))
1478 free(temp);
1479 }
1480 DosSleep(1);
1481 }
1482 }
1483 break;
1484
1485 case IDM_EDIT:
1486 if (!TestBinary(wk->li->list[0])) {
1487 wk->li->type = IDM_EDITTEXT;
1488 goto SkipEditing;
1489 }
1490 else
1491 wk->li->type = IDM_EDITBINARY;
1492 // intentional fallthru
1493 case IDM_EDITBINARY:
1494 if (*bined) {
1495 ExecOnList((HWND) 0,
1496 bined,
1497 WINDOWED | SEPARATE, NULL, NULL, wk->li->list, NULL,
1498 pszSrcFile, __LINE__);
1499 break;
1500 }
1501 // else intentional fallthru
1502 case IDM_EDITTEXT:
1503 SkipEditing:
1504 if (*editor)
1505 ExecOnList((HWND) 0,
1506 editor,
1507 WINDOWED | SEPARATE, NULL, NULL, wk->li->list, NULL,
1508 pszSrcFile, __LINE__);
1509 else {
1510
1511 CHAR *temp;
1512 UINT x;
1513 ULONG viewtype;
1514
1515 viewtype = (wk->li->type == IDM_EDITTEXT) ? 8 :
1516 (wk->li->type == IDM_EDITBINARY) ? 16 : 0;
1517 for (x = 0; wk->li->list[x]; x++) {
1518 temp = xstrdup(wk->li->list[x], pszSrcFile, __LINE__);
1519 if (temp && WinIsWindow(hab2, wk->hwndCnr)) {
1520 if (!PostMsg(wk->hwndCnr,
1521 UM_LOADFILE,
1522 MPFROMLONG(4 + viewtype), MPFROMP(temp)))
1523 free(temp);
1524 }
1525 DosSleep(1);
1526 }
1527 }
1528 break;
1529
1530 case IDM_SHADOW2:
1531 case IDM_OBJECT:
1532 case IDM_SHADOW:
1533 {
1534 CHAR objectpath[CCHMAXPATH];
1535 APIRET rc;
1536
1537 if (!*wk->li->targetpath || IsFile(wk->li->targetpath)) {
1538 GetDesktopName(objectpath, sizeof(objectpath));
1539 rc = WinDlgBox(HWND_DESKTOP,
1540 wk->hwndFrame,
1541 ObjCnrDlgProc,
1542 FM3ModHandle,
1543 OBJCNR_FRAME, MPFROMP(objectpath));
1544 if (rc) {
1545 if (rc > 1)
1546 strcpy(objectpath, "<WP_DESKTOP>");
1547 }
1548 else
1549 break;
1550 }
1551 else
1552 strcpy(objectpath, wk->li->targetpath);
1553 AddNote(GetPString(IDS_MAKINGOBJSTEXT));
1554 MakeShadows(wk->hwndFrame,
1555 wk->li->list,
1556 (wk->li->type == IDM_SHADOW) +
1557 (wk->li->type == IDM_SHADOW2) * 2,
1558 objectpath, NULL);
1559 AddNote(GetPString(IDS_MADEOBJSTEXT));
1560 }
1561 break;
1562
1563 case IDM_JAVAEXE:
1564 {
1565 CHAR javaexe[CCHMAXPATH] = {0};
1566
1567 strcpy(javaexe, PCSZ_STARDOTEXE);
1568 if (insert_filename(HWND_DESKTOP, javaexe, TRUE, FALSE) &&
1569 *javaexe && !strchr(javaexe, '*') && !strchr(javaexe, '?'))
1570 PrfWriteProfileString(fmprof, appname, "JavaExe", javaexe);
1571 }
1572 break;
1573
1574 case IDM_PRINT:
1575 if (WinDlgBox(HWND_DESKTOP,
1576 wk->hwndFrame,
1577 PrintDlgProc,
1578 FM3ModHandle, PRN_FRAME, MPFROMP(wk->li))) {
1579 if (wk->li && wk->li->list && wk->li->list[0]) {
1580 strcpy(wk->li->targetpath, printer);
1581 if (xbeginthread(PrintListThread,
1582 65536,
1583 wk->li,
1584 pszSrcFile,
1585 __LINE__) != -1)
1586 {
1587 wk->li = NULL; // prevent LISTINFO li from being freed here
1588 }
1589 }
1590 }
1591 break;
1592
1593 case IDM_ATTRS:
1594 if (WinDlgBox(HWND_DESKTOP,
1595 wk->hwndFrame,
1596 AttrListDlgProc,
1597 FM3ModHandle, ATR_FRAME, MPFROMP(wk->li))) {
1598 if (wk->li && wk->li->list && wk->li->list[0])
1599 Broadcast(hab2,
1600 wk->hwndCnr,
1601 UM_UPDATERECORDLIST, MPFROMP(wk->li->list), MPVOID);
1602 }
1603 break;
1604
1605 case IDM_PERMDELETE:
1606 case IDM_DELETE:
1607 {
1608 CHECKLIST cl;
1609 INT isdir = 0, sysdir = 0, ro = 0, hs = 0;
1610 UINT x;
1611 FILESTATUS3 fsa;
1612 CHAR prompt[CCHMAXPATH * 3];
1613 APIRET error = 0, rc;
1614 HOBJECT hObjectdest, hObjectofObject;
1615 BYTE G_abSupportedDrives[24] = {0};
1616 ULONG cbSupportedDrives = sizeof(G_abSupportedDrives);
1617 INT retrn = 0;
1618
1619 for (x = 0; wk->li->list[x]; x++) {
1620 if (IsRoot(wk->li->list[x])) {
1621 wk->li->list = RemoveFromList(wk->li->list,
1622 wk->li->list[x]);
1623 if (!wk->li->list)
1624 break;
1625 x--;
1626 continue;
1627 }
1628 DosError(FERR_DISABLEHARDERR);
1629 if (DosQueryPathInfo(wk->li->list[x],
1630 FIL_STANDARD, &fsa,
1631 (ULONG) sizeof(FILESTATUS3))) {
1632 wk->li->list = RemoveFromList(wk->li->list,
1633 wk->li->list[x]);
1634 if (!wk->li->list)
1635 break;
1636 x--;
1637 continue;
1638 }
1639 if (fsa.attrFile & FILE_DIRECTORY) {
1640 isdir++;
1641 if (stristr(wk->li->list[x], ":\\OS2\\") ||
1642 !stricmp(wk->li->list[x] + 1, ":\\OS2"))
1643 sysdir++;
1644 }
1645 else {
1646 if (fsa.attrFile & (FILE_HIDDEN | FILE_SYSTEM))
1647 hs++;
1648 if (fsa.attrFile & FILE_READONLY)
1649 ro++;
1650 }
1651 }
1652 if (!wk->li->list)
1653 break;
1654 if (fConfirmDelete || isdir || hs || ro) {
1655 memset(&cl, 0, sizeof(cl));
1656 cl.size = sizeof(cl);
1657 cl.list = wk->li->list;
1658 cl.prompt = prompt;
1659 cl.flags |= CHECK_FILES;
1660 cl.cmd = wk->li->type;
1661 sprintf(prompt,
1662 GetPString(IDS_DELPROMPT1TEXT),
1663 (wk->li->type == IDM_DELETE) ?
1664 NullStr :
1665 GetPString(IDS_PERMANENTLYTEXT),
1666 &"s"[wk->li->list[1] == NULL]);
1667 if (isdir) {
1668 sprintf(&prompt[strlen(prompt)],
1669 GetPString(IDS_DELPROMPT2TEXT),
1670 isdir,
1671 (isdir > 1) ?
1672 GetPString(IDS_ARETEXT) :
1673 GetPString(IDS_ISTEXT),
1674 (isdir == 1) ?
1675 GetPString(IDS_ATEXT) :
1676 NullStr,
1677 (isdir > 1) ?
1678 GetPString(IDS_IESTEXT) : GetPString(IDS_YTEXT));
1679 if (sysdir)
1680 sprintf(&prompt[strlen(prompt)],
1681 GetPString(IDS_DELPROMPT3TEXT),
1682 sysdir,
1683 (sysdir == 1) ?
1684 GetPString(IDS_YTEXT) : GetPString(IDS_IESTEXT));
1685 }
1686 if (ro)
1687 sprintf(&prompt[strlen(prompt)],
1688 GetPString(IDS_DELPROMPT4TEXT),
1689 ro,
1690 &"s"[ro == 1],
1691 (ro > 1) ?
1692 GetPString(IDS_ARETEXT) : GetPString(IDS_ISTEXT));
1693 if (hs)
1694 sprintf(&prompt[strlen(prompt)],
1695 GetPString(IDS_DELPROMPT5TEXT),
1696 hs,
1697 &"s"[hs == 1],
1698 (hs > 1) ?
1699 GetPString(IDS_ARETEXT) : GetPString(IDS_ISTEXT));
1700 if ((ro || hs || sysdir) && !fAlertBeepOff)
1701 DosBeep(300, 100); // Wake up user
1702 strcat(prompt, GetPString(IDS_DELPROMPT6TEXT));
1703 error = WinDlgBox(HWND_DESKTOP,
1704 wk->hwndFrame,
1705 CheckListProc,
1706 FM3ModHandle, CHECK_FRAME, MPFROMP(&cl));
1707 if (!error || error == 65535)
1708 break;
1709 wk->li->list = cl.list;
1710 if (!wk->li->list || !wk->li->list[0])
1711 break;
1712 }
1713 if (fVerify && driveflags[toupper(*wk->li->list[0]) - 'A'] & DRIVE_WRITEVERIFYOFF)
1714 DosSetVerify(FALSE);
1715 DosRequestMutexSem(hmtxFM2Delete, SEM_INDEFINITE_WAIT); // Prevent race 12-3-08 GKY
1716 for (x = 0; wk->li->list[x]; x++) {
1717 fsa.attrFile = 0;
1718 DosError(FERR_DISABLEHARDERR);
1719 DosQueryPathInfo(wk->li->list[x],
1720 FIL_STANDARD,
1721 &fsa, (ULONG) sizeof(FILESTATUS3));
1722 if (fsa.attrFile & FILE_DIRECTORY) {
1723 error = (APIRET) wipeallf(ignorereadonly, "%s%s*",
1724 wk->li->list[x],
1725 (*wk->li->list[x] &&
1726 wk->li->
1727 list[x][strlen(wk->li->list[x]) - 1]
1728 != '\\') ? PCSZ_BACKSLASH : NullStr);
1729 DosError(FERR_DISABLEHARDERR);
1730 if (!error)
1731 error = DosDeleteDir(wk->li->list[x]);
1732 else
1733 DosDeleteDir(wk->li->list[x]);
1734 }
1735 else {
1736
1737 DosError(FERR_DISABLEHARDERR);
1738 if (wk->li->type == IDM_DELETE) {
1739 if (fTrashCan) {
1740 hObjectdest = WinQueryObject("<XWP_TRASHCAN>");
1741 rc = PrfQueryProfileData(HINI_USER,
1742 "XWorkplace",
1743 "TrashCan::Drives",
1744 G_abSupportedDrives,
1745 &cbSupportedDrives);
1746 if (hObjectdest != NULLHANDLE &&
1747 (rc ? (G_abSupportedDrives[toupper(*wk->li->list[x]) - 'C'] & 1)
1748 :((driveflags[toupper(*wk->li->list[x]) - 'A'] &
1749 DRIVE_LOCALHD )))) {
1750 hObjectofObject = WinQueryObject(wk->li->list[x]);
1751 retrn = make_deleteable(wk->li->list[x], error, ignorereadonly);
1752 if (retrn == SM2_CANCEL)
1753 break;
1754 if (retrn == SM2_DONTASK)
1755 ignorereadonly = TRUE;
1756 if (retrn == SM2_NO)
1757 continue;
1758 error = WinMoveObject(hObjectofObject, hObjectdest, 0);
1759 }
1760 else
1761 error = DosDelete(wk->li->list[x]);
1762 }
1763 else
1764 error = DosDelete(wk->li->list[x]);
1765 }
1766 else
1767 error = DosForceDelete(wk->li->list[x]);
1768 if (error) {
1769
1770 DosError(FERR_DISABLEHARDERR);
1771 retrn = make_deleteable(wk->li->list[x], error, ignorereadonly);
1772 if (retrn == SM2_CANCEL)
1773 break;
1774 if (retrn == SM2_DONTASK)
1775 ignorereadonly = TRUE;
1776 if (retrn == SM2_NO)
1777 continue;
1778 if (wk->li->type == IDM_DELETE) {
1779 if (fTrashCan) {
1780 hObjectdest = WinQueryObject("<XWP_TRASHCAN>");
1781 rc = PrfQueryProfileData(HINI_USER,
1782 "XWorkplace",
1783 "TrashCan::Drives",
1784 G_abSupportedDrives,
1785 &cbSupportedDrives);
1786 if (hObjectdest != NULLHANDLE &&
1787 (rc ? (G_abSupportedDrives[toupper(*wk->li->list[x]) - 'C'] & 1)
1788 :((driveflags[toupper(*wk->li->list[x]) - 'A'] &
1789 DRIVE_LOCALHD )))) {
1790 hObjectofObject = WinQueryObject(wk->li->list[x]);
1791 error = WinMoveObject(hObjectofObject, hObjectdest, 0);
1792 }
1793 else
1794 error = DosDelete(wk->li->list[x]);
1795 }
1796 else
1797 error = DosDelete(wk->li->list[x]);
1798 }
1799 else
1800 error = xDosForceDelete(wk->li->list[x]);
1801 }
1802 DosReleaseMutexSem(hmtxFM2Delete);
1803 }
1804 if (fWarnReadOnly && error == ERROR_FILE_EXISTS) {
1805 retrn = SM2_NO;
1806 }
1807 if (error && (retrn == SM2_YES || retrn == SM2_DONTASK || retrn == -1)) {
1808 if (LogFileHandle)
1809 fprintf(LogFileHandle,
1810 GetPString(IDS_DELETEFAILED1TEXT),
1811 wk->li->list[x], error);
1812 if (Dos_Error(MB_ENTERCANCEL,
1813 error,
1814 wk->hwndFrame,
1815 pszSrcFile,
1816 __LINE__,
1817 GetPString(IDS_DELETEFAILED2TEXT),
1818 wk->li->list[x]) == MBID_CANCEL) {
1819 DosSetVerify(fVerify);
1820 break;
1821 }
1822 }
1823 else {
1824 if (LogFileHandle)
1825 fprintf(LogFileHandle,
1826 GetPString(IDS_DELETEDTEXT), wk->li->list[x]);
1827 sprintf(prompt,
1828 GetPString(IDS_DELETEDTEXT), wk->li->list[x]);
1829 AddNote(prompt);
1830 }
1831 if (AddToList(wk->li->list[x], &files, &numfiles, &numalloc)) {
1832 Broadcast(hab2,
1833 wk->hwndCnr,
1834 UM_UPDATERECORD,
1835 MPFROMP(wk->li->list[x]), MPVOID);
1836 } ;
1837 } // for
1838 }
1839 if (fVerify)
1840 DosSetVerify(fVerify);
1841 break;
1842 } // switch
1843 if (files) {
1844 Broadcast(hab2,
1845 wk->hwndCnr,
1846 UM_UPDATERECORDLIST, MPFROMP(files), MPVOID);
1847 FreeList(files);
1848 }
1849 if (WinIsWindow(hab2, wk->hwndCnr))
1850 PostMsg(wk->hwndCnr, UM_RESCAN, MPVOID, MPVOID);
1851
1852 WinDestroyMsgQueue(hmq2);
1853 }
1854 DecrThreadUsage();
1855 WinTerminate(hab2);
1856 }
1857 }
1858 FreeListInfo(wk->li);
1859 free(wk);
1860# ifdef FORTIFY
1861 Fortify_LeaveScope();
1862# endif
1863 DosPostEventSem(CompactSem);
1864 }
1865}
1866
1867#pragma alloc_text(MASSACTION,MassAction)
1868#pragma alloc_text(ACTION,Action)
1869#pragma alloc_text(UNDO,FreeUndo,Undo)
Note: See TracBrowser for help on using the repository browser.