source: trunk/dll/comp.c@ 1029

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

Fixed early memory free; Added free_... functions to make fortify checking easier; Added fortify scopes; Delete now moves to trash can on systems with the xworkplace trash can installed.

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