source: trunk/dll/comp.c@ 1063

Last change on this file since 1063 was 1063, checked in by Gregg Young, 17 years ago

Fortify ifdef reformat

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