source: trunk/dll/comp.c@ 1179

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

Ticket 187: Draft 2: Move remaining function declarations

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