source: trunk/dll/comp.c@ 1444

Last change on this file since 1444 was 1444, checked in by Gregg Young, 16 years ago

Rework of drivebar to rescan all drives and refresh media buttons and menu items grey out inappropriate menu items. Streamline Tree scan code and use semaphores to serialize access. Add NOEASUPPORT and LOCALHD driveflag; .LONGNAME usage fixes; (Tickets 377-386)

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