source: trunk/dll/comp.c@ 1157

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

Ticket 187: Draft 1: Functions only

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