source: trunk/dll/comp.c@ 1065

Last change on this file since 1065 was 1065, checked in by John Small, 17 years ago

Ticket 230: Simplified code and eliminated some local variables by incorporating
all the details view settings (both the global variables and those in the
DIRCNRDATA struct) into a new struct: DETAILS_SETTINGS.

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