source: trunk/dll/comp.c@ 1354

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

Added driveflags to over ride write verify for USB removable drives that fail when it is on (Ticket 323); A flag to prevent directory name from being broadcast to drives in the tree cnr prior to a recursive scan of the drive (causes dbl directory names Ticket 321) Add option for multithreaded recursive scan of user selected drives at startup (Ticket 322).

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