source: trunk/dll/comp.c@ 1877

Last change on this file since 1877 was 1877, checked in by Gregg Young, 10 years ago

Remove debug code

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