source: trunk/dll/comp.c@ 1175

Last change on this file since 1175 was 1175, checked in by Steven Levine, 17 years ago

Avoid aliased pszLongName pointer in ActionCnrThread IDM_MOVE

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