source: trunk/dll/comp.c@ 1681

Last change on this file since 1681 was 1681, checked in by Gregg Young, 13 years ago

Fix snapshot file to actually load and save (with/without subdirectories) properly. Toggle of include subdirectories leaves snapshot file loaded. Added an indicator (textbox) that a list (snapshot) file is loaded. Ticket 490

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