source: trunk/dll/comp.c@ 1205

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

Ticket 187: Move datadevlarations/definitions out of fm3dll.h

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