source: trunk/dll/comp.c@ 1685

Last change on this file since 1685 was 1685, checked in by Gregg Young, 12 years ago

Changes to fix broken snapshot file; provide a warning for delete of readonly files; Fix the disappearing file sizes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 104.0 KB
Line 
1
2/***********************************************************************
3
4 $Id: comp.c 1685 2013-03-10 16:51:30Z gyoung $
5
6 Compare directories
7
8 Copyright (c) 1993-02 M. Kimes
9 Copyright (c) 2003, 2013 Steven H. Levine
10
11 16 Oct 02 MK Baseline
12 04 Nov 03 SHL Force window refresh after subdir toggle
13 01 Aug 04 SHL Rework lstrip/rstrip usage
14 24 May 05 SHL Rework Win_Error usage
15 24 May 05 SHL Rework for CNRITEM.szSubject
16 25 May 05 SHL Rework with ULONGLONG
17 06 Jun 05 SHL Drop unused
18 12 Jul 06 SHL Renames and comments
19 13 Jul 06 SHL Use Runtime_Error
20 26 Jul 06 SHL Drop unreachable CN_... code
21 29 Jul 06 SHL Use xfgets_bstripcr
22 15 Aug 06 SHL Turn off hide not selected on dir change
23 19 Oct 06 SHL Correct . and .. detect
24 03 Nov 06 SHL Count thread usage
25 22 Mar 07 GKY Use QWL_USER
26 29 Jul 07 SHL Use Win_Error to report container errors
27 01 Aug 07 SHL Rework to sync with CNRITEM mods
28 01 Aug 07 SHL Rework to remove vast amount of duplicate code
29 03 Aug 07 GKY Enlarged and made setable everywhere Findbuf (speed file loading)
30 06 Aug 07 SHL Move BldFullPathName here to be near primary caller
31 07 Aug 07 SHL COMP_COLLECT: Avoid collecting empty entries when nothing selected
32 06 Aug 07 GKY Reduce DosSleep times (ticket 148)
33 13 Aug 07 SHL Sync code with other FilesToGet usage
34 13 Aug 07 SHL Move #pragma alloc_text to end for OpenWatcom compat
35 20 Aug 07 SHL Correct remaining pcil/pcir typos (we hope)
36 20 Aug 07 SHL Revert to DosSleep(0)
37 20 Aug 07 SHL Use GetMSecTimer for timing
38 20 Aug 07 SHL A few more speed up tweaks. Some experimental timing code
39 26 Aug 07 GKY DosSleep(1) in loops changed to (0)
40 27 Sep 07 SHL Correct ULONGLONG size formatting
41 30 Dec 07 GKY Use TestCDates for compare by file date/time
42 04 Jan 08 SHL Avoid traps if CM_ALLOCRECORD returns less that requested
43 05 Jan 08 SHL Use WM_TIMER for progress messaging
44 05 Jan 08 SHL Use ITIMER_DESC for hogging control
45 12 Jan 08 SHL Correct select count display regression
46 12 Jan 08 SHL Localize SpecialSelect here and rename
47 12 Jan 08 SHL Use SleepIfNeeded
48 12 Jan 08 SHL Reduce/eliminate more DosSleep calls
49 16 Jan 08 SHL Update total/select counts with WM_TIMER only
50 17 Jan 08 SHL Change hide not selected button to 3 state
51 18 Jan 08 SHL Honor filters in actions
52 20 Jan 08 GKY Compare dialog now saves and restores size and position
53 29 Feb 08 GKY Use xfree where appropriate
54 29 Feb 08 GKY Refactor global command line variables to notebook.h
55 16 Mar 08 GKY Prevent trap caused by files that exceed maxpath length
56 11 Jul 08 JBS Ticket 230: Simplified code and eliminated some local variables by incorporating
57 all the details view settings (both the global variables and those in the
58 DIRCNRDATA struct) into a new struct: DETAILS_SETTINGS.
59 08 Sep 08 SHL Avoid aliased pszLongName pointer in ActionCnrThread IDM_MOVE
60 10 Dec 08 SHL Integrate exception handler support
61 25 Dec 08 GKY Add code to allow write verify to be turned off on a per drive basis.
62 11 Jan 09 GKY Replace font names in the string file with global set at compile in init.c
63 07 Feb 09 GKY Add *DateFormat functions to format dates based on locale
64 08 Mar 09 GKY Renamed commafmt.h i18nutil.h
65 08 Mar 09 GKY Removed variable aurguments from docopyf and unlinkf (not used)
66 08 Mar 09 GKY Additional strings move to PCSZs in init.c & String Table
67 15 Mar 09 GKY Use WriteDetailsSwitchs to save detail switch changes to the ini file.
68 28 Jun 09 GKY Added AddBackslashToPath() to remove repeatative code.
69 13 Jul 09 SHL Sync with renames
70 26 Sep 09 SHL Don't hide if nothing selected
71 27 Sep 09 SHL Support AND'ed selections
72 27 Sep 09 SHL Rework CompSelect for size and speed
73 27 Sep 09 SHL Allow fast cancel
74 27 Sep 09 SHL Drop unused reset logic
75 17 JAN 10 GKY Changes to get working with Watcom 1.9 Beta (1/16/10). Mostly cast CHAR CONSTANT * as CHAR *.
76 23 Oct 10 GKY Add ForwardslashToBackslash function to streamline code
77 29 May 11 SHL Rework >65K records logic - prior fix was not quite right
78 12 Jun 11 GKY Added SleepIfNeeded in the container fill loop
79 02 Jan 12 GKY Added pszFmtFileSize to container info to fix loss of file sizes on move and copy.
80 12 Aug 12 GKY Add ability to change and save PresParam
81 12 Aug 12 GKY Fix loading of a list file in the right compare container
82 12 Aug 12 GKY Allow for selection of include subdirectories or a list file on initial startup of compare dirs
83 05 Jan 13 GKY Fix snapshot file to actually load and save (with/without subdirectories) properly.
84 05 Jan 13 GKY Toggle of include subdirectories leaves snapshot file loaded.
85 05 Jan 13 GKY Added an indicator (textbox) that a list (snapshot) file is loaded.
86 06 Jan 13 GKY Added optional confirmation dialogs for delete move and copy to compare dir Ticket 277
87 06 Jan 13 GKY Added EA compare option to compare dir Ticket 80
88 06 Mar 13 SHL ActionCnrThread: need to strdup pszFmtFileSize to avoid aliased pointers
89 09 Mar 13 SHL SetButtonEnables: correct enable support for newish buttons
90
91***********************************************************************/
92
93#include <stdlib.h>
94#include <string.h>
95#include <share.h>
96#include <io.h>
97#include <ctype.h>
98#include <limits.h> // USHRT_MAX
99
100#define INCL_DOS
101#define INCL_WIN
102#define INCL_DOSERRORS
103#define INCL_GPI
104#define INCL_LONGLONG
105
106#include "fm3dll.h"
107#include "fm3dll2.h" // #define's for UM_*, control id's, etc.
108#include "mainwnd2.h" // Data declaration(s)
109#include "inis.h" // Data declaration(s)
110#include "init.h" // Data declaration(s)
111#include "newview.h" // Data declarations
112#include "fm3dlg.h"
113#include "fm3str.h"
114#include "pathutil.h" // BldFullPathName
115#include "filldir.h" // EmptyCnr...
116#include "makelist.h" // AddToFileList...
117#include "errutil.h" // Dos_Error...
118#include "strutil.h" // GetPString
119#include "tmrsvcs.h" // IsITimerExpired
120#include "comp.h"
121#include "misc.h" // AddToListboxBottom, AdjustCnrColRO, AdjustCnrColVis,
122 // AdjustCnrColsForPref, CurrentRecord,
123 // AdjustDetailsSwitches, LoadDetailsSwitches, SetCnrCols
124 // SetDetailsSwitches
125#include "select.h" // Deselect, Deselect, InvertAll
126#include "mkdir.h" // MassMkdir
127#include "valid.h" // TestCDates
128#include "walkem.h" // WalkTwoCmpDlgProc
129#include "common.h" // DecrThreadUsage, IncrThreadUsage
130#include "defview.h" // DefaultViewKeys
131#include "draglist.h" // DoFileDrag
132#include "systemf.h" // ExecOnList
133#include "filter.h" // Filter
134#include "mainwnd.h" // GetNextWindowPos
135#include "shadow.h" // OpenObject
136#include "chklist.h" // PopupMenu
137#include "presparm.h" // SetPresParams
138#include "collect.h" // StartCollector
139#include "subj.h" // Subject
140#include "copyf.h" // docopyf
141#include "getnames.h" // export_filename
142#include "wrappers.h" // xDosFindNext
143#include "notebook.h" // External compare/dircompare
144#include "i18nutil.h" // CommaFmtULL
145#include "fortify.h" // 06 May 08 SHL added
146#include "excputil.h" // xbeginthread
147#include "info.h" // driveflags
148#include "worker.h" // MOVEIT
149#include "rename.h" // RenameProc
150
151typedef struct
152{
153 CHAR filename[CCHMAXPATH];
154 CHAR dirname[CCHMAXPATH];
155 BOOL recurse;
156}
157SNAPSTUFF;
158
159// Data definitions
160static PSZ pszSrcFile = __FILE__;
161
162#pragma data_seg(GLOBAL1)
163BOOL fSelectedAlways;
164
165/**
166 * Write directory tree to snapshot file; recurse if requested
167 */
168
169static VOID SnapShot(char *path, FILE *fp, BOOL recurse)
170{
171 PFILEFINDBUF4L pffb;
172 char *mask, *enddir;
173 HDIR hdir = HDIR_CREATE;
174 ULONG ulFindCnt;
175 //CHAR szDate[DATE_BUF_BYTES];
176
177 // 13 Aug 07 SHL fixme to use FileToGet
178 pffb = xmalloc(sizeof(FILEFINDBUF4L), pszSrcFile, __LINE__);
179 if (pffb) {
180 mask = xmalloc(CCHMAXPATH, pszSrcFile, __LINE__);
181 if (mask) {
182 BldFullPathName(mask, path, "*");
183 enddir = strrchr(mask, '\\');
184 enddir++;
185 ulFindCnt = 1;
186 // 13 Aug 07 SHL fixme to report errors
187 if (!xDosFindFirst(mask,
188 &hdir,
189 FILE_NORMAL | FILE_DIRECTORY |
190 FILE_ARCHIVED | FILE_READONLY | FILE_HIDDEN |
191 FILE_SYSTEM,
192 pffb, sizeof(FILEFINDBUF4L), &ulFindCnt, FIL_QUERYEASIZEL)) {
193 do {
194 strcpy(enddir, pffb->achName);
195 if (!(pffb->attrFile & FILE_DIRECTORY)) {
196 //FDateFormat(szDate, pffb->fdateLastWrite);
197 fprintf(fp,
198 "\"%s\",%u,%llu,%lu/%lu/%lu,%02u:%02u:%02u,%lu,%lu,N\n",
199 mask,
200 enddir - mask,
201 pffb->cbFile,
202 pffb->fdateLastWrite.year + 1980,
203 pffb->fdateLastWrite.month,
204 pffb->fdateLastWrite.day,
205 pffb->ftimeLastWrite.hours,
206 pffb->ftimeLastWrite.minutes,
207 pffb->ftimeLastWrite.twosecs,
208 pffb->attrFile,
209 pffb->cbList > 4 ? pffb->cbList / 2 : 0);
210 }
211 // Skip . and ..
212 else if (recurse &&
213 (pffb->achName[0] != '.' ||
214 (pffb->achName[1] &&
215 (pffb->achName[1] != '.' || pffb->achName[2])))) {
216 SnapShot(mask, fp, recurse);
217 }
218 ulFindCnt = 1;
219 } while (!xDosFindNext(hdir, pffb, sizeof(FILEFINDBUF4L), &ulFindCnt, FIL_QUERYEASIZEL));
220 DosFindClose(hdir);
221 }
222 free(mask);
223 }
224 free(pffb);
225 }
226}
227
228/**
229 * Write snapshot file thread
230 * Write directory tree to snapshot file
231 */
232
233static VOID StartSnapThread(VOID *pargs)
234{
235 SNAPSTUFF *sf = (SNAPSTUFF *)pargs;
236 FILE *fp;
237 CHAR *modew = "w";
238
239 if (sf) {
240 if (*sf->dirname && *sf->filename) {
241 priority_normal();
242 ForwardslashToBackslash(sf->dirname);
243 AddBackslashToPath(sf->dirname);
244 fp = xfopen(sf->filename, modew, pszSrcFile, __LINE__, FALSE);
245 if (fp) {
246 fprintf(fp, "\"%s\"\n", sf->dirname);
247 //DbgMsg(pszSrcFile, __LINE__, "recurse %i", sf->recurse);
248 SnapShot(sf->dirname, fp, sf->recurse);
249 fclose(fp);
250 }
251 }
252 free(sf);
253 }
254}
255
256/**
257 * Compare files thread
258 * Scan files and update container select flags
259 */
260
261static VOID CompareFilesThread(VOID *args)
262{
263 FCOMPARE fc;
264 HAB hab2;
265 HMQ hmq2;
266 FILE *fp1, *fp2;
267 ULONG len1, len2;
268 ULONG offset = 0;
269 LONG numread1, numread2;
270 CHAR s[1024], ss[1024], *p1, *p2;
271 CHAR *moderb = "rb";
272
273 if (args) {
274 fc = *(FCOMPARE *)args;
275 hab2 = WinInitialize(0);
276 if (hab2) {
277# ifdef FORTIFY
278 Fortify_EnterScope();
279# endif
280 hmq2 = WinCreateMsgQueue(hab2, 0);
281 if (hmq2) {
282 WinCancelShutdown(hmq2, TRUE);
283 IncrThreadUsage();
284 if (!IsFile(fc.file1) || IsRoot(fc.file1)) {
285 p1 = strrchr(fc.file2, '\\');
286 if (p1) {
287 if (fc.file1[strlen(fc.file1) - 1] == '\\')
288 p1++;
289 strcat(fc.file1, p1);
290 }
291 }
292 else if (!IsFile(fc.file2) || IsRoot(fc.file2)) {
293 p1 = strrchr(fc.file1, '\\');
294 if (p1) {
295 if (fc.file2[strlen(fc.file2) - 1] == '\\')
296 p1++;
297 strcat(fc.file2, p1);
298 }
299 }
300 sprintf(s, GetPString(IDS_COMPCOMPARETEXT), fc.file1);
301 AddToListboxBottom(fc.hwndList, s);
302 sprintf(s, GetPString(IDS_COMPTOTEXT), fc.file2);
303 AddToListboxBottom(fc.hwndList, s);
304 fp1 = xfsopen(fc.file1, moderb, SH_DENYNO, pszSrcFile, __LINE__, TRUE);
305 if (!fp1) {
306 sprintf(s, GetPString(IDS_COMPCANTOPENTEXT), fc.file1);
307 AddToListboxBottom(fc.hwndList, s);
308 WinSetWindowText(fc.hwndHelp, (CHAR *) GetPString(IDS_ERRORTEXT));
309 }
310 else {
311 fp2 = xfsopen(fc.file2, moderb, SH_DENYNO, pszSrcFile, __LINE__, TRUE);
312 if (!fp2) {
313 sprintf(s, GetPString(IDS_COMPCANTOPENTEXT), fc.file2);
314 AddToListboxBottom(fc.hwndList, s);
315 WinSetWindowText(fc.hwndHelp, (CHAR *) GetPString(IDS_ERRORTEXT));
316 }
317 else {
318 len1 = filelength(fileno(fp1));
319 len2 = filelength(fileno(fp2));
320 if (len1 != len2) {
321 strcpy(s, GetPString(IDS_COMPDIFSIZESTEXT));
322 AddToListboxBottom(fc.hwndList, s);
323 sprintf(s, GetPString(IDS_COMPVSBYTESTEXT), len1, len2);
324 AddToListboxBottom(fc.hwndList, s);
325 WinSetWindowText(fc.hwndHelp,
326 (CHAR *) GetPString(IDS_COMPDONTMATCHTEXT));
327 }
328 else {
329 WinSetWindowText(fc.hwndHelp,
330 (CHAR *) GetPString(IDS_COMPCOMPARINGTEXT));
331 while (WinIsWindow(hab2, fc.hwndList)) {
332 numread1 = fread(s, 1, 1024, fp1);
333 numread2 = fread(ss, 1, 1024, fp2);
334 if (numread1 != numread2 || feof(fp1) != feof(fp2)) {
335 sprintf(s, GetPString(IDS_COMPREADERRORTEXT),
336 offset, offset);
337 AddToListboxBottom(fc.hwndList, s);
338 WinSetWindowText(fc.hwndHelp, (CHAR *) GetPString(IDS_ERRORTEXT));
339 break;
340 }
341 else if (!numread1 && feof(fp1) && feof(fp2)) {
342 AddToListboxBottom(fc.hwndList,
343 GetPString(IDS_COMPFILESMATCHTEXT));
344 if (!stricmp(fc.file1, fc.file2))
345 AddToListboxBottom(fc.hwndList,
346 GetPString(IDS_COMPWONDERWHYTEXT));
347 WinSetWindowText(fc.hwndHelp,
348 (CHAR *) GetPString(IDS_COMPCOMPLETETEXT));
349 break;
350 }
351 else if (numread1 <= 0 || numread2 <= 0) {
352 if (offset == len1)
353 break;
354 else {
355 sprintf(s, GetPString(IDS_COMPMATCHREADERRORTEXT),
356 offset, offset);
357 WinSetWindowText(fc.hwndHelp,
358 (CHAR *) GetPString(IDS_COMPODDERRORTEXT));
359 AddToListboxBottom(fc.hwndList, s);
360 break;
361 }
362 }
363 else if (memcmp(s, ss, numread1)) {
364 p1 = s;
365 p2 = ss;
366 while (p1 < s + numread1) {
367 if (*p1 != *p2) {
368 sprintf(s, GetPString(IDS_COMPMISMATCHERRORTEXT),
369 offset + (p1 - s), offset + (p1 - s));
370 AddToListboxBottom(fc.hwndList, s);
371 WinSetWindowText(fc.hwndHelp,
372 (CHAR *) GetPString(IDS_COMPDONTMATCHTEXT));
373 break;
374 }
375 p1++;
376 p2++;
377 }
378 break;
379 }
380 offset += numread1;
381 }
382 }
383 fclose(fp2);
384 }
385 fclose(fp1);
386 }
387 DecrThreadUsage();
388 WinDestroyMsgQueue(hmq2);
389 }
390 WinTerminate(hab2);
391# ifdef FORTIFY
392 Fortify_LeaveScope();
393# endif
394 }
395 }
396}
397
398/**
399 * Select directories to compare dialog procedure
400 */
401
402MRESULT EXPENTRY CFileDlgProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
403{
404 FCOMPARE *fc;
405
406 switch (msg) {
407 case WM_INITDLG:
408 if (!mp2)
409 WinDismissDlg(hwnd, 0);
410 else {
411 WinSetWindowPtr(hwnd, QWL_USER, mp2);
412 fc = (FCOMPARE *)mp2;
413 fc->hwndReport = hwnd;
414 fc->hwndList = WinWindowFromID(hwnd, FCMP_LISTBOX);
415 fc->hwndHelp = WinWindowFromID(hwnd, FCMP_HELP);
416 if (!*fc->file1 || !fc->file2) {
417 WinDismissDlg(hwnd, 0);
418 break;
419 }
420 MakeFullName(fc->file1);
421 MakeFullName(fc->file2);
422 if (!stricmp(fc->file1, fc->file2)) {
423 saymsg(MB_CANCEL, hwnd,
424 GetPString(IDS_COMPSILLYALERTTEXT),
425 GetPString(IDS_COMPTOITSELFTEXT));
426 WinDismissDlg(hwnd, 0);
427 break;
428 }
429 if (xbeginthread(CompareFilesThread,
430 65536,
431 fc,
432 pszSrcFile,
433 __LINE__) == -1)
434 {
435 WinDismissDlg(hwnd, 0);
436 }
437 }
438 break;
439
440 case WM_ADJUSTWINDOWPOS:
441 PostMsg(hwnd, UM_SETDIR, MPVOID, MPVOID);
442 break;
443
444 case UM_SETDIR:
445 PaintRecessedWindow(WinWindowFromID(hwnd, FCMP_HELP),
446 (HPS)0, FALSE, TRUE);
447 return 0;
448
449 case WM_COMMAND:
450 switch (SHORT1FROMMP(mp1)) {
451 case DID_OK:
452 WinDismissDlg(hwnd, 0);
453 break;
454 case DID_CANCEL:
455 WinDismissDlg(hwnd, 1);
456 break;
457 }
458 return 0;
459
460 case WM_DESTROY:
461 DosSleep(50); // Let others die first
462 break;
463 }
464 return WinDefDlgProc(hwnd, msg, mp1, mp2);
465}
466int ConfirmAction(HWND hwnd, CHAR *OldName, CHAR *NewName);
467
468/**
469 * ConfirmAction provides an optional confirmation dialog
470 * for move and copy operations.
471 */
472int ConfirmAction(HWND hwnd, CHAR *OldName, CHAR *NewName)
473{
474 MOVEIT mv;
475 int rc;
476
477 memset(&mv, 0, sizeof(MOVEIT));
478 mv.rename = FALSE;
479 mv.source = OldName;
480 mv.compare = TRUE;
481 strcpy(mv.target, NewName);
482 rc = WinDlgBox(HWND_DESKTOP,
483 hwnd,
484 RenameProc,
485 FM3ModHandle, REN_FRAME, (PVOID) & mv);
486 if (!rc)
487 return 1;
488
489 DosSleep(1);
490 if (mv.skip || !*mv.target)
491 return 1;
492 if (mv.dontask)
493 return 2;
494 return 0;
495}
496
497/**
498 * Action Thread
499 * Do requested action on container contents
500 */
501static VOID ActionCnrThread(VOID *args)
502{
503 COMPARE *cmp = (COMPARE *)args;
504 HAB hab;
505 HMQ hmq;
506 HWND hwndCnrS, hwndCnrD;
507 PCNRITEM pciS, pciD, pciNextS, pciNextD;
508 CHAR szNewName[CCHMAXPATH], szDirName[CCHMAXPATH], *p;
509 APIRET rc;
510 ITIMER_DESC itdSleep = { 0 };
511 BOOL fConfirmAction = FALSE;
512 BOOL dontask = FALSE;
513 BOOL enddelete = FALSE;
514
515 if (!cmp) {
516 Runtime_Error(pszSrcFile, __LINE__, NULL);
517 return;
518 }
519
520 DosError(FERR_DISABLEHARDERR);
521
522 hab = WinInitialize(0);
523 if (hab) {
524# ifdef FORTIFY
525 Fortify_EnterScope();
526# endif
527 hmq = WinCreateMsgQueue(hab, 0);
528 if (hmq) {
529 WinCancelShutdown(hmq, TRUE);
530 IncrThreadUsage();
531 priority_normal();
532 switch (cmp->action) {
533 case COMP_DELETELEFT:
534 hwndCnrS = WinWindowFromID(cmp->hwnd, COMP_LEFTDIR);
535 hwndCnrD = WinWindowFromID(cmp->hwnd, COMP_RIGHTDIR);
536 cmp->action = IDM_DELETE;
537 break;
538 case COMP_DELETERIGHT:
539 hwndCnrS = WinWindowFromID(cmp->hwnd, COMP_RIGHTDIR);
540 hwndCnrD = WinWindowFromID(cmp->hwnd, COMP_LEFTDIR);
541 cmp->action = IDM_DELETE;
542 break;
543 case COMP_MOVELEFT:
544 cmp->action = IDM_MOVE;
545 hwndCnrS = WinWindowFromID(cmp->hwnd, COMP_LEFTDIR);
546 hwndCnrD = WinWindowFromID(cmp->hwnd, COMP_RIGHTDIR);
547 break;
548 case COMP_MOVERIGHT:
549 cmp->action = IDM_MOVE;
550 hwndCnrS = WinWindowFromID(cmp->hwnd, COMP_RIGHTDIR);
551 hwndCnrD = WinWindowFromID(cmp->hwnd, COMP_LEFTDIR);
552 break;
553 case COMP_COPYLEFT:
554 cmp->action = IDM_COPY;
555 hwndCnrS = WinWindowFromID(cmp->hwnd, COMP_LEFTDIR);
556 hwndCnrD = WinWindowFromID(cmp->hwnd, COMP_RIGHTDIR);
557 break;
558 case COMP_COPYRIGHT:
559 cmp->action = IDM_COPY;
560 hwndCnrS = WinWindowFromID(cmp->hwnd, COMP_RIGHTDIR);
561 hwndCnrD = WinWindowFromID(cmp->hwnd, COMP_LEFTDIR);
562 break;
563 default:
564 Runtime_Error(pszSrcFile, __LINE__, "bad case %u", cmp->action);
565 goto Abort;
566 }
567
568 pciS = WinSendMsg(hwndCnrS, CM_QUERYRECORD, MPVOID,
569 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
570 pciD = WinSendMsg(hwndCnrD, CM_QUERYRECORD, MPVOID,
571 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
572 fConfirmAction = WinQueryButtonCheckstate(cmp->hwnd, COMP_CONFIRMACTION);
573 InitITimer(&itdSleep, 500); // Sleep every 500 mSec
574
575 while (pciS && (INT)pciS != -1 && pciD && (INT)pciD != -1) {
576
577 if (cmp->cmp->stop)
578 break; // 27 Sep 09 SHL
579
580 pciNextS = WinSendMsg(hwndCnrS, CM_QUERYRECORD, MPFROMP(pciS),
581 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
582 pciNextD = WinSendMsg(hwndCnrD, CM_QUERYRECORD, MPFROMP(pciD),
583 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
584
585 // Process file if selected and not filtered
586 if (*pciS->pszFileName &&
587 pciS->rc.flRecordAttr & CRA_SELECTED &&
588 ~pciS->rc.flRecordAttr & CRA_FILTERED)
589 {
590 // Source name not blank
591 switch (cmp->action) {
592 case IDM_DELETE:
593
594 if (fConfirmAction && !dontask) {
595 rc = saymsg2(NULL, 0, cmp->hwnd, GetPString(IDS_CONFIRMDELETE), GetPString(IDS_DOYOUWISHTODELETE),
596 pciS->pszFileName);
597 if (rc == 3 || rc == 4) {
598 if (rc == 4)
599 enddelete = TRUE;
600 break;
601 }
602 else if (rc == 2)
603 dontask = TRUE;
604 }
605 if (!unlinkf(pciS->pszFileName)) {
606 WinSendMsg(hwndCnrS, CM_SETRECORDEMPHASIS, MPFROMP(pciS),
607 MPFROM2SHORT(FALSE, CRA_SELECTED));
608
609 if (!*pciD->pszFileName) {
610 // Other side is blank - remove from both sides
611 RemoveCnrItems(hwndCnrS, pciS, 1, CMA_FREE | CMA_INVALIDATE);
612 if (pciD->rc.flRecordAttr & CRA_SELECTED)
613 WinSendMsg(hwndCnrD, CM_SETRECORDEMPHASIS, MPFROMP(pciD),
614 MPFROM2SHORT(FALSE, CRA_SELECTED));
615 RemoveCnrItems(hwndCnrD, pciD, 1, CMA_FREE | CMA_INVALIDATE);
616 }
617 else {
618 // Other side is not blank - blank just this side
619 FreeCnrItemData(pciS);
620 // 29 Aug 08 SHL Point pci fields at NullStr to sync with FreeCnrItemData mods
621 pciS->pszFileName = NullStr;
622 pciS->pszDisplayName = pciS->pszFileName;
623 pciS->rc.pszIcon = pciS->pszFileName;
624 pciS->flags = 0; // Just on one side
625 WinSendMsg(hwndCnrS, CM_INVALIDATERECORD, MPFROMP(&pciS),
626 MPFROM2SHORT(1, CMA_ERASE | CMA_TEXTCHANGED));
627 pciD->flags = 0; // Just on one side
628 if (pciD->pszSubject != NullStr) {
629 xfree(pciD->pszSubject, pszSrcFile, __LINE__);
630 pciD->pszSubject = NullStr;
631 }
632 }
633 if (hwndCnrS == WinWindowFromID(cmp->hwnd, COMP_LEFTDIR))
634 cmp->cmp->totalleft--;
635 else
636 cmp->cmp->totalright--;
637 }
638 break;
639
640 case IDM_MOVE:
641 {
642 BOOL fResetVerify = FALSE;
643
644 if (hwndCnrS == WinWindowFromID(cmp->hwnd, COMP_RIGHTDIR))
645 BldFullPathName(szNewName, cmp->leftdir, pciS->pszDisplayName);
646 else
647 BldFullPathName(szNewName, cmp->rightdir, pciS->pszDisplayName);
648 // Make directory if required
649 strcpy(szDirName, szNewName);
650 p = strrchr(szDirName, '\\');
651 if (fVerify && (driveflags[toupper(*szNewName) - 'A'] & DRIVE_WRITEVERIFYOFF ||
652 driveflags[toupper(*pciS->pszFileName) - 'A'] & DRIVE_WRITEVERIFYOFF)) {
653 DosSetVerify(FALSE);
654 fResetVerify = TRUE;
655 }
656 if (p) {
657 if (p > szDirName + 2)
658 p++;
659 *p = 0;
660 if (IsFile(szDirName) == -1)
661 MassMkdir(hwndMain, szDirName);
662 }
663 if (fConfirmAction && pciS->flags & CNRITEM_EXISTS && !dontask) {
664 rc = ConfirmAction(cmp->hwnd, pciS->pszFileName, szNewName);
665 if (rc == 1)
666 break;
667 else if (rc == 2)
668 dontask = TRUE;
669 }
670 rc = docopyf(MOVE, pciS->pszFileName, szNewName);
671 if (fResetVerify) {
672 DosSetVerify(fVerify);
673 fResetVerify = FALSE;
674 }
675 if (!rc && stricmp(pciS->pszFileName, szNewName)) {
676 WinSendMsg(hwndCnrS, CM_SETRECORDEMPHASIS, MPFROMP(pciS),
677 MPFROM2SHORT(FALSE, CRA_SELECTED));
678 if (pciD->rc.flRecordAttr & CRA_SELECTED)
679 WinSendMsg(hwndCnrD, CM_SETRECORDEMPHASIS, MPFROMP(pciD),
680 MPFROM2SHORT(FALSE, CRA_SELECTED));
681 FreeCnrItemData(pciD);
682 pciD->pszFileName = xstrdup(szNewName, pszSrcFile, __LINE__);
683 if (hwndCnrS == WinWindowFromID(cmp->hwnd, COMP_RIGHTDIR)) {
684 pciD->pszDisplayName = pciD->pszFileName + strlen(cmp->leftdir);
685 if (cmp->leftdir[strlen(cmp->leftdir) - 1] != '\\')
686 pciD->pszDisplayName++;
687 }
688 else {
689 pciD->pszDisplayName = pciD->pszFileName + strlen(cmp->rightdir);
690 if (cmp->rightdir[strlen(cmp->rightdir) - 1] != '\\')
691 pciD->pszDisplayName++;
692 }
693 pciD->pszLongName = pciS->pszLongName;
694 pciS->pszLongName = NullStr; // 07 Sep 08 SHL avoid aliased pointer
695 if (pciD->pszSubject != NullStr) {
696 xfree(pciD->pszSubject, pszSrcFile, __LINE__);
697 pciD->pszSubject = NullStr;
698 }
699 pciD->attrFile = pciS->attrFile;
700 pciD->pszDispAttr = pciS->pszDispAttr;
701 pciD->flags = 0; // Just on one side
702 pciD->date = pciS->date;
703 pciD->time = pciS->time;
704 pciD->ladate = pciS->ladate;
705 pciD->latime = pciS->latime;
706 pciD->crdate = pciS->crdate;
707 pciD->crtime = pciS->crtime;
708 // 2013-03-06 SHL
709 if (pciS->pszFmtFileSize == NullStr)
710 pciD->pszFmtFileSize = pciS->pszFmtFileSize;
711 else
712 pciD->pszFmtFileSize = strdup(pciS->pszFmtFileSize);
713 pciD->cbFile = pciS->cbFile;
714 pciD->easize = pciS->easize;
715
716 if (pciS->pszFileName != NullStr) {
717 xfree(pciS->pszFileName, pszSrcFile, __LINE__);
718 pciS->pszFileName = NullStr;
719 pciS->pszDisplayName = pciS->pszFileName;
720 pciS->rc.pszIcon = pciS->pszFileName;
721 }
722 if (pciS->pszSubject != NullStr) {
723 xfree(pciS->pszSubject, pszSrcFile, __LINE__);
724 pciS->pszSubject = NullStr;
725 }
726 pciS->flags = 0; // Just on one side
727
728 WinSendMsg(hwndCnrS, CM_INVALIDATERECORD, MPFROMP(&pciS),
729 MPFROM2SHORT(1, CMA_ERASE | CMA_TEXTCHANGED));
730
731 WinSendMsg(hwndCnrD, CM_INVALIDATERECORD, MPFROMP(&pciD),
732 MPFROM2SHORT(1, CMA_ERASE | CMA_TEXTCHANGED));
733
734 if (hwndCnrS == WinWindowFromID(cmp->hwnd, COMP_LEFTDIR))
735 cmp->cmp->totalleft--;
736 else
737 cmp->cmp->totalright--;
738 }
739 else if (rc) {
740 rc = Dos_Error(MB_ENTERCANCEL,
741 rc,
742 HWND_DESKTOP,
743 pszSrcFile,
744 __LINE__,
745 GetPString(IDS_COMPMOVEFAILEDTEXT),
746 pciS->pszFileName, szNewName);
747 if (rc == MBID_CANCEL) // Cause loop to break
748 pciNextS = NULL;
749 }
750 break;
751 }
752
753 case IDM_COPY:
754 {
755 BOOL fResetVerify = FALSE;
756
757 if (hwndCnrS == WinWindowFromID(cmp->hwnd, COMP_RIGHTDIR))
758 BldFullPathName(szNewName, cmp->leftdir, pciS->pszDisplayName);
759 else
760 BldFullPathName(szNewName, cmp->rightdir, pciS->pszDisplayName);
761 // Make directory if required
762 strcpy(szDirName, szNewName);
763 p = strrchr(szDirName, '\\');
764 if (fVerify && (driveflags[toupper(*szNewName) - 'A'] & DRIVE_WRITEVERIFYOFF ||
765 driveflags[toupper(*pciS->pszFileName) - 'A'] & DRIVE_WRITEVERIFYOFF)) {
766 DosSetVerify(FALSE);
767 fResetVerify = TRUE;
768 }
769 if (p) {
770 if (p > szDirName + 2)
771 p++;
772 *p = 0;
773 if (IsFile(szDirName) == -1)
774 MassMkdir(hwndMain, szDirName);
775 }
776 if (fConfirmAction && pciS->flags & CNRITEM_EXISTS && !dontask) {
777 rc = ConfirmAction(cmp->hwnd, pciS->pszFileName, szNewName);
778 if (rc == 1)
779 break;
780 else if (rc == 2)
781 dontask = TRUE;
782 }
783 rc = docopyf(COPY, pciS->pszFileName, szNewName);
784 if (fResetVerify) {
785 DosSetVerify(fVerify);
786 fResetVerify = FALSE;
787 }
788 if (rc) {
789 rc = Dos_Error(MB_ENTERCANCEL,
790 rc,
791 HWND_DESKTOP,
792 pszSrcFile,
793 __LINE__,
794 GetPString(IDS_COMPCOPYFAILEDTEXT),
795 pciS->pszFileName, szNewName);
796 if (rc == MBID_CANCEL)
797 pciNextS = NULL; // Cause loop to break
798 }
799 else {
800 WinSendMsg(hwndCnrS, CM_SETRECORDEMPHASIS, MPFROMP(pciS),
801 MPFROM2SHORT(FALSE, CRA_SELECTED));
802 if (pciD->rc.flRecordAttr & CRA_SELECTED)
803 WinSendMsg(hwndCnrD, CM_SETRECORDEMPHASIS, MPFROMP(pciD),
804 MPFROM2SHORT(FALSE, CRA_SELECTED));
805 if (~pciD->flags & CNRITEM_EXISTS) {
806 if (hwndCnrD == WinWindowFromID(cmp->hwnd, COMP_LEFTDIR))
807 cmp->cmp->totalleft++;
808 else
809 cmp->cmp->totalright++;
810 }
811 FreeCnrItemData(pciD);
812 pciD->pszFileName = xstrdup(szNewName, pszSrcFile, __LINE__);
813 if (hwndCnrS == WinWindowFromID(cmp->hwnd, COMP_RIGHTDIR)) {
814 pciD->pszDisplayName = pciD->pszFileName + strlen(cmp->leftdir);
815 if (cmp->leftdir[strlen(cmp->leftdir) - 1] != '\\')
816 pciD->pszDisplayName++;
817 }
818 else {
819 pciD->pszDisplayName = pciD->pszFileName + strlen(cmp->rightdir);
820 if (cmp->rightdir[strlen(cmp->rightdir) - 1] != '\\')
821 pciD->pszDisplayName++;
822 }
823 pciD->attrFile = pciS->attrFile;
824 pciD->pszDispAttr = pciS->pszDispAttr;
825 pciD->flags = CNRITEM_EXISTS; // Now on both sides
826 pciD->date = pciS->date;
827 pciD->time = pciS->time;
828 pciD->ladate = pciS->ladate;
829 pciD->latime = pciS->latime;
830 pciD->crdate = pciS->crdate;
831 pciD->crtime = pciS->crtime;
832 // 2013-03-06 SHL
833 if (pciS->pszFmtFileSize == NullStr)
834 pciD->pszFmtFileSize = pciS->pszFmtFileSize;
835 else
836 pciD->pszFmtFileSize = strdup(pciS->pszFmtFileSize);
837 pciD->cbFile = pciS->cbFile;
838 pciD->easize = pciS->easize;
839
840 // Forget status until we regenerate it
841 if (pciS->pszSubject != NullStr) {
842 xfree(pciS->pszSubject, pszSrcFile, __LINE__);
843 pciS->pszSubject = NullStr;
844 }
845 pciS->flags = CNRITEM_EXISTS; // Now on both sides
846
847 WinSendMsg(hwndCnrS, CM_INVALIDATERECORD, MPFROMP(&pciS),
848 MPFROM2SHORT(1, CMA_ERASE | CMA_TEXTCHANGED));
849 WinSendMsg(hwndCnrD, CM_INVALIDATERECORD, MPFROMP(&pciD),
850 MPFROM2SHORT(1, CMA_ERASE | CMA_TEXTCHANGED));
851 }
852 break;
853 }
854
855 default:
856 break;
857 } // switch
858
859 } // if have name
860 if (enddelete)
861 break;
862 pciS = pciNextS;
863 pciD = pciNextD;
864
865 SleepIfNeeded(&itdSleep, 0);
866 } // while
867 WinPostMsg(cmp->hwnd, WM_TIMER, MPFROMLONG(ID_COMP_TIMER), 0); // Force update
868 Abort:
869 WinDestroyMsgQueue(hmq);
870 }
871 PostMsg(cmp->hwnd, UM_CONTAINER_FILLED, MPFROMLONG(1), MPVOID);
872 DecrThreadUsage();
873 free(cmp);
874 WinTerminate(hab);
875# ifdef FORTIFY
876 Fortify_LeaveScope();
877# endif
878 }
879 else
880 xfree(cmp, pszSrcFile, __LINE__);
881}
882
883static VOID CompSelect(HWND hwndCnrS, HWND hwndCnrD, HWND hwnd, INT action, USHORT shiftstate, BOOL *stop);
884
885/**
886 * Update container selection flags thread
887 */
888
889static VOID SelectCnrsThread(VOID *args)
890{
891 COMPARE *cmp = (COMPARE *)args;
892 HAB hab;
893 HMQ hmq;
894
895 if (!cmp) {
896 Runtime_Error(pszSrcFile, __LINE__, NULL);
897 return;
898 }
899
900 DosError(FERR_DISABLEHARDERR);
901
902 hab = WinInitialize(0);
903 if (hab) {
904# ifdef FORTIFY
905 Fortify_EnterScope();
906# endif
907 hmq = WinCreateMsgQueue(hab, 0);
908 if (hmq) {
909 WinCancelShutdown(hmq, TRUE);
910 IncrThreadUsage();
911 priority_normal();
912 switch (cmp->action) {
913 case IDM_INVERT:
914 InvertAll(WinWindowFromID(cmp->hwnd, COMP_LEFTDIR));
915 InvertAll(WinWindowFromID(cmp->hwnd, COMP_RIGHTDIR));
916 break;
917
918 case IDM_DESELECTALL:
919 Deselect(WinWindowFromID(cmp->hwnd, COMP_LEFTDIR));
920 Deselect(WinWindowFromID(cmp->hwnd, COMP_RIGHTDIR));
921 break;
922
923 default:
924 CompSelect(WinWindowFromID(cmp->hwnd, COMP_LEFTDIR),
925 WinWindowFromID(cmp->hwnd, COMP_RIGHTDIR),
926 cmp->hwnd,
927 cmp->action,
928 cmp->shiftstate,
929 &cmp->cmp->stop);
930 break;
931 }
932 if (!PostMsg(cmp->hwnd, UM_CONTAINER_FILLED, MPFROMLONG(1L), MPVOID))
933 WinSendMsg(cmp->hwnd, UM_CONTAINER_FILLED, MPFROMLONG(1L), MPVOID);
934 WinDestroyMsgQueue(hmq);
935 }
936 DecrThreadUsage();
937 free(cmp);
938 WinTerminate(hab);
939# ifdef FORTIFY
940 Fortify_LeaveScope();
941# endif
942 }
943 else
944 free(cmp);
945}
946
947/**
948 * Set item selections for CompSelect
949 */
950
951static VOID CompSelectSetSelects(PCNRITEM pciS, PCNRITEM pciD, BOOL matchS, BOOL matchD, BOOL wantAnd);
952
953static VOID CompSelectSetSelects(PCNRITEM pciS, PCNRITEM pciD, BOOL matchS, BOOL matchD, BOOL wantAnd)
954{
955 ULONG oldSel;
956 ULONG newSel;
957
958 oldSel = pciS->rc.flRecordAttr & CRA_SELECTED;
959 newSel = matchS ? (wantAnd ? oldSel : CRA_SELECTED) : (wantAnd ? 0 : oldSel);
960 if ((pciS->rc.flRecordAttr & CRA_SELECTED) != newSel)
961 WinSendMsg(pciS->hwndCnr, CM_SETRECORDEMPHASIS, MPFROMP(pciS),
962 MPFROM2SHORT(newSel ? TRUE : FALSE, CRA_SELECTED));
963
964 oldSel = pciD->rc.flRecordAttr & CRA_SELECTED;
965 newSel = matchD ? (wantAnd ? oldSel : CRA_SELECTED) : (wantAnd ? 0 : oldSel);
966 if ((pciD->rc.flRecordAttr & CRA_SELECTED) != newSel) {
967 WinSendMsg(pciD->hwndCnr, CM_SETRECORDEMPHASIS, MPFROMP(pciD),
968 MPFROM2SHORT(newSel ? TRUE : FALSE, CRA_SELECTED));
969 }
970}
971
972/**
973 * Clear item selections for CompSelect
974 */
975
976static BOOL CompSelectClearSelects(PCNRITEM pciS, PCNRITEM pciD, BOOL matchS, BOOL matchD);
977
978static BOOL CompSelectClearSelects(PCNRITEM pciS, PCNRITEM pciD, BOOL matchS, BOOL matchD)
979{
980 BOOL changed;
981
982 if ((pciS->rc.flRecordAttr & CRA_SELECTED) && matchS) {
983 WinSendMsg(pciS->hwndCnr, CM_SETRECORDEMPHASIS, MPFROMP(pciS),
984 MPFROM2SHORT(FALSE, CRA_SELECTED));
985 changed = TRUE;
986 }
987 else
988 changed = FALSE;
989
990 if ((pciD->rc.flRecordAttr & CRA_SELECTED) && matchD) {
991 WinSendMsg(pciD->hwndCnr, CM_SETRECORDEMPHASIS, MPFROMP(pciD),
992 MPFROM2SHORT(FALSE, CRA_SELECTED));
993 changed = TRUE;
994 }
995
996 return changed;
997}
998
999/**
1000 * Do select actions for compare directories containers
1001 * @param action is select mode
1002 */
1003
1004static VOID CompSelect(HWND hwndCnrS, HWND hwndCnrD, HWND hwnd, INT action, USHORT shiftstate, BOOL *stop)
1005{
1006 PCNRITEM pciS;
1007 PCNRITEM pciD;
1008 PCNRITEM *pciSa = NULL;
1009 PCNRITEM *pciDa = NULL;
1010 CNRINFO cnri;
1011 BOOL slow = FALSE;
1012 UINT x;
1013 UINT numD;
1014 UINT numS;
1015 ITIMER_DESC itdSleep = { 0 };
1016 BOOL fUpdateHideButton = FALSE;
1017 BOOL wantAnd = (shiftstate & (KC_SHIFT | KC_ALT | KC_CTRL)) == KC_CTRL;
1018 BOOL matched;
1019
1020 if (!hwndCnrS || !hwndCnrD) {
1021 Runtime_Error(pszSrcFile, __LINE__, "hwndCnrS %p hwndCnrD %p", hwndCnrS, hwndCnrD);
1022 return;
1023 }
1024
1025 memset(&cnri, 0, sizeof(CNRINFO));
1026 cnri.cb = sizeof(CNRINFO);
1027 WinSendMsg(hwndCnrD, CM_QUERYCNRINFO, MPFROMP(&cnri),
1028 MPFROMLONG(sizeof(CNRINFO)));
1029 numD = cnri.cRecords;
1030 memset(&cnri, 0, sizeof(CNRINFO));
1031 cnri.cb = sizeof(CNRINFO);
1032 WinSendMsg(hwndCnrS, CM_QUERYCNRINFO, MPFROMP(&cnri),
1033 MPFROMLONG(sizeof(CNRINFO)));
1034 numS = cnri.cRecords;
1035 if (!numD || numS != numD) {
1036 Runtime_Error(pszSrcFile, __LINE__, "numD %u != numS %u", numD, numS);
1037 return;
1038 }
1039
1040 pciDa = xmalloc(sizeof(PCNRITEM) * numD, pszSrcFile, __LINE__);
1041 if (!pciDa)
1042 return;
1043
1044 pciSa = xmalloc(sizeof(PCNRITEM) * numS, pszSrcFile, __LINE__);
1045 if (!pciSa) {
1046 free(pciDa);
1047 return;
1048 }
1049
1050 InitITimer(&itdSleep, 500); // Sleep every 500 mSec
1051
1052Restart:
1053
1054 memset(pciDa, 0, sizeof(PCNRITEM) * numD);
1055 memset(pciSa, 0, sizeof(PCNRITEM) * numS);
1056
1057 pciD = (PCNRITEM)WinSendMsg(hwndCnrD, CM_QUERYRECORD, MPVOID,
1058 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
1059 x = 0;
1060 while (pciD && (INT)pciD != -1 && x < numD) {
1061 pciDa[x] = pciD;
1062 x++;
1063 if (!slow)
1064 pciD = (PCNRITEM) pciD->rc.preccNextRecord;
1065 else
1066 pciD = (PCNRITEM) WinSendMsg(hwndCnrD, CM_QUERYRECORD, MPFROMP(pciD),
1067 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
1068 SleepIfNeeded(&itdSleep, 0);
1069 } // while
1070
1071 if (numD != x) {
1072 // Something out of sync - fixme to document why slow logic needed
1073 if (!slow) {
1074 slow = TRUE;
1075 goto Restart;
1076 }
1077 free(pciDa);
1078 free(pciSa);
1079 Runtime_Error(pszSrcFile, __LINE__, "numD %u != x %lu", numD, x);
1080 return;
1081 }
1082
1083 pciS = (PCNRITEM) WinSendMsg(hwndCnrS, CM_QUERYRECORD, MPVOID,
1084 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
1085 x = 0;
1086 while (pciS && (INT)pciS != -1 && x < numS) {
1087 pciSa[x] = pciS;
1088 x++;
1089 if (!slow)
1090 pciS = (PCNRITEM) pciS->rc.preccNextRecord;
1091 else
1092 pciS = (PCNRITEM) WinSendMsg(hwndCnrS, CM_QUERYRECORD, MPFROMP(pciS),
1093 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
1094 SleepIfNeeded(&itdSleep, 0);
1095 } // while
1096
1097 if (numS != x) {
1098 if (!slow) {
1099 slow = TRUE;
1100 goto Restart;
1101 }
1102 free(pciSa);
1103 free(pciDa);
1104 Runtime_Error(pszSrcFile, __LINE__, "numS (%lu) != x (%lu)", numS, x);
1105 return;
1106 }
1107
1108 switch (action) {
1109 case IDM_SELECTIDENTICAL:
1110 // Same Date/size including EAs
1111 for (x = 0; x < numS; x++) {
1112 pciS = pciSa[x];
1113 if (~pciS->rc.flRecordAttr & CRA_FILTERED) {
1114 matched = pciS->flags & CNRITEM_EXISTS &&
1115 ~pciS->flags & CNRITEM_SMALLER &&
1116 ~pciS->flags & CNRITEM_LARGER &&
1117 ~pciS->flags & CNRITEM_NEWER &&
1118 ~pciS->flags & CNRITEM_OLDER &&
1119 ~pciS->flags & CNRITEM_EASDIFFER;
1120 CompSelectSetSelects(pciS, pciDa[x], matched, matched, wantAnd);
1121 }
1122 SleepIfNeeded(&itdSleep, 0);
1123 } // for
1124 break;
1125
1126 case IDM_SELECTSAME:
1127 // Same Size including EAs
1128 for (x = 0; x < numS; x++) {
1129 pciS = pciSa[x];
1130 if (~pciS->rc.flRecordAttr & CRA_FILTERED) {
1131 matched = pciS->flags & CNRITEM_EXISTS &&
1132 ~pciS->flags & CNRITEM_SMALLER &&
1133 ~pciS->flags & CNRITEM_LARGER &&
1134 ~pciS->flags & CNRITEM_EASDIFFER;
1135 CompSelectSetSelects(pciS, pciDa[x], matched, matched, wantAnd);
1136 }
1137 SleepIfNeeded(&itdSleep, 0);
1138 } // for
1139 break;
1140
1141 case IDM_SELECTSAMECONTENT:
1142 for (x = 0; x < numS && !*stop; x++) {
1143
1144 pciS = pciSa[x];
1145 if (~pciS->rc.flRecordAttr & CRA_FILTERED) {
1146 matched = FALSE;
1147 pciD = pciDa[x];
1148 if (pciS->flags & CNRITEM_EXISTS) {
1149 FILE *fp1 = NULL;
1150 FILE *fp2 = NULL;
1151 UINT errLineNo = 0;
1152 UINT compErrno = 0;
1153 CHAR buf1[1024];
1154 CHAR buf2[1024];
1155 HAB hab = WinQueryAnchorBlock(hwndCnrS);
1156 CHAR *moderb = "rb";
1157
1158 if (!*pciS->pszFileName ||
1159 !*pciD->pszFileName) {
1160 Runtime_Error(pszSrcFile, __LINE__,
1161 "CNRITEM_EXISTS set with null file name for index %u", x);
1162 break;
1163 }
1164
1165 fp1 = xfsopen(pciS->pszFileName, moderb, SH_DENYNO, pszSrcFile, __LINE__, TRUE);
1166 if (!fp1) {
1167 errLineNo = __LINE__;
1168 compErrno = errno;
1169 }
1170 else {
1171 fp2 = xfsopen(pciD->pszFileName, moderb, SH_DENYNO, pszSrcFile, __LINE__, TRUE);
1172 if (!fp2) {
1173 errLineNo = __LINE__;
1174 compErrno = errno;
1175 }
1176 else {
1177 size_t len1 = filelength(fileno(fp1));
1178 size_t len2 = filelength(fileno(fp2));
1179 if (len1 == len2) {
1180 setbuf(fp1, NULL);
1181 setbuf(fp2, NULL);
1182 while (WinIsWindow(hab, hwndCnrS)) {
1183 size_t numread1 = fread(buf1, 1, 1024, fp1);
1184 size_t numread2 = fread(buf2, 1, 1024, fp2);
1185
1186 if (!numread1 || !numread2 || numread1 != numread2) {
1187 if (ferror(fp1) || ferror(fp2)) {
1188 errLineNo = __LINE__;
1189 compErrno = errno;
1190 }
1191 else if (feof(fp1) && feof(fp2))
1192 matched = TRUE;
1193 break;
1194 }
1195 else if (memcmp(buf1, buf2, numread1))
1196 break;
1197 } // while
1198 } // same len
1199 } // if open ok
1200 } // if open ok
1201 if (fp1)
1202 fclose(fp1);
1203 if (fp2)
1204 fclose(fp2);
1205
1206 if (errLineNo) {
1207 Runtime_Error(pszSrcFile, errLineNo,
1208 "error %d while comparing", compErrno);
1209 }
1210 } // if exists
1211 CompSelectSetSelects(pciS, pciD, matched, matched, wantAnd);
1212 } // if not filtered
1213 SleepIfNeeded(&itdSleep, 0);
1214 } // for
1215 break;
1216
1217 case IDM_SELECTBOTH:
1218 for (x = 0; x < numS; x++) {
1219 pciS = pciSa[x];
1220 if (~pciS->rc.flRecordAttr & CRA_FILTERED) {
1221 pciD = pciDa[x];
1222 matched = pciS->flags & CNRITEM_EXISTS;
1223 CompSelectSetSelects(pciS, pciD, matched, matched, wantAnd);
1224 }
1225 SleepIfNeeded(&itdSleep, 0);
1226 } // for
1227 break;
1228
1229 case IDM_SELECTONE:
1230 for (x = 0; x < numS; x++) {
1231 pciS = pciSa[x];
1232 if (~pciS->rc.flRecordAttr & CRA_FILTERED) {
1233 pciD = pciDa[x];
1234 CompSelectSetSelects(pciS,
1235 pciD,
1236 ~pciS->flags & CNRITEM_EXISTS && *pciS->pszFileName,
1237 ~pciD->flags & CNRITEM_EXISTS && *pciD->pszFileName,
1238 wantAnd);
1239 }
1240 SleepIfNeeded(&itdSleep, 0);
1241 } // for
1242 break;
1243
1244 case IDM_SELECTBIGGER:
1245 for (x = 0; x < numS; x++) {
1246 pciS = pciSa[x];
1247 if (~pciS->rc.flRecordAttr & CRA_FILTERED) {
1248 pciD = pciDa[x];
1249 CompSelectSetSelects(pciS,
1250 pciD,
1251 pciS->flags & CNRITEM_LARGER,
1252 pciD->flags & CNRITEM_LARGER,
1253 wantAnd);
1254 }
1255 SleepIfNeeded(&itdSleep, 0);
1256 } // for
1257 break;
1258
1259 case IDM_SELECTSMALLER:
1260 for (x = 0; x < numS; x++) {
1261 pciS = pciSa[x];
1262 if (~pciS->rc.flRecordAttr & CRA_FILTERED) {
1263 pciD = pciDa[x];
1264 CompSelectSetSelects(pciS,
1265 pciD,
1266 pciS->flags & CNRITEM_SMALLER,
1267 pciD->flags & CNRITEM_SMALLER,
1268 wantAnd);
1269 }
1270 SleepIfNeeded(&itdSleep, 0);
1271 } // for
1272 break;
1273
1274 case IDM_SELECTNEWER:
1275 for (x = 0; x < numS; x++) {
1276 pciS = pciSa[x];
1277 if (~pciS->rc.flRecordAttr & CRA_FILTERED) {
1278 pciD = pciDa[x];
1279 CompSelectSetSelects(pciS,
1280 pciD,
1281 pciS->flags & CNRITEM_NEWER,
1282 pciD->flags & CNRITEM_NEWER,
1283 wantAnd);
1284 }
1285 SleepIfNeeded(&itdSleep, 0);
1286 } // for
1287 break;
1288
1289 case IDM_SELECTOLDER:
1290 for (x = 0; x < numS; x++) {
1291 pciS = pciSa[x];
1292 if (~pciS->rc.flRecordAttr & CRA_FILTERED) {
1293 pciD = pciDa[x];
1294 CompSelectSetSelects(pciS,
1295 pciD,
1296 pciS->flags & CNRITEM_OLDER,
1297 pciD->flags & CNRITEM_OLDER,
1298 wantAnd);
1299 }
1300 SleepIfNeeded(&itdSleep, 0);
1301 } // for
1302 break;
1303
1304 case IDM_SELECTEAS:
1305 for (x = 0; x < numS; x++) {
1306 pciS = pciSa[x];
1307 if (~pciS->rc.flRecordAttr & CRA_FILTERED) {
1308 pciD = pciDa[x];
1309 CompSelectSetSelects(pciS,
1310 pciD,
1311 pciS->flags & CNRITEM_EASDIFFER,
1312 pciD->flags & CNRITEM_EASDIFFER,
1313 wantAnd);
1314 }
1315 SleepIfNeeded(&itdSleep, 0);
1316 } // for
1317 break;
1318
1319 case IDM_DESELECTBOTH:
1320 for (x = 0; x < numS; x++) {
1321 pciS = pciSa[x];
1322 if (~pciS->rc.flRecordAttr & CRA_FILTERED) {
1323 matched = pciS->flags & CNRITEM_EXISTS;
1324 if (CompSelectClearSelects(pciS, pciDa[x], matched, matched))
1325 fUpdateHideButton = TRUE;
1326 }
1327 SleepIfNeeded(&itdSleep, 0);
1328 } // for
1329 break;
1330
1331 case IDM_DESELECTONE:
1332 for (x = 0; x < numS; x++) {
1333 pciS = pciSa[x];
1334 if (~pciS->rc.flRecordAttr & CRA_FILTERED) {
1335 pciD = pciDa[x];
1336 if (CompSelectClearSelects(pciS,
1337 pciD,
1338 ~pciS->flags & CNRITEM_EXISTS && *pciS->pszFileName,
1339 ~pciD->flags & CNRITEM_EXISTS && *pciD->pszFileName)) {
1340 fUpdateHideButton = TRUE;
1341 }
1342 }
1343 SleepIfNeeded(&itdSleep, 0);
1344 } // for
1345 break;
1346
1347 case IDM_DESELECTBIGGER:
1348 for (x = 0; x < numS; x++) {
1349 pciS = pciSa[x];
1350 if (~pciS->rc.flRecordAttr & CRA_FILTERED) {
1351 pciD = pciDa[x];
1352 if (CompSelectClearSelects(pciS,
1353 pciD,
1354 pciS->flags & CNRITEM_LARGER,
1355 pciD->flags & CNRITEM_LARGER)) {
1356 fUpdateHideButton = TRUE;
1357 }
1358 }
1359 SleepIfNeeded(&itdSleep, 0);
1360 } // for
1361 break;
1362
1363 case IDM_DESELECTSMALLER:
1364 for (x = 0; x < numS; x++) {
1365 pciS = pciSa[x];
1366 if (~pciS->rc.flRecordAttr & CRA_FILTERED) {
1367 pciD = pciDa[x];
1368 if (CompSelectClearSelects(pciS,
1369 pciD,
1370 pciS->flags & CNRITEM_SMALLER,
1371 pciD->flags & CNRITEM_SMALLER)) {
1372 fUpdateHideButton = TRUE;
1373 }
1374 }
1375 SleepIfNeeded(&itdSleep, 0);
1376 } // for
1377 break;
1378
1379 case IDM_DESELECTNEWER:
1380 for (x = 0; x < numS; x++) {
1381 pciS = pciSa[x];
1382 if (~pciS->rc.flRecordAttr & CRA_FILTERED) {
1383 pciD = pciDa[x];
1384 if (CompSelectClearSelects(pciS,
1385 pciD,
1386 pciS->flags & CNRITEM_NEWER,
1387 pciD->flags & CNRITEM_NEWER)) {
1388 fUpdateHideButton = TRUE;
1389 }
1390 }
1391 SleepIfNeeded(&itdSleep, 0);
1392 } // for
1393 break;
1394
1395 case IDM_DESELECTOLDER:
1396 for (x = 0; x < numS; x++) {
1397 pciS = pciSa[x];
1398 if (~pciS->rc.flRecordAttr & CRA_FILTERED) {
1399 pciD = pciDa[x];
1400 if (CompSelectClearSelects(pciS,
1401 pciD,
1402 pciS->flags & CNRITEM_OLDER,
1403 pciD->flags & CNRITEM_OLDER)) {
1404 fUpdateHideButton = TRUE;
1405 }
1406 }
1407 SleepIfNeeded(&itdSleep, 0);
1408 } // for
1409 break;
1410
1411 case IDM_DESELECTEAS:
1412 for (x = 0; x < numS; x++) {
1413 pciS = pciSa[x];
1414 if (~pciS->rc.flRecordAttr & CRA_FILTERED) {
1415 pciD = pciDa[x];
1416 if (CompSelectClearSelects(pciS,
1417 pciD,
1418 pciS->flags & CNRITEM_EASDIFFER,
1419 pciD->flags & CNRITEM_EASDIFFER)) {
1420 fUpdateHideButton = TRUE;
1421 }
1422 }
1423 SleepIfNeeded(&itdSleep, 0);
1424 } // for
1425 break;
1426
1427 default:
1428 break;
1429 } // switch action
1430
1431 free(pciSa);
1432 free(pciDa);
1433
1434 if (fUpdateHideButton) {
1435 if (WinQueryButtonCheckstate(hwnd,COMP_HIDENOTSELECTED) == 1)
1436 WinCheckButton(hwnd, COMP_HIDENOTSELECTED, 2);
1437 }
1438
1439 WinPostMsg(hwnd, WM_TIMER, MPFROMLONG(ID_COMP_TIMER), 0); // Force update
1440 DosPostEventSem(CompactSem);
1441}
1442
1443/**
1444 * Build FILELIST given pathname
1445 */
1446
1447static VOID FillDirList(CHAR *str, UINT skiplen, BOOL recurse,
1448 FILELIST ***list, UINT *pnumfiles, UINT *pnumalloc)
1449{
1450 CHAR *enddir;
1451 ULONG x;
1452 CHAR *maskstr;
1453 PFILEFINDBUF4L pffbArray;
1454 PFILEFINDBUF4L pffbFile;
1455 HDIR hDir;
1456 ULONG ulFindCnt;
1457 ULONG ulBufBytes = sizeof(FILEFINDBUF4L) * FilesToGet;
1458 APIRET rc;
1459 static BOOL fDone;
1460 ITIMER_DESC itdSleep = { 0 }; // 30 May 11 GKY
1461
1462 if (!str || !*str) {
1463 Runtime_Error(pszSrcFile, __LINE__, NULL);
1464 return;
1465 }
1466
1467 maskstr = xmalloc(CCHMAXPATH + 100, pszSrcFile, __LINE__);
1468 if (!maskstr)
1469 return;
1470 pffbArray = xmalloc(ulBufBytes, pszSrcFile, __LINE__);
1471 if (!pffbArray) {
1472 free(maskstr);
1473 return;
1474 }
1475 x = strlen(str);
1476 memcpy(maskstr, str, x + 1);
1477 enddir = maskstr + x;
1478 if (*(enddir - 1) != '\\') {
1479 *enddir = '\\';
1480 enddir++;
1481 *enddir = 0;
1482 }
1483 *enddir = '*';
1484 *(enddir + 1) = 0;
1485 hDir = HDIR_CREATE;
1486 DosError(FERR_DISABLEHARDERR);
1487 ulFindCnt = FilesToGet;
1488 rc = xDosFindFirst(maskstr, &hDir,
1489 FILE_NORMAL | FILE_READONLY | FILE_ARCHIVED |
1490 FILE_SYSTEM | FILE_HIDDEN |
1491 (recurse ? FILE_DIRECTORY : 0),
1492 pffbArray, ulBufBytes, &ulFindCnt, FIL_QUERYEASIZEL);
1493 if (!rc) {
1494 InitITimer(&itdSleep, 500);
1495 do {
1496 pffbFile = pffbArray;
1497 for (x = 0; x < ulFindCnt; x++) {
1498 if (pffbFile->attrFile & FILE_DIRECTORY) {
1499 // Skip . and ..
1500 if (recurse &&
1501 (pffbFile->achName[0] != '.' ||
1502 (pffbFile->achName[1] &&
1503 (pffbFile->achName[1] != '.' || pffbFile->achName[2])))) {
1504 if (fForceUpper)
1505 strupr(pffbFile->achName);
1506 else if (fForceLower)
1507 strlwr(pffbFile->achName);
1508 memcpy(enddir, pffbFile->achName, pffbFile->cchName + 1);
1509 FillDirList(maskstr, skiplen, recurse, list, pnumfiles, pnumalloc);
1510 }
1511 }
1512 else {
1513 if (fForceUpper)
1514 strupr(pffbFile->achName);
1515 else if (fForceLower)
1516 strlwr(pffbFile->achName);
1517 memcpy(enddir, pffbFile->achName, pffbFile->cchName + 1);
1518 if (strlen(maskstr) > CCHMAXPATH) {
1519 // Complain if pathnames exceeds max
1520 DosFindClose(hDir);
1521 free(pffbArray);
1522 free(maskstr);
1523 if (!fDone) {
1524 fDone = TRUE;
1525 saymsg(MB_OK | MB_ICONASTERISK,
1526 HWND_DESKTOP,
1527 GetPString(IDS_WARNINGTEXT),
1528 GetPString(IDS_LENGTHEXCEEDSMAXPATHTEXT));
1529 }
1530 return;
1531 }
1532 if (AddToFileList(maskstr + skiplen,
1533 pffbFile, list, pnumfiles, pnumalloc)) {
1534 goto Abort;
1535 }
1536 }
1537 pffbFile = (PFILEFINDBUF4L)((PBYTE)pffbFile + pffbFile->oNextEntryOffset);
1538 } // for
1539 DosError(FERR_DISABLEHARDERR);
1540 ulFindCnt = FilesToGet;
1541 rc = xDosFindNext(hDir, pffbArray, ulBufBytes, &ulFindCnt, FIL_QUERYEASIZEL);
1542 SleepIfNeeded(&itdSleep, 1);
1543 } while (!rc);
1544
1545Abort:
1546
1547 DosFindClose(hDir);
1548 DosSleep(0);
1549 }
1550
1551 if (rc && rc != ERROR_NO_MORE_FILES) {
1552 Dos_Error(MB_ENTER, rc, HWND_DESKTOP, pszSrcFile, __LINE__,
1553 GetPString(IDS_CANTFINDDIRTEXT), maskstr);
1554 }
1555
1556 xfree(maskstr, pszSrcFile, __LINE__);
1557 xfree(pffbArray, pszSrcFile, __LINE__);
1558}
1559
1560#define GetHwndLeft(h) (WinWindowFromID(h,COMP_LEFTDIR))
1561#define GetHwndRight(h) (WinWindowFromID(h,COMP_RIGHTDIR))
1562
1563/**
1564 * Compare names for qsort
1565 */
1566
1567static int CompNames(const void *n1, const void *n2)
1568{
1569 FILELIST *fl1 = *(FILELIST **)n1;
1570 FILELIST *fl2 = *(FILELIST **)n2;
1571
1572 return stricmp(fl1->fname, fl2->fname);
1573}
1574
1575/**
1576 * Fill left and right containers
1577 */
1578
1579static VOID FillCnrsThread(VOID *args)
1580{
1581 COMPARE *cmp = (COMPARE *)args;
1582 HAB hab;
1583 HMQ hmq;
1584 BOOL notified = FALSE;
1585 ITIMER_DESC itdSleep = { 0 };
1586
1587 CHAR szBuf[CCHMAXPATH];
1588 CNRINFO cnri;
1589
1590# ifdef FORTIFY
1591 // 10 May 08 SHL fixme to suppress W111
1592 Fortify_EnterScope();
1593# endif
1594
1595 if (!cmp) {
1596 Runtime_Error(pszSrcFile, __LINE__, NULL);
1597# ifdef FORTIFY
1598 // 10 May 08 SHL fixme to suppress W111
1599 Fortify_LeaveScope();
1600# endif
1601 return; // 10 Dec 08 SHL was _endthread
1602 }
1603
1604 DosError(FERR_DISABLEHARDERR);
1605
1606 InitITimer(&itdSleep, 500); // Sleep every 500 mSec
1607
1608 hab = WinInitialize(0);
1609 if (!hab)
1610 Win_Error(NULLHANDLE, NULLHANDLE, pszSrcFile, __LINE__, "WinInitialize");
1611 else {
1612 hmq = WinCreateMsgQueue(hab, 0);
1613 if (!hmq)
1614 Win_Error(NULLHANDLE, NULLHANDLE, pszSrcFile, __LINE__,
1615 "WinCreateMsgQueue");
1616 else {
1617 INT x;
1618 UINT l;
1619 UINT r;
1620 // UINT cntr;
1621 FILELIST **filesl = NULL;
1622 FILELIST **filesr = NULL;
1623 UINT numallocl = 0;
1624 UINT numallocr = 0;
1625 UINT lenl; // Directory prefix length
1626 UINT lenr;
1627 ULONG ulRecsNeeded;
1628 CHAR *pch;
1629 HWND hwndLeft;
1630 HWND hwndRight;
1631
1632 WinCancelShutdown(hmq, TRUE);
1633 IncrThreadUsage();
1634
1635 hwndLeft = GetHwndLeft(cmp->hwnd);
1636 hwndRight = GetHwndRight(cmp->hwnd);
1637 lenl = strlen(cmp->leftdir);
1638 if (cmp->leftdir[strlen(cmp->leftdir) - 1] != '\\')
1639 lenl++;
1640 lenr = strlen(cmp->rightdir);
1641 if (cmp->rightdir[strlen(cmp->rightdir) - 1] != '\\')
1642 lenr++;
1643 priority_normal();
1644 // Clear containers
1645 RemoveCnrItems(hwndRight, NULL, 0, CMA_FREE | CMA_INVALIDATE);
1646 RemoveCnrItems(hwndLeft, NULL, 0, CMA_FREE | CMA_INVALIDATE);
1647 cmp->cmp->totalleft = 0;
1648 cmp->cmp->totalright = 0;
1649
1650 // Build list of all files in left directory
1651 if (fForceLower)
1652 strlwr(cmp->leftdir);
1653 else if (fForceUpper)
1654 strupr(cmp->leftdir);
1655 FillDirList(cmp->leftdir, lenl, cmp->includesubdirs,
1656 &filesl, &cmp->cmp->totalleft, &numallocl);
1657
1658 if (filesl)
1659 qsort(filesl, cmp->cmp->totalleft, sizeof(CHAR *), CompNames);
1660
1661 // Build list of all files in right directory
1662 //DbgMsg(pszSrcFile, __LINE__, "list file %s", cmp->rightlist);
1663 if (!*cmp->rightlist) {
1664 if (fForceLower)
1665 strlwr(cmp->rightdir);
1666 else if (fForceUpper)
1667 strupr(cmp->rightdir);
1668 FillDirList(cmp->rightdir, lenr, cmp->includesubdirs,
1669 &filesr, &cmp->cmp->totalright, &numallocr);
1670 }
1671 else {
1672 // Use snapshot file
1673 FILE *fp;
1674 FILEFINDBUF4L fb4;
1675 CHAR str[CCHMAXPATH * 2], *p;
1676 CHAR *moder = "r";
1677 BOOL fFixedSnap = TRUE;
1678
1679 memset(&fb4, 0, sizeof(fb4));
1680 fp = xfopen(cmp->rightlist, moder, pszSrcFile, __LINE__, FALSE);
1681 if (fp) {
1682 while (!feof(fp)) {
1683 // First get name of directory
1684 if (!xfgets_bstripcr(str, sizeof(str), fp, pszSrcFile, __LINE__))
1685 break; // EOF
1686 p = str;
1687 if (*p == '\"') {
1688 // Quoted
1689 p++;
1690 if (*p && *p != '\"') {
1691 p = strchr(p, '\"');
1692 if (p) {
1693 *p = 0;
1694 if (*(str + 1)) {
1695 strcpy(cmp->rightdir, str + 1);
1696 if (fForceUpper)
1697 strupr(cmp->rightdir);
1698 else if (fForceLower)
1699 strlwr(cmp->rightdir);
1700 p = cmp->rightdir + (strlen(cmp->rightdir) - 1);
1701 if (p - cmp->rightdir > 3 && *p == '\\')
1702 *p = 0; // Chop trailing slash
1703 break;
1704 }
1705 }
1706 }
1707 }
1708 } // while !EOF
1709
1710 memset(&cnri, 0, sizeof(cnri));
1711 cnri.cb = sizeof(cnri);
1712 WinSetDlgItemText(cmp->hwnd, COMP_LISTLOADED, "List File Loaded");
1713 cnri.pszCnrTitle = cmp->rightdir;
1714 if (!WinSendMsg(hwndRight, CM_SETCNRINFO,
1715 MPFROMP(&cnri), MPFROMLONG(CMA_CNRTITLE))) {
1716 Win_Error(hwndRight, cmp->hwnd, pszSrcFile, __LINE__, "CM_SETCNRINFO");
1717 WinSetDlgItemText(cmp->hwnd, COMP_LISTLOADED, "");
1718 }
1719
1720 if (*cmp->rightdir) {
1721 lenr = strlen(cmp->rightdir);
1722 if (cmp->rightdir[strlen(cmp->rightdir) - 1] != '\\')
1723 lenr++;
1724 //DbgMsg(pszSrcFile, __LINE__, "end of file %i", feof(fp));
1725 while (!feof(fp)) {
1726 if (!xfgets_bstripcr
1727 (str, sizeof(str), fp, pszSrcFile, __LINE__)) {
1728 break;
1729 }
1730 p = str;
1731 if (*p == '\"') {
1732 p++;
1733 if (*p && *p != '\"') {
1734 p = strchr(p, '\"');
1735 if (p) {
1736 *p = 0;
1737 p++;
1738 if (*p == ',') {
1739 p++;
1740 if (!cmp->includesubdirs && atol(p) > lenr)
1741 continue;
1742 p = strchr(p, ',');
1743 if (p) {
1744 p++;
1745 //DbgMsg(pszSrcFile, __LINE__, "DS %ul comma %ul", strchr(p, '/') ? strchr(p, '/') : strchr(p, DateSeparator[0]), strchr(p, ','));
1746 if (((strchr(p, '/') ? strchr(p, '/') : strchr(p, DateSeparator[0])) - strchr(p, ',')) > 5) {
1747 CHAR szTemp[30];
1748 CHAR *q;
1749 int i;
1750
1751 memset(szTemp, 0, sizeof(szTemp));
1752 i = (strchr(p, '/') ? strchr(p, '/') : strchr(p, DateSeparator[0])) - 3 - p;
1753 strncpy(&szTemp, p, i);
1754 for (q = szTemp; q = strchr(szTemp, ',');) {
1755 strcpy(q, q + 1);
1756 }
1757 fb4.cbFile = atoll(szTemp);
1758 fFixedSnap = FALSE;
1759
1760 }
1761 else
1762 fb4.cbFile = atoll(p);
1763 if (!strchr(p, '/'))
1764 fFixedSnap = FALSE;
1765 p = (strchr(p, '/') ? strchr(p, '/') : strchr(p, DateSeparator[0])) - 6;
1766 p = strchr(p, ',');
1767 if (p) {
1768 p++;
1769 if (ulDateFmt == 2 || ulDateFmt == 3 || fFixedSnap)
1770 fb4.fdateLastWrite.year = atol(p) - 1980;
1771 else if (ulDateFmt == 1)
1772 fb4.fdateLastWrite.day = atol(p);
1773 else
1774 fb4.fdateLastWrite.month = atol(p);
1775 p = strchr(p, '/') ? strchr(p, '/') : strchr(p, DateSeparator[0]);
1776 if (p) {
1777 p++;
1778 if (ulDateFmt == 2 || ulDateFmt == 1 || fFixedSnap)
1779 fb4.fdateLastWrite.month = atol(p);
1780 else
1781 fb4.fdateLastWrite.day = atol(p);
1782 p = strchr(p, '/') ? strchr(p, '/') : strchr(p, DateSeparator[0]);
1783 if (p) {
1784 p++;
1785 if (ulDateFmt == 2 || fFixedSnap)
1786 fb4.fdateLastWrite.day = atol(p);
1787 else if (ulDateFmt == 3)
1788 fb4.fdateLastWrite.month = atol(p);
1789 else
1790 fb4.fdateLastWrite.year = atol(p) - 1980;
1791 p = strchr(p, ',');
1792 if (p) {
1793 p++;
1794 fb4.ftimeLastWrite.hours = atol(p);
1795 p = strchr(p, ':') ? strchr(p, ':') : strchr(p, TimeSeparator[0]);
1796 if (p) {
1797 p++;
1798 fb4.ftimeLastWrite.minutes = atol(p);
1799 p = strchr(p, ':') ? strchr(p, ':') : strchr(p, TimeSeparator[0]);
1800 if (p) {
1801 p++;
1802 fb4.ftimeLastWrite.twosecs = atol(p);
1803 p = strchr(p, ',');
1804 if (p) {
1805 p++;
1806 fb4.attrFile = atol(p);
1807 p = strchr(p, ',');
1808 if (p) {
1809 p++;
1810 fb4.cbList = atol(p) * 2;
1811 if (fForceUpper)
1812 strupr(str + 1);
1813 else if (fForceLower)
1814 strlwr(str + 1);
1815 if (AddToFileList((str + 1) + lenr,
1816 &fb4,
1817 &filesr,
1818 &cmp->cmp->totalright,
1819 &numallocr))
1820 break;
1821 }
1822 }
1823 }
1824 }
1825 }
1826 }
1827 }
1828 }
1829 }
1830 }
1831 }
1832 }
1833 }
1834 } // while
1835 } // if have rightdir
1836 fclose(fp);
1837 if (!filesr)
1838 saymsg(MB_OK | MB_ICONASTERISK, HWND_DESKTOP,
1839 GetPString(IDS_WARNINGTEXT),
1840 GetPString(IDS_SNAPSHOTFILEBADFORMAT));
1841 }
1842 else
1843 saymsg(MB_OK | MB_ICONASTERISK, HWND_DESKTOP,
1844 GetPString(IDS_WARNINGTEXT),
1845 GetPString(IDS_SNAPSHOTFILELOADFAILED), cmp->rightlist);
1846 } // if snapshot file
1847
1848 if (filesr)
1849 qsort(filesr, cmp->cmp->totalright, sizeof(CHAR *), CompNames);
1850
1851 // We now have two lists of files, both sorted.
1852 // Count total number of container entries required on each side
1853 l = 0;
1854 r = 0;
1855 ulRecsNeeded = 0;
1856 while ((filesl && filesl[l]) || (filesr && filesr[r])) {
1857
1858 if (cmp->stop)
1859 break; // Cancel requested
1860
1861 if (filesl && filesl[l]) {
1862 if (filesr && filesr[r])
1863 x = stricmp(filesl[l]->fname, filesr[r]->fname);
1864 else
1865 x = -1; // Left side list longer
1866 }
1867 else
1868 x = +1; // Right side list longer
1869
1870 if (x <= 0)
1871 l++; // On left side
1872 if (x >= 0)
1873 r++; // On right side
1874
1875 ulRecsNeeded++; // Count how many entries req'd
1876
1877 } // while counting
1878
1879 if (cmp->stop)
1880 ulRecsNeeded = 0;
1881
1882 // Insert records into the containers
1883
1884 if (ulRecsNeeded) {
1885
1886 PCNRITEM pcilFirst;
1887 PCNRITEM pcirFirst;
1888 PCNRITEM pcil = NULL;
1889 PCNRITEM pcir = NULL;
1890 INT ret;
1891 ULONG ulRecsAllocated = 0;
1892 ULONG insertedl;
1893 ULONG insertedr;
1894
1895 l = 0;
1896 r = 0;
1897
1898 // Use send to get message on screen quickly
1899 WinSendMsg(cmp->hwnd, UM_CONTAINERHWND, MPVOID, MPVOID);
1900
1901 cmp->cmp->totalleft = 0;
1902 cmp->cmp->totalright = 0;
1903
1904 while ((filesl && filesl[l]) || (filesr && filesr[r])) {
1905
1906 ULONG ulRecsToInsert; // limited to USHRT_MAX
1907
1908 if (cmp->stop)
1909 break;
1910
1911 // Check alloc needed
1912 if (!pcil || !pcir) {
1913 if (pcil != pcir) {
1914 Runtime_Error(pszSrcFile, __LINE__, GetPString(IDS_LEFTRIGHTOUTOFSYNC));
1915 cmp->stop = TRUE;
1916 break;
1917 }
1918 ulRecsToInsert = ulRecsNeeded - ulRecsAllocated;
1919 if (ulRecsToInsert > USHRT_MAX)
1920 ulRecsToInsert = USHRT_MAX;
1921
1922 pcilFirst = WinSendMsg(hwndLeft,
1923 CM_ALLOCRECORD,
1924 MPFROMLONG(EXTRA_RECORD_BYTES),
1925 MPFROMLONG(ulRecsToInsert));
1926 if (!pcilFirst) {
1927 Win_Error(hwndLeft, cmp->hwnd, pszSrcFile, __LINE__, PCSZ_CM_ALLOCRECORD);
1928 cmp->stop = TRUE;
1929 break;
1930 }
1931 pcirFirst = WinSendMsg(hwndRight, CM_ALLOCRECORD,
1932 MPFROMLONG(EXTRA_RECORD_BYTES),
1933 MPFROMLONG(ulRecsToInsert));
1934 if (!pcirFirst) {
1935 Win_Error(hwndRight, cmp->hwnd, pszSrcFile, __LINE__, PCSZ_CM_ALLOCRECORD);
1936 FreeCnrItemList(hwndLeft, pcilFirst);
1937 pcilFirst = NULL;
1938 cmp->stop = TRUE;
1939 break;
1940 }
1941 pcil = pcilFirst;
1942 pcir = pcirFirst;
1943 insertedl = 0;
1944 insertedr = 0;
1945 ulRecsAllocated += ulRecsToInsert;
1946 } // if need alloc
1947
1948 pcir->hwndCnr = hwndRight;
1949 pcir->rc.hptrIcon = (HPOINTER)0;
1950 pcil->hwndCnr = hwndLeft;
1951 pcil->rc.hptrIcon = (HPOINTER)0;
1952
1953 if (filesl && filesl[l]) {
1954 if (filesr && filesr[r])
1955 x = stricmp(filesl[l]->fname, filesr[r]->fname);
1956 else
1957 x = -1; // Left side list longer
1958 }
1959 else
1960 x = +1; // Right side list longer
1961
1962 if (x <= 0) {
1963 // File appears on left side
1964 cmp->cmp->totalleft++;
1965 insertedl++;
1966 BldFullPathName(szBuf, cmp->leftdir, filesl[l]->fname);
1967 pcil->pszFileName = xstrdup(szBuf, pszSrcFile, __LINE__);
1968 pcil->pszDisplayName = pcil->pszFileName + lenl;
1969 pcil->attrFile = filesl[l]->attrFile;
1970 pcil->pszDispAttr = FileAttrToString(pcil->attrFile);
1971 pcil->cbFile = filesl[l]->cbFile;
1972 // 12 Jan 08 SHL fixme to use cached size here too
1973 CommaFmtULL(szBuf, sizeof(szBuf), pcil->cbFile, ' ');
1974 pcil->pszFmtFileSize = xstrdup(szBuf, pszSrcFile, __LINE__);
1975 pcil->easize = filesl[l]->easize;
1976 pcil->date.day = filesl[l]->date.day;
1977 pcil->date.month = filesl[l]->date.month;
1978 pcil->date.year = filesl[l]->date.year + 1980;
1979 pcil->time.seconds = filesl[l]->time.twosecs * 2;
1980 pcil->time.minutes = filesl[l]->time.minutes;
1981 pcil->time.hours = filesl[l]->time.hours;
1982 pcil->ladate.day = filesl[l]->ladate.day;
1983 pcil->ladate.month = filesl[l]->ladate.month;
1984 pcil->ladate.year = filesl[l]->ladate.year + 1980;
1985 pcil->latime.seconds = filesl[l]->latime.twosecs * 2;
1986 pcil->latime.minutes = filesl[l]->latime.minutes;
1987 pcil->latime.hours = filesl[l]->latime.hours;
1988 pcil->crdate.day = filesl[l]->crdate.day;
1989 pcil->crdate.month = filesl[l]->crdate.month;
1990 pcil->crdate.year = filesl[l]->crdate.year + 1980;
1991 pcil->crtime.seconds = filesl[l]->crtime.twosecs * 2;
1992 pcil->crtime.minutes = filesl[l]->crtime.minutes;
1993 pcil->crtime.hours = filesl[l]->crtime.hours;
1994 if (*cmp->dcd.mask.szMask) {
1995 if (!Filter((PMINIRECORDCORE)pcil, (PVOID)&cmp->dcd.mask)) {
1996 pcil->rc.flRecordAttr |= CRA_FILTERED;
1997 pcir->rc.flRecordAttr |= CRA_FILTERED;
1998 }
1999 }
2000 } // if on left
2001
2002 if (x >= 0) {
2003 // File appears on right side
2004 cmp->cmp->totalright++;
2005 insertedr++;
2006 BldFullPathName(szBuf, cmp->rightdir, filesr[r]->fname);
2007 pcir->pszFileName = xstrdup(szBuf, pszSrcFile, __LINE__); // 31 Jul 07 SHL
2008 pcir->pszDisplayName = pcir->pszFileName + lenr;
2009 pcir->attrFile = filesr[r]->attrFile;
2010 // pcir->rc.hptrIcon = hptrFile;
2011 pcir->pszDispAttr = FileAttrToString(pcir->attrFile);
2012 pcir->cbFile = filesr[r]->cbFile;
2013 // 12 Jan 08 SHL fixme to used cached size here too
2014 CommaFmtULL(szBuf, sizeof(szBuf), pcir->cbFile, ' ');
2015 pcir->pszFmtFileSize = xstrdup(szBuf, pszSrcFile, __LINE__);
2016 pcir->easize = filesr[r]->easize;
2017 pcir->date.day = filesr[r]->date.day;
2018 pcir->date.month = filesr[r]->date.month;
2019 pcir->date.year = filesr[r]->date.year + 1980;
2020 pcir->time.seconds = filesr[r]->time.twosecs * 2;
2021 pcir->time.minutes = filesr[r]->time.minutes;
2022 pcir->time.hours = filesr[r]->time.hours;
2023 pcir->ladate.day = filesr[r]->ladate.day;
2024 pcir->ladate.month = filesr[r]->ladate.month;
2025 pcir->ladate.year = filesr[r]->ladate.year + 1980;
2026 pcir->latime.seconds = filesr[r]->latime.twosecs * 2;
2027 pcir->latime.minutes = filesr[r]->latime.minutes;
2028 pcir->latime.hours = filesr[r]->latime.hours;
2029 pcir->crdate.day = filesr[r]->crdate.day;
2030 pcir->crdate.month = filesr[r]->crdate.month;
2031 pcir->crdate.year = filesr[r]->crdate.year + 1980;
2032 pcir->crtime.seconds = filesr[r]->crtime.twosecs * 2;
2033 pcir->crtime.minutes = filesr[r]->crtime.minutes;
2034 pcir->crtime.hours = filesr[r]->crtime.hours;
2035 // Bypass check if already filtered on left side
2036 if (~pcir->rc.flRecordAttr & CRA_FILTERED &&
2037 *cmp->dcd.mask.szMask) {
2038 if (!Filter((PMINIRECORDCORE)pcir, (PVOID)&cmp->dcd.mask)) {
2039 pcil->rc.flRecordAttr |= CRA_FILTERED;
2040 pcir->rc.flRecordAttr |= CRA_FILTERED;
2041 }
2042 }
2043 } // if on right
2044
2045 if (x == 0) {
2046 // File appears on both sides
2047 pcil->flags |= CNRITEM_EXISTS;
2048 pcir->flags |= CNRITEM_EXISTS;
2049 pch = szBuf;
2050 // Subject field holds status messages
2051 *pch = 0;
2052 if (pcil->cbFile > pcir->cbFile) {
2053 pcil->flags |= CNRITEM_LARGER;
2054 pcir->flags |= CNRITEM_SMALLER;
2055 strcpy(pch, GetPString(IDS_LARGERTEXT));
2056 pch += 6;
2057 }
2058 else if (pcil->cbFile < pcir->cbFile) {
2059 pcil->flags |= CNRITEM_SMALLER;
2060 pcir->flags |= CNRITEM_LARGER;
2061 strcpy(pch, GetPString(IDS_SMALLERTEXT));
2062 pch += 7;
2063 }
2064 if (pcil->easize != pcir->easize) {
2065 pcil->flags |= CNRITEM_EASDIFFER;
2066 pcir->flags |= CNRITEM_EASDIFFER;
2067 if (pch != szBuf) {
2068 strcpy(pch, ", ");
2069 pch += 2;
2070 }
2071 strcpy(pch, GetPString(IDS_EASDIFFERTEXT));
2072 pch += 10;
2073 }
2074 ret = TestCDates(&pcir->date, &pcir->time,
2075 &pcil->date, &pcil->time);
2076 if (ret == 1) {
2077 pcil->flags |= CNRITEM_NEWER;
2078 pcir->flags |= CNRITEM_OLDER;
2079 if (pch != szBuf) {
2080 strcpy(pch, ", ");
2081 pch += 2;
2082 }
2083 strcpy(pch, GetPString(IDS_NEWERTEXT));
2084 pch += 5;
2085 }
2086 else if (ret == -1) {
2087 pcil->flags |= CNRITEM_OLDER;
2088 pcir->flags |= CNRITEM_NEWER;
2089 if (pch != szBuf) {
2090 strcpy(pch, ", ");
2091 pch += 2;
2092 }
2093 strcpy(pch, GetPString(IDS_OLDERTEXT));
2094 pch += 5;
2095 }
2096 pcil->pszSubject = *szBuf ?
2097 xstrdup(szBuf, pszSrcFile, __LINE__) :
2098 NullStr;
2099
2100 } // if on both sides
2101
2102 if (x <= 0)
2103 free(filesl[l++]); // Done with item on left
2104
2105 if (x >= 0)
2106 free(filesr[r++]); // Done with item on right
2107
2108 // Ensure empty buffers point somewhere
2109 if (!pcil->pszFileName) {
2110 pcil->pszFileName = NullStr;
2111 pcil->pszDisplayName = pcil->pszFileName;
2112 }
2113
2114 if (!pcir->pszFileName) {
2115 pcir->pszFileName = NullStr;
2116 pcir->pszDisplayName = pcir->pszFileName;
2117 }
2118
2119 pcil->rc.pszIcon = pcil->pszDisplayName;
2120 pcir->rc.pszIcon = pcir->pszDisplayName;
2121
2122 pcil->pszLongName = NullStr;
2123 pcir->pszLongName = NullStr;
2124
2125 if (!pcil->pszSubject)
2126 if (!pcir->pszSubject)
2127 pcir->pszSubject = NullStr;
2128
2129 if (!pcil->pszDispAttr)
2130 pcil->pszDispAttr = NullStr;
2131 if (!pcir->pszDispAttr)
2132 pcir->pszDispAttr = NullStr;
2133
2134 // Avoid hogging systems
2135 SleepIfNeeded(&itdSleep, 0);
2136
2137 pcil = (PCNRITEM)pcil->rc.preccNextRecord;
2138 pcir = (PCNRITEM)pcir->rc.preccNextRecord;
2139
2140 if (pcil == NULL || pcir == NULL) {
2141 RECORDINSERT ri;
2142 if (pcil != pcir) {
2143 Runtime_Error(pszSrcFile, __LINE__, "pcil and pcir out of sync");
2144 cmp->stop = TRUE;
2145 break;
2146 }
2147 // Say inserting
2148 WinSendMsg(cmp->hwnd, UM_CONTAINERDIR, MPVOID, MPVOID);
2149
2150 // Insert left side
2151 memset(&ri, 0, sizeof(RECORDINSERT));
2152 ri.cb = sizeof(RECORDINSERT);
2153 ri.pRecordOrder = (PRECORDCORE)CMA_END;
2154 ri.pRecordParent = (PRECORDCORE)NULL;
2155 ri.zOrder = (ULONG)CMA_TOP;
2156 ri.cRecordsInsert = ulRecsToInsert;
2157 ri.fInvalidateRecord = FALSE;
2158
2159 if (!WinSendMsg(hwndLeft, CM_INSERTRECORD,
2160 MPFROMP(pcilFirst), MPFROMP(&ri))) {
2161 Win_Error(hwndLeft, cmp->hwnd, pszSrcFile, __LINE__, "CM_INSERTRECORD");
2162 FreeCnrItemList(hwndLeft, pcilFirst);
2163 cmp->cmp->totalleft -= insertedl;
2164 }
2165 pcilFirst = NULL;
2166
2167 // Insert right side
2168 memset(&ri, 0, sizeof(RECORDINSERT));
2169 ri.cb = sizeof(RECORDINSERT);
2170 ri.pRecordOrder = (PRECORDCORE)CMA_END;
2171 ri.pRecordParent = (PRECORDCORE)NULL;
2172 ri.zOrder = (ULONG)CMA_TOP;
2173 ri.cRecordsInsert = ulRecsToInsert;
2174 ri.fInvalidateRecord = FALSE;
2175
2176 if (!WinSendMsg(hwndRight, CM_INSERTRECORD,
2177 MPFROMP(pcirFirst), MPFROMP(&ri))) {
2178 Win_Error(hwndRight, cmp->hwnd, pszSrcFile, __LINE__, "CM_INSERTRECORD");
2179 // 2011-05-29 SHL fixme?
2180 RemoveCnrItems(hwndLeft, NULL, 0, CMA_FREE | CMA_INVALIDATE);
2181 FreeCnrItemList(hwndRight, pcirFirst);
2182 cmp->cmp->totalright -= insertedr;
2183 }
2184 pcirFirst = NULL;
2185 } // if need insert
2186
2187 } // while filling left or right
2188
2189 // If stopped early clean up
2190
2191 if (cmp->stop) {
2192 // Free up container records that we did not insert in container
2193 if (pcilFirst)
2194 FreeCnrItemList(hwndLeft, pcilFirst);
2195
2196 // Free up items we did not insert in container
2197 if (filesl) {
2198 for(; filesl[l]; l++) {
2199 free(filesl[l]);
2200 }
2201 }
2202
2203 if (pcirFirst)
2204 FreeCnrItemList(hwndRight, pcirFirst);
2205
2206 if (filesr) {
2207 for (; filesr[r]; r++) {
2208 free(filesr[r]);
2209 }
2210 }
2211 } // if insufficient resources
2212
2213 xfree(filesl, pszSrcFile, __LINE__); // Free header - have already freed elements
2214 filesl = NULL;
2215 xfree(filesr, pszSrcFile, __LINE__);
2216 filesr = NULL;
2217
2218 } // if ulRecsNeeded
2219
2220 Deselect(hwndLeft);
2221 Deselect(hwndRight);
2222
2223 // Request window update
2224 if (!PostMsg(cmp->hwnd, UM_CONTAINER_FILLED, MPVOID, MPVOID))
2225 WinSendMsg(cmp->hwnd, UM_CONTAINER_FILLED, MPVOID, MPVOID);
2226 notified = TRUE;
2227
2228 if (filesl)
2229 FreeList((CHAR **)filesl); // Must have failed to create container
2230 if (filesr)
2231 FreeList((CHAR **)filesr);
2232
2233 WinDestroyMsgQueue(hmq);
2234 } // if have queue
2235 if (!notified)
2236 PostMsg(cmp->hwnd, UM_CONTAINER_FILLED, MPVOID, MPVOID);
2237 DecrThreadUsage();
2238 WinTerminate(hab);
2239 }
2240 free(cmp);
2241 DosPostEventSem(CompactSem);
2242
2243# ifdef FORTIFY
2244 Fortify_LeaveScope();
2245# endif
2246
2247}
2248
2249/**
2250 * Find matching item in other container
2251 * @return PCNRITEM or NULL
2252 */
2253
2254static PCNRITEM FindMatchingItem(PCNRITEM pciFindS, HWND hwndCnrS, HWND hwndCnrD);
2255
2256static PCNRITEM FindMatchingItem(PCNRITEM pciFindS, HWND hwndCnrS, HWND hwndCnrD)
2257{
2258
2259 PCNRITEM pciS;
2260 PCNRITEM pciD;
2261
2262 pciS = WinSendMsg(hwndCnrS, CM_QUERYRECORD, MPVOID,
2263 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
2264 pciD = WinSendMsg(hwndCnrD, CM_QUERYRECORD, MPVOID,
2265 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
2266 while (pciS && (INT)pciS != -1 && pciD && (INT)pciD != -1) {
2267
2268 if (pciS == pciFindS)
2269 break;
2270
2271 pciS = WinSendMsg(hwndCnrS, CM_QUERYRECORD, MPFROMP(pciS),
2272 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
2273 pciD = WinSendMsg(hwndCnrD, CM_QUERYRECORD, MPFROMP(pciD),
2274 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
2275 } // while
2276
2277 if (pciS != pciFindS)
2278 pciD = NULL;
2279
2280 return pciD;
2281}
2282
2283/**
2284 * Set button/window enables
2285 */
2286
2287static VOID SetButtonEnables(COMPARE* cmp, BOOL fEnable);
2288
2289static VOID SetButtonEnables(COMPARE* cmp, BOOL fEnable)
2290{
2291 HWND hwnd = cmp->hwnd;
2292 HWND hwndLeft = GetHwndLeft(hwnd);
2293 HWND hwndRight = GetHwndRight(hwnd);
2294
2295 if (!fEnable) {
2296 // Disable before
2297 WinEnableWindowUpdate(hwndLeft, fEnable);
2298 WinEnableWindowUpdate(hwndRight, fEnable);
2299 }
2300 WinEnableWindow(hwndLeft, fEnable);
2301 WinEnableWindow(hwndRight, fEnable);
2302 if (fEnable) {
2303 // Enable after
2304 WinEnableWindowUpdate(hwndLeft, fEnable);
2305 WinEnableWindowUpdate(hwndRight, fEnable);
2306 }
2307
2308 WinEnableWindow(WinWindowFromID(hwnd, DID_OK), fEnable);
2309 WinEnableWindow(WinWindowFromID(hwnd, COMP_COLLECT), fEnable);
2310 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTBOTH), fEnable);
2311 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTONE), fEnable);
2312 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTNEWER), fEnable);
2313 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTEAS), fEnable); // 2013-03-09 SHL
2314 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTOLDER), fEnable);
2315 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTBIGGER), fEnable);
2316 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTSMALLER), fEnable);
2317 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTBOTH), fEnable);
2318 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTONE), fEnable);
2319 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTNEWER), fEnable);
2320 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTEAS), fEnable); // 2013-03-09 SHL
2321 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTOLDER), fEnable);
2322 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTBIGGER), fEnable);
2323 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTSMALLER), fEnable);
2324 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTALL), fEnable);
2325 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTSAMECONTENT), fEnable);
2326 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTIDENTICAL), fEnable);
2327 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTSAME), fEnable);
2328 WinEnableWindow(WinWindowFromID(hwnd, IDM_INVERT), fEnable);
2329 WinEnableWindow(WinWindowFromID(hwnd, COMP_SETDIRS), fEnable);
2330 WinEnableWindow(WinWindowFromID(hwnd, COMP_DELETELEFT), fEnable);
2331 WinEnableWindow(WinWindowFromID(hwnd, COMP_FILTER), fEnable);
2332 if (!fEnable || !*cmp->rightlist) {
2333 WinEnableWindow(WinWindowFromID(hwnd, COMP_COPYLEFT), fEnable);
2334 WinEnableWindow(WinWindowFromID(hwnd, COMP_MOVELEFT), fEnable);
2335 WinEnableWindow(WinWindowFromID(hwnd, COMP_DELETERIGHT), fEnable);
2336 WinEnableWindow(WinWindowFromID(hwnd, COMP_COPYRIGHT), fEnable);
2337 WinEnableWindow(WinWindowFromID(hwnd, COMP_MOVERIGHT), fEnable);
2338 }
2339 WinEnableWindow(WinWindowFromID(hwnd, COMP_INCLUDESUBDIRS), fEnable);
2340 WinEnableWindow(WinWindowFromID(hwnd, COMP_HIDENOTSELECTED), fEnable);
2341 WinEnableWindow(WinWindowFromID(hwnd, COMP_CONFIRMACTION), fEnable); // 2013-03-09 SHL
2342}
2343
2344/**
2345 * Compare directories dialog procedure
2346 */
2347
2348MRESULT EXPENTRY CompareDlgProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
2349{
2350 COMPARE *cmp;
2351 BOOL temp;
2352 CHAR szPathName[CCHMAXPATH];
2353 CHAR s[81];
2354
2355 static HPOINTER hptr;
2356
2357 switch (msg) {
2358 case WM_INITDLG:
2359 cmp = (COMPARE *)mp2;
2360 if (!cmp) {
2361 Runtime_Error(pszSrcFile, __LINE__, NULL);
2362 WinDismissDlg(hwnd, 0);
2363 }
2364 else {
2365 if (!hptr)
2366 hptr = WinLoadPointer(HWND_DESKTOP, FM3ModHandle, COMPARE_ICON);
2367 WinDefDlgProc(hwnd, WM_SETICON, MPFROMLONG(hptr), MPVOID);
2368 cmp->hwnd = hwnd;
2369 WinSetWindowPtr(hwnd, QWL_USER, (PVOID)cmp);
2370 {
2371 SWP swp;
2372 ULONG size = sizeof(SWP);
2373
2374 PrfQueryProfileData(fmprof, FM3Str, "CompDir.Position", (PVOID) &swp, &size);
2375 swp.fl &= ~SWP_SIZE; // 04 Feb 09 SHL ignore saved size
2376 WinSetWindowPos(hwnd,
2377 HWND_TOP,
2378 swp.x,
2379 swp.y,
2380 swp.cx,
2381 swp.cy,
2382 swp.fl);
2383 }
2384 SetCnrCols(GetHwndLeft(hwnd), TRUE);
2385 SetCnrCols(GetHwndRight(hwnd), TRUE);
2386 if (cmp->listfile) {
2387 CHAR fullname[CCHMAXPATH];
2388
2389 strcpy(fullname, PCSZ_STARDOTPMD);
2390 if (insert_filename(HWND_DESKTOP, fullname, TRUE, FALSE) &&
2391 *fullname && !strchr(fullname, '*') && !strchr(fullname, '?'))
2392 strcpy(cmp->rightlist, fullname);
2393 }
2394 WinSendMsg(hwnd, UM_SETUP, MPVOID, MPVOID);
2395 WinSendMsg(hwnd, UM_SETDIR, MPVOID, MPVOID);
2396 PostMsg(hwnd, UM_STRETCH, MPVOID, MPVOID);
2397 {
2398 USHORT ids[] = {COMP_FRAME, COMP_LEFTDIR, COMP_RIGHTDIR, COMP_COLLECT,
2399 COMP_VIEW, COMP_NOTE, COMP_TOTALLEFT, COMP_SELLEFT, COMP_TOTALRIGHT,
2400 COMP_SELRIGHT, COMP_CNRMENU, COMP_DIRMENU, COMP_MENU,
2401 COMP_INCLUDESUBDIRS, COMP_SETDIRS, COMP_COPYLEFT, COMP_MOVELEFT,
2402 COMP_DELETELEFT, COMP_COPYRIGHT, COMP_MOVERIGHT, COMP_DELETERIGHT,
2403 COMP_TOTALLEFTHDR, COMP_SELLEFTHDR, COMP_TOTALRIGHTHDR,
2404 COMP_SELRIGHTHDR, COMP_FILTER, COMP_HIDENOTSELECTED, 0};
2405 UINT x;
2406 CHAR s[24];
2407
2408 for (x = 0; ids[x]; x++) {
2409 sprintf(s, "CompDir%i", ids[x]);
2410 RestorePresParams(WinWindowFromID(hwnd, ids[x]), s);
2411 }
2412 }
2413 WinStartTimer(WinQueryAnchorBlock(hwnd), hwnd, ID_COMP_TIMER, 500);
2414 }
2415 break;
2416
2417 case UM_STRETCH:
2418 {
2419 SWP swp, swpC;
2420 LONG titl, szbx, szby, sz;
2421 HWND hwndActive;
2422
2423 WinQueryWindowPos(hwnd, &swp);
2424 if (!(swp.fl & (SWP_HIDE | SWP_MINIMIZE))) {
2425 hwndActive = WinQueryFocus(HWND_DESKTOP);
2426 szbx = SysVal(SV_CXSIZEBORDER);
2427 szby = SysVal(SV_CYSIZEBORDER);
2428 titl = SysVal(SV_CYTITLEBAR);
2429 titl += 26;
2430 swp.cx -= (szbx * 2);
2431 sz = (swp.cx / 8);
2432 WinQueryWindowPos(WinWindowFromID(hwnd, COMP_LEFTDIR), &swpC);
2433 WinSetWindowPos(WinWindowFromID(hwnd, COMP_LEFTDIR), HWND_TOP,
2434 szbx + 6,
2435 swpC.y,
2436 (swp.cx / 2) - (szbx + 6),
2437 ((swp.cy - swpC.y) - titl) - szby,
2438 SWP_MOVE | SWP_SIZE);
2439 WinSetWindowPos(WinWindowFromID(hwnd, COMP_RIGHTDIR), HWND_TOP,
2440 (swp.cx / 2) + (szbx + 6),
2441 swpC.y,
2442 (swp.cx / 2) - (szbx + 6),
2443 ((swp.cy - swpC.y) - titl) - szby,
2444 SWP_MOVE | SWP_SIZE);
2445 WinSetWindowPos(WinWindowFromID(hwnd, COMP_TOTALLEFTHDR), HWND_TOP,
2446 szbx + 6,
2447 ((swp.cy - titl) - szby) + 4,
2448 sz - (szbx + 6), 20, SWP_MOVE | SWP_SIZE);
2449 WinSetWindowPos(WinWindowFromID(hwnd, COMP_TOTALLEFT), HWND_TOP,
2450 sz + (szbx + 6),
2451 ((swp.cy - titl) - szby) + 4,
2452 sz - (szbx + 6), 20, SWP_MOVE | SWP_SIZE);
2453 WinSetWindowPos(WinWindowFromID(hwnd, COMP_SELLEFTHDR), HWND_TOP,
2454 (sz * 2) + (szbx + 6),
2455 ((swp.cy - titl) - szby) + 4,
2456 sz - (szbx + 6), 20, SWP_MOVE | SWP_SIZE);
2457 WinSetWindowPos(WinWindowFromID(hwnd, COMP_SELLEFT), HWND_TOP,
2458 (sz * 3) + (szbx + 6),
2459 ((swp.cy - titl) - szby) + 4,
2460 sz - (szbx + 6), 20, SWP_MOVE | SWP_SIZE);
2461 WinSetWindowPos(WinWindowFromID(hwnd, COMP_TOTALRIGHTHDR), HWND_TOP,
2462 (sz * 4) + (szbx + 6),
2463 ((swp.cy - titl) - szby) + 4,
2464 sz - (szbx + 6), 20, SWP_MOVE | SWP_SIZE);
2465 WinSetWindowPos(WinWindowFromID(hwnd, COMP_TOTALRIGHT), HWND_TOP,
2466 (sz * 5) + (szbx + 6),
2467 ((swp.cy - titl) - szby) + 4,
2468 sz - (szbx + 6), 20, SWP_MOVE | SWP_SIZE);
2469 WinSetWindowPos(WinWindowFromID(hwnd, COMP_SELRIGHTHDR), HWND_TOP,
2470 (sz * 6) + (szbx + 6),
2471 ((swp.cy - titl) - szby) + 4,
2472 sz - (szbx + 6), 20, SWP_MOVE | SWP_SIZE);
2473 WinSetWindowPos(WinWindowFromID(hwnd, COMP_SELRIGHT), HWND_TOP,
2474 (sz * 7) + (szbx + 6),
2475 ((swp.cy - titl) - szby) + 4,
2476 sz - (szbx + 6), 20, SWP_MOVE | SWP_SIZE);
2477 PaintRecessedWindow(WinWindowFromID(hwnd, COMP_TOTALLEFT),
2478 (HPS)0, FALSE, FALSE);
2479 PaintRecessedWindow(WinWindowFromID(hwnd, COMP_SELLEFT),
2480 (HPS)0, FALSE, FALSE);
2481 PaintRecessedWindow(WinWindowFromID(hwnd, COMP_TOTALRIGHT),
2482 (HPS)0, FALSE, FALSE);
2483 PaintRecessedWindow(WinWindowFromID(hwnd, COMP_SELRIGHT),
2484 (HPS)0, FALSE, FALSE);
2485 PaintRecessedWindow(GetHwndLeft(hwnd), (HPS)0,
2486 (hwndActive == GetHwndLeft(hwnd)), TRUE);
2487 PaintRecessedWindow(GetHwndRight(hwnd), (HPS)0,
2488 (hwndActive == GetHwndRight(hwnd)), TRUE);
2489 }
2490 }
2491 return 0;
2492
2493 case WM_ADJUSTWINDOWPOS:
2494 PostMsg(hwnd, UM_STRETCH, MPVOID, MPVOID);
2495 break;
2496
2497 case UM_SETUP:
2498 {
2499 CNRINFO cnri;
2500 BOOL tempsubj;
2501
2502 cmp = INSTDATA(hwnd);
2503 if (!cmp)
2504 Runtime_Error(pszSrcFile, __LINE__, NULL);
2505 else {
2506 cmp->dcd.size = sizeof(DIRCNRDATA);
2507 cmp->dcd.type = DIR_FRAME;
2508 cmp->dcd.hwndFrame = hwnd;
2509 cmp->dcd.hwndClient = hwnd;
2510 cmp->dcd.mask.attrFile = (FILE_DIRECTORY | FILE_ARCHIVED |
2511 FILE_READONLY | FILE_SYSTEM | FILE_HIDDEN);
2512 LoadDetailsSwitches(PCSZ_DIRCMP, &cmp->dcd.ds, FALSE);
2513 cmp->dcd.ds.detailslongname = FALSE;
2514 cmp->dcd.ds.detailsicon = FALSE; // TRUE;
2515 }
2516 memset(&cnri, 0, sizeof(CNRINFO));
2517 cnri.cb = sizeof(CNRINFO);
2518 WinSendDlgItemMsg(hwnd, COMP_LEFTDIR, CM_QUERYCNRINFO,
2519 MPFROMP(&cnri), MPFROMLONG(sizeof(CNRINFO)));
2520 cnri.flWindowAttr |= (CA_OWNERDRAW | CV_MINI);
2521 cnri.xVertSplitbar = DIR_SPLITBAR_OFFSET - 68;
2522 WinSendDlgItemMsg(hwnd, COMP_LEFTDIR, CM_SETCNRINFO, MPFROMP(&cnri),
2523 MPFROMLONG(CMA_FLWINDOWATTR | CMA_XVERTSPLITBAR));
2524 memset(&cnri, 0, sizeof(CNRINFO));
2525 cnri.cb = sizeof(CNRINFO);
2526 WinSendDlgItemMsg(hwnd, COMP_RIGHTDIR, CM_QUERYCNRINFO,
2527 MPFROMP(&cnri), MPFROMLONG(sizeof(CNRINFO)));
2528 cnri.flWindowAttr |= (CA_OWNERDRAW | CV_MINI);
2529 cnri.xVertSplitbar = DIR_SPLITBAR_OFFSET - 54;
2530 WinSendDlgItemMsg(hwnd, COMP_RIGHTDIR, CM_SETCNRINFO, MPFROMP(&cnri),
2531 MPFROMLONG(CMA_FLWINDOWATTR | CMA_XVERTSPLITBAR));
2532 AdjustCnrColRO(GetHwndLeft(hwnd), GetPString(IDS_FILENAMECOLTEXT), TRUE, FALSE);
2533 AdjustCnrColRO(GetHwndLeft(hwnd), GetPString(IDS_LONGNAMECOLTEXT), TRUE, FALSE);
2534 AdjustCnrColRO(GetHwndRight(hwnd), GetPString(IDS_FILENAMECOLTEXT), TRUE, FALSE);
2535 AdjustCnrColRO(GetHwndRight(hwnd), GetPString(IDS_LONGNAMECOLTEXT), TRUE, FALSE);
2536 AdjustCnrColsForPref(GetHwndLeft(hwnd), cmp->leftdir, &cmp->dcd.ds, TRUE);
2537 tempsubj = cmp->dcd.ds.detailssubject;
2538 cmp->dcd.ds.detailssubject = FALSE;
2539 AdjustCnrColsForPref(GetHwndRight(hwnd), cmp->rightdir, &cmp->dcd.ds, TRUE);
2540 if (*cmp->rightlist) {
2541 AdjustCnrColVis(GetHwndRight(hwnd), GetPString(IDS_LADATECOLTEXT), FALSE,
2542 FALSE);
2543 AdjustCnrColVis(GetHwndRight(hwnd), GetPString(IDS_LATIMECOLTEXT), FALSE,
2544 FALSE);
2545 AdjustCnrColVis(GetHwndRight(hwnd), GetPString(IDS_CRDATECOLTEXT), FALSE,
2546 FALSE);
2547 AdjustCnrColVis(GetHwndRight(hwnd), GetPString(IDS_CRTIMECOLTEXT), FALSE,
2548 FALSE);
2549 }
2550 cmp->dcd.ds.detailssubject = tempsubj;
2551 }
2552 return 0;
2553
2554 case WM_DRAWITEM:
2555 if (mp2) {
2556 POWNERITEM pown = (POWNERITEM)mp2;
2557 PCNRDRAWITEMINFO pcown;
2558 PCNRITEM pci;
2559
2560 pcown = (PCNRDRAWITEMINFO)pown->hItem;
2561 if (pcown) {
2562 pci = (PCNRITEM)pcown->pRecord;
2563 // 01 Aug 07 SHL if field null or blank, we draw
2564 // fixme to document why - probably to optimize and bypass draw?
2565 if (pci && (INT)pci != -1 && !*pci->pszFileName)
2566 return MRFROMLONG(TRUE);
2567 }
2568 }
2569 return 0;
2570
2571 case UM_CONTAINERHWND:
2572 // Building list
2573 WinSetDlgItemText(hwnd, COMP_NOTE, (CHAR *) GetPString(IDS_COMPHOLDBLDLISTTEXT));
2574 return 0;
2575
2576 case UM_CONTAINERDIR:
2577 // Filling container
2578 WinSetDlgItemText(hwnd, COMP_NOTE, (CHAR *) GetPString(IDS_COMPHOLDFILLCNRTEXT));
2579 return 0;
2580
2581 case WM_TIMER:
2582 // Show current totals
2583 cmp = INSTDATA(hwnd);
2584 if (!cmp) {
2585 Runtime_Error(pszSrcFile, __LINE__, "pCompare NULL");
2586 WinDismissDlg(hwnd, 0);
2587 }
2588 else {
2589 if (cmp->uOldTotalLeft != cmp->totalleft) {
2590 cmp->uOldTotalLeft = cmp->totalleft;
2591 sprintf(s, " %d", cmp->totalleft);
2592 WinSetDlgItemText(hwnd, COMP_TOTALLEFT, s);
2593 }
2594 if (cmp->uOldTotalRight != cmp->totalright) {
2595 cmp->uOldTotalRight = cmp->totalright;
2596 sprintf(s, " %d", cmp->totalright);
2597 WinSetDlgItemText(hwnd, COMP_TOTALRIGHT, s);
2598 }
2599 if (cmp->uOldSelLeft != cmp->selleft) {
2600 cmp->uOldSelLeft = cmp->selleft;
2601 sprintf(s, " %d", cmp->selleft);
2602 WinSetDlgItemText(hwnd, COMP_SELLEFT, s);
2603 }
2604 if (cmp->uOldSelRight != cmp->selright) {
2605 cmp->uOldSelRight = cmp->selright;
2606 sprintf(s, " %d", cmp->selright);
2607 WinSetDlgItemText(hwnd, COMP_SELRIGHT, s);
2608 }
2609 }
2610 break;
2611
2612 case UM_CONTAINER_FILLED:
2613 cmp = INSTDATA(hwnd);
2614 if (!cmp) {
2615 Runtime_Error(pszSrcFile, __LINE__, "pCompare NULL");
2616 WinDismissDlg(hwnd, 0);
2617 }
2618 else if (cmp->stop) {
2619 // Delayed cancel
2620 WinDismissDlg(hwnd, 1);
2621 }
2622 else {
2623 cmp->filling = FALSE;
2624 SetButtonEnables(cmp, TRUE);
2625 WinPostMsg(hwnd, WM_TIMER, MPFROMLONG(ID_COMP_TIMER), 0); // Force counts to update
2626 if (*cmp->dcd.mask.szMask) {
2627 sprintf(s, GetPString(IDS_COMPREADYFILTEREDTEXT), cmp->dcd.mask.szMask);
2628 WinSetDlgItemText(hwnd, COMP_NOTE, s);
2629 }
2630 else
2631 WinSetDlgItemText(hwnd, COMP_NOTE, (CHAR *) GetPString(IDS_COMPREADYTEXT));
2632 }
2633 break;
2634
2635 case WM_INITMENU:
2636 cmp = INSTDATA(hwnd);
2637 if (cmp) {
2638 switch (SHORT1FROMMP(mp1)) {
2639 case IDM_COMMANDSMENU:
2640 SetupCommandMenu(cmp->dcd.hwndLastMenu, hwnd);
2641 break;
2642 }
2643 }
2644 break;
2645
2646 case WM_MENUEND:
2647 cmp = INSTDATA(hwnd);
2648 if (cmp) {
2649 if ((HWND)mp2 == cmp->dcd.hwndLastMenu) {
2650 MarkAll(GetHwndLeft(hwnd), TRUE, FALSE, TRUE);
2651 MarkAll(GetHwndRight(hwnd), TRUE, FALSE, TRUE);
2652 WinDestroyWindow(cmp->dcd.hwndLastMenu);
2653 cmp->dcd.hwndLastMenu = (HWND)0;
2654 }
2655 }
2656 break;
2657
2658 case WM_CONTROL:
2659 switch (SHORT1FROMMP(mp1)) {
2660 case COMP_INCLUDESUBDIRS:
2661 switch (SHORT2FROMMP(mp1)) {
2662 case BN_CLICKED:
2663 cmp = INSTDATA(hwnd);
2664 //if (cmp)
2665 // *cmp->rightlist = 0;
2666 PostMsg(hwnd, UM_SETUP, MPVOID, MPVOID);
2667 PostMsg(hwnd, UM_SETDIR, MPVOID, MPVOID);
2668 break;
2669 }
2670 break;
2671 case COMP_HIDENOTSELECTED:
2672 switch (SHORT2FROMMP(mp1)) {
2673 case BN_CLICKED:
2674 WinSendMsg(hwnd, UM_HIDENOTSELECTED, MPVOID, MPVOID);
2675 break;
2676 }
2677 break;
2678
2679 case COMP_LEFTDIR:
2680 case COMP_RIGHTDIR:
2681 switch (SHORT2FROMMP(mp1)) {
2682 case CN_KILLFOCUS:
2683 PaintRecessedWindow(WinWindowFromID(hwnd, SHORT1FROMMP(mp1)),
2684 (HPS)0, FALSE, TRUE);
2685 break;
2686
2687 case CN_SETFOCUS:
2688 PaintRecessedWindow(WinWindowFromID(hwnd, SHORT1FROMMP(mp1)),
2689 (HPS)0, TRUE, TRUE);
2690 break;
2691
2692 case CN_ENTER:
2693 if (mp2) {
2694
2695 PCNRITEM pci = (PCNRITEM)((PNOTIFYRECORDENTER)mp2)->pRecord;
2696 HWND hwndCnr = WinWindowFromID(hwnd, SHORT1FROMMP(mp1));
2697
2698 SetShiftState();
2699 if (pci) {
2700 if (pci->rc.flRecordAttr & CRA_INUSE || !pci || !*pci->pszFileName)
2701 break;
2702 WinSendMsg(hwndCnr, CM_SETRECORDEMPHASIS, MPFROMP(pci),
2703 MPFROM2SHORT(TRUE, CRA_INUSE));
2704 if (pci->attrFile & FILE_DIRECTORY) {
2705 if ((shiftstate & (KC_CTRL | KC_SHIFT)) == (KC_CTRL | KC_SHIFT))
2706 OpenObject(pci->pszFileName, Settings, hwnd);
2707 else
2708 OpenObject(pci->pszFileName, Default, hwnd);
2709 }
2710 else
2711 DefaultViewKeys(hwnd, hwnd, HWND_DESKTOP, NULL,
2712 pci->pszFileName);
2713 WinSendMsg(hwndCnr, CM_SETRECORDEMPHASIS,
2714 MPFROMP(pci),
2715 MPFROM2SHORT(FALSE,
2716 CRA_INUSE | (fUnHilite ? CRA_SELECTED : 0)));
2717 }
2718 }
2719 break;
2720
2721 case CN_CONTEXTMENU:
2722 cmp = INSTDATA(hwnd);
2723 if (cmp) {
2724 PCNRITEM pci = (PCNRITEM)mp2;
2725 USHORT id = COMP_CNRMENU; // Assume container menu
2726
2727 if (cmp->dcd.hwndLastMenu)
2728 WinDestroyWindow(cmp->dcd.hwndLastMenu);
2729 cmp->dcd.hwndLastMenu = (HWND)0;
2730 cmp->hwndCalling = WinWindowFromID(hwnd, SHORT1FROMMP(mp1));
2731 if (pci) {
2732 if (!pci || !*pci->pszFileName || *cmp->rightlist)
2733 break;
2734 id = COMP_MENU; // Want container item menu
2735 WinSendMsg(cmp->hwndCalling, CM_SETRECORDEMPHASIS,
2736 MPFROMP(pci), MPFROM2SHORT(TRUE, CRA_CURSORED));
2737 }
2738 cmp->dcd.hwndLastMenu = WinLoadMenu(HWND_DESKTOP, FM3ModHandle, id);
2739 if (cmp->dcd.hwndLastMenu) {
2740 switch (id) {
2741 case COMP_CNRMENU:
2742 if (SHORT1FROMMP(mp1) == COMP_RIGHTDIR)
2743 WinSendMsg(cmp->dcd.hwndLastMenu, MM_DELETEITEM,
2744 MPFROM2SHORT(IDM_SHOWSUBJECT, FALSE), MPVOID);
2745 SetDetailsSwitches(cmp->dcd.hwndLastMenu, &cmp->dcd.ds);
2746 if (SHORT1FROMMP(mp1) == COMP_LEFTDIR)
2747 WinSendMsg(cmp->dcd.hwndLastMenu, MM_DELETEITEM,
2748 MPFROM2SHORT(IDM_LOADLISTFILE, 0), MPVOID);
2749 else if (*cmp->rightlist)
2750 WinSendMsg(cmp->dcd.hwndLastMenu, MM_DELETEITEM,
2751 MPFROM2SHORT(IDM_SAVELISTFILE, 0), MPVOID);
2752 break;
2753 case COMP_MENU:
2754 // Can't compare what's not there
2755 if (~pci->flags & CNRITEM_EXISTS) {
2756 WinSendMsg(cmp->dcd.hwndLastMenu, MM_DELETEITEM,
2757 MPFROM2SHORT(IDM_COMPARE, 0), MPVOID);
2758 }
2759 break;
2760 } // switch
2761 PopupMenu(hwnd, hwnd, cmp->dcd.hwndLastMenu);
2762 }
2763 }
2764 break;
2765
2766 case CN_INITDRAG:
2767 cmp = INSTDATA(hwnd);
2768 if (*cmp->rightlist && SHORT1FROMMP(mp1) == COMP_RIGHTDIR)
2769 break;
2770 DoFileDrag(WinWindowFromID(hwnd, SHORT1FROMMP(mp1)),
2771 (HWND)0, mp2, NULL, NULL, TRUE);
2772 break;
2773
2774 case CN_BEGINEDIT:
2775 case CN_REALLOCPSZ:
2776 // fixme to be gone - field edits not allowed?
2777 Runtime_Error(pszSrcFile, __LINE__,
2778 "CN_BEGINEDIT/CN_REALLOCPSZ unexpected");
2779 break;
2780
2781 case CN_EMPHASIS:
2782 {
2783 PNOTIFYRECORDEMPHASIS pnre = mp2;
2784 BOOL fSelected;
2785 if (pnre->fEmphasisMask & CRA_SELECTED) {
2786 // Select toggled
2787 PCNRITEM pci = (PCNRITEM)pnre->pRecord;
2788 if (pci) {
2789 if (!*pci->pszFileName) {
2790 // User clicked on empty slot - just clear
2791 if (pci->rc.flRecordAttr & CRA_SELECTED)
2792 WinSendDlgItemMsg(hwnd, SHORT1FROMMP(mp1),
2793 CM_SETRECORDEMPHASIS,
2794 MPFROMP(pci),
2795 MPFROM2SHORT(FALSE, CRA_SELECTED));
2796 }
2797 else {
2798 BOOL fUpdateHideButton = FALSE;
2799 cmp = INSTDATA(hwnd);
2800 if (SHORT1FROMMP(mp1) == COMP_LEFTDIR) {
2801 fSelected = pci->rc.flRecordAttr & CRA_SELECTED;
2802 cmp->selleft += fSelected ? 1 : -1;
2803 if (!fSelected)
2804 fUpdateHideButton = TRUE;
2805 }
2806 else if (SHORT1FROMMP(mp1) == COMP_RIGHTDIR) {
2807 fSelected = pci->rc.flRecordAttr & CRA_SELECTED;
2808 cmp->selright += fSelected ? 1 : -1;
2809 if (!fSelected)
2810 fUpdateHideButton = TRUE;
2811 }
2812 else {
2813 Runtime_Error(pszSrcFile, __LINE__,
2814 "mp1 %u unexpected", SHORT1FROMMP(mp1));
2815 }
2816 if (fUpdateHideButton) {
2817 ULONG state = WinQueryButtonCheckstate(hwnd,COMP_HIDENOTSELECTED);
2818 if (state == 1) {
2819 WinCheckButton(hwnd, COMP_HIDENOTSELECTED, 2);
2820 }
2821 }
2822 }
2823 }
2824 }
2825 }
2826 break;
2827
2828 case CN_SCROLL:
2829 cmp = INSTDATA(hwnd);
2830 if (!cmp->forcescroll) {
2831
2832 PNOTIFYSCROLL pns = mp2;
2833
2834 if (pns->fScroll & CMA_VERTICAL) {
2835 cmp->forcescroll = TRUE;
2836 // Scroll other window to match
2837 WinSendDlgItemMsg(hwnd,
2838 SHORT1FROMMP(mp1) == COMP_LEFTDIR ?
2839 COMP_RIGHTDIR : COMP_LEFTDIR,
2840 CM_SCROLLWINDOW,
2841 MPFROMSHORT(CMA_VERTICAL),
2842 MPFROMLONG(pns->lScrollInc));
2843 cmp->forcescroll = FALSE;
2844 }
2845 }
2846 break;
2847 } // switch COMP_LEFTDIR mp1
2848 break; // COMP_LEFTDIR / COMP_RIGHTDIR
2849 } // switch WM_CONTROL mp1
2850 return 0; // WM_CONTROL
2851
2852 case UM_SETDIR:
2853 cmp = INSTDATA(hwnd);
2854 if (cmp) {
2855 COMPARE *forthread;
2856 CNRINFO cnri;
2857 if (cmp->includesubdirs)
2858 WinCheckButton(hwnd, COMP_INCLUDESUBDIRS, TRUE);
2859 cmp->includesubdirs = WinQueryButtonCheckstate(hwnd,
2860 COMP_INCLUDESUBDIRS);
2861 memset(&cnri, 0, sizeof(CNRINFO));
2862 cnri.cb = sizeof(CNRINFO);
2863 cnri.pszCnrTitle = cmp->leftdir;
2864 cnri.flWindowAttr = CV_DETAIL | CV_MINI |
2865 CA_CONTAINERTITLE | CA_TITLESEPARATOR |
2866 CA_DETAILSVIEWTITLES | CA_OWNERDRAW;
2867 WinSendDlgItemMsg(hwnd, COMP_LEFTDIR, CM_SETCNRINFO, MPFROMP(&cnri),
2868 MPFROMLONG(CMA_CNRTITLE | CMA_FLWINDOWATTR));
2869 WinSetDlgItemText(hwnd, COMP_LISTLOADED, "");
2870 cnri.pszCnrTitle = cmp->rightdir;
2871 WinSendDlgItemMsg(hwnd, COMP_RIGHTDIR, CM_SETCNRINFO, MPFROMP(&cnri),
2872 MPFROMLONG(CMA_CNRTITLE | CMA_FLWINDOWATTR));
2873 WinCheckButton(hwnd, COMP_HIDENOTSELECTED, 0);
2874 cmp->filling = TRUE;
2875# ifdef FORTIFY
2876 Fortify_EnterScope();
2877# endif
2878 forthread = xmalloc(sizeof(COMPARE), pszSrcFile, __LINE__);
2879 if (!forthread)
2880 WinDismissDlg(hwnd, 0);
2881 else {
2882 *forthread = *cmp;
2883 forthread->cmp = cmp;
2884 if (xbeginthread(FillCnrsThread,
2885 122880,
2886 forthread,
2887 pszSrcFile,
2888 __LINE__) == -1)
2889 {
2890 WinDismissDlg(hwnd, 0);
2891 free(forthread);
2892# ifdef FORTIFY
2893 Fortify_LeaveScope();
2894# endif
2895 }
2896 else {
2897 WinSetDlgItemText(hwnd, COMP_NOTE,
2898 (CHAR *) GetPString(IDS_COMPHOLDREADDISKTEXT));
2899 SetButtonEnables(cmp, FALSE);
2900 cmp->includesubdirs = FALSE;
2901 cmp->selleft = 0;
2902 cmp->selright = 0;
2903 }
2904 }
2905 }
2906 return 0;
2907
2908 case UM_FILTER:
2909 cmp = INSTDATA(hwnd);
2910 if (cmp) {
2911 if (mp1)
2912 SetMask((CHAR *)mp1, &cmp->dcd.mask);
2913
2914 WinSetDlgItemText(hwnd, COMP_NOTE,
2915 (CHAR *) GetPString(IDS_COMPHOLDFILTERINGTEXT));
2916 // cmp->dcd.suspendview = 1; // 12 Jan 08 SHL appears not to be used here
2917 priority_idle(); // Don't hog resources
2918 WinSendMsg(GetHwndLeft(hwnd), CM_FILTER, MPFROMP(Filter),
2919 MPFROMP(&cmp->dcd.mask));
2920 WinSendMsg(GetHwndRight(hwnd), CM_FILTER, MPFROMP(Filter),
2921 MPFROMP(&cmp->dcd.mask));
2922 priority_normal();
2923 // cmp->dcd.suspendview = 0; // 12 Jan 08 SHL appears not to be used here
2924 if (*cmp->dcd.mask.szMask) {
2925 sprintf(s,
2926 GetPString(IDS_COMPREADYFILTEREDTEXT),
2927 cmp->dcd.mask.szMask);
2928 WinSetDlgItemText(hwnd, COMP_NOTE, s);
2929 }
2930 else
2931 WinSetDlgItemText(hwnd, COMP_NOTE, (CHAR *) GetPString(IDS_COMPREADYTEXT));
2932 }
2933 return 0;
2934
2935 case UM_HIDENOTSELECTED:
2936 cmp = INSTDATA(hwnd);
2937 if (cmp) {
2938 ULONG wasHidden = WinQueryButtonCheckstate(hwnd,
2939 COMP_HIDENOTSELECTED);
2940 ULONG nowHidden = wasHidden != 1 && (cmp->selleft || cmp->selright);
2941
2942 // cmp->dcd.suspendview = 1; // 12 Jan 08 SHL appears not to be used here
2943 // 26 Sep 09 SHL Unhide if nothing selected
2944 if (nowHidden) {
2945 // Hide items not selected on both sides
2946 BOOL needRefresh = FALSE;
2947 HWND hwndl = WinWindowFromID(cmp->hwnd, COMP_LEFTDIR);
2948 HWND hwndr = WinWindowFromID(cmp->hwnd, COMP_RIGHTDIR);
2949 PCNRITEM pcil = WinSendMsg(hwndl, CM_QUERYRECORD, MPVOID,
2950 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
2951 PCNRITEM pcir = WinSendMsg(hwndr, CM_QUERYRECORD, MPVOID,
2952 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
2953
2954 while (pcil && (INT)pcil != -1 && pcir && (INT)pcir != -1) {
2955 if (~pcil->rc.flRecordAttr & CRA_SELECTED &&
2956 ~pcir->rc.flRecordAttr & CRA_SELECTED) {
2957 if (~pcil->rc.flRecordAttr & CRA_FILTERED) {
2958 needRefresh = TRUE;
2959 pcil->rc.flRecordAttr |= CRA_FILTERED;
2960 }
2961 if (~pcir->rc.flRecordAttr & CRA_FILTERED) {
2962 pcir->rc.flRecordAttr |= CRA_FILTERED;
2963 needRefresh = TRUE;
2964 }
2965 }
2966 pcil = WinSendMsg(hwndl, CM_QUERYRECORD, MPFROMP(pcil),
2967 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
2968 pcir = WinSendMsg(hwndr, CM_QUERYRECORD, MPFROMP(pcir),
2969 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
2970 } // while
2971 if (needRefresh) {
2972 WinSendMsg(hwndl, CM_INVALIDATERECORD,
2973 MPVOID, MPFROM2SHORT(0, CMA_REPOSITION));
2974 WinSendMsg(hwndr, CM_INVALIDATERECORD,
2975 MPVOID, MPFROM2SHORT(0, CMA_REPOSITION));
2976 }
2977 }
2978 else {
2979 // Unhide
2980 WinSendMsg(GetHwndLeft(hwnd), CM_FILTER, MPFROMP(Filter),
2981 MPFROMP(&cmp->dcd.mask));
2982 WinSendMsg(GetHwndRight(hwnd), CM_FILTER, MPFROMP(Filter),
2983 MPFROMP(&cmp->dcd.mask));
2984 }
2985 if (*cmp->dcd.mask.szMask) {
2986 sprintf(s,
2987 GetPString(IDS_COMPREADYFILTEREDTEXT),
2988 cmp->dcd.mask.szMask);
2989 WinSetDlgItemText(hwnd, COMP_NOTE, s);
2990 }
2991 else
2992 WinSetDlgItemText(hwnd, COMP_NOTE, (CHAR *) GetPString(IDS_COMPREADYTEXT));
2993 WinCheckButton(hwnd, COMP_HIDENOTSELECTED, nowHidden);
2994 }
2995 return 0;
2996
2997 case WM_COMMAND:
2998 // 29 Apr 09 SHL fixme to support more context menu items - IDM_VIEW, IDM_EDIT etc.
2999 switch (SHORT1FROMMP(mp1)) {
3000 case IDM_COMPARE:
3001 cmp = INSTDATA(hwnd);
3002 if (cmp) {
3003 PCNRITEM pci;
3004 pci = (PCNRITEM)WinSendMsg(cmp->hwndCalling,
3005 CM_QUERYRECORDEMPHASIS,
3006 MPFROMLONG(CMA_FIRST),
3007 MPFROMSHORT(CRA_CURSORED));
3008 if (pci && *pci->pszFileName) {
3009 if (cmp->hwndCalling == GetHwndLeft(hwnd))
3010 strcpy(szPathName, cmp->rightdir);
3011 else
3012 strcpy(szPathName, cmp->leftdir);
3013 AddBackslashToPath(szPathName);
3014 strcat(szPathName, pci->pszDisplayName);
3015 if (*compare) {
3016 CHAR *fakelist[3];
3017 fakelist[0] = pci->pszFileName;
3018 fakelist[1] = szPathName;
3019 fakelist[2] = NULL;
3020 ExecOnList(hwnd, compare, WINDOWED | SEPARATEKEEP,
3021 NULL, NULL, fakelist, NULL,
3022 pszSrcFile, __LINE__);
3023 }
3024 else {
3025 FCOMPARE fc;
3026 memset(&fc, 0, sizeof(fc));
3027 fc.size = sizeof(fc);
3028 fc.hwndParent = hwnd;
3029 strcpy(fc.file1, pci->pszFileName);
3030 strcpy(fc.file2, szPathName);
3031 WinDlgBox(HWND_DESKTOP, hwnd,
3032 CFileDlgProc, FM3ModHandle, FCMP_FRAME, (PVOID)&fc);
3033 }
3034 }
3035 }
3036 break;
3037
3038 case IDM_DELETE:
3039 cmp = INSTDATA(hwnd);
3040 if (!cmp)
3041 Runtime_Error(pszSrcFile, __LINE__, NULL);
3042 else {
3043 PCNRITEM pciS;
3044 PCNRITEM pciD;
3045 HWND hwndCnrS;
3046 HWND hwndCnrD;
3047 pciS = (PCNRITEM)WinSendMsg(cmp->hwndCalling,
3048 CM_QUERYRECORDEMPHASIS,
3049 MPFROMLONG(CMA_FIRST),
3050 MPFROMSHORT(CRA_CURSORED));
3051 if (!pciS)
3052 Runtime_Error(pszSrcFile, __LINE__, NULL);
3053 else {
3054 // Find matching record
3055 if (cmp->hwndCalling == GetHwndLeft(hwnd)) {
3056 hwndCnrS = GetHwndLeft(hwnd);
3057 hwndCnrD = GetHwndRight(hwnd);
3058 }
3059 else {
3060 hwndCnrS = GetHwndRight(hwnd);
3061 hwndCnrD = GetHwndLeft(hwnd);
3062 }
3063
3064 pciD = FindMatchingItem(pciS, hwndCnrS, hwndCnrD);
3065
3066 if (!pciD)
3067 Runtime_Error(pszSrcFile, __LINE__, NULL);
3068 else if (!pciS->pszFileName)
3069 Runtime_Error(pszSrcFile, __LINE__, NULL);
3070 else {
3071 if (!unlinkf(pciS->pszFileName)) {
3072 WinSendMsg(hwndCnrS, CM_SETRECORDEMPHASIS, MPFROMP(pciS),
3073 MPFROM2SHORT(FALSE, CRA_SELECTED));
3074
3075 if (!*pciD->pszFileName) {
3076 // Other side is blank - remove from both sides
3077 RemoveCnrItems(hwndCnrS, pciS, 1, CMA_FREE | CMA_INVALIDATE);
3078 if (pciD->rc.flRecordAttr & CRA_SELECTED)
3079 WinSendMsg(hwndCnrD, CM_SETRECORDEMPHASIS, MPFROMP(pciD),
3080 MPFROM2SHORT(FALSE, CRA_SELECTED));
3081 RemoveCnrItems(hwndCnrD, pciD, 1, CMA_FREE | CMA_INVALIDATE);
3082 }
3083 else {
3084 // Other side is not blank - just blank this side
3085 FreeCnrItemData(pciS);
3086 pciS->pszFileName = NullStr;
3087 pciS->pszDisplayName = pciS->pszFileName;
3088 pciS->rc.pszIcon = pciS->pszFileName;
3089 pciS->flags = 0; // Just on one side
3090 WinSendMsg(hwndCnrS, CM_INVALIDATERECORD, MPFROMP(&pciS),
3091 MPFROM2SHORT(1, CMA_ERASE | CMA_TEXTCHANGED));
3092 pciD->flags = 0; // Just on one side
3093 if (pciD->pszSubject != NullStr) {
3094 xfree(pciD->pszSubject, pszSrcFile, __LINE__);
3095 pciD->pszSubject = NullStr;
3096 }
3097 }
3098 if (hwndCnrS == GetHwndLeft(hwnd))
3099 cmp->totalleft--;
3100 else
3101 cmp->totalright--;
3102 // Force displayed counts to update
3103 WinPostMsg(hwnd, WM_TIMER, MPFROMLONG(ID_COMP_TIMER), 0);
3104 }
3105 }
3106 }
3107 }
3108 break; // IDM_DELETE
3109
3110 case COMP_FILTER:
3111 case IDM_FILTER:
3112 cmp = INSTDATA(hwnd);
3113 if (cmp) {
3114 BOOL empty = FALSE;
3115 PCNRITEM pci;
3116 CHAR *p;
3117 BOOL temp;
3118
3119 if (!*cmp->dcd.mask.szMask) {
3120 empty = TRUE;
3121 temp = fSelectedAlways;
3122 fSelectedAlways = TRUE;
3123 pci = (PCNRITEM)CurrentRecord(hwnd);
3124 fSelectedAlways = temp;
3125 // 01 Aug 07 SHL
3126 if (pci && ~pci->attrFile & FILE_DIRECTORY) {
3127 p = strrchr(pci->pszFileName, '\\');
3128 if (p) {
3129 p++;
3130 strcpy(cmp->dcd.mask.szMask, p);
3131 }
3132 }
3133 }
3134 cmp->dcd.mask.fNoAttribs = TRUE;
3135 cmp->dcd.mask.attrFile = ALLATTRS;
3136 cmp->dcd.mask.antiattr = 0;
3137 if (WinDlgBox(HWND_DESKTOP, hwnd, PickMaskDlgProc,
3138 FM3ModHandle, MSK_FRAME, MPFROMP(&cmp->dcd.mask))) {
3139 cmp->dcd.mask.attrFile = ALLATTRS;
3140 cmp->dcd.mask.antiattr = 0;
3141 WinSendMsg(hwnd, UM_FILTER, MPVOID, MPVOID);
3142 }
3143 else if (empty) {
3144 *cmp->dcd.mask.szMask = 0;
3145 cmp->dcd.mask.attrFile = ALLATTRS;
3146 cmp->dcd.mask.antiattr = 0;
3147 }
3148 }
3149 break;
3150
3151 case IDM_SHOWSUBJECT:
3152 case IDM_SHOWEAS:
3153 case IDM_SHOWSIZE:
3154 case IDM_SHOWLWDATE:
3155 case IDM_SHOWLWTIME:
3156 case IDM_SHOWLADATE:
3157 case IDM_SHOWLATIME:
3158 case IDM_SHOWCRDATE:
3159 case IDM_SHOWCRTIME:
3160 case IDM_SHOWATTR:
3161 cmp = INSTDATA(hwnd);
3162 if (cmp) {
3163 DIRCNRDATA dcd1;
3164 BOOL tempsubj;
3165
3166 dcd1 = cmp->dcd;
3167 AdjustDetailsSwitches(GetHwndLeft(hwnd),
3168 (HWND)0, SHORT1FROMMP(mp1),
3169 cmp->leftdir, PCSZ_DIRCMP, &cmp->dcd.ds, TRUE);
3170 tempsubj = cmp->dcd.ds.detailssubject;
3171 cmp->dcd = dcd1;
3172 cmp->dcd.ds.detailssubject = FALSE;
3173 AdjustDetailsSwitches(GetHwndRight(hwnd),
3174 cmp->dcd.hwndLastMenu, SHORT1FROMMP(mp1),
3175 cmp->rightdir, PCSZ_DIRCMP, &cmp->dcd.ds, TRUE);
3176 cmp->dcd.ds.detailssubject = tempsubj;
3177 WriteDetailsSwitches(PCSZ_DIRCMP, &cmp->dcd.ds, TRUE);
3178 }
3179 break;
3180
3181 case IDM_LOADLISTFILE:
3182 cmp = INSTDATA(hwnd);
3183 if (cmp) {
3184 CHAR fullname[CCHMAXPATH];
3185
3186 strcpy(fullname, PCSZ_STARDOTPMD);
3187 if (insert_filename(HWND_DESKTOP, fullname, TRUE, FALSE) &&
3188 *fullname && !strchr(fullname, '*') && !strchr(fullname, '?')) {
3189 strcpy(cmp->rightlist, fullname);
3190 PostMsg(hwnd, UM_SETUP, MPVOID, MPVOID);
3191 PostMsg(hwnd, UM_SETDIR, MPVOID, MPVOID);
3192 }
3193 }
3194 break;
3195
3196 case IDM_SAVELISTFILE:
3197 cmp = INSTDATA(hwnd);
3198 if (cmp) {
3199 SNAPSTUFF *sf;
3200 CHAR fullname[CCHMAXPATH];
3201
3202 strcpy(fullname, PCSZ_STARDOTPMD);
3203 if (export_filename(HWND_DESKTOP, fullname, 1) && *fullname &&
3204 !strchr(fullname, '*') && !strchr(fullname, '?')) {
3205 sf = xmallocz(sizeof(SNAPSTUFF), pszSrcFile, __LINE__);
3206 if (sf) {
3207 strcpy(sf->filename, fullname);
3208 if (GetHwndLeft(hwnd) == cmp->hwndCalling)
3209 strcpy(sf->dirname, cmp->leftdir);
3210 else
3211 strcpy(sf->dirname, cmp->rightdir);
3212 sf->recurse = WinQueryButtonCheckstate(hwnd, COMP_INCLUDESUBDIRS);
3213 //DbgMsg(pszSrcFile, __LINE__, "recurse %i %i", sf->recurse, cmp->includesubdirs);
3214 if (xbeginthread(StartSnapThread,
3215 65536,
3216 sf,
3217 pszSrcFile,
3218 __LINE__) == -1)
3219 {
3220 free(sf);
3221 }
3222 }
3223 }
3224 }
3225 break;
3226
3227 case COMP_SETDIRS:
3228 cmp = INSTDATA(hwnd);
3229 if (cmp) {
3230 WALK2 wa;
3231 memset(&wa, 0, sizeof(wa));
3232 wa.size = sizeof(wa);
3233 strcpy(wa.szCurrentPath1, cmp->leftdir);
3234 strcpy(wa.szCurrentPath2, cmp->rightdir);
3235 wa.includesubdirs = WinQueryButtonCheckstate(hwnd,
3236 COMP_INCLUDESUBDIRS);
3237 if (WinDlgBox(HWND_DESKTOP,
3238 hwnd,
3239 WalkTwoCmpDlgProc,
3240 FM3ModHandle,
3241 WALK2_FRAME,
3242 MPFROMP(&wa)) &&
3243 !IsFile(wa.szCurrentPath1) &&
3244 !IsFile(wa.szCurrentPath2)) {
3245 strcpy(cmp->leftdir, wa.szCurrentPath1);
3246 strcpy(cmp->rightdir, wa.szCurrentPath2);
3247 cmp->includesubdirs = wa.includesubdirs;
3248 if (!cmp->includesubdirs)
3249 WinCheckButton(hwnd, COMP_INCLUDESUBDIRS, FALSE);
3250 cmp->listfile = wa.listfile;
3251 if (cmp->listfile) {
3252 CHAR fullname[CCHMAXPATH];
3253
3254 strcpy(fullname, PCSZ_STARDOTPMD);
3255 if (insert_filename(HWND_DESKTOP, fullname, TRUE, FALSE) &&
3256 *fullname && !strchr(fullname, '*') && !strchr(fullname, '?'))
3257 strcpy(cmp->rightlist, fullname);
3258 }
3259 else
3260 *cmp->rightlist = 0;
3261 PostMsg(hwnd, UM_SETUP, MPVOID, MPVOID);
3262 PostMsg(hwnd, UM_SETDIR, MPVOID, MPVOID);
3263 }
3264 }
3265 break;
3266
3267 case COMP_COPYLEFT:
3268 case COMP_MOVELEFT:
3269 case COMP_COPYRIGHT:
3270 case COMP_MOVERIGHT:
3271 case COMP_DELETELEFT:
3272 case COMP_DELETERIGHT:
3273 cmp = INSTDATA(hwnd);
3274 if (cmp) {
3275 COMPARE *forthread;
3276
3277 cmp->filling = TRUE;
3278 forthread = xmalloc(sizeof(COMPARE), pszSrcFile, __LINE__);
3279 if (forthread) {
3280 *forthread = *cmp;
3281 forthread->cmp = cmp;
3282 forthread->action = SHORT1FROMMP(mp1);
3283 if (xbeginthread(ActionCnrThread,
3284 122880,
3285 forthread,
3286 pszSrcFile,
3287 __LINE__) == -1)
3288 {
3289 free(forthread);
3290 }
3291 else {
3292 WinEnableWindowUpdate(GetHwndLeft(hwnd), FALSE);
3293 WinEnableWindowUpdate(GetHwndRight(hwnd), FALSE);
3294 switch (SHORT1FROMMP(mp1)) {
3295 case COMP_DELETELEFT:
3296 case COMP_DELETERIGHT:
3297 WinSetDlgItemText(hwnd, COMP_NOTE,
3298 (CHAR *) GetPString(IDS_COMPHOLDDELETINGTEXT));
3299 break;
3300 case COMP_MOVELEFT:
3301 case COMP_MOVERIGHT:
3302 WinSetDlgItemText(hwnd, COMP_NOTE,
3303 (CHAR *) GetPString(IDS_COMPHOLDMOVINGTEXT));
3304 break;
3305 case COMP_COPYLEFT:
3306 case COMP_COPYRIGHT:
3307 WinSetDlgItemText(hwnd, COMP_NOTE,
3308 (CHAR *) GetPString(IDS_COMPHOLDCOPYINGTEXT));
3309 break;
3310 default:
3311 Runtime_Error(pszSrcFile, __LINE__, "mp1 %u unexpected", SHORT1FROMMP(mp1));
3312 }
3313 SetButtonEnables(cmp, FALSE);
3314 }
3315 }
3316 }
3317 break;
3318
3319 case DID_OK:
3320 {
3321 SWP swp;
3322 ULONG size = sizeof(SWP);
3323 USHORT ids[] = {COMP_FRAME, COMP_LEFTDIR, COMP_RIGHTDIR, COMP_COLLECT,
3324 COMP_VIEW, COMP_NOTE, COMP_TOTALLEFT, COMP_SELLEFT, COMP_TOTALRIGHT,
3325 COMP_SELRIGHT, COMP_CNRMENU, COMP_DIRMENU, COMP_MENU,
3326 COMP_INCLUDESUBDIRS, COMP_SETDIRS, COMP_COPYLEFT, COMP_MOVELEFT,
3327 COMP_DELETELEFT, COMP_COPYRIGHT, COMP_MOVERIGHT, COMP_DELETERIGHT,
3328 COMP_TOTALLEFTHDR, COMP_SELLEFTHDR, COMP_TOTALRIGHTHDR,
3329 COMP_SELRIGHTHDR, COMP_FILTER, COMP_HIDENOTSELECTED, 0};
3330 UINT x;
3331 CHAR s[24];
3332 WinQueryWindowPos(hwnd, &swp);
3333 PrfWriteProfileData(fmprof, FM3Str, "CompDir.Position", (PVOID) &swp,
3334 size);
3335 for (x = 0; ids[x]; x++) {
3336 sprintf(s, "CompDir%i", ids[x]);
3337 SavePresParams(WinWindowFromID(hwnd, ids[x]), s);
3338 }
3339 }
3340 WinDismissDlg(hwnd, 0);
3341 break;
3342 case DID_CANCEL:
3343 cmp = INSTDATA(hwnd);
3344 if (!cmp)
3345 Runtime_Error(pszSrcFile, __LINE__, NULL);
3346 else {
3347 cmp->stop = TRUE; // In case thread running
3348 if (cmp->filling)
3349 break; // UM_CONTAINER_FILLED will dismiss
3350 }
3351 {
3352 SWP swp;
3353 ULONG size = sizeof(SWP);
3354 WinQueryWindowPos(hwnd, &swp);
3355 PrfWriteProfileData(fmprof, FM3Str, "CompDir.Position", (PVOID) &swp,
3356 size);
3357 }
3358 WinDismissDlg(hwnd, 1);
3359 break;
3360
3361 case IDM_HELP:
3362 if (hwndHelp)
3363 WinSendMsg(hwndHelp, HM_DISPLAY_HELP,
3364 MPFROM2SHORT(HELP_COMPARE, 0), MPFROMSHORT(HM_RESOURCEID));
3365 break;
3366
3367 case IDM_DESELECTALL:
3368 case IDM_SELECTNEWER:
3369 case IDM_SELECTOLDER:
3370 case IDM_SELECTBIGGER:
3371 case IDM_SELECTSMALLER:
3372 case IDM_SELECTEAS:
3373 case IDM_DESELECTNEWER:
3374 case IDM_DESELECTOLDER:
3375 case IDM_DESELECTBIGGER:
3376 case IDM_DESELECTSMALLER:
3377 case IDM_DESELECTONE:
3378 case IDM_DESELECTBOTH:
3379 case IDM_DESELECTEAS:
3380 case IDM_SELECTBOTH:
3381 case IDM_SELECTONE:
3382 case IDM_SELECTSAMECONTENT:
3383 case IDM_SELECTIDENTICAL: // Name, size and time
3384 case IDM_SELECTSAME: // Name and size
3385 case IDM_INVERT:
3386
3387
3388 cmp = INSTDATA(hwnd);
3389 if (!cmp)
3390 Runtime_Error(pszSrcFile, __LINE__, NULL);
3391 else {
3392 COMPARE *forthread;
3393
3394 cmp->filling = TRUE;
3395 forthread = xmalloc(sizeof(COMPARE), pszSrcFile, __LINE__);
3396 if (forthread) {
3397 *forthread = *cmp;
3398 forthread->cmp = cmp;
3399 forthread->action = SHORT1FROMMP(mp1);
3400 SetShiftState();
3401 forthread->shiftstate = shiftstate; // For and'ed actions
3402
3403 if (xbeginthread(SelectCnrsThread,
3404 65536,
3405 forthread,
3406 pszSrcFile,
3407 __LINE__) == -1)
3408 {
3409 free(forthread);
3410 }
3411 else {
3412 WinEnableWindowUpdate(GetHwndLeft(hwnd), FALSE);
3413 WinEnableWindowUpdate(GetHwndRight(hwnd), FALSE);
3414 switch (SHORT1FROMMP(mp1)) {
3415 case IDM_DESELECTALL:
3416 case IDM_DESELECTNEWER:
3417 case IDM_DESELECTOLDER:
3418 case IDM_DESELECTBIGGER:
3419 case IDM_DESELECTSMALLER:
3420 case IDM_DESELECTONE:
3421 case IDM_DESELECTBOTH:
3422 WinSetDlgItemText(hwnd, COMP_NOTE,
3423 (CHAR *) GetPString(IDS_COMPHOLDDESELTEXT));
3424 break;
3425 case IDM_INVERT:
3426 WinSetDlgItemText(hwnd, COMP_NOTE,
3427 (CHAR *) GetPString(IDS_COMPHOLDINVERTTEXT));
3428 break;
3429 default:
3430 WinSetDlgItemText(hwnd, COMP_NOTE,
3431 (CHAR *) GetPString(IDS_COMPHOLDSELTEXT));
3432 break;
3433 }
3434 SetButtonEnables(cmp, FALSE);
3435 }
3436 }
3437 }
3438 break;
3439
3440 case COMP_COLLECT:
3441 cmp = INSTDATA(hwnd);
3442 if (!cmp)
3443 Runtime_Error(pszSrcFile, __LINE__, NULL);
3444 else {
3445 CHAR **listl;
3446 CHAR **listr = NULL;
3447 if (!Collector) {
3448 SWP swp;
3449 HWND hwndC;
3450 if (!fAutoTile &&
3451 !ParentIsDesktop(hwnd, cmp->hwndParent) &&
3452 !fExternalCollector &&
3453 !strcmp(realappname, FM3Str)) {
3454 GetNextWindowPos(cmp->hwndParent, &swp, NULL, NULL);
3455 }
3456 hwndC = StartCollector(fExternalCollector ||
3457 strcmp(realappname, FM3Str) ?
3458 HWND_DESKTOP :
3459 cmp->hwndParent,
3460 4);
3461 if (hwndC) {
3462 if (!fAutoTile &&
3463 !ParentIsDesktop(hwnd, cmp->hwndParent) &&
3464 !fExternalCollector &&
3465 !strcmp(realappname, FM3Str)) {
3466 WinSetWindowPos(hwndC, HWND_TOP,
3467 swp.x, swp.y, swp.cx, swp.cy,
3468 SWP_MOVE | SWP_SIZE | SWP_SHOW | SWP_ZORDER);
3469 }
3470 else if (!ParentIsDesktop(hwnd, cmp->hwndParent) &&
3471 fAutoTile &&
3472 !strcmp(realappname, FM3Str)) {
3473 TileChildren(cmp->hwndParent, TRUE);
3474 }
3475 DosSleep(1); // 12 Jan 08 SHL Let screen update
3476 PostMsg(hwnd, WM_COMMAND, MPFROM2SHORT(COMP_COLLECT, 0), MPVOID);
3477 break;
3478 }
3479 }
3480 else
3481 StartCollector(cmp->hwndParent, 4);
3482
3483 temp = fSelectedAlways;
3484 fSelectedAlways = TRUE;
3485 listl = BuildList(GetHwndLeft(hwnd));
3486 if (!*cmp->rightlist)
3487 listr = BuildList(GetHwndRight(hwnd));
3488 fSelectedAlways = temp;
3489
3490 if (listl || listr) {
3491 if (Collector) {
3492 // 07 Aug 07 SHL Avoid collected from empty list
3493 if (listl && listl[0] && *listl[0]) {
3494 if (PostMsg(Collector, WM_COMMAND,
3495 MPFROM2SHORT(IDM_COLLECTOR, 0), MPFROMP(listl)))
3496 listl = NULL; // Collector will free
3497 }
3498 if (listr && listr[0] && *listr[0]) {
3499 if (PostMsg(Collector, WM_COMMAND,
3500 MPFROM2SHORT(IDM_COLLECTOR, 0), MPFROMP(listr)))
3501 listr = NULL; // Collector will free
3502 }
3503 WinSetWindowPos(WinQueryWindow(WinQueryWindow(Collector,
3504 QW_PARENT),
3505 QW_PARENT),
3506 HWND_TOP, 0, 0, 0, 0,
3507 SWP_ACTIVATE);
3508 }
3509 FreeList(listl);
3510 FreeList(listr);
3511 }
3512 }
3513 break;
3514 } // switch mp1
3515 return 0;
3516
3517 case WM_CLOSE:
3518 cmp = INSTDATA(hwnd);
3519 if (!cmp)
3520 Runtime_Error(pszSrcFile, __LINE__, NULL);
3521 else {
3522 cmp->stop = TRUE; // In case thread running
3523 if (cmp->filling)
3524 break; // UM_CONTAINER_FILLED will dismiss
3525 }
3526 WinDismissDlg(hwnd, 0);
3527 return 0;
3528
3529 case WM_DESTROY:
3530 cmp = INSTDATA(hwnd);
3531 if (cmp) {
3532 // 17 Jan 08 SHL fixme to know if stop really needed?
3533 WinStopTimer(WinQueryAnchorBlock(hwnd), hwnd, ID_COMP_TIMER);
3534 if (cmp->dcd.hwndLastMenu)
3535 WinDestroyWindow(cmp->dcd.hwndLastMenu);
3536 if (cmp->dcd.hwndObject) {
3537 WinSetWindowPtr(cmp->dcd.hwndObject, QWL_USER, (PVOID)NULL);
3538 if (!PostMsg(cmp->dcd.hwndObject, WM_CLOSE, MPVOID, MPVOID))
3539 WinSendMsg(cmp->dcd.hwndObject, WM_CLOSE, MPVOID, MPVOID);
3540 }
3541 free(cmp);
3542 }
3543 EmptyCnr(GetHwndLeft(hwnd));
3544 EmptyCnr(GetHwndRight(hwnd));
3545 DosPostEventSem(CompactSem);
3546 break;
3547 }
3548 return WinDefDlgProc(hwnd, msg, mp1, mp2);
3549}
3550
3551#undef GetHwndLeft
3552#undef GetHwndRight
3553
3554#pragma alloc_text(COMPAREDIR,FillCnrsThread,FillDirList,CompNames,BldFullPathName)
3555#pragma alloc_text(COMPAREDIR1,CompareDlgProc)
3556#pragma alloc_text(COMPAREDIR2,SelectCnrsThread,ActionCnrThread)
3557#pragma alloc_text(COMPAREFILE,CFileDlgProc,CompareFilesThread)
3558#pragma alloc_text(SNAPSHOT,SnapShot,StartSnapThread)
3559#pragma alloc_text(COMPSELECT,CompSelect,CompSelectSetSelects,CompSelectClearSelects)
3560
Note: See TracBrowser for help on using the repository browser.