source: trunk/dll/comp.c

Last change on this file was 1915, checked in by Gregg Young, 7 days ago

Improve readability of insert_filename (use 0,1,2 instead of FALSE, TRUE,2 for loadit). Fix it so pszIDrive is only set from lastfilename if filename is NULL.

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