source: trunk/dll/comp.c@ 1000

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

Prevent trap and provide error message when file names that exceed maxpath are encountered (ticket 223)

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