source: trunk/dll/comp.c@ 1036

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

More fortify changes eliminated the leave scope wrapper except in mainwnd.c Wrapper only unlaods stuuff (archivers, commands, etc

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 100.3 KB
Line 
1
2/***********************************************************************
3
4 $Id: comp.c 1036 2008-07-01 22:53:51Z 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 xfree(mask, pszSrcFile, __LINE__);
149 }
150 xfree(pffb, pszSrcFile, __LINE__);
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 xfree(sf, pszSrcFile, __LINE__);
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 hmq2 = WinCreateMsgQueue(hab2, 0);
204 if (hmq2) {
205# ifdef FORTIFY
206 Fortify_EnterScope();
207# endif
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(pszSrcFile, __LINE__);
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 hmq = WinCreateMsgQueue(hab, 0);
411 if (hmq) {
412# ifdef FORTIFY
413 Fortify_EnterScope();
414# endif
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 xfree(cmp, pszSrcFile, __LINE__);
694 WinTerminate(hab);
695# ifdef FORTIFY
696 Fortify_LeaveScope(pszSrcFile, __LINE__);
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 hmq = WinCreateMsgQueue(hab, 0);
723 if (hmq) {
724# ifdef FORTIFY
725 Fortify_EnterScope();
726# endif
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 xfree(cmp, pszSrcFile, __LINE__);
759 WinTerminate(hab);
760# ifdef FORTIFY
761 Fortify_LeaveScope(pszSrcFile, __LINE__);
762# endif
763 }
764 else
765 xfree(cmp, pszSrcFile, __LINE__);
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 xfree(pciDa, pszSrcFile, __LINE__);
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 xfree(pciDa, pszSrcFile, __LINE__);
844 xfree(pciSa, pszSrcFile, __LINE__);
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 xfree(pciSa, pszSrcFile, __LINE__);
871 xfree(pciDa, pszSrcFile, __LINE__);
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 xfree(pciSa, pszSrcFile, __LINE__);
1315 xfree(pciDa, pszSrcFile, __LINE__);
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 xfree(maskstr, pszSrcFile, __LINE__);
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 xfree(pffbArray, pszSrcFile, __LINE__);
1405 xfree(maskstr, pszSrcFile, __LINE__);
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# ifdef FORTIFY
1958 xfree(filesl[l++], pszSrcFile, __LINE__);
1959# else
1960 free(filesl[l++]); // Done with item on left
1961# endif
1962 }
1963 if (x >= 0) {
1964# ifdef FORTIFY
1965 xfree(filesr[r++], pszSrcFile, __LINE__);
1966# else
1967 free(filesr[r++]); // Done with item on right
1968#endif
1969 }
1970 // Ensure empty buffers point somewhere
1971 if (!pcil->pszFileName) {
1972 pcil->pszFileName = NullStr;
1973 pcil->pszDisplayName = pcil->pszFileName;
1974 }
1975
1976 if (!pcir->pszFileName) {
1977 pcir->pszFileName = NullStr;
1978 pcir->pszDisplayName = pcir->pszFileName;
1979 }
1980
1981 pcil->rc.pszIcon = pcil->pszDisplayName;
1982 pcir->rc.pszIcon = pcir->pszDisplayName;
1983
1984 pcil->pszLongName = NullStr;
1985 pcir->pszLongName = NullStr;
1986
1987 if (!pcil->pszSubject)
1988 if (!pcir->pszSubject)
1989 pcir->pszSubject = NullStr;
1990
1991 if (!pcil->pszDispAttr)
1992 pcil->pszDispAttr = NullStr;
1993 if (!pcir->pszDispAttr)
1994 pcir->pszDispAttr = NullStr;
1995
1996 // Avoid hogging systems
1997 SleepIfNeeded(&itdSleep, 0);
1998
1999 pcilLast = pcil;
2000 pcirLast = pcir;
2001 pcil = (PCNRITEM)pcil->rc.preccNextRecord;
2002 pcir = (PCNRITEM)pcir->rc.preccNextRecord;
2003
2004 } // while filling left or right
2005
2006 // If stopped early CM_ALLOCATERECORD partially failed
2007 // Free up container records we did not use on other side
2008 // Free up items we did not insert in container
2009 if (recsGotten < recsNeeded) {
2010 if (pcil) {
2011 if (pcilLast)
2012 pcilLast->rc.preccNextRecord = NULL;
2013 else
2014 pcilFirst = NULL;
2015 FreeCnrItemList(hwndLeft, pcil);
2016 }
2017 if (filesl) {
2018 for(; filesl[l]; l++) {
2019# ifdef FORTIFY
2020 xfree(filesl[l], pszSrcFile, __LINE__);
2021# else
2022 free(filesl[l]);
2023# endif
2024 }
2025 }
2026 if (pcir) {
2027 if (pcirLast)
2028 pcirLast->rc.preccNextRecord = NULL;
2029 else
2030 pcirFirst = NULL;
2031 FreeCnrItemList(hwndRight, pcir);
2032 }
2033 if (filesr) {
2034 for (; filesr[r]; r++) {
2035# ifdef FORTIFY
2036 xfree(filesr[r], pszSrcFile, __LINE__);
2037# else
2038 free(filesr[r]);
2039# endif
2040 }
2041 }
2042 // Reduce count to match what is in containers
2043 recsNeeded = recsGotten;
2044 } // if insufficient resources
2045
2046 xfree(filesl, pszSrcFile, __LINE__); // Free header - have already freed elements
2047 filesl = NULL;
2048 xfree(filesr, pszSrcFile, __LINE__);
2049 filesr = NULL;
2050
2051 // Say inserting
2052 WinSendMsg(cmp->hwnd, UM_CONTAINERDIR, MPVOID, MPVOID);
2053
2054 // Insert left 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(hwndLeft, CM_INSERTRECORD,
2064 MPFROMP(pcilFirst), MPFROMP(&ri))) {
2065 Win_Error(hwndLeft, cmp->hwnd, pszSrcFile, __LINE__, "CM_INSERTRECORD");
2066 FreeCnrItemList(hwndLeft, pcilFirst);
2067 cmp->cmp->totalleft = 0;
2068 }
2069
2070 // Insert right side
2071 memset(&ri, 0, sizeof(RECORDINSERT));
2072 ri.cb = sizeof(RECORDINSERT);
2073 ri.pRecordOrder = (PRECORDCORE)CMA_END;
2074 ri.pRecordParent = (PRECORDCORE)NULL;
2075 ri.zOrder = (ULONG)CMA_TOP;
2076 ri.cRecordsInsert = recsNeeded;
2077 ri.fInvalidateRecord = FALSE;
2078
2079 if (!WinSendMsg(hwndRight, CM_INSERTRECORD,
2080 MPFROMP(pcirFirst), MPFROMP(&ri))) {
2081 Win_Error(hwndRight, cmp->hwnd, pszSrcFile, __LINE__, "CM_INSERTRECORD");
2082 RemoveCnrItems(hwndLeft, NULL, 0, CMA_FREE | CMA_INVALIDATE);
2083 FreeCnrItemList(hwndRight, pcirFirst);
2084 cmp->cmp->totalright = 0;
2085 }
2086
2087 // DbgMsg(pszSrcFile, __LINE__, "FillCnrsThread filled");
2088
2089 } // if recsNeeded
2090
2091 Deselect(hwndLeft);
2092 Deselect(hwndRight);
2093
2094 // DbgMsg(pszSrcFile, __LINE__, "FillCnrsThread deselected");
2095
2096 // Request window update
2097 if (!PostMsg(cmp->hwnd, UM_CONTAINER_FILLED, MPVOID, MPVOID))
2098 WinSendMsg(cmp->hwnd, UM_CONTAINER_FILLED, MPVOID, MPVOID);
2099 notified = TRUE;
2100
2101 // DbgMsg(pszSrcFile, __LINE__, "FillCnrsThread FILLED posted");
2102
2103 if (filesl)
2104 FreeList((CHAR **)filesl); // Must have failed to create container
2105 if (filesr)
2106 FreeList((CHAR **)filesr);
2107
2108 WinDestroyMsgQueue(hmq);
2109 } // if have queue
2110 if (!notified)
2111 PostMsg(cmp->hwnd, UM_CONTAINER_FILLED, MPVOID, MPVOID);
2112 DecrThreadUsage();
2113 WinTerminate(hab);
2114 }
2115 xfree(cmp, pszSrcFile, __LINE__);
2116 DosPostEventSem(CompactSem);
2117
2118# ifdef FORTIFY
2119 Fortify_LeaveScope(pszSrcFile, __LINE__);
2120# endif
2121
2122 // DbgMsg(pszSrcFile, __LINE__, "FillCnrsThread exit");
2123}
2124
2125// fixme to be gone - use variable?
2126#define hwndLeft (WinWindowFromID(hwnd,COMP_LEFTDIR))
2127#define hwndRight (WinWindowFromID(hwnd,COMP_RIGHTDIR))
2128
2129//=== CompareDlgProc() Compare directories dialog procedure ===
2130
2131MRESULT EXPENTRY CompareDlgProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
2132{
2133 COMPARE *cmp;
2134 BOOL temp;
2135 CHAR s[81];
2136
2137 static HPOINTER hptr;
2138
2139 switch (msg) {
2140 case WM_INITDLG:
2141 cmp = (COMPARE *)mp2;
2142 if (!cmp) {
2143 Runtime_Error2(pszSrcFile, __LINE__, IDS_NODATATEXT);
2144 WinDismissDlg(hwnd, 0);
2145 }
2146 else {
2147 if (!hptr)
2148 hptr = WinLoadPointer(HWND_DESKTOP, FM3ModHandle, COMPARE_ICON);
2149 WinDefDlgProc(hwnd, WM_SETICON, MPFROMLONG(hptr), MPVOID);
2150 cmp->hwnd = hwnd;
2151 WinSetWindowPtr(hwnd, QWL_USER, (PVOID)cmp);
2152 {
2153 SWP swp;
2154 ULONG size = sizeof(SWP);
2155
2156 PrfQueryProfileData(fmprof, FM3Str, "CompDir.Position", (PVOID) &swp, &size);
2157 WinSetWindowPos(hwnd,
2158 HWND_TOP,
2159 swp.x,
2160 swp.y,
2161 swp.cx,
2162 swp.cy,
2163 swp.fl);
2164 }
2165 SetCnrCols(hwndLeft, TRUE);
2166 SetCnrCols(hwndRight, TRUE);
2167 WinSendMsg(hwnd, UM_SETUP, MPVOID, MPVOID);
2168 WinSendMsg(hwnd, UM_SETDIR, MPVOID, MPVOID);
2169 PostMsg(hwnd, UM_STRETCH, MPVOID, MPVOID);
2170 {
2171 USHORT ids[] = { COMP_LEFTDIR, COMP_RIGHTDIR, COMP_TOTALLEFT,
2172 COMP_TOTALRIGHT, COMP_SELLEFT, COMP_SELRIGHT,
2173 0
2174 };
2175 UINT x;
2176 for (x = 0; ids[x]; x++) {
2177 SetPresParams(WinWindowFromID(hwnd, ids[x]),
2178 &RGBGREY,
2179 &RGBBLACK, &RGBBLACK, GetPString(IDS_8HELVTEXT));
2180 }
2181 }
2182 WinStartTimer(WinQueryAnchorBlock(hwnd), hwnd, ID_TIMER, 500);
2183 }
2184 break;
2185
2186 case UM_STRETCH:
2187 {
2188 SWP swp, swpC;
2189 LONG titl, szbx, szby, sz;
2190 HWND hwndActive;
2191
2192 WinQueryWindowPos(hwnd, &swp);
2193 if (!(swp.fl & (SWP_HIDE | SWP_MINIMIZE))) {
2194 hwndActive = WinQueryFocus(HWND_DESKTOP);
2195 szbx = SysVal(SV_CXSIZEBORDER);
2196 szby = SysVal(SV_CYSIZEBORDER);
2197 titl = SysVal(SV_CYTITLEBAR);
2198 titl += 26;
2199 swp.cx -= (szbx * 2);
2200 sz = (swp.cx / 8);
2201 WinQueryWindowPos(WinWindowFromID(hwnd, COMP_LEFTDIR), &swpC);
2202 WinSetWindowPos(WinWindowFromID(hwnd, COMP_LEFTDIR), HWND_TOP,
2203 szbx + 6,
2204 swpC.y,
2205 (swp.cx / 2) - (szbx + 6),
2206 ((swp.cy - swpC.y) - titl) - szby,
2207 SWP_MOVE | SWP_SIZE);
2208 WinSetWindowPos(WinWindowFromID(hwnd, COMP_RIGHTDIR), HWND_TOP,
2209 (swp.cx / 2) + (szbx + 6),
2210 swpC.y,
2211 (swp.cx / 2) - (szbx + 6),
2212 ((swp.cy - swpC.y) - titl) - szby,
2213 SWP_MOVE | SWP_SIZE);
2214 WinSetWindowPos(WinWindowFromID(hwnd, COMP_TOTALLEFTHDR), HWND_TOP,
2215 szbx + 6,
2216 ((swp.cy - titl) - szby) + 4,
2217 sz - (szbx + 6), 20, SWP_MOVE | SWP_SIZE);
2218 WinSetWindowPos(WinWindowFromID(hwnd, COMP_TOTALLEFT), HWND_TOP,
2219 sz + (szbx + 6),
2220 ((swp.cy - titl) - szby) + 4,
2221 sz - (szbx + 6), 20, SWP_MOVE | SWP_SIZE);
2222 WinSetWindowPos(WinWindowFromID(hwnd, COMP_SELLEFTHDR), HWND_TOP,
2223 (sz * 2) + (szbx + 6),
2224 ((swp.cy - titl) - szby) + 4,
2225 sz - (szbx + 6), 20, SWP_MOVE | SWP_SIZE);
2226 WinSetWindowPos(WinWindowFromID(hwnd, COMP_SELLEFT), HWND_TOP,
2227 (sz * 3) + (szbx + 6),
2228 ((swp.cy - titl) - szby) + 4,
2229 sz - (szbx + 6), 20, SWP_MOVE | SWP_SIZE);
2230 WinSetWindowPos(WinWindowFromID(hwnd, COMP_TOTALRIGHTHDR), HWND_TOP,
2231 (sz * 4) + (szbx + 6),
2232 ((swp.cy - titl) - szby) + 4,
2233 sz - (szbx + 6), 20, SWP_MOVE | SWP_SIZE);
2234 WinSetWindowPos(WinWindowFromID(hwnd, COMP_TOTALRIGHT), HWND_TOP,
2235 (sz * 5) + (szbx + 6),
2236 ((swp.cy - titl) - szby) + 4,
2237 sz - (szbx + 6), 20, SWP_MOVE | SWP_SIZE);
2238 WinSetWindowPos(WinWindowFromID(hwnd, COMP_SELRIGHTHDR), HWND_TOP,
2239 (sz * 6) + (szbx + 6),
2240 ((swp.cy - titl) - szby) + 4,
2241 sz - (szbx + 6), 20, SWP_MOVE | SWP_SIZE);
2242 WinSetWindowPos(WinWindowFromID(hwnd, COMP_SELRIGHT), HWND_TOP,
2243 (sz * 7) + (szbx + 6),
2244 ((swp.cy - titl) - szby) + 4,
2245 sz - (szbx + 6), 20, SWP_MOVE | SWP_SIZE);
2246 PaintRecessedWindow(WinWindowFromID(hwnd, COMP_TOTALLEFT),
2247 (HPS)0, FALSE, FALSE);
2248 PaintRecessedWindow(WinWindowFromID(hwnd, COMP_SELLEFT),
2249 (HPS)0, FALSE, FALSE);
2250 PaintRecessedWindow(WinWindowFromID(hwnd, COMP_TOTALRIGHT),
2251 (HPS)0, FALSE, FALSE);
2252 PaintRecessedWindow(WinWindowFromID(hwnd, COMP_SELRIGHT),
2253 (HPS)0, FALSE, FALSE);
2254 PaintRecessedWindow(hwndLeft, (HPS)0,
2255 (hwndActive == hwndLeft), TRUE);
2256 PaintRecessedWindow(hwndRight, (HPS)0,
2257 (hwndActive == hwndRight), TRUE);
2258 }
2259 }
2260 return 0;
2261
2262 case WM_ADJUSTWINDOWPOS:
2263 PostMsg(hwnd, UM_STRETCH, MPVOID, MPVOID);
2264 break;
2265
2266 case UM_SETUP:
2267 {
2268 CNRINFO cnri;
2269 BOOL tempsubj;
2270
2271 cmp = INSTDATA(hwnd);
2272 if (!cmp)
2273 Runtime_Error2(pszSrcFile, __LINE__, IDS_NODATATEXT);
2274 else {
2275 cmp->dcd.size = sizeof(DIRCNRDATA);
2276 cmp->dcd.type = DIR_FRAME;
2277 cmp->dcd.hwndFrame = hwnd;
2278 cmp->dcd.hwndClient = hwnd;
2279 cmp->dcd.mask.attrFile = (FILE_DIRECTORY | FILE_ARCHIVED |
2280 FILE_READONLY | FILE_SYSTEM | FILE_HIDDEN);
2281 LoadDetailsSwitches("DirCmp", &cmp->dcd);
2282 cmp->dcd.detailslongname = FALSE;
2283 cmp->dcd.detailsicon = FALSE; // TRUE;
2284 }
2285 memset(&cnri, 0, sizeof(CNRINFO));
2286 cnri.cb = sizeof(CNRINFO);
2287 WinSendDlgItemMsg(hwnd, COMP_LEFTDIR, CM_QUERYCNRINFO,
2288 MPFROMP(&cnri), MPFROMLONG(sizeof(CNRINFO)));
2289 cnri.flWindowAttr |= (CA_OWNERDRAW | CV_MINI);
2290 cnri.xVertSplitbar = DIR_SPLITBAR_OFFSET - 68;
2291 WinSendDlgItemMsg(hwnd, COMP_LEFTDIR, CM_SETCNRINFO, MPFROMP(&cnri),
2292 MPFROMLONG(CMA_FLWINDOWATTR | CMA_XVERTSPLITBAR));
2293 memset(&cnri, 0, sizeof(CNRINFO));
2294 cnri.cb = sizeof(CNRINFO);
2295 WinSendDlgItemMsg(hwnd, COMP_RIGHTDIR, CM_QUERYCNRINFO,
2296 MPFROMP(&cnri), MPFROMLONG(sizeof(CNRINFO)));
2297 cnri.flWindowAttr |= (CA_OWNERDRAW | CV_MINI);
2298 cnri.xVertSplitbar = DIR_SPLITBAR_OFFSET - 54;
2299 WinSendDlgItemMsg(hwnd, COMP_RIGHTDIR, CM_SETCNRINFO, MPFROMP(&cnri),
2300 MPFROMLONG(CMA_FLWINDOWATTR | CMA_XVERTSPLITBAR));
2301 AdjustCnrColRO(hwndLeft, GetPString(IDS_FILENAMECOLTEXT), TRUE, FALSE);
2302 AdjustCnrColRO(hwndLeft, GetPString(IDS_LONGNAMECOLTEXT), TRUE, FALSE);
2303 AdjustCnrColRO(hwndRight, GetPString(IDS_FILENAMECOLTEXT), TRUE, FALSE);
2304 AdjustCnrColRO(hwndRight, GetPString(IDS_LONGNAMECOLTEXT), TRUE, FALSE);
2305 AdjustCnrColsForPref(hwndLeft, cmp->leftdir, &cmp->dcd, TRUE);
2306 tempsubj = cmp->dcd.detailssubject;
2307 cmp->dcd.detailssubject = FALSE;
2308 AdjustCnrColsForPref(hwndRight, cmp->rightdir, &cmp->dcd, TRUE);
2309 if (*cmp->rightlist) {
2310 AdjustCnrColVis(hwndRight, GetPString(IDS_LADATECOLTEXT), FALSE,
2311 FALSE);
2312 AdjustCnrColVis(hwndRight, GetPString(IDS_LATIMECOLTEXT), FALSE,
2313 FALSE);
2314 AdjustCnrColVis(hwndRight, GetPString(IDS_CRDATECOLTEXT), FALSE,
2315 FALSE);
2316 AdjustCnrColVis(hwndRight, GetPString(IDS_CRTIMECOLTEXT), FALSE,
2317 FALSE);
2318 }
2319 cmp->dcd.detailssubject = tempsubj;
2320 }
2321 return 0;
2322
2323 case WM_DRAWITEM:
2324 if (mp2) {
2325 POWNERITEM pown = (POWNERITEM)mp2;
2326 PCNRDRAWITEMINFO pcown;
2327 PCNRITEM pci;
2328
2329 pcown = (PCNRDRAWITEMINFO)pown->hItem;
2330 if (pcown) {
2331 pci = (PCNRITEM)pcown->pRecord;
2332 // 01 Aug 07 SHL if field null or blank, we draw
2333 // fixme to document why - probably to optimize and bypass draw?
2334 if (pci && (INT)pci != -1 && !*pci->pszFileName)
2335 return MRFROMLONG(TRUE);
2336 }
2337 }
2338 return 0;
2339
2340 case UM_CONTAINERHWND:
2341 // Building list
2342 WinSetDlgItemText(hwnd, COMP_NOTE, GetPString(IDS_COMPHOLDBLDLISTTEXT));
2343 return 0;
2344
2345 case UM_CONTAINERDIR:
2346 // Filling container
2347 WinSetDlgItemText(hwnd, COMP_NOTE, GetPString(IDS_COMPHOLDFILLCNRTEXT));
2348 return 0;
2349
2350 case WM_TIMER:
2351 // Show current totals
2352 cmp = INSTDATA(hwnd);
2353 if (!cmp) {
2354 Runtime_Error(pszSrcFile, __LINE__, "pCompare NULL");
2355 WinDismissDlg(hwnd, 0);
2356 }
2357 else {
2358 if (cmp->uOldTotalLeft != cmp->totalleft) {
2359 cmp->uOldTotalLeft = cmp->totalleft;
2360 sprintf(s, " %d", cmp->totalleft);
2361 WinSetDlgItemText(hwnd, COMP_TOTALLEFT, s);
2362 }
2363 if (cmp->uOldTotalRight != cmp->totalright) {
2364 cmp->uOldTotalRight = cmp->totalright;
2365 sprintf(s, " %d", cmp->totalright);
2366 WinSetDlgItemText(hwnd, COMP_TOTALRIGHT, s);
2367 }
2368 if (cmp->uOldSelLeft != cmp->selleft) {
2369 cmp->uOldSelLeft = cmp->selleft;
2370 sprintf(s, " %d", cmp->selleft);
2371 WinSetDlgItemText(hwnd, COMP_SELLEFT, s);
2372 }
2373 if (cmp->uOldSelRight != cmp->selright) {
2374 cmp->uOldSelRight = cmp->selright;
2375 sprintf(s, " %d", cmp->selright);
2376 WinSetDlgItemText(hwnd, COMP_SELRIGHT, s);
2377 }
2378 }
2379 break;
2380
2381 case UM_CONTAINER_FILLED:
2382 cmp = INSTDATA(hwnd);
2383 if (!cmp) {
2384 Runtime_Error(pszSrcFile, __LINE__, "pCompare NULL");
2385 WinDismissDlg(hwnd, 0);
2386 }
2387 else {
2388 cmp->filling = FALSE;
2389 WinEnableWindow(hwndLeft, TRUE);
2390 WinEnableWindow(hwndRight, TRUE);
2391 WinEnableWindowUpdate(hwndLeft, TRUE);
2392 WinEnableWindowUpdate(hwndRight, TRUE);
2393 WinPostMsg(hwnd, WM_TIMER, MPFROMLONG(ID_TIMER), 0); // Force update
2394 // 12 Jan 08 SHL fixme to have SetButtonEnables(COMPARE* pcmp, BOOL fEnable)
2395 // to replace duplicated code here and elsewhere
2396 WinEnableWindow(WinWindowFromID(hwnd, DID_OK), TRUE);
2397 WinEnableWindow(WinWindowFromID(hwnd, DID_CANCEL), TRUE);
2398 WinEnableWindow(WinWindowFromID(hwnd, COMP_COLLECT), TRUE);
2399 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTBOTH), TRUE);
2400 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTONE), TRUE);
2401 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTNEWER), TRUE);
2402 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTOLDER), TRUE);
2403 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTBIGGER), TRUE);
2404 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTSMALLER), TRUE);
2405 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTBOTH), TRUE);
2406 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTONE), TRUE);
2407 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTNEWER), TRUE);
2408 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTOLDER), TRUE);
2409 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTBIGGER), TRUE);
2410 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTSMALLER), TRUE);
2411 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTALL), TRUE);
2412 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTSAMECONTENT), TRUE);
2413 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTIDENTICAL), TRUE);
2414 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTSAME), TRUE);
2415 WinEnableWindow(WinWindowFromID(hwnd, IDM_INVERT), TRUE);
2416 WinEnableWindow(WinWindowFromID(hwnd, COMP_SETDIRS), TRUE);
2417 WinEnableWindow(WinWindowFromID(hwnd, COMP_DELETELEFT), TRUE);
2418 WinEnableWindow(WinWindowFromID(hwnd, COMP_FILTER), TRUE);
2419 if (!*cmp->rightlist) {
2420 WinEnableWindow(WinWindowFromID(hwnd, COMP_COPYLEFT), TRUE);
2421 WinEnableWindow(WinWindowFromID(hwnd, COMP_MOVELEFT), TRUE);
2422 WinEnableWindow(WinWindowFromID(hwnd, COMP_DELETERIGHT), TRUE);
2423 WinEnableWindow(WinWindowFromID(hwnd, COMP_COPYRIGHT), TRUE);
2424 WinEnableWindow(WinWindowFromID(hwnd, COMP_MOVERIGHT), TRUE);
2425 }
2426 WinEnableWindow(WinWindowFromID(hwnd, COMP_INCLUDESUBDIRS), TRUE);
2427 WinEnableWindow(WinWindowFromID(hwnd, COMP_HIDENOTSELECTED), TRUE);
2428 if (*cmp->dcd.mask.szMask) {
2429 sprintf(s,
2430 GetPString(IDS_COMPREADYFILTEREDTEXT),
2431 cmp->dcd.mask.szMask);
2432 WinSetDlgItemText(hwnd, COMP_NOTE, s);
2433 }
2434 else
2435 WinSetDlgItemText(hwnd, COMP_NOTE, GetPString(IDS_COMPREADYTEXT));
2436 }
2437 break;
2438
2439 case WM_INITMENU:
2440 cmp = INSTDATA(hwnd);
2441 if (cmp) {
2442 switch (SHORT1FROMMP(mp1)) {
2443 case IDM_COMMANDSMENU:
2444 SetupCommandMenu(cmp->dcd.hwndLastMenu, hwnd);
2445 break;
2446 }
2447 }
2448 break;
2449
2450 case WM_MENUEND:
2451 cmp = INSTDATA(hwnd);
2452 if (cmp) {
2453 if ((HWND)mp2 == cmp->dcd.hwndLastMenu) {
2454 MarkAll(hwndLeft, TRUE, FALSE, TRUE);
2455 MarkAll(hwndRight, TRUE, FALSE, TRUE);
2456 WinDestroyWindow(cmp->dcd.hwndLastMenu);
2457 cmp->dcd.hwndLastMenu = (HWND)0;
2458 }
2459 }
2460 break;
2461
2462 case WM_CONTROL:
2463 switch (SHORT1FROMMP(mp1)) {
2464 case COMP_INCLUDESUBDIRS:
2465 switch (SHORT2FROMMP(mp1)) {
2466 case BN_CLICKED:
2467 cmp = INSTDATA(hwnd);
2468 if (cmp)
2469 *cmp->rightlist = 0;
2470 PostMsg(hwnd, UM_SETUP, MPVOID, MPVOID);
2471 PostMsg(hwnd, UM_SETDIR, MPVOID, MPVOID);
2472 break;
2473 }
2474 break;
2475 case COMP_HIDENOTSELECTED:
2476 switch (SHORT2FROMMP(mp1)) {
2477 case BN_CLICKED:
2478 WinSendMsg(hwnd, UM_HIDENOTSELECTED, MPVOID, MPVOID);
2479 break;
2480 }
2481 break;
2482
2483 case COMP_LEFTDIR:
2484 case COMP_RIGHTDIR:
2485 switch (SHORT2FROMMP(mp1)) {
2486 case CN_KILLFOCUS:
2487 PaintRecessedWindow(WinWindowFromID(hwnd, SHORT1FROMMP(mp1)),
2488 (HPS)0, FALSE, TRUE);
2489 break;
2490
2491 case CN_SETFOCUS:
2492 PaintRecessedWindow(WinWindowFromID(hwnd, SHORT1FROMMP(mp1)),
2493 (HPS)0, TRUE, TRUE);
2494 break;
2495
2496 case CN_ENTER:
2497 if (mp2) {
2498
2499 PCNRITEM pci = (PCNRITEM)((PNOTIFYRECORDENTER)mp2)->pRecord;
2500 HWND hwndCnr = WinWindowFromID(hwnd, SHORT1FROMMP(mp1));
2501
2502 SetShiftState();
2503 if (pci) {
2504 if (pci->rc.flRecordAttr & CRA_INUSE || !pci || !*pci->pszFileName)
2505 break;
2506 WinSendMsg(hwndCnr, CM_SETRECORDEMPHASIS, MPFROMP(pci),
2507 MPFROM2SHORT(TRUE, CRA_INUSE));
2508 if (pci->attrFile & FILE_DIRECTORY) {
2509 if ((shiftstate & (KC_CTRL | KC_SHIFT)) == (KC_CTRL | KC_SHIFT))
2510 OpenObject(pci->pszFileName, Settings, hwnd);
2511 else
2512 OpenObject(pci->pszFileName, Default, hwnd);
2513 }
2514 else
2515 DefaultViewKeys(hwnd, hwnd, HWND_DESKTOP, NULL,
2516 pci->pszFileName);
2517 WinSendMsg(hwndCnr, CM_SETRECORDEMPHASIS,
2518 MPFROMP(pci),
2519 MPFROM2SHORT(FALSE,
2520 CRA_INUSE | (fUnHilite ? CRA_SELECTED : 0)));
2521 }
2522 }
2523 break;
2524
2525 case CN_CONTEXTMENU:
2526 cmp = INSTDATA(hwnd);
2527 if (cmp) {
2528 PCNRITEM pci = (PCNRITEM)mp2;
2529 USHORT id = COMP_CNRMENU;
2530
2531 if (cmp->dcd.hwndLastMenu)
2532 WinDestroyWindow(cmp->dcd.hwndLastMenu);
2533 cmp->dcd.hwndLastMenu = (HWND)0;
2534 cmp->hwndCalling = WinWindowFromID(hwnd, SHORT1FROMMP(mp1));
2535 if (pci) {
2536 if (!pci || !*pci->pszFileName || *cmp->rightlist)
2537 break;
2538 id = COMP_MENU;
2539 WinSendMsg(cmp->hwndCalling, CM_SETRECORDEMPHASIS,
2540 MPFROMP(pci), MPFROM2SHORT(TRUE, CRA_CURSORED));
2541 }
2542 cmp->dcd.hwndLastMenu = WinLoadMenu(HWND_DESKTOP, FM3ModHandle, id);
2543 if (cmp->dcd.hwndLastMenu) {
2544 if (id == COMP_CNRMENU) {
2545 if (SHORT1FROMMP(mp1) == COMP_RIGHTDIR)
2546 WinSendMsg(cmp->dcd.hwndLastMenu, MM_DELETEITEM,
2547 MPFROM2SHORT(IDM_SHOWSUBJECT, FALSE), MPVOID);
2548 SetDetailsSwitches(cmp->dcd.hwndLastMenu, &cmp->dcd);
2549 if (SHORT1FROMMP(mp1) == COMP_LEFTDIR)
2550 WinSendMsg(cmp->dcd.hwndLastMenu, MM_DELETEITEM,
2551 MPFROM2SHORT(IDM_LOADLISTFILE, 0), MPVOID);
2552 else if (*cmp->rightlist)
2553 WinSendMsg(cmp->dcd.hwndLastMenu, MM_DELETEITEM,
2554 MPFROM2SHORT(IDM_SAVELISTFILE, 0), MPVOID);
2555 }
2556 PopupMenu(hwnd, hwnd, cmp->dcd.hwndLastMenu);
2557 }
2558 }
2559 break;
2560
2561 case CN_INITDRAG:
2562 cmp = INSTDATA(hwnd);
2563 if (*cmp->rightlist && SHORT1FROMMP(mp1) == COMP_RIGHTDIR)
2564 break;
2565 DoFileDrag(WinWindowFromID(hwnd, SHORT1FROMMP(mp1)),
2566 (HWND)0, mp2, NULL, NULL, TRUE);
2567 break;
2568
2569 case CN_BEGINEDIT:
2570 case CN_REALLOCPSZ:
2571 // fixme to be gone - field edits not allowed?
2572 Runtime_Error(pszSrcFile, __LINE__,
2573 "CN_BEGINEDIT/CN_REALLOCPSZ unexpected");
2574 break;
2575
2576 case CN_EMPHASIS:
2577 {
2578 PNOTIFYRECORDEMPHASIS pnre = mp2;
2579 BOOL fSelected;
2580 if (pnre->fEmphasisMask & CRA_SELECTED) {
2581 // Select toggled
2582 PCNRITEM pci = (PCNRITEM)pnre->pRecord;
2583 if (pci) {
2584 if (!*pci->pszFileName) {
2585 // Slot empty
2586 // 17 Jan 08 SHL fixme to know how can get here
2587 // 12 Jan 08 SHL fixme to know if select counts need update?
2588 if (pci->rc.flRecordAttr & CRA_SELECTED)
2589 WinSendDlgItemMsg(hwnd, SHORT1FROMMP(mp1),
2590 CM_SETRECORDEMPHASIS,
2591 MPFROMP(pci),
2592 MPFROM2SHORT(FALSE, CRA_SELECTED));
2593 }
2594 else {
2595 BOOL fUpdateHideButton = FALSE;
2596 cmp = INSTDATA(hwnd);
2597 if (SHORT1FROMMP(mp1) == COMP_LEFTDIR) {
2598 fSelected = pci->rc.flRecordAttr & CRA_SELECTED;
2599 cmp->selleft += fSelected ? 1 : -1;
2600 if (!fSelected)
2601 fUpdateHideButton = TRUE;
2602 }
2603 else if (SHORT1FROMMP(mp1) == COMP_RIGHTDIR) {
2604 fSelected = pci->rc.flRecordAttr & CRA_SELECTED;
2605 cmp->selright += fSelected ? 1 : -1;
2606 if (!fSelected)
2607 fUpdateHideButton = TRUE;
2608 }
2609 else {
2610 Runtime_Error(pszSrcFile, __LINE__,
2611 "mp1 %u unexpected", SHORT1FROMMP(mp1));
2612 }
2613 if (fUpdateHideButton) {
2614 ULONG state = WinQueryButtonCheckstate(hwnd,COMP_HIDENOTSELECTED);
2615 if (state == 1) {
2616 WinCheckButton(hwnd, COMP_HIDENOTSELECTED, 2);
2617 }
2618 }
2619 }
2620 }
2621 }
2622 }
2623 break;
2624
2625 case CN_SCROLL:
2626 cmp = INSTDATA(hwnd);
2627 if (!cmp->forcescroll) {
2628
2629 PNOTIFYSCROLL pns = mp2;
2630
2631 if (pns->fScroll & CMA_VERTICAL) {
2632 cmp->forcescroll = TRUE;
2633 // Scroll other window to match
2634 WinSendDlgItemMsg(hwnd,
2635 SHORT1FROMMP(mp1) == COMP_LEFTDIR ?
2636 COMP_RIGHTDIR : COMP_LEFTDIR,
2637 CM_SCROLLWINDOW,
2638 MPFROMSHORT(CMA_VERTICAL),
2639 MPFROMLONG(pns->lScrollInc));
2640 cmp->forcescroll = FALSE;
2641 }
2642 }
2643 break;
2644 } // switch COMP_LEFTDIR mp1
2645 break; // COMP_LEFTDIR / COMP_RIGHTDIR
2646 } // switch WM_CONTROL mp1
2647 return 0; // WM_CONTROL
2648
2649 case UM_SETDIR:
2650 cmp = INSTDATA(hwnd);
2651 if (cmp) {
2652 COMPARE *forthread;
2653 CNRINFO cnri;
2654 cmp->includesubdirs = WinQueryButtonCheckstate(hwnd,
2655 COMP_INCLUDESUBDIRS);
2656 memset(&cnri, 0, sizeof(CNRINFO));
2657 cnri.cb = sizeof(CNRINFO);
2658 cnri.pszCnrTitle = cmp->leftdir;
2659 cnri.flWindowAttr = CV_DETAIL | CV_MINI |
2660 CA_CONTAINERTITLE | CA_TITLESEPARATOR |
2661 CA_DETAILSVIEWTITLES | CA_OWNERDRAW;
2662 WinSendDlgItemMsg(hwnd, COMP_LEFTDIR, CM_SETCNRINFO, MPFROMP(&cnri),
2663 MPFROMLONG(CMA_CNRTITLE | CMA_FLWINDOWATTR));
2664 cnri.pszCnrTitle = cmp->rightdir;
2665 WinSendDlgItemMsg(hwnd, COMP_RIGHTDIR, CM_SETCNRINFO, MPFROMP(&cnri),
2666 MPFROMLONG(CMA_CNRTITLE | CMA_FLWINDOWATTR));
2667 WinCheckButton(hwnd, COMP_HIDENOTSELECTED, 0);
2668 cmp->filling = TRUE;
2669# ifdef FORTIFY
2670 Fortify_EnterScope();
2671# endif
2672 forthread = xmalloc(sizeof(COMPARE), pszSrcFile, __LINE__);
2673 if (!forthread)
2674 WinDismissDlg(hwnd, 0);
2675 else {
2676 *forthread = *cmp;
2677 forthread->cmp = cmp;
2678 if (_beginthread(FillCnrsThread, NULL, 122880, (PVOID)forthread) ==
2679 -1) {
2680 Runtime_Error(pszSrcFile, __LINE__,
2681 GetPString(IDS_COULDNTSTARTTHREADTEXT));
2682 WinDismissDlg(hwnd, 0);
2683 xfree(forthread, pszSrcFile, __LINE__);
2684# ifdef FORTIFY
2685 Fortify_LeaveScope();
2686# endif
2687 }
2688 else {
2689 WinEnableWindowUpdate(hwndLeft, FALSE);
2690 WinEnableWindowUpdate(hwndRight, FALSE);
2691 cmp->selleft = cmp->selright = 0;
2692 WinSetDlgItemText(hwnd, COMP_NOTE,
2693 GetPString(IDS_COMPHOLDREADDISKTEXT));
2694 WinEnableWindow(hwndRight, FALSE);
2695 WinEnableWindow(hwndLeft, FALSE);
2696 WinEnableWindow(WinWindowFromID(hwnd, DID_OK), FALSE);
2697 WinEnableWindow(WinWindowFromID(hwnd, DID_CANCEL), FALSE);
2698 WinEnableWindow(WinWindowFromID(hwnd, COMP_COLLECT), FALSE);
2699 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTBOTH), FALSE);
2700 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTONE), FALSE);
2701 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTNEWER), FALSE);
2702 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTOLDER), FALSE);
2703 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTBIGGER), FALSE);
2704 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTSMALLER), FALSE);
2705 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTBOTH), FALSE);
2706 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTONE), FALSE);
2707 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTNEWER), FALSE);
2708 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTOLDER), FALSE);
2709 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTBIGGER), FALSE);
2710 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTSMALLER), FALSE);
2711 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTALL), FALSE);
2712 WinEnableWindow(WinWindowFromID(hwnd, COMP_SETDIRS), FALSE);
2713 WinEnableWindow(WinWindowFromID(hwnd, COMP_DELETELEFT), FALSE);
2714 WinEnableWindow(WinWindowFromID(hwnd, COMP_DELETERIGHT), FALSE);
2715 WinEnableWindow(WinWindowFromID(hwnd, COMP_COPYLEFT), FALSE);
2716 WinEnableWindow(WinWindowFromID(hwnd, COMP_MOVELEFT), FALSE);
2717 WinEnableWindow(WinWindowFromID(hwnd, COMP_COPYRIGHT), FALSE);
2718 WinEnableWindow(WinWindowFromID(hwnd, COMP_MOVERIGHT), FALSE);
2719 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTSAMECONTENT), FALSE);
2720 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTIDENTICAL), FALSE);
2721 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTSAME), FALSE);
2722 WinEnableWindow(WinWindowFromID(hwnd, IDM_INVERT), FALSE);
2723 WinEnableWindow(WinWindowFromID(hwnd, COMP_FILTER), FALSE);
2724 WinEnableWindow(WinWindowFromID(hwnd, COMP_INCLUDESUBDIRS), FALSE);
2725 WinEnableWindow(WinWindowFromID(hwnd, COMP_HIDENOTSELECTED), FALSE);
2726 }
2727 }
2728 }
2729 return 0;
2730
2731 case UM_FILTER:
2732 cmp = INSTDATA(hwnd);
2733 if (cmp) {
2734 if (mp1) {
2735 DosEnterCritSec();
2736 SetMask((CHAR *)mp1, &cmp->dcd.mask);
2737 DosExitCritSec();
2738 }
2739 WinSetDlgItemText(hwnd, COMP_NOTE,
2740 GetPString(IDS_COMPHOLDFILTERINGTEXT));
2741 // cmp->dcd.suspendview = 1; // 12 Jan 08 SHL appears not to be used here
2742 priority_idle(); // Don't hog resources
2743 WinSendMsg(hwndLeft, CM_FILTER, MPFROMP(Filter),
2744 MPFROMP(&cmp->dcd.mask));
2745 WinSendMsg(hwndRight, CM_FILTER, MPFROMP(Filter),
2746 MPFROMP(&cmp->dcd.mask));
2747 priority_normal();
2748 // cmp->dcd.suspendview = 0; // 12 Jan 08 SHL appears not to be used here
2749 if (*cmp->dcd.mask.szMask) {
2750 sprintf(s,
2751 GetPString(IDS_COMPREADYFILTEREDTEXT),
2752 cmp->dcd.mask.szMask);
2753 WinSetDlgItemText(hwnd, COMP_NOTE, s);
2754 }
2755 else
2756 WinSetDlgItemText(hwnd, COMP_NOTE, GetPString(IDS_COMPREADYTEXT));
2757 }
2758 return 0;
2759
2760 case UM_HIDENOTSELECTED:
2761 cmp = INSTDATA(hwnd);
2762 if (cmp) {
2763 ULONG wasHidden = WinQueryButtonCheckstate(hwnd,
2764 COMP_HIDENOTSELECTED);
2765
2766 // cmp->dcd.suspendview = 1; // 12 Jan 08 SHL appears not to be used here
2767 if (wasHidden != 1) {
2768 // Hide if not selected on both sides
2769 BOOL needRefresh = FALSE;
2770 HWND hwndl = WinWindowFromID(cmp->hwnd, COMP_LEFTDIR);
2771 HWND hwndr = WinWindowFromID(cmp->hwnd, COMP_RIGHTDIR);
2772 PCNRITEM pcil = WinSendMsg(hwndl, CM_QUERYRECORD, MPVOID,
2773 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
2774 PCNRITEM pcir = WinSendMsg(hwndr, CM_QUERYRECORD, MPVOID,
2775 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
2776
2777 while (pcil && (INT)pcil != -1 && pcir && (INT)pcir != -1) {
2778 if (~pcil->rc.flRecordAttr & CRA_SELECTED &&
2779 ~pcir->rc.flRecordAttr & CRA_SELECTED) {
2780 // 17 Jan 08 SHL fixme to optimize refresh
2781 pcil->rc.flRecordAttr |= CRA_FILTERED;
2782 pcir->rc.flRecordAttr |= CRA_FILTERED;
2783 needRefresh = TRUE;
2784 }
2785 pcil = WinSendMsg(hwndl, CM_QUERYRECORD, MPFROMP(pcil),
2786 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
2787 pcir = WinSendMsg(hwndr, CM_QUERYRECORD, MPFROMP(pcir),
2788 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
2789 } // while
2790 if (needRefresh) {
2791 WinSendMsg(hwndl, CM_INVALIDATERECORD,
2792 MPVOID, MPFROM2SHORT(0, CMA_REPOSITION));
2793 WinSendMsg(hwndr, CM_INVALIDATERECORD,
2794 MPVOID, MPFROM2SHORT(0, CMA_REPOSITION));
2795 }
2796 }
2797 else {
2798 // Unhide
2799 WinSendMsg(hwndLeft, CM_FILTER, MPFROMP(Filter),
2800 MPFROMP(&cmp->dcd.mask));
2801 WinSendMsg(hwndRight, CM_FILTER, MPFROMP(Filter),
2802 MPFROMP(&cmp->dcd.mask));
2803 }
2804 // cmp->dcd.suspendview = 0; // 12 Jan 08 SHL appears not to be used here
2805 if (*cmp->dcd.mask.szMask) {
2806 sprintf(s,
2807 GetPString(IDS_COMPREADYFILTEREDTEXT),
2808 cmp->dcd.mask.szMask);
2809 WinSetDlgItemText(hwnd, COMP_NOTE, s);
2810 }
2811 else
2812 WinSetDlgItemText(hwnd, COMP_NOTE, GetPString(IDS_COMPREADYTEXT));
2813 WinCheckButton(hwnd, COMP_HIDENOTSELECTED, wasHidden != 1 ? 1 : 0);
2814 }
2815 return 0;
2816
2817 case WM_COMMAND:
2818 switch (SHORT1FROMMP(mp1)) {
2819 case IDM_COMPARE:
2820 cmp = INSTDATA(hwnd);
2821 if (cmp) {
2822 PCNRITEM pci;
2823 CHAR ofile[CCHMAXPATH];
2824
2825 pci = (PCNRITEM)WinSendMsg(cmp->hwndCalling,
2826 CM_QUERYRECORDEMPHASIS,
2827 MPFROMLONG(CMA_FIRST),
2828 MPFROMSHORT(CRA_CURSORED));
2829 // 01 Aug 07 SHL
2830 if (pci && *pci->pszFileName) {
2831 if (cmp->hwndCalling == hwndLeft)
2832 strcpy(ofile, cmp->rightdir);
2833 else
2834 strcpy(ofile, cmp->leftdir);
2835 if (ofile[strlen(ofile) - 1] != '\\')
2836 strcat(ofile, "\\");
2837 strcat(ofile, pci->pszDisplayName);
2838 if (*compare) {
2839 CHAR *fakelist[3];
2840 fakelist[0] = pci->pszFileName;
2841 fakelist[1] = ofile;
2842 fakelist[2] = NULL;
2843 ExecOnList(hwnd, compare,
2844 WINDOWED | SEPARATEKEEP, NULL, fakelist, NULL,
2845 pszSrcFile, __LINE__);
2846 }
2847 else {
2848 FCOMPARE fc;
2849 memset(&fc, 0, sizeof(fc));
2850 fc.size = sizeof(fc);
2851 fc.hwndParent = hwnd;
2852 strcpy(fc.file1, pci->pszFileName);
2853 strcpy(fc.file2, ofile);
2854 WinDlgBox(HWND_DESKTOP, hwnd,
2855 CFileDlgProc, FM3ModHandle, FCMP_FRAME, (PVOID)&fc);
2856 }
2857 }
2858 }
2859 break;
2860
2861 case COMP_FILTER:
2862 case IDM_FILTER:
2863 cmp = INSTDATA(hwnd);
2864 if (cmp) {
2865 BOOL empty = FALSE;
2866 PCNRITEM pci;
2867 CHAR *p;
2868 BOOL temp;
2869
2870 if (!*cmp->dcd.mask.szMask) {
2871 empty = TRUE;
2872 temp = fSelectedAlways;
2873 fSelectedAlways = TRUE;
2874 pci = (PCNRITEM)CurrentRecord(hwnd);
2875 fSelectedAlways = temp;
2876 // 01 Aug 07 SHL
2877 if (pci && ~pci->attrFile & FILE_DIRECTORY) {
2878 p = strrchr(pci->pszFileName, '\\');
2879 if (p) {
2880 p++;
2881 strcpy(cmp->dcd.mask.szMask, p);
2882 }
2883 }
2884 }
2885 cmp->dcd.mask.fNoAttribs = TRUE;
2886 cmp->dcd.mask.attrFile = ALLATTRS;
2887 cmp->dcd.mask.antiattr = 0;
2888 if (WinDlgBox(HWND_DESKTOP, hwnd, PickMaskDlgProc,
2889 FM3ModHandle, MSK_FRAME, MPFROMP(&cmp->dcd.mask))) {
2890 cmp->dcd.mask.attrFile = ALLATTRS;
2891 cmp->dcd.mask.antiattr = 0;
2892 WinSendMsg(hwnd, UM_FILTER, MPVOID, MPVOID);
2893 }
2894 else if (empty) {
2895 *cmp->dcd.mask.szMask = 0;
2896 cmp->dcd.mask.attrFile = ALLATTRS;
2897 cmp->dcd.mask.antiattr = 0;
2898 }
2899 }
2900 break;
2901
2902 case IDM_SHOWSUBJECT:
2903 case IDM_SHOWEAS:
2904 case IDM_SHOWSIZE:
2905 case IDM_SHOWLWDATE:
2906 case IDM_SHOWLWTIME:
2907 case IDM_SHOWLADATE:
2908 case IDM_SHOWLATIME:
2909 case IDM_SHOWCRDATE:
2910 case IDM_SHOWCRTIME:
2911 case IDM_SHOWATTR:
2912 cmp = INSTDATA(hwnd);
2913 if (cmp) {
2914 DIRCNRDATA dcd1;
2915 BOOL tempsubj;
2916
2917 dcd1 = cmp->dcd;
2918 AdjustDetailsSwitches(hwndLeft,
2919 (HWND)0, SHORT1FROMMP(mp1),
2920 cmp->leftdir, "DirCmp", &cmp->dcd, TRUE);
2921 tempsubj = cmp->dcd.detailssubject;
2922 cmp->dcd = dcd1;
2923 cmp->dcd.detailssubject = FALSE;
2924 AdjustDetailsSwitches(hwndRight,
2925 cmp->dcd.hwndLastMenu, SHORT1FROMMP(mp1),
2926 cmp->rightdir, "DirCmp", &cmp->dcd, TRUE);
2927 cmp->dcd.detailssubject = tempsubj;
2928 }
2929 break;
2930
2931 case IDM_LOADLISTFILE:
2932 cmp = INSTDATA(hwnd);
2933 if (cmp) {
2934 CHAR fullname[CCHMAXPATH];
2935
2936 strcpy(fullname, "*.PMD");
2937 if (insert_filename(HWND_DESKTOP, fullname, TRUE, FALSE) &&
2938 *fullname && !strchr(fullname, '*') && !strchr(fullname, '?')) {
2939 strcpy(cmp->rightlist, fullname);
2940 PostMsg(hwnd, UM_SETUP, MPVOID, MPVOID);
2941 PostMsg(hwnd, UM_SETDIR, MPVOID, MPVOID);
2942 }
2943 }
2944 break;
2945
2946 case IDM_SAVELISTFILE:
2947 cmp = INSTDATA(hwnd);
2948 if (cmp) {
2949 SNAPSTUFF *sf;
2950 CHAR fullname[CCHMAXPATH];
2951
2952 strcpy(fullname, "*.PMD");
2953 if (export_filename(HWND_DESKTOP, fullname, 1) && *fullname &&
2954 !strchr(fullname, '*') && !strchr(fullname, '?')) {
2955 sf = xmallocz(sizeof(SNAPSTUFF), pszSrcFile, __LINE__);
2956 if (sf) {
2957 strcpy(sf->filename, fullname);
2958 if (hwndLeft == cmp->hwndCalling)
2959 strcpy(sf->dirname, cmp->leftdir);
2960 else
2961 strcpy(sf->dirname, cmp->rightdir);
2962 sf->recurse = cmp->includesubdirs;
2963 if (_beginthread(StartSnap, NULL, 65536, (PVOID)sf) == -1) {
2964 Runtime_Error(pszSrcFile, __LINE__,
2965 GetPString(IDS_COULDNTSTARTTHREADTEXT));
2966 xfree(sf, pszSrcFile, __LINE__);
2967 }
2968 }
2969 }
2970 }
2971 break;
2972
2973 case COMP_SETDIRS:
2974 cmp = INSTDATA(hwnd);
2975 if (cmp) {
2976 WALK2 wa;
2977 memset(&wa, 0, sizeof(wa));
2978 wa.size = sizeof(wa);
2979 strcpy(wa.szCurrentPath1, cmp->leftdir);
2980 strcpy(wa.szCurrentPath2, cmp->rightdir);
2981 if (WinDlgBox(HWND_DESKTOP,
2982 hwnd,
2983 WalkTwoCmpDlgProc,
2984 FM3ModHandle,
2985 WALK2_FRAME,
2986 MPFROMP(&wa)) &&
2987 !IsFile(wa.szCurrentPath1) &&
2988 !IsFile(wa.szCurrentPath2)) {
2989 strcpy(cmp->leftdir, wa.szCurrentPath1);
2990 strcpy(cmp->rightdir, wa.szCurrentPath2);
2991 *cmp->rightlist = 0;
2992 PostMsg(hwnd, UM_SETUP, MPVOID, MPVOID);
2993 PostMsg(hwnd, UM_SETDIR, MPVOID, MPVOID);
2994 }
2995 }
2996 break;
2997
2998 case COMP_COPYLEFT:
2999 case COMP_MOVELEFT:
3000 case COMP_COPYRIGHT:
3001 case COMP_MOVERIGHT:
3002 case COMP_DELETELEFT:
3003 case COMP_DELETERIGHT:
3004 cmp = INSTDATA(hwnd);
3005 if (cmp) {
3006 COMPARE *forthread;
3007
3008 cmp->filling = TRUE;
3009 forthread = xmalloc(sizeof(COMPARE), pszSrcFile, __LINE__);
3010 if (forthread) {
3011 *forthread = *cmp;
3012 forthread->cmp = cmp;
3013 forthread->action = SHORT1FROMMP(mp1);
3014 if (_beginthread(ActionCnrThread, NULL, 122880, (PVOID)forthread)
3015 == -1) {
3016 Runtime_Error(pszSrcFile, __LINE__,
3017 GetPString(IDS_COULDNTSTARTTHREADTEXT));
3018 xfree(forthread, pszSrcFile, __LINE__);
3019 }
3020 else {
3021 WinEnableWindowUpdate(hwndLeft, FALSE);
3022 WinEnableWindowUpdate(hwndRight, FALSE);
3023 switch (SHORT1FROMMP(mp1)) {
3024 case COMP_DELETELEFT:
3025 case COMP_DELETERIGHT:
3026 WinSetDlgItemText(hwnd, COMP_NOTE,
3027 GetPString(IDS_COMPHOLDDELETINGTEXT));
3028 break;
3029 case COMP_MOVELEFT:
3030 case COMP_MOVERIGHT:
3031 WinSetDlgItemText(hwnd, COMP_NOTE,
3032 GetPString(IDS_COMPHOLDMOVINGTEXT));
3033 break;
3034 case COMP_COPYLEFT:
3035 case COMP_COPYRIGHT:
3036 WinSetDlgItemText(hwnd, COMP_NOTE,
3037 GetPString(IDS_COMPHOLDCOPYINGTEXT));
3038 break;
3039 default:
3040 Runtime_Error(pszSrcFile, __LINE__, "mp1 %u unexpected", SHORT1FROMMP(mp1));
3041 }
3042 WinEnableWindow(hwndRight, FALSE);
3043 WinEnableWindow(hwndLeft, FALSE);
3044 WinEnableWindow(WinWindowFromID(hwnd, DID_OK), FALSE);
3045 WinEnableWindow(WinWindowFromID(hwnd, DID_CANCEL), FALSE);
3046 WinEnableWindow(WinWindowFromID(hwnd, COMP_COLLECT), FALSE);
3047 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTBOTH), FALSE);
3048 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTONE), FALSE);
3049 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTNEWER), FALSE);
3050 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTOLDER), FALSE);
3051 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTBIGGER), FALSE);
3052 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTSMALLER), FALSE);
3053 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTBOTH), FALSE);
3054 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTONE), FALSE);
3055 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTNEWER), FALSE);
3056 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTOLDER), FALSE);
3057 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTBIGGER), FALSE);
3058 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTSMALLER), FALSE);
3059 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTALL), FALSE);
3060 WinEnableWindow(WinWindowFromID(hwnd, COMP_SETDIRS), FALSE);
3061 WinEnableWindow(WinWindowFromID(hwnd, COMP_DELETELEFT), FALSE);
3062 WinEnableWindow(WinWindowFromID(hwnd, COMP_DELETERIGHT), FALSE);
3063 WinEnableWindow(WinWindowFromID(hwnd, COMP_COPYLEFT), FALSE);
3064 WinEnableWindow(WinWindowFromID(hwnd, COMP_MOVELEFT), FALSE);
3065 WinEnableWindow(WinWindowFromID(hwnd, COMP_COPYRIGHT), FALSE);
3066 WinEnableWindow(WinWindowFromID(hwnd, COMP_MOVERIGHT), FALSE);
3067 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTSAMECONTENT), FALSE);
3068 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTIDENTICAL), FALSE);
3069 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTSAME), FALSE);
3070 WinEnableWindow(WinWindowFromID(hwnd, IDM_INVERT), FALSE);
3071 WinEnableWindow(WinWindowFromID(hwnd, COMP_FILTER), FALSE);
3072 WinEnableWindow(WinWindowFromID(hwnd, COMP_INCLUDESUBDIRS), FALSE);
3073 WinEnableWindow(WinWindowFromID(hwnd, COMP_HIDENOTSELECTED), FALSE);
3074 }
3075 }
3076 }
3077 break;
3078
3079 case DID_OK:
3080 {
3081 SWP swp;
3082 ULONG size = sizeof(SWP);
3083
3084 WinQueryWindowPos(hwnd, &swp);
3085 PrfWriteProfileData(fmprof, FM3Str, "CompDir.Position", (PVOID) &swp,
3086 size);
3087 }
3088 WinDismissDlg(hwnd, 0);
3089 break;
3090 case DID_CANCEL:
3091 {
3092 SWP swp;
3093 ULONG size = sizeof(SWP);
3094
3095 WinQueryWindowPos(hwnd, &swp);
3096 PrfWriteProfileData(fmprof, FM3Str, "CompDir.Position", (PVOID) &swp,
3097 size);
3098 }
3099 WinDismissDlg(hwnd, 1);
3100 break;
3101
3102 case IDM_HELP:
3103 if (hwndHelp)
3104 WinSendMsg(hwndHelp, HM_DISPLAY_HELP,
3105 MPFROM2SHORT(HELP_COMPARE, 0), MPFROMSHORT(HM_RESOURCEID));
3106 break;
3107
3108 case IDM_DESELECTALL:
3109 case IDM_SELECTNEWER:
3110 case IDM_SELECTOLDER:
3111 case IDM_SELECTBIGGER:
3112 case IDM_SELECTSMALLER:
3113 case IDM_DESELECTNEWER:
3114 case IDM_DESELECTOLDER:
3115 case IDM_DESELECTBIGGER:
3116 case IDM_DESELECTSMALLER:
3117 case IDM_DESELECTONE:
3118 case IDM_DESELECTBOTH:
3119 case IDM_SELECTBOTH:
3120 case IDM_SELECTONE:
3121 case IDM_SELECTSAMECONTENT:
3122 case IDM_SELECTIDENTICAL: // Name, size and time
3123 case IDM_SELECTSAME: // Name and size
3124 case IDM_INVERT:
3125 cmp = INSTDATA(hwnd);
3126 if (!cmp)
3127 Runtime_Error2(pszSrcFile, __LINE__, IDS_NODATATEXT);
3128 else {
3129 COMPARE *forthread;
3130
3131 cmp->filling = TRUE;
3132 forthread = xmalloc(sizeof(COMPARE), pszSrcFile, __LINE__);
3133 if (forthread) {
3134 *forthread = *cmp;
3135 forthread->cmp = cmp;
3136 forthread->action = SHORT1FROMMP(mp1);
3137 if (_beginthread(SelectCnrsThread, NULL, 65536, (PVOID)forthread)
3138 == -1) {
3139 Runtime_Error(pszSrcFile, __LINE__,
3140 GetPString(IDS_COULDNTSTARTTHREADTEXT));
3141 xfree(forthread, pszSrcFile, __LINE__);
3142 }
3143 else {
3144 WinEnableWindowUpdate(hwndLeft, FALSE);
3145 WinEnableWindowUpdate(hwndRight, FALSE);
3146 switch (SHORT1FROMMP(mp1)) {
3147 case IDM_DESELECTALL:
3148 case IDM_DESELECTNEWER:
3149 case IDM_DESELECTOLDER:
3150 case IDM_DESELECTBIGGER:
3151 case IDM_DESELECTSMALLER:
3152 case IDM_DESELECTONE:
3153 case IDM_DESELECTBOTH:
3154 WinSetDlgItemText(hwnd, COMP_NOTE,
3155 GetPString(IDS_COMPHOLDDESELTEXT));
3156 break;
3157 case IDM_INVERT:
3158 WinSetDlgItemText(hwnd, COMP_NOTE,
3159 GetPString(IDS_COMPHOLDINVERTTEXT));
3160 break;
3161 default:
3162 WinSetDlgItemText(hwnd, COMP_NOTE,
3163 GetPString(IDS_COMPHOLDSELTEXT));
3164 break;
3165 }
3166 WinEnableWindow(hwndRight, FALSE);
3167 WinEnableWindow(hwndLeft, FALSE);
3168 WinEnableWindow(WinWindowFromID(hwnd, DID_OK), FALSE);
3169 WinEnableWindow(WinWindowFromID(hwnd, DID_CANCEL), FALSE);
3170 WinEnableWindow(WinWindowFromID(hwnd, COMP_COLLECT), FALSE);
3171 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTBOTH), FALSE);
3172 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTONE), FALSE);
3173 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTNEWER), FALSE);
3174 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTOLDER), FALSE);
3175 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTBIGGER), FALSE);
3176 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTSMALLER), FALSE);
3177 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTBOTH), FALSE);
3178 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTONE), FALSE);
3179 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTNEWER), FALSE);
3180 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTOLDER), FALSE);
3181 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTBIGGER), FALSE);
3182 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTSMALLER), FALSE);
3183 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTALL), FALSE);
3184 WinEnableWindow(WinWindowFromID(hwnd, COMP_INCLUDESUBDIRS), FALSE);
3185 WinEnableWindow(WinWindowFromID(hwnd, COMP_HIDENOTSELECTED), FALSE);
3186 WinEnableWindow(WinWindowFromID(hwnd, COMP_SETDIRS), FALSE);
3187 WinEnableWindow(WinWindowFromID(hwnd, COMP_DELETELEFT), FALSE);
3188 WinEnableWindow(WinWindowFromID(hwnd, COMP_DELETERIGHT), FALSE);
3189 WinEnableWindow(WinWindowFromID(hwnd, COMP_COPYLEFT), FALSE);
3190 WinEnableWindow(WinWindowFromID(hwnd, COMP_MOVELEFT), FALSE);
3191 WinEnableWindow(WinWindowFromID(hwnd, COMP_COPYRIGHT), FALSE);
3192 WinEnableWindow(WinWindowFromID(hwnd, COMP_MOVERIGHT), FALSE);
3193 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTSAMECONTENT), FALSE);
3194 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTIDENTICAL), FALSE);
3195 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTSAME), FALSE);
3196 WinEnableWindow(WinWindowFromID(hwnd, IDM_INVERT), FALSE);
3197 WinEnableWindow(WinWindowFromID(hwnd, COMP_FILTER), FALSE);
3198 }
3199 }
3200 }
3201 break;
3202
3203 case COMP_COLLECT:
3204 cmp = INSTDATA(hwnd);
3205 if (!cmp)
3206 Runtime_Error2(pszSrcFile, __LINE__, IDS_NODATATEXT);
3207 else {
3208 CHAR **listl;
3209 CHAR **listr = NULL;
3210 if (!Collector) {
3211 SWP swp;
3212 HWND hwndC;
3213 if (!fAutoTile &&
3214 !ParentIsDesktop(hwnd, cmp->hwndParent) &&
3215 !fExternalCollector &&
3216 !strcmp(realappname, FM3Str)) {
3217 GetNextWindowPos(cmp->hwndParent, &swp, NULL, NULL);
3218 }
3219 hwndC = StartCollector(fExternalCollector ||
3220 strcmp(realappname, FM3Str) ?
3221 HWND_DESKTOP :
3222 cmp->hwndParent,
3223 4);
3224 if (hwndC) {
3225 if (!fAutoTile &&
3226 !ParentIsDesktop(hwnd, cmp->hwndParent) &&
3227 !fExternalCollector &&
3228 !strcmp(realappname, FM3Str)) {
3229 WinSetWindowPos(hwndC, HWND_TOP,
3230 swp.x, swp.y, swp.cx, swp.cy,
3231 SWP_MOVE | SWP_SIZE | SWP_SHOW | SWP_ZORDER);
3232 }
3233 else if (!ParentIsDesktop(hwnd, cmp->hwndParent) &&
3234 fAutoTile &&
3235 !strcmp(realappname, FM3Str)) {
3236 TileChildren(cmp->hwndParent, TRUE);
3237 }
3238 DosSleep(1); // 12 Jan 08 SHL Let screen update
3239 PostMsg(hwnd, WM_COMMAND, MPFROM2SHORT(COMP_COLLECT, 0), MPVOID);
3240 break;
3241 }
3242 }
3243 else
3244 StartCollector(cmp->hwndParent, 4);
3245
3246 temp = fSelectedAlways;
3247 fSelectedAlways = TRUE;
3248 listl = BuildList(hwndLeft);
3249 if (!*cmp->rightlist)
3250 listr = BuildList(hwndRight);
3251 fSelectedAlways = temp;
3252
3253 if (listl || listr) {
3254 if (Collector) {
3255 // 07 Aug 07 SHL Avoid collected from empty list
3256 if (listl && listl[0] && *listl[0]) {
3257 if (PostMsg(Collector, WM_COMMAND,
3258 MPFROM2SHORT(IDM_COLLECTOR, 0), MPFROMP(listl)))
3259 listl = NULL; // Collector will free
3260 }
3261 if (listr && listr[0] && *listr[0]) {
3262 if (PostMsg(Collector, WM_COMMAND,
3263 MPFROM2SHORT(IDM_COLLECTOR, 0), MPFROMP(listr)))
3264 listr = NULL; // Collector will free
3265 }
3266 WinSetWindowPos(WinQueryWindow(WinQueryWindow(Collector,
3267 QW_PARENT),
3268 QW_PARENT),
3269 HWND_TOP, 0, 0, 0, 0,
3270 SWP_ACTIVATE);
3271 }
3272 FreeList(listl);
3273 FreeList(listr);
3274 }
3275 }
3276 break;
3277 }
3278 return 0;
3279
3280 case WM_CLOSE:
3281 // 18 Jan 08 SHL fixme to hold off if thread busy?
3282 WinDismissDlg(hwnd, 0);
3283 return 0;
3284
3285 case WM_DESTROY:
3286 cmp = INSTDATA(hwnd);
3287 if (cmp) {
3288 // 17 Jan 08 SHL fixme to know if stop really needed?
3289 WinStopTimer(WinQueryAnchorBlock(hwnd), hwnd, ID_TIMER);
3290 if (cmp->dcd.hwndLastMenu)
3291 WinDestroyWindow(cmp->dcd.hwndLastMenu);
3292 if (cmp->dcd.hwndObject) {
3293 WinSetWindowPtr(cmp->dcd.hwndObject, QWL_USER, (PVOID)NULL);
3294 if (!PostMsg(cmp->dcd.hwndObject, WM_CLOSE, MPVOID, MPVOID))
3295 WinSendMsg(cmp->dcd.hwndObject, WM_CLOSE, MPVOID, MPVOID);
3296 }
3297 xfree(cmp, pszSrcFile, __LINE__);
3298 }
3299 EmptyCnr(hwndLeft);
3300 EmptyCnr(hwndRight);
3301 DosPostEventSem(CompactSem);
3302 break;
3303 }
3304 return WinDefDlgProc(hwnd, msg, mp1, mp2);
3305}
3306
3307#pragma alloc_text(COMPAREDIR,FillCnrsThread,FillDirList,CompNames,BldFullPathName)
3308#pragma alloc_text(COMPAREDIR1,CompareDlgProc)
3309#pragma alloc_text(COMPAREDIR2,SelectCnrsThread,ActionCnrThread)
3310#pragma alloc_text(COMPAREFILE,CFileDlgProc,CompareFilesThread)
3311#pragma alloc_text(SNAPSHOT,SnapShot,StartSnap)
3312#pragma alloc_text(COMPSELECT,CompSelect)
3313
Note: See TracBrowser for help on using the repository browser.