source: trunk/dll/comp.c@ 1878

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

Remove some dead code and comments source files starting with A-D

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 104.2 KB
Line 
1
2/***********************************************************************
3
4 $Id: comp.c 1878 2015-10-11 22:24:39Z 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 FILELIST **filesl = NULL;
1628 FILELIST **filesr = NULL;
1629 UINT numallocl = 0;
1630 UINT numallocr = 0;
1631 UINT lenl; // Directory prefix length
1632 UINT lenr;
1633 ULONG ulRecsNeeded;
1634 CHAR *pch;
1635 HWND hwndLeft;
1636 HWND hwndRight;
1637
1638 WinCancelShutdown(hmq, TRUE);
1639 IncrThreadUsage();
1640
1641 hwndLeft = GetHwndLeft(cmp->hwnd);
1642 hwndRight = GetHwndRight(cmp->hwnd);
1643 lenl = strlen(cmp->leftdir);
1644 if (cmp->leftdir[strlen(cmp->leftdir) - 1] != '\\')
1645 lenl++;
1646 lenr = strlen(cmp->rightdir);
1647 if (cmp->rightdir[strlen(cmp->rightdir) - 1] != '\\')
1648 lenr++;
1649 priority_normal();
1650 // Clear containers
1651 RemoveCnrItems(hwndRight, NULL, 0, CMA_FREE | CMA_INVALIDATE);
1652 RemoveCnrItems(hwndLeft, NULL, 0, CMA_FREE | CMA_INVALIDATE);
1653 cmp->cmp->totalleft = 0;
1654 cmp->cmp->totalright = 0;
1655
1656 // Build list of all files in left directory
1657 if (fForceLower)
1658 strlwr(cmp->leftdir);
1659 else if (fForceUpper)
1660 strupr(cmp->leftdir);
1661 FillDirList(cmp->leftdir, lenl, cmp->includesubdirs,
1662 &filesl, &cmp->cmp->totalleft, &numallocl);
1663 if (filesl)
1664 qsort(filesl, cmp->cmp->totalleft, sizeof(CHAR *), CompNames);
1665 // Build list of all files in right directory
1666 if (!*cmp->rightlist) {
1667 if (fForceLower)
1668 strlwr(cmp->rightdir);
1669 else if (fForceUpper)
1670 strupr(cmp->rightdir);
1671 FillDirList(cmp->rightdir, lenr, cmp->includesubdirs,
1672 &filesr, &cmp->cmp->totalright, &numallocr);
1673 }
1674 else {
1675 // Use snapshot file
1676 FILE *fp;
1677 FILEFINDBUF4L fb4;
1678 CHAR str[CCHMAXPATH * 2], *p;
1679 CHAR *moder = "r";
1680 BOOL fFixedSnap = TRUE;
1681
1682 memset(&fb4, 0, sizeof(fb4));
1683 fp = xfopen(cmp->rightlist, moder, pszSrcFile, __LINE__, FALSE);
1684 if (fp) {
1685 while (!feof(fp)) {
1686 // First get name of directory
1687 if (!xfgets_bstripcr(str, sizeof(str), fp, pszSrcFile, __LINE__))
1688 break; // EOF
1689 p = str;
1690 if (*p == '\"') {
1691 // Quoted
1692 p++;
1693 if (*p && *p != '\"') {
1694 p = strchr(p, '\"');
1695 if (p) {
1696 *p = 0;
1697 if (*(str + 1)) {
1698 strcpy(cmp->rightdir, str + 1);
1699 if (fForceUpper)
1700 strupr(cmp->rightdir);
1701 else if (fForceLower)
1702 strlwr(cmp->rightdir);
1703 p = cmp->rightdir + (strlen(cmp->rightdir) - 1);
1704 if (p - cmp->rightdir > 3 && *p == '\\')
1705 *p = 0; // Chop trailing slash
1706 break;
1707 }
1708 }
1709 }
1710 }
1711 } // while !EOF
1712
1713 memset(&cnri, 0, sizeof(cnri));
1714 cnri.cb = sizeof(cnri);
1715 WinSetDlgItemText(cmp->hwnd, COMP_LISTLOADED, "List File Loaded");
1716 cnri.pszCnrTitle = cmp->rightdir;
1717 if (!WinSendMsg(hwndRight, CM_SETCNRINFO,
1718 MPFROMP(&cnri), MPFROMLONG(CMA_CNRTITLE))) {
1719 Win_Error(hwndRight, cmp->hwnd, pszSrcFile, __LINE__, "CM_SETCNRINFO");
1720 WinSetDlgItemText(cmp->hwnd, COMP_LISTLOADED, "");
1721 }
1722
1723 if (*cmp->rightdir) {
1724 lenr = strlen(cmp->rightdir);
1725 if (cmp->rightdir[strlen(cmp->rightdir) - 1] != '\\')
1726 lenr++;
1727 while (!feof(fp)) {
1728 if (!xfgets_bstripcr
1729 (str, sizeof(str), fp, pszSrcFile, __LINE__)) {
1730 break;
1731 }
1732 p = str;
1733 if (*p == '\"') {
1734 p++;
1735 if (*p && *p != '\"') {
1736 p = strchr(p, '\"');
1737 if (p) {
1738 *p = 0;
1739 p++;
1740 if (*p == ',') {
1741 p++;
1742 if (!cmp->includesubdirs && atol(p) > lenr)
1743 continue;
1744 p = strchr(p, ',');
1745 if (p) {
1746 p++;
1747 if (((strchr(p, '/') ? strchr(p, '/') : strchr(p, DateSeparator[0])) - strchr(p, ',')) > 5) {
1748 CHAR szTemp[30];
1749 CHAR *q;
1750 int i;
1751
1752 memset(szTemp, 0, sizeof(szTemp));
1753 i = (strchr(p, '/') ? strchr(p, '/') : strchr(p, DateSeparator[0])) - 3 - p;
1754 strncpy(&szTemp, p, i);
1755 for (q = szTemp; q = strchr(szTemp, ',');) {
1756 strcpy(q, q + 1);
1757 }
1758 fb4.cbFile = atoll(szTemp);
1759 fFixedSnap = FALSE;
1760
1761 }
1762 else
1763 fb4.cbFile = atoll(p);
1764 if (!strchr(p, '/'))
1765 fFixedSnap = FALSE;
1766 p = (strchr(p, '/') ? strchr(p, '/') : strchr(p, DateSeparator[0])) - 6;
1767 p = strchr(p, ',');
1768 if (p) {
1769 p++;
1770 if (ulDateFmt == 2 || ulDateFmt == 3 || fFixedSnap)
1771 fb4.fdateLastWrite.year = atol(p) - 1980;
1772 else if (ulDateFmt == 1)
1773 fb4.fdateLastWrite.day = atol(p);
1774 else
1775 fb4.fdateLastWrite.month = atol(p);
1776 p = strchr(p, '/') ? strchr(p, '/') : strchr(p, DateSeparator[0]);
1777 if (p) {
1778 p++;
1779 if (ulDateFmt == 2 || ulDateFmt == 1 || fFixedSnap)
1780 fb4.fdateLastWrite.month = atol(p);
1781 else
1782 fb4.fdateLastWrite.day = atol(p);
1783 p = strchr(p, '/') ? strchr(p, '/') : strchr(p, DateSeparator[0]);
1784 if (p) {
1785 p++;
1786 if (ulDateFmt == 2 || fFixedSnap)
1787 fb4.fdateLastWrite.day = atol(p);
1788 else if (ulDateFmt == 3)
1789 fb4.fdateLastWrite.month = atol(p);
1790 else
1791 fb4.fdateLastWrite.year = atol(p) - 1980;
1792 p = strchr(p, ',');
1793 if (p) {
1794 p++;
1795 fb4.ftimeLastWrite.hours = atol(p);
1796 p = strchr(p, ':') ? strchr(p, ':') : strchr(p, TimeSeparator[0]);
1797 if (p) {
1798 p++;
1799 fb4.ftimeLastWrite.minutes = atol(p);
1800 p = strchr(p, ':') ? strchr(p, ':') : strchr(p, TimeSeparator[0]);
1801 if (p) {
1802 p++;
1803 fb4.ftimeLastWrite.twosecs = atol(p);
1804 p = strchr(p, ',');
1805 if (p) {
1806 p++;
1807 fb4.attrFile = atol(p);
1808 p = strchr(p, ',');
1809 if (p) {
1810 p++;
1811 fb4.cbList = atol(p) * 2;
1812 if (fForceUpper)
1813 strupr(str + 1);
1814 else if (fForceLower)
1815 strlwr(str + 1);
1816 if (AddToFileList((str + 1) + lenr,
1817 &fb4,
1818 &filesr,
1819 &cmp->cmp->totalright,
1820 &numallocr))
1821 break;
1822 }
1823 }
1824 }
1825 }
1826 }
1827 }
1828 }
1829 }
1830 }
1831 }
1832 }
1833 }
1834 }
1835 } // while
1836 } // if have rightdir
1837 fclose(fp);
1838 if (!filesr)
1839 saymsg(MB_OK | MB_ICONASTERISK, HWND_DESKTOP,
1840 GetPString(IDS_WARNINGTEXT),
1841 GetPString(IDS_SNAPSHOTFILEBADFORMAT));
1842 }
1843 else
1844 saymsg(MB_OK | MB_ICONASTERISK, HWND_DESKTOP,
1845 GetPString(IDS_WARNINGTEXT),
1846 GetPString(IDS_SNAPSHOTFILELOADFAILED), cmp->rightlist);
1847 } // if snapshot file
1848
1849 if (filesr)
1850 qsort(filesr, cmp->cmp->totalright, sizeof(CHAR *), CompNames);
1851
1852 // We now have two lists of files, both sorted.
1853 // Count total number of container entries required on each side
1854 l = 0;
1855 r = 0;
1856 ulRecsNeeded = 0;
1857 while ((filesl && filesl[l]) || (filesr && filesr[r])) {
1858
1859 if (cmp->stop)
1860 break; // Cancel requested
1861
1862 if (filesl && filesl[l]) {
1863 if (filesr && filesr[r])
1864 x = stricmp(filesl[l]->fname, filesr[r]->fname);
1865 else
1866 x = -1; // Left side list longer
1867 }
1868 else
1869 x = +1; // Right side list longer
1870
1871 if (x <= 0)
1872 l++; // On left side
1873 if (x >= 0)
1874 r++; // On right side
1875
1876 ulRecsNeeded++; // Count how many entries req'd
1877
1878 } // while counting
1879
1880 if (cmp->stop)
1881 ulRecsNeeded = 0;
1882
1883 // Insert records into the containers
1884
1885 if (ulRecsNeeded) {
1886
1887 PCNRITEM pcilFirst;
1888 PCNRITEM pcirFirst;
1889 PCNRITEM pcil = NULL;
1890 PCNRITEM pcir = NULL;
1891 INT ret;
1892 ULONG ulRecsAllocated = 0;
1893 ULONG insertedl;
1894 ULONG insertedr;
1895
1896 l = 0;
1897 r = 0;
1898
1899 // Use send to get message on screen quickly
1900 WinSendMsg(cmp->hwnd, UM_CONTAINERHWND, MPVOID, MPVOID);
1901
1902 cmp->cmp->totalleft = 0;
1903 cmp->cmp->totalright = 0;
1904
1905 while ((filesl && filesl[l]) || (filesr && filesr[r])) {
1906
1907 ULONG ulRecsToInsert; // limited to USHRT_MAX
1908
1909 if (cmp->stop)
1910 break;
1911
1912 // Check alloc needed
1913 if (!pcil || !pcir) {
1914 if (pcil != pcir) {
1915 Runtime_Error(pszSrcFile, __LINE__, GetPString(IDS_LEFTRIGHTOUTOFSYNC));
1916 cmp->stop = TRUE;
1917 break;
1918 }
1919 ulRecsToInsert = ulRecsNeeded - ulRecsAllocated;
1920 if (ulRecsToInsert > USHRT_MAX)
1921 ulRecsToInsert = USHRT_MAX;
1922
1923 pcilFirst = WinSendMsg(hwndLeft,
1924 CM_ALLOCRECORD,
1925 MPFROMLONG(EXTRA_RECORD_BYTES),
1926 MPFROMLONG(ulRecsToInsert));
1927 if (!pcilFirst) {
1928 Win_Error(hwndLeft, cmp->hwnd, pszSrcFile, __LINE__, PCSZ_CM_ALLOCRECORD);
1929 cmp->stop = TRUE;
1930 break;
1931 }
1932 pcirFirst = WinSendMsg(hwndRight, CM_ALLOCRECORD,
1933 MPFROMLONG(EXTRA_RECORD_BYTES),
1934 MPFROMLONG(ulRecsToInsert));
1935 if (!pcirFirst) {
1936 Win_Error(hwndRight, cmp->hwnd, pszSrcFile, __LINE__, PCSZ_CM_ALLOCRECORD);
1937 FreeCnrItemList(hwndLeft, pcilFirst);
1938 pcilFirst = NULL;
1939 cmp->stop = TRUE;
1940 break;
1941 }
1942 pcil = pcilFirst;
1943 pcir = pcirFirst;
1944 insertedl = 0;
1945 insertedr = 0;
1946 ulRecsAllocated += ulRecsToInsert;
1947 } // if need alloc
1948
1949 pcir->hwndCnr = hwndRight;
1950 pcir->rc.hptrIcon = (HPOINTER)0;
1951 pcil->hwndCnr = hwndLeft;
1952 pcil->rc.hptrIcon = (HPOINTER)0;
1953
1954 if (filesl && filesl[l]) {
1955 if (filesr && filesr[r])
1956 x = stricmp(filesl[l]->fname, filesr[r]->fname);
1957 else
1958 x = -1; // Left side list longer
1959 }
1960 else
1961 x = +1; // Right side list longer
1962
1963 if (x <= 0) {
1964 // File appears on left side
1965 cmp->cmp->totalleft++;
1966 insertedl++;
1967 BldFullPathName(szBuf, cmp->leftdir, filesl[l]->fname);
1968 pcil->pszFileName = xstrdup(szBuf, pszSrcFile, __LINE__);
1969 pcil->pszDisplayName = pcil->pszFileName + lenl;
1970 pcil->attrFile = filesl[l]->attrFile;
1971 pcil->pszDispAttr = FileAttrToString(pcil->attrFile);
1972 pcil->cbFile = filesl[l]->cbFile;
1973 // 12 Jan 08 SHL fixme to use cached size here too
1974 CommaFmtULL(szBuf, sizeof(szBuf), pcil->cbFile, ' ');
1975 pcil->pszFmtFileSize = xstrdup(szBuf, pszSrcFile, __LINE__);
1976 pcil->easize = filesl[l]->easize;
1977 pcil->date.day = filesl[l]->date.day;
1978 pcil->date.month = filesl[l]->date.month;
1979 pcil->date.year = filesl[l]->date.year + 1980;
1980 pcil->time.seconds = filesl[l]->time.twosecs * 2;
1981 pcil->time.minutes = filesl[l]->time.minutes;
1982 pcil->time.hours = filesl[l]->time.hours;
1983 pcil->ladate.day = filesl[l]->ladate.day;
1984 pcil->ladate.month = filesl[l]->ladate.month;
1985 pcil->ladate.year = filesl[l]->ladate.year + 1980;
1986 pcil->latime.seconds = filesl[l]->latime.twosecs * 2;
1987 pcil->latime.minutes = filesl[l]->latime.minutes;
1988 pcil->latime.hours = filesl[l]->latime.hours;
1989 pcil->crdate.day = filesl[l]->crdate.day;
1990 pcil->crdate.month = filesl[l]->crdate.month;
1991 pcil->crdate.year = filesl[l]->crdate.year + 1980;
1992 pcil->crtime.seconds = filesl[l]->crtime.twosecs * 2;
1993 pcil->crtime.minutes = filesl[l]->crtime.minutes;
1994 pcil->crtime.hours = filesl[l]->crtime.hours;
1995 DosRequestMutexSem(hmtxFiltering, SEM_INDEFINITE_WAIT);
1996 if (cmp && *cmp->dcd.mask.szMask) {
1997 if (!Filter((PMINIRECORDCORE)pcil, (PVOID)&cmp->dcd.mask)) {
1998 pcil->rc.flRecordAttr |= CRA_FILTERED;
1999 pcir->rc.flRecordAttr |= CRA_FILTERED;
2000 }
2001 }
2002 DosReleaseMutexSem(hmtxFiltering);
2003 } // if on left
2004
2005 if (x >= 0) {
2006 // File appears on right side
2007 cmp->cmp->totalright++;
2008 insertedr++;
2009 BldFullPathName(szBuf, cmp->rightdir, filesr[r]->fname);
2010 pcir->pszFileName = xstrdup(szBuf, pszSrcFile, __LINE__); // 31 Jul 07 SHL
2011 pcir->pszDisplayName = pcir->pszFileName + lenr;
2012 pcir->attrFile = filesr[r]->attrFile;
2013 pcir->pszDispAttr = FileAttrToString(pcir->attrFile);
2014 pcir->cbFile = filesr[r]->cbFile;
2015 // 12 Jan 08 SHL fixme to used cached size here too
2016 CommaFmtULL(szBuf, sizeof(szBuf), pcir->cbFile, ' ');
2017 pcir->pszFmtFileSize = xstrdup(szBuf, pszSrcFile, __LINE__);
2018 pcir->easize = filesr[r]->easize;
2019 pcir->date.day = filesr[r]->date.day;
2020 pcir->date.month = filesr[r]->date.month;
2021 pcir->date.year = filesr[r]->date.year + 1980;
2022 pcir->time.seconds = filesr[r]->time.twosecs * 2;
2023 pcir->time.minutes = filesr[r]->time.minutes;
2024 pcir->time.hours = filesr[r]->time.hours;
2025 pcir->ladate.day = filesr[r]->ladate.day;
2026 pcir->ladate.month = filesr[r]->ladate.month;
2027 pcir->ladate.year = filesr[r]->ladate.year + 1980;
2028 pcir->latime.seconds = filesr[r]->latime.twosecs * 2;
2029 pcir->latime.minutes = filesr[r]->latime.minutes;
2030 pcir->latime.hours = filesr[r]->latime.hours;
2031 pcir->crdate.day = filesr[r]->crdate.day;
2032 pcir->crdate.month = filesr[r]->crdate.month;
2033 pcir->crdate.year = filesr[r]->crdate.year + 1980;
2034 pcir->crtime.seconds = filesr[r]->crtime.twosecs * 2;
2035 pcir->crtime.minutes = filesr[r]->crtime.minutes;
2036 pcir->crtime.hours = filesr[r]->crtime.hours;
2037 // Bypass check if already filtered on left side
2038 DosRequestMutexSem(hmtxFiltering, SEM_INDEFINITE_WAIT);
2039 if (cmp && ~pcir->rc.flRecordAttr & CRA_FILTERED &&
2040 *cmp->dcd.mask.szMask) {
2041 if (!Filter((PMINIRECORDCORE)pcir, (PVOID)&cmp->dcd.mask)) {
2042 pcil->rc.flRecordAttr |= CRA_FILTERED;
2043 pcir->rc.flRecordAttr |= CRA_FILTERED;
2044 }
2045 }
2046 DosReleaseMutexSem(hmtxFiltering);
2047 } // if on right
2048
2049 if (x == 0) {
2050 // File appears on both sides
2051 pcil->flags |= CNRITEM_EXISTS;
2052 pcir->flags |= CNRITEM_EXISTS;
2053 pch = szBuf;
2054 // Subject field holds status messages
2055 *pch = 0;
2056 if (pcil->cbFile > pcir->cbFile) {
2057 pcil->flags |= CNRITEM_LARGER;
2058 pcir->flags |= CNRITEM_SMALLER;
2059 strcpy(pch, GetPString(IDS_LARGERTEXT));
2060 pch += 6;
2061 }
2062 else if (pcil->cbFile < pcir->cbFile) {
2063 pcil->flags |= CNRITEM_SMALLER;
2064 pcir->flags |= CNRITEM_LARGER;
2065 strcpy(pch, GetPString(IDS_SMALLERTEXT));
2066 pch += 7;
2067 }
2068 if (pcil->easize != pcir->easize) {
2069 pcil->flags |= CNRITEM_EASDIFFER;
2070 pcir->flags |= CNRITEM_EASDIFFER;
2071 if (pch != szBuf) {
2072 strcpy(pch, ", ");
2073 pch += 2;
2074 }
2075 strcpy(pch, GetPString(IDS_EASDIFFERTEXT));
2076 pch += 10;
2077 }
2078 ret = TestCDates(&pcir->date, &pcir->time,
2079 &pcil->date, &pcil->time);
2080 if (ret == 1) {
2081 pcil->flags |= CNRITEM_NEWER;
2082 pcir->flags |= CNRITEM_OLDER;
2083 if (pch != szBuf) {
2084 strcpy(pch, ", ");
2085 pch += 2;
2086 }
2087 strcpy(pch, GetPString(IDS_NEWERTEXT));
2088 pch += 5;
2089 }
2090 else if (ret == -1) {
2091 pcil->flags |= CNRITEM_OLDER;
2092 pcir->flags |= CNRITEM_NEWER;
2093 if (pch != szBuf) {
2094 strcpy(pch, ", ");
2095 pch += 2;
2096 }
2097 strcpy(pch, GetPString(IDS_OLDERTEXT));
2098 pch += 5;
2099 }
2100 pcil->pszSubject = *szBuf ?
2101 xstrdup(szBuf, pszSrcFile, __LINE__) :
2102 NullStr;
2103
2104 } // if on both sides
2105
2106 if (x <= 0)
2107 free(filesl[l++]); // Done with item on left
2108
2109 if (x >= 0)
2110 free(filesr[r++]); // Done with item on right
2111
2112 // Ensure empty buffers point somewhere
2113 if (!pcil->pszFileName) {
2114 pcil->pszFileName = NullStr;
2115 pcil->pszDisplayName = pcil->pszFileName;
2116 }
2117
2118 if (!pcir->pszFileName) {
2119 pcir->pszFileName = NullStr;
2120 pcir->pszDisplayName = pcir->pszFileName;
2121 }
2122
2123 pcil->rc.pszIcon = pcil->pszDisplayName;
2124 pcir->rc.pszIcon = pcir->pszDisplayName;
2125
2126 pcil->pszLongName = NullStr;
2127 pcir->pszLongName = NullStr;
2128
2129 if (!pcil->pszSubject)
2130 if (!pcir->pszSubject)
2131 pcir->pszSubject = NullStr;
2132
2133 if (!pcil->pszDispAttr)
2134 pcil->pszDispAttr = NullStr;
2135 if (!pcir->pszDispAttr)
2136 pcir->pszDispAttr = NullStr;
2137
2138 // Avoid hogging systems
2139 SleepIfNeeded(&itdSleep, 0);
2140
2141 pcil = (PCNRITEM)pcil->rc.preccNextRecord;
2142 pcir = (PCNRITEM)pcir->rc.preccNextRecord;
2143
2144 if (pcil == NULL || pcir == NULL) {
2145 RECORDINSERT ri;
2146 if (pcil != pcir) {
2147 Runtime_Error(pszSrcFile, __LINE__, "pcil and pcir out of sync");
2148 cmp->stop = TRUE;
2149 break;
2150 }
2151 // Say inserting
2152 WinSendMsg(cmp->hwnd, UM_CONTAINERDIR, MPVOID, MPVOID);
2153
2154 // Insert left side
2155 memset(&ri, 0, sizeof(RECORDINSERT));
2156 ri.cb = sizeof(RECORDINSERT);
2157 ri.pRecordOrder = (PRECORDCORE)CMA_END;
2158 ri.pRecordParent = (PRECORDCORE)NULL;
2159 ri.zOrder = (ULONG)CMA_TOP;
2160 ri.cRecordsInsert = ulRecsToInsert;
2161 ri.fInvalidateRecord = FALSE;
2162
2163 if (!WinSendMsg(hwndLeft, CM_INSERTRECORD,
2164 MPFROMP(pcilFirst), MPFROMP(&ri))) {
2165 Win_Error(hwndLeft, cmp->hwnd, pszSrcFile, __LINE__, "CM_INSERTRECORD");
2166 FreeCnrItemList(hwndLeft, pcilFirst);
2167 cmp->cmp->totalleft -= insertedl;
2168 }
2169 pcilFirst = NULL;
2170
2171 // Insert right side
2172 memset(&ri, 0, sizeof(RECORDINSERT));
2173 ri.cb = sizeof(RECORDINSERT);
2174 ri.pRecordOrder = (PRECORDCORE)CMA_END;
2175 ri.pRecordParent = (PRECORDCORE)NULL;
2176 ri.zOrder = (ULONG)CMA_TOP;
2177 ri.cRecordsInsert = ulRecsToInsert;
2178 ri.fInvalidateRecord = FALSE;
2179
2180 if (!WinSendMsg(hwndRight, CM_INSERTRECORD,
2181 MPFROMP(pcirFirst), MPFROMP(&ri))) {
2182 Win_Error(hwndRight, cmp->hwnd, pszSrcFile, __LINE__, "CM_INSERTRECORD");
2183 // 2011-05-29 SHL fixme?
2184 RemoveCnrItems(hwndLeft, NULL, 0, CMA_FREE | CMA_INVALIDATE);
2185 FreeCnrItemList(hwndRight, pcirFirst);
2186 cmp->cmp->totalright -= insertedr;
2187 }
2188 pcirFirst = NULL;
2189 } // if need insert
2190
2191 } // while filling left or right
2192
2193 // If stopped early clean up
2194
2195 if (cmp->stop) {
2196 // Free up container records that we did not insert in container
2197 if (pcilFirst)
2198 FreeCnrItemList(hwndLeft, pcilFirst);
2199
2200 // Free up items we did not insert in container
2201 if (filesl) {
2202 for(; filesl[l]; l++) {
2203 free(filesl[l]);
2204 }
2205 }
2206
2207 if (pcirFirst)
2208 FreeCnrItemList(hwndRight, pcirFirst);
2209
2210 if (filesr) {
2211 for (; filesr[r]; r++) {
2212 free(filesr[r]);
2213 }
2214 }
2215 } // if insufficient resources
2216
2217 xfree(filesl, pszSrcFile, __LINE__); // Free header - have already freed elements
2218 filesl = NULL;
2219 xfree(filesr, pszSrcFile, __LINE__);
2220 filesr = NULL;
2221
2222 } // if ulRecsNeeded
2223
2224 Deselect(hwndLeft);
2225 Deselect(hwndRight);
2226
2227 // Request window update
2228 if (!PostMsg(cmp->hwnd, UM_CONTAINER_FILLED, MPVOID, MPVOID))
2229 WinSendMsg(cmp->hwnd, UM_CONTAINER_FILLED, MPVOID, MPVOID);
2230 notified = TRUE;
2231
2232 if (filesl)
2233 FreeList((CHAR **)filesl); // Must have failed to create container
2234 if (filesr)
2235 FreeList((CHAR **)filesr);
2236
2237 WinDestroyMsgQueue(hmq);
2238 } // if have queue
2239 if (!notified)
2240 PostMsg(cmp->hwnd, UM_CONTAINER_FILLED, MPVOID, MPVOID);
2241 DecrThreadUsage();
2242 WinTerminate(hab);
2243 }
2244 DosRequestMutexSem(hmtxFiltering, SEM_INDEFINITE_WAIT);
2245 free(cmp);
2246 cmp = NULL;
2247 DosReleaseMutexSem(hmtxFiltering);
2248 DosPostEventSem(CompactSem);
2249
2250# ifdef FORTIFY
2251 Fortify_LeaveScope();
2252# endif
2253
2254}
2255
2256/**
2257 * Find matching item in other container
2258 * @return PCNRITEM or NULL
2259 */
2260
2261static PCNRITEM FindMatchingItem(PCNRITEM pciFindS, HWND hwndCnrS, HWND hwndCnrD);
2262
2263static PCNRITEM FindMatchingItem(PCNRITEM pciFindS, HWND hwndCnrS, HWND hwndCnrD)
2264{
2265
2266 PCNRITEM pciS;
2267 PCNRITEM pciD;
2268
2269 pciS = WinSendMsg(hwndCnrS, CM_QUERYRECORD, MPVOID,
2270 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
2271 pciD = WinSendMsg(hwndCnrD, CM_QUERYRECORD, MPVOID,
2272 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
2273 while (pciS && (INT)pciS != -1 && pciD && (INT)pciD != -1) {
2274
2275 if (pciS == pciFindS)
2276 break;
2277
2278 pciS = WinSendMsg(hwndCnrS, CM_QUERYRECORD, MPFROMP(pciS),
2279 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
2280 pciD = WinSendMsg(hwndCnrD, CM_QUERYRECORD, MPFROMP(pciD),
2281 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
2282 } // while
2283
2284 if (pciS != pciFindS)
2285 pciD = NULL;
2286
2287 return pciD;
2288}
2289
2290/**
2291 * Set button/window enables
2292 */
2293
2294static VOID SetButtonEnables(COMPARE* cmp, BOOL fEnable);
2295
2296static VOID SetButtonEnables(COMPARE* cmp, BOOL fEnable)
2297{
2298 HWND hwnd = cmp->hwnd;
2299 HWND hwndLeft = GetHwndLeft(hwnd);
2300 HWND hwndRight = GetHwndRight(hwnd);
2301
2302 if (!fEnable) {
2303 // Disable before
2304 WinEnableWindowUpdate(hwndLeft, fEnable);
2305 WinEnableWindowUpdate(hwndRight, fEnable);
2306 }
2307 WinEnableWindow(hwndLeft, fEnable);
2308 WinEnableWindow(hwndRight, fEnable);
2309 if (fEnable) {
2310 // Enable after
2311 WinEnableWindowUpdate(hwndLeft, fEnable);
2312 WinEnableWindowUpdate(hwndRight, fEnable);
2313 }
2314
2315 WinEnableWindow(WinWindowFromID(hwnd, DID_OK), fEnable);
2316 WinEnableWindow(WinWindowFromID(hwnd, COMP_COLLECT), fEnable);
2317 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTBOTH), fEnable);
2318 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTONE), fEnable);
2319 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTNEWER), fEnable);
2320 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTEAS), fEnable); // 2013-03-09 SHL
2321 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTOLDER), fEnable);
2322 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTBIGGER), fEnable);
2323 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTSMALLER), fEnable);
2324 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTBOTH), fEnable);
2325 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTONE), fEnable);
2326 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTNEWER), fEnable);
2327 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTEAS), fEnable); // 2013-03-09 SHL
2328 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTOLDER), fEnable);
2329 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTBIGGER), fEnable);
2330 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTSMALLER), fEnable);
2331 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTALL), fEnable);
2332 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTSAMECONTENT), fEnable);
2333 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTIDENTICAL), fEnable);
2334 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTSAME), fEnable);
2335 WinEnableWindow(WinWindowFromID(hwnd, IDM_INVERT), fEnable);
2336 WinEnableWindow(WinWindowFromID(hwnd, COMP_SETDIRS), fEnable);
2337 WinEnableWindow(WinWindowFromID(hwnd, COMP_DELETELEFT), fEnable);
2338 WinEnableWindow(WinWindowFromID(hwnd, COMP_FILTER), fEnable);
2339 if (!fEnable || !*cmp->rightlist) {
2340 WinEnableWindow(WinWindowFromID(hwnd, COMP_COPYLEFT), fEnable);
2341 WinEnableWindow(WinWindowFromID(hwnd, COMP_MOVELEFT), fEnable);
2342 WinEnableWindow(WinWindowFromID(hwnd, COMP_DELETERIGHT), fEnable);
2343 WinEnableWindow(WinWindowFromID(hwnd, COMP_COPYRIGHT), fEnable);
2344 WinEnableWindow(WinWindowFromID(hwnd, COMP_MOVERIGHT), fEnable);
2345 }
2346 WinEnableWindow(WinWindowFromID(hwnd, COMP_INCLUDESUBDIRS), fEnable);
2347 WinEnableWindow(WinWindowFromID(hwnd, COMP_HIDENOTSELECTED), fEnable);
2348 WinEnableWindow(WinWindowFromID(hwnd, COMP_CONFIRMACTION), fEnable); // 2013-03-09 SHL
2349}
2350
2351/**
2352 * Compare directories dialog procedure
2353 */
2354
2355MRESULT EXPENTRY CompareDlgProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
2356{
2357 COMPARE *cmp;
2358 BOOL temp;
2359 CHAR szPathName[CCHMAXPATH];
2360 CHAR s[81];
2361
2362 static HPOINTER hptr;
2363
2364 switch (msg) {
2365 case WM_INITDLG:
2366 cmp = (COMPARE *)mp2;
2367 if (!cmp) {
2368 Runtime_Error(pszSrcFile, __LINE__, NULL);
2369 WinDismissDlg(hwnd, 0);
2370 }
2371 else {
2372 if (!hptr)
2373 hptr = WinLoadPointer(HWND_DESKTOP, FM3ModHandle, COMPARE_ICON);
2374 WinDefDlgProc(hwnd, WM_SETICON, MPFROMLONG(hptr), MPVOID);
2375 cmp->hwnd = hwnd;
2376 WinSetWindowPtr(hwnd, QWL_USER, (PVOID)cmp);
2377 {
2378 SWP swp;
2379 ULONG size = sizeof(SWP);
2380
2381 PrfQueryProfileData(fmprof, FM3Str, "CompDir.Position", (PVOID) &swp, &size);
2382 swp.fl &= ~SWP_SIZE; // 04 Feb 09 SHL ignore saved size
2383 WinSetWindowPos(hwnd,
2384 HWND_TOP,
2385 swp.x,
2386 swp.y,
2387 swp.cx,
2388 swp.cy,
2389 swp.fl);
2390 }
2391 SetCnrCols(GetHwndLeft(hwnd), TRUE);
2392 SetCnrCols(GetHwndRight(hwnd), TRUE);
2393 if (cmp->listfile) {
2394 CHAR fullname[CCHMAXPATH];
2395
2396 strcpy(fullname, PCSZ_STARDOTPMD);
2397 if (insert_filename(HWND_DESKTOP, fullname, TRUE, FALSE) &&
2398 *fullname && !strchr(fullname, '*') && !strchr(fullname, '?'))
2399 strcpy(cmp->rightlist, fullname);
2400 }
2401 WinSendMsg(hwnd, UM_SETUP, MPVOID, MPVOID);
2402 WinSendMsg(hwnd, UM_SETDIR, MPVOID, MPVOID);
2403 PostMsg(hwnd, UM_STRETCH, MPVOID, MPVOID);
2404 {
2405 USHORT ids[] = {COMP_FRAME, COMP_LEFTDIR, COMP_RIGHTDIR, COMP_COLLECT,
2406 COMP_VIEW, COMP_NOTE, COMP_TOTALLEFT, COMP_SELLEFT, COMP_TOTALRIGHT,
2407 COMP_SELRIGHT, COMP_CNRMENU, COMP_DIRMENU, COMP_MENU,
2408 COMP_INCLUDESUBDIRS, COMP_SETDIRS, COMP_COPYLEFT, COMP_MOVELEFT,
2409 COMP_DELETELEFT, COMP_COPYRIGHT, COMP_MOVERIGHT, COMP_DELETERIGHT,
2410 COMP_TOTALLEFTHDR, COMP_SELLEFTHDR, COMP_TOTALRIGHTHDR,
2411 COMP_SELRIGHTHDR, COMP_FILTER, COMP_HIDENOTSELECTED, 0};
2412 UINT x;
2413 CHAR s[24];
2414
2415 for (x = 0; ids[x]; x++) {
2416 sprintf(s, "CompDir%i", ids[x]);
2417 RestorePresParams(WinWindowFromID(hwnd, ids[x]), s);
2418 }
2419 }
2420 WinStartTimer(WinQueryAnchorBlock(hwnd), hwnd, ID_COMP_TIMER, 500);
2421 }
2422 break;
2423
2424 case UM_STRETCH:
2425 {
2426 SWP swp, swpC;
2427 LONG titl, szbx, szby, sz;
2428 HWND hwndActive;
2429
2430 WinQueryWindowPos(hwnd, &swp);
2431 if (!(swp.fl & (SWP_HIDE | SWP_MINIMIZE))) {
2432 hwndActive = WinQueryFocus(HWND_DESKTOP);
2433 szbx = SysVal(SV_CXSIZEBORDER);
2434 szby = SysVal(SV_CYSIZEBORDER);
2435 titl = SysVal(SV_CYTITLEBAR);
2436 titl += 26;
2437 swp.cx -= (szbx * 2);
2438 sz = (swp.cx / 8);
2439 WinQueryWindowPos(WinWindowFromID(hwnd, COMP_LEFTDIR), &swpC);
2440 WinSetWindowPos(WinWindowFromID(hwnd, COMP_LEFTDIR), HWND_TOP,
2441 szbx + 6,
2442 swpC.y,
2443 (swp.cx / 2) - (szbx + 6),
2444 ((swp.cy - swpC.y) - titl) - szby,
2445 SWP_MOVE | SWP_SIZE);
2446 WinSetWindowPos(WinWindowFromID(hwnd, COMP_RIGHTDIR), HWND_TOP,
2447 (swp.cx / 2) + (szbx + 6),
2448 swpC.y,
2449 (swp.cx / 2) - (szbx + 6),
2450 ((swp.cy - swpC.y) - titl) - szby,
2451 SWP_MOVE | SWP_SIZE);
2452 WinSetWindowPos(WinWindowFromID(hwnd, COMP_TOTALLEFTHDR), HWND_TOP,
2453 szbx + 6,
2454 ((swp.cy - titl) - szby) + 4,
2455 sz - (szbx + 6), 20, SWP_MOVE | SWP_SIZE);
2456 WinSetWindowPos(WinWindowFromID(hwnd, COMP_TOTALLEFT), HWND_TOP,
2457 sz + (szbx + 6),
2458 ((swp.cy - titl) - szby) + 4,
2459 sz - (szbx + 6), 20, SWP_MOVE | SWP_SIZE);
2460 WinSetWindowPos(WinWindowFromID(hwnd, COMP_SELLEFTHDR), HWND_TOP,
2461 (sz * 2) + (szbx + 6),
2462 ((swp.cy - titl) - szby) + 4,
2463 sz - (szbx + 6), 20, SWP_MOVE | SWP_SIZE);
2464 WinSetWindowPos(WinWindowFromID(hwnd, COMP_SELLEFT), HWND_TOP,
2465 (sz * 3) + (szbx + 6),
2466 ((swp.cy - titl) - szby) + 4,
2467 sz - (szbx + 6), 20, SWP_MOVE | SWP_SIZE);
2468 WinSetWindowPos(WinWindowFromID(hwnd, COMP_TOTALRIGHTHDR), HWND_TOP,
2469 (sz * 4) + (szbx + 6),
2470 ((swp.cy - titl) - szby) + 4,
2471 sz - (szbx + 6), 20, SWP_MOVE | SWP_SIZE);
2472 WinSetWindowPos(WinWindowFromID(hwnd, COMP_TOTALRIGHT), HWND_TOP,
2473 (sz * 5) + (szbx + 6),
2474 ((swp.cy - titl) - szby) + 4,
2475 sz - (szbx + 6), 20, SWP_MOVE | SWP_SIZE);
2476 WinSetWindowPos(WinWindowFromID(hwnd, COMP_SELRIGHTHDR), HWND_TOP,
2477 (sz * 6) + (szbx + 6),
2478 ((swp.cy - titl) - szby) + 4,
2479 sz - (szbx + 6), 20, SWP_MOVE | SWP_SIZE);
2480 WinSetWindowPos(WinWindowFromID(hwnd, COMP_SELRIGHT), HWND_TOP,
2481 (sz * 7) + (szbx + 6),
2482 ((swp.cy - titl) - szby) + 4,
2483 sz - (szbx + 6), 20, SWP_MOVE | SWP_SIZE);
2484 PaintRecessedWindow(WinWindowFromID(hwnd, COMP_TOTALLEFT),
2485 (HPS)0, FALSE, FALSE);
2486 PaintRecessedWindow(WinWindowFromID(hwnd, COMP_SELLEFT),
2487 (HPS)0, FALSE, FALSE);
2488 PaintRecessedWindow(WinWindowFromID(hwnd, COMP_TOTALRIGHT),
2489 (HPS)0, FALSE, FALSE);
2490 PaintRecessedWindow(WinWindowFromID(hwnd, COMP_SELRIGHT),
2491 (HPS)0, FALSE, FALSE);
2492 PaintRecessedWindow(GetHwndLeft(hwnd), (HPS)0,
2493 (hwndActive == GetHwndLeft(hwnd)), TRUE);
2494 PaintRecessedWindow(GetHwndRight(hwnd), (HPS)0,
2495 (hwndActive == GetHwndRight(hwnd)), TRUE);
2496 }
2497 }
2498 return 0;
2499
2500 case WM_ADJUSTWINDOWPOS:
2501 PostMsg(hwnd, UM_STRETCH, MPVOID, MPVOID);
2502 break;
2503
2504 case UM_SETUP:
2505 {
2506 CNRINFO cnri;
2507 BOOL tempsubj;
2508
2509 cmp = INSTDATA(hwnd);
2510 if (!cmp)
2511 Runtime_Error(pszSrcFile, __LINE__, NULL);
2512 else {
2513 cmp->dcd.size = sizeof(DIRCNRDATA);
2514 cmp->dcd.type = DIR_FRAME;
2515 cmp->dcd.hwndFrame = hwnd;
2516 cmp->dcd.hwndClient = hwnd;
2517 cmp->dcd.mask.attrFile = (FILE_DIRECTORY | FILE_ARCHIVED |
2518 FILE_READONLY | FILE_SYSTEM | FILE_HIDDEN);
2519 LoadDetailsSwitches(PCSZ_DIRCMP, &cmp->dcd.ds, FALSE);
2520 cmp->dcd.ds.detailslongname = FALSE;
2521 cmp->dcd.ds.detailsicon = FALSE; // TRUE;
2522 }
2523 memset(&cnri, 0, sizeof(CNRINFO));
2524 cnri.cb = sizeof(CNRINFO);
2525 WinSendDlgItemMsg(hwnd, COMP_LEFTDIR, CM_QUERYCNRINFO,
2526 MPFROMP(&cnri), MPFROMLONG(sizeof(CNRINFO)));
2527 cnri.flWindowAttr |= (CA_OWNERDRAW | CV_MINI);
2528 cnri.xVertSplitbar = DIR_SPLITBAR_OFFSET - 68;
2529 WinSendDlgItemMsg(hwnd, COMP_LEFTDIR, CM_SETCNRINFO, MPFROMP(&cnri),
2530 MPFROMLONG(CMA_FLWINDOWATTR | CMA_XVERTSPLITBAR));
2531 memset(&cnri, 0, sizeof(CNRINFO));
2532 cnri.cb = sizeof(CNRINFO);
2533 WinSendDlgItemMsg(hwnd, COMP_RIGHTDIR, CM_QUERYCNRINFO,
2534 MPFROMP(&cnri), MPFROMLONG(sizeof(CNRINFO)));
2535 cnri.flWindowAttr |= (CA_OWNERDRAW | CV_MINI);
2536 cnri.xVertSplitbar = DIR_SPLITBAR_OFFSET - 54;
2537 WinSendDlgItemMsg(hwnd, COMP_RIGHTDIR, CM_SETCNRINFO, MPFROMP(&cnri),
2538 MPFROMLONG(CMA_FLWINDOWATTR | CMA_XVERTSPLITBAR));
2539 AdjustCnrColRO(GetHwndLeft(hwnd), GetPString(IDS_FILENAMECOLTEXT), TRUE, FALSE);
2540 AdjustCnrColRO(GetHwndLeft(hwnd), GetPString(IDS_LONGNAMECOLTEXT), TRUE, FALSE);
2541 AdjustCnrColRO(GetHwndRight(hwnd), GetPString(IDS_FILENAMECOLTEXT), TRUE, FALSE);
2542 AdjustCnrColRO(GetHwndRight(hwnd), GetPString(IDS_LONGNAMECOLTEXT), TRUE, FALSE);
2543 AdjustCnrColsForPref(GetHwndLeft(hwnd), cmp->leftdir, &cmp->dcd.ds, TRUE);
2544 tempsubj = cmp->dcd.ds.detailssubject;
2545 cmp->dcd.ds.detailssubject = FALSE;
2546 AdjustCnrColsForPref(GetHwndRight(hwnd), cmp->rightdir, &cmp->dcd.ds, TRUE);
2547 if (*cmp->rightlist) {
2548 AdjustCnrColVis(GetHwndRight(hwnd), GetPString(IDS_LADATECOLTEXT), FALSE,
2549 FALSE);
2550 AdjustCnrColVis(GetHwndRight(hwnd), GetPString(IDS_LATIMECOLTEXT), FALSE,
2551 FALSE);
2552 AdjustCnrColVis(GetHwndRight(hwnd), GetPString(IDS_CRDATECOLTEXT), FALSE,
2553 FALSE);
2554 AdjustCnrColVis(GetHwndRight(hwnd), GetPString(IDS_CRTIMECOLTEXT), FALSE,
2555 FALSE);
2556 }
2557 cmp->dcd.ds.detailssubject = tempsubj;
2558 }
2559 return 0;
2560
2561 case WM_DRAWITEM:
2562 if (mp2) {
2563 POWNERITEM pown = (POWNERITEM)mp2;
2564 PCNRDRAWITEMINFO pcown;
2565 PCNRITEM pci;
2566
2567 pcown = (PCNRDRAWITEMINFO)pown->hItem;
2568 if (pcown) {
2569 pci = (PCNRITEM)pcown->pRecord;
2570 // 01 Aug 07 SHL if field null or blank, we draw
2571 // fixme to document why - probably to optimize and bypass draw?
2572 if (pci && (INT)pci != -1 && !*pci->pszFileName && pci->pszFileName != NullStr)
2573 return MRFROMLONG(TRUE);
2574 }
2575 }
2576 return 0;
2577
2578 case UM_CONTAINERHWND:
2579 // Building list
2580 WinSetDlgItemText(hwnd, COMP_NOTE, (CHAR *) GetPString(IDS_COMPHOLDBLDLISTTEXT));
2581 return 0;
2582
2583 case UM_CONTAINERDIR:
2584 // Filling container
2585 WinSetDlgItemText(hwnd, COMP_NOTE, (CHAR *) GetPString(IDS_COMPHOLDFILLCNRTEXT));
2586 return 0;
2587
2588 case WM_TIMER:
2589 // Show current totals
2590 cmp = INSTDATA(hwnd);
2591 if (!cmp) {
2592 Runtime_Error(pszSrcFile, __LINE__, "pCompare NULL");
2593 WinDismissDlg(hwnd, 0);
2594 }
2595 else {
2596 if (cmp->uOldTotalLeft != cmp->totalleft) {
2597 cmp->uOldTotalLeft = cmp->totalleft;
2598 sprintf(s, " %d", cmp->totalleft);
2599 WinSetDlgItemText(hwnd, COMP_TOTALLEFT, s);
2600 }
2601 if (cmp->uOldTotalRight != cmp->totalright) {
2602 cmp->uOldTotalRight = cmp->totalright;
2603 sprintf(s, " %d", cmp->totalright);
2604 WinSetDlgItemText(hwnd, COMP_TOTALRIGHT, s);
2605 }
2606 if (cmp->uOldSelLeft != cmp->selleft) {
2607 cmp->uOldSelLeft = cmp->selleft;
2608 sprintf(s, " %d", cmp->selleft);
2609 WinSetDlgItemText(hwnd, COMP_SELLEFT, s);
2610 }
2611 if (cmp->uOldSelRight != cmp->selright) {
2612 cmp->uOldSelRight = cmp->selright;
2613 sprintf(s, " %d", cmp->selright);
2614 WinSetDlgItemText(hwnd, COMP_SELRIGHT, s);
2615 }
2616 }
2617 break;
2618
2619 case UM_CONTAINER_FILLED:
2620 cmp = INSTDATA(hwnd);
2621 if (!cmp) {
2622 Runtime_Error(pszSrcFile, __LINE__, "pCompare NULL");
2623 WinDismissDlg(hwnd, 0);
2624 }
2625 else if (cmp->stop) {
2626 // Delayed cancel
2627 WinDismissDlg(hwnd, 1);
2628 }
2629 else {
2630 cmp->filling = FALSE;
2631 SetButtonEnables(cmp, TRUE);
2632 WinPostMsg(hwnd, WM_TIMER, MPFROMLONG(ID_COMP_TIMER), 0); // Force counts to update
2633 if (*cmp->dcd.mask.szMask) {
2634 sprintf(s, GetPString(IDS_COMPREADYFILTEREDTEXT), cmp->dcd.mask.szMask);
2635 WinSetDlgItemText(hwnd, COMP_NOTE, s);
2636 }
2637 else
2638 WinSetDlgItemText(hwnd, COMP_NOTE, (CHAR *) GetPString(IDS_COMPREADYTEXT));
2639 }
2640 break;
2641
2642 case WM_INITMENU:
2643 cmp = INSTDATA(hwnd);
2644 if (cmp) {
2645 switch (SHORT1FROMMP(mp1)) {
2646 case IDM_COMMANDSMENU:
2647 SetupCommandMenu(cmp->dcd.hwndLastMenu, hwnd);
2648 break;
2649 }
2650 }
2651 break;
2652
2653 case WM_MENUEND:
2654 cmp = INSTDATA(hwnd);
2655 if (cmp) {
2656 if ((HWND)mp2 == cmp->dcd.hwndLastMenu) {
2657 MarkAll(GetHwndLeft(hwnd), TRUE, FALSE, TRUE);
2658 MarkAll(GetHwndRight(hwnd), TRUE, FALSE, TRUE);
2659 WinDestroyWindow(cmp->dcd.hwndLastMenu);
2660 cmp->dcd.hwndLastMenu = (HWND)0;
2661 }
2662 }
2663 break;
2664
2665 case WM_CONTROL:
2666 switch (SHORT1FROMMP(mp1)) {
2667 case COMP_INCLUDESUBDIRS:
2668 switch (SHORT2FROMMP(mp1)) {
2669 case BN_CLICKED:
2670 cmp = INSTDATA(hwnd);
2671 PostMsg(hwnd, UM_SETUP, MPVOID, MPVOID);
2672 PostMsg(hwnd, UM_SETDIR, MPVOID, MPVOID);
2673 break;
2674 }
2675 break;
2676 case COMP_HIDENOTSELECTED:
2677 switch (SHORT2FROMMP(mp1)) {
2678 case BN_CLICKED:
2679 WinSendMsg(hwnd, UM_HIDENOTSELECTED, MPVOID, MPVOID);
2680 break;
2681 }
2682 break;
2683
2684 case COMP_LEFTDIR:
2685 case COMP_RIGHTDIR:
2686 switch (SHORT2FROMMP(mp1)) {
2687 case CN_KILLFOCUS:
2688 PaintRecessedWindow(WinWindowFromID(hwnd, SHORT1FROMMP(mp1)),
2689 (HPS)0, FALSE, TRUE);
2690 break;
2691
2692 case CN_SETFOCUS:
2693 PaintRecessedWindow(WinWindowFromID(hwnd, SHORT1FROMMP(mp1)),
2694 (HPS)0, TRUE, TRUE);
2695 break;
2696
2697 case CN_ENTER:
2698 if (mp2) {
2699
2700 PCNRITEM pci = (PCNRITEM)((PNOTIFYRECORDENTER)mp2)->pRecord;
2701 HWND hwndCnr = WinWindowFromID(hwnd, SHORT1FROMMP(mp1));
2702
2703 SetShiftState();
2704 if (pci) {
2705 if (pci->rc.flRecordAttr & CRA_INUSE || !pci || !*pci->pszFileName)
2706 break;
2707 WinSendMsg(hwndCnr, CM_SETRECORDEMPHASIS, MPFROMP(pci),
2708 MPFROM2SHORT(TRUE, CRA_INUSE));
2709 if (pci->attrFile & FILE_DIRECTORY) {
2710 if ((shiftstate & (KC_CTRL | KC_SHIFT)) == (KC_CTRL | KC_SHIFT))
2711 OpenObject(pci->pszFileName, Settings, hwnd);
2712 else
2713 OpenObject(pci->pszFileName, Default, hwnd);
2714 }
2715 else
2716 DefaultViewKeys(hwnd, hwnd, HWND_DESKTOP, NULL,
2717 pci->pszFileName);
2718 WinSendMsg(hwndCnr, CM_SETRECORDEMPHASIS,
2719 MPFROMP(pci),
2720 MPFROM2SHORT(FALSE,
2721 CRA_INUSE | (fUnHilite ? CRA_SELECTED : 0)));
2722 }
2723 }
2724 break;
2725
2726 case CN_CONTEXTMENU:
2727 cmp = INSTDATA(hwnd);
2728 if (cmp) {
2729 PCNRITEM pci = (PCNRITEM)mp2;
2730 USHORT id = COMP_CNRMENU; // Assume container menu
2731
2732 if (cmp->dcd.hwndLastMenu)
2733 WinDestroyWindow(cmp->dcd.hwndLastMenu);
2734 cmp->dcd.hwndLastMenu = (HWND)0;
2735 cmp->hwndCalling = WinWindowFromID(hwnd, SHORT1FROMMP(mp1));
2736 if (pci) {
2737 if (!pci || !*pci->pszFileName || *cmp->rightlist)
2738 break;
2739 id = COMP_MENU; // Want container item menu
2740 WinSendMsg(cmp->hwndCalling, CM_SETRECORDEMPHASIS,
2741 MPFROMP(pci), MPFROM2SHORT(TRUE, CRA_CURSORED));
2742 }
2743 cmp->dcd.hwndLastMenu = WinLoadMenu(HWND_DESKTOP, FM3ModHandle, id);
2744 if (cmp->dcd.hwndLastMenu) {
2745 switch (id) {
2746 case COMP_CNRMENU:
2747 if (SHORT1FROMMP(mp1) == COMP_RIGHTDIR)
2748 WinSendMsg(cmp->dcd.hwndLastMenu, MM_DELETEITEM,
2749 MPFROM2SHORT(IDM_SHOWSUBJECT, FALSE), MPVOID);
2750 SetDetailsSwitches(cmp->dcd.hwndLastMenu, &cmp->dcd.ds);
2751 if (SHORT1FROMMP(mp1) == COMP_LEFTDIR)
2752 WinSendMsg(cmp->dcd.hwndLastMenu, MM_DELETEITEM,
2753 MPFROM2SHORT(IDM_LOADLISTFILE, 0), MPVOID);
2754 else if (*cmp->rightlist)
2755 WinSendMsg(cmp->dcd.hwndLastMenu, MM_DELETEITEM,
2756 MPFROM2SHORT(IDM_SAVELISTFILE, 0), MPVOID);
2757 break;
2758 case COMP_MENU:
2759 // Can't compare what's not there
2760 if (~pci->flags & CNRITEM_EXISTS) {
2761 WinSendMsg(cmp->dcd.hwndLastMenu, MM_DELETEITEM,
2762 MPFROM2SHORT(IDM_COMPARE, 0), MPVOID);
2763 }
2764 break;
2765 } // switch
2766 PopupMenu(hwnd, hwnd, cmp->dcd.hwndLastMenu);
2767 }
2768 }
2769 break;
2770
2771 case CN_INITDRAG:
2772 cmp = INSTDATA(hwnd);
2773 if (*cmp->rightlist && SHORT1FROMMP(mp1) == COMP_RIGHTDIR)
2774 break;
2775 DoFileDrag(WinWindowFromID(hwnd, SHORT1FROMMP(mp1)),
2776 (HWND)0, mp2, NULL, NULL, TRUE);
2777 break;
2778
2779 case CN_BEGINEDIT:
2780 case CN_REALLOCPSZ:
2781 // fixme to be gone - field edits not allowed?
2782 Runtime_Error(pszSrcFile, __LINE__,
2783 "CN_BEGINEDIT/CN_REALLOCPSZ unexpected");
2784 break;
2785
2786 case CN_EMPHASIS:
2787 {
2788 PNOTIFYRECORDEMPHASIS pnre = mp2;
2789 BOOL fSelected;
2790 if (pnre->fEmphasisMask & CRA_SELECTED) {
2791 // Select toggled
2792 PCNRITEM pci = (PCNRITEM)pnre->pRecord;
2793 if (pci) {
2794 if (!*pci->pszFileName) {
2795 // User clicked on empty slot - just clear
2796 if (pci->rc.flRecordAttr & CRA_SELECTED)
2797 WinSendDlgItemMsg(hwnd, SHORT1FROMMP(mp1),
2798 CM_SETRECORDEMPHASIS,
2799 MPFROMP(pci),
2800 MPFROM2SHORT(FALSE, CRA_SELECTED));
2801 }
2802 else {
2803 BOOL fUpdateHideButton = FALSE;
2804 cmp = INSTDATA(hwnd);
2805 if (SHORT1FROMMP(mp1) == COMP_LEFTDIR) {
2806 fSelected = pci->rc.flRecordAttr & CRA_SELECTED;
2807 cmp->selleft += fSelected ? 1 : -1;
2808 if (!fSelected)
2809 fUpdateHideButton = TRUE;
2810 }
2811 else if (SHORT1FROMMP(mp1) == COMP_RIGHTDIR) {
2812 fSelected = pci->rc.flRecordAttr & CRA_SELECTED;
2813 cmp->selright += fSelected ? 1 : -1;
2814 if (!fSelected)
2815 fUpdateHideButton = TRUE;
2816 }
2817 else {
2818 Runtime_Error(pszSrcFile, __LINE__,
2819 "mp1 %u unexpected", SHORT1FROMMP(mp1));
2820 }
2821 if (fUpdateHideButton) {
2822 ULONG state = WinQueryButtonCheckstate(hwnd,COMP_HIDENOTSELECTED);
2823 if (state == 1) {
2824 WinCheckButton(hwnd, COMP_HIDENOTSELECTED, 2);
2825 }
2826 }
2827 }
2828 }
2829 }
2830 }
2831 break;
2832
2833 case CN_SCROLL:
2834 cmp = INSTDATA(hwnd);
2835 if (!cmp->forcescroll) {
2836
2837 PNOTIFYSCROLL pns = mp2;
2838
2839 if (pns->fScroll & CMA_VERTICAL) {
2840 cmp->forcescroll = TRUE;
2841 // Scroll other window to match
2842 WinSendDlgItemMsg(hwnd,
2843 SHORT1FROMMP(mp1) == COMP_LEFTDIR ?
2844 COMP_RIGHTDIR : COMP_LEFTDIR,
2845 CM_SCROLLWINDOW,
2846 MPFROMSHORT(CMA_VERTICAL),
2847 MPFROMLONG(pns->lScrollInc));
2848 cmp->forcescroll = FALSE;
2849 }
2850 }
2851 break;
2852 } // switch COMP_LEFTDIR mp1
2853 break; // COMP_LEFTDIR / COMP_RIGHTDIR
2854 } // switch WM_CONTROL mp1
2855 return 0; // WM_CONTROL
2856
2857 case UM_SETDIR:
2858 cmp = INSTDATA(hwnd);
2859 if (cmp) {
2860 COMPARE *forthread;
2861 CNRINFO cnri;
2862 if (cmp->includesubdirs)
2863 WinCheckButton(hwnd, COMP_INCLUDESUBDIRS, TRUE);
2864 cmp->includesubdirs = WinQueryButtonCheckstate(hwnd,
2865 COMP_INCLUDESUBDIRS);
2866 memset(&cnri, 0, sizeof(CNRINFO));
2867 cnri.cb = sizeof(CNRINFO);
2868 cnri.pszCnrTitle = cmp->leftdir;
2869 cnri.flWindowAttr = CV_DETAIL | CV_MINI |
2870 CA_CONTAINERTITLE | CA_TITLESEPARATOR |
2871 CA_DETAILSVIEWTITLES | CA_OWNERDRAW;
2872 WinSendDlgItemMsg(hwnd, COMP_LEFTDIR, CM_SETCNRINFO, MPFROMP(&cnri),
2873 MPFROMLONG(CMA_CNRTITLE | CMA_FLWINDOWATTR));
2874 WinSetDlgItemText(hwnd, COMP_LISTLOADED, "");
2875 cnri.pszCnrTitle = cmp->rightdir;
2876 WinSendDlgItemMsg(hwnd, COMP_RIGHTDIR, CM_SETCNRINFO, MPFROMP(&cnri),
2877 MPFROMLONG(CMA_CNRTITLE | CMA_FLWINDOWATTR));
2878 WinCheckButton(hwnd, COMP_HIDENOTSELECTED, 0);
2879 cmp->filling = TRUE;
2880# ifdef FORTIFY
2881 Fortify_EnterScope();
2882# endif
2883 forthread = xmalloc(sizeof(COMPARE), pszSrcFile, __LINE__);
2884 if (!forthread)
2885 WinDismissDlg(hwnd, 0);
2886 else {
2887 *forthread = *cmp;
2888 forthread->cmp = cmp;
2889 if (xbeginthread(FillCnrsThread,
2890 122880,
2891 forthread,
2892 pszSrcFile,
2893 __LINE__) == -1)
2894 {
2895 WinDismissDlg(hwnd, 0);
2896 free(forthread);
2897# ifdef FORTIFY
2898 Fortify_LeaveScope();
2899# endif
2900 }
2901 else {
2902 WinSetDlgItemText(hwnd, COMP_NOTE,
2903 (CHAR *) GetPString(IDS_COMPHOLDREADDISKTEXT));
2904 SetButtonEnables(cmp, FALSE);
2905 cmp->includesubdirs = FALSE;
2906 cmp->selleft = 0;
2907 cmp->selright = 0;
2908 }
2909 }
2910 }
2911 return 0;
2912
2913 case UM_FILTER:
2914 cmp = INSTDATA(hwnd);
2915 if (cmp) {
2916 if (mp1)
2917 SetMask((CHAR *)mp1, &cmp->dcd.mask);
2918
2919 WinSetDlgItemText(hwnd, COMP_NOTE,
2920 (CHAR *) GetPString(IDS_COMPHOLDFILTERINGTEXT));
2921 priority_idle(); // Don't hog resources
2922 WinSendMsg(GetHwndLeft(hwnd), CM_FILTER, MPFROMP(Filter),
2923 MPFROMP(&cmp->dcd.mask));
2924 WinSendMsg(GetHwndRight(hwnd), CM_FILTER, MPFROMP(Filter),
2925 MPFROMP(&cmp->dcd.mask));
2926 priority_normal();
2927 if (*cmp->dcd.mask.szMask) {
2928 sprintf(s,
2929 GetPString(IDS_COMPREADYFILTEREDTEXT),
2930 cmp->dcd.mask.szMask);
2931 WinSetDlgItemText(hwnd, COMP_NOTE, s);
2932 }
2933 else
2934 WinSetDlgItemText(hwnd, COMP_NOTE, (CHAR *) GetPString(IDS_COMPREADYTEXT));
2935 }
2936 return 0;
2937
2938 case UM_HIDENOTSELECTED:
2939 cmp = INSTDATA(hwnd);
2940 if (cmp) {
2941 ULONG wasHidden = WinQueryButtonCheckstate(hwnd,
2942 COMP_HIDENOTSELECTED);
2943 ULONG nowHidden = wasHidden != 1 && (cmp->selleft || cmp->selright);
2944
2945 // cmp->dcd.suspendview = 1; // 12 Jan 08 SHL appears not to be used here
2946 // 26 Sep 09 SHL Unhide if nothing selected
2947 if (nowHidden) {
2948 // Hide items not selected on both sides
2949 BOOL needRefresh = FALSE;
2950 HWND hwndl = WinWindowFromID(cmp->hwnd, COMP_LEFTDIR);
2951 HWND hwndr = WinWindowFromID(cmp->hwnd, COMP_RIGHTDIR);
2952 PCNRITEM pcil = WinSendMsg(hwndl, CM_QUERYRECORD, MPVOID,
2953 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
2954 PCNRITEM pcir = WinSendMsg(hwndr, CM_QUERYRECORD, MPVOID,
2955 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
2956
2957 while (pcil && (INT)pcil != -1 && pcir && (INT)pcir != -1) {
2958 if (~pcil->rc.flRecordAttr & CRA_SELECTED &&
2959 ~pcir->rc.flRecordAttr & CRA_SELECTED) {
2960 if (~pcil->rc.flRecordAttr & CRA_FILTERED) {
2961 needRefresh = TRUE;
2962 pcil->rc.flRecordAttr |= CRA_FILTERED;
2963 }
2964 if (~pcir->rc.flRecordAttr & CRA_FILTERED) {
2965 pcir->rc.flRecordAttr |= CRA_FILTERED;
2966 needRefresh = TRUE;
2967 }
2968 }
2969 pcil = WinSendMsg(hwndl, CM_QUERYRECORD, MPFROMP(pcil),
2970 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
2971 pcir = WinSendMsg(hwndr, CM_QUERYRECORD, MPFROMP(pcir),
2972 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
2973 } // while
2974 if (needRefresh) {
2975 WinSendMsg(hwndl, CM_INVALIDATERECORD,
2976 MPVOID, MPFROM2SHORT(0, CMA_REPOSITION));
2977 WinSendMsg(hwndr, CM_INVALIDATERECORD,
2978 MPVOID, MPFROM2SHORT(0, CMA_REPOSITION));
2979 }
2980 }
2981 else {
2982 // Unhide
2983 WinSendMsg(GetHwndLeft(hwnd), CM_FILTER, MPFROMP(Filter),
2984 MPFROMP(&cmp->dcd.mask));
2985 WinSendMsg(GetHwndRight(hwnd), CM_FILTER, MPFROMP(Filter),
2986 MPFROMP(&cmp->dcd.mask));
2987 }
2988 if (*cmp->dcd.mask.szMask) {
2989 sprintf(s,
2990 GetPString(IDS_COMPREADYFILTEREDTEXT),
2991 cmp->dcd.mask.szMask);
2992 WinSetDlgItemText(hwnd, COMP_NOTE, s);
2993 }
2994 else
2995 WinSetDlgItemText(hwnd, COMP_NOTE, (CHAR *) GetPString(IDS_COMPREADYTEXT));
2996 WinCheckButton(hwnd, COMP_HIDENOTSELECTED, nowHidden);
2997 }
2998 return 0;
2999
3000 case WM_COMMAND:
3001 // 29 Apr 09 SHL fixme to support more context menu items - IDM_VIEW, IDM_EDIT etc.
3002 switch (SHORT1FROMMP(mp1)) {
3003 case IDM_COMPARE:
3004 cmp = INSTDATA(hwnd);
3005 if (cmp) {
3006 PCNRITEM pci;
3007 pci = (PCNRITEM)WinSendMsg(cmp->hwndCalling,
3008 CM_QUERYRECORDEMPHASIS,
3009 MPFROMLONG(CMA_FIRST),
3010 MPFROMSHORT(CRA_CURSORED));
3011 if (pci && *pci->pszFileName) {
3012 if (cmp->hwndCalling == GetHwndLeft(hwnd))
3013 strcpy(szPathName, cmp->rightdir);
3014 else
3015 strcpy(szPathName, cmp->leftdir);
3016 AddBackslashToPath(szPathName);
3017 strcat(szPathName, pci->pszDisplayName);
3018 if (*compare) {
3019 CHAR *fakelist[3];
3020 fakelist[0] = pci->pszFileName;
3021 fakelist[1] = szPathName;
3022 fakelist[2] = NULL;
3023 ExecOnList(hwnd, compare, WINDOWED | SEPARATEKEEP,
3024 NULL, NULL, fakelist, NULL,
3025 pszSrcFile, __LINE__);
3026 }
3027 else {
3028 FCOMPARE fc;
3029 memset(&fc, 0, sizeof(fc));
3030 fc.size = sizeof(fc);
3031 fc.hwndParent = hwnd;
3032 strcpy(fc.file1, pci->pszFileName);
3033 strcpy(fc.file2, szPathName);
3034 WinDlgBox(HWND_DESKTOP, hwnd,
3035 CFileDlgProc, FM3ModHandle, FCMP_FRAME, (PVOID)&fc);
3036 }
3037 }
3038 }
3039 break;
3040
3041 case IDM_DELETE:
3042 cmp = INSTDATA(hwnd);
3043 if (!cmp)
3044 Runtime_Error(pszSrcFile, __LINE__, NULL);
3045 else {
3046 PCNRITEM pciS;
3047 PCNRITEM pciD;
3048 HWND hwndCnrS;
3049 HWND hwndCnrD;
3050 pciS = (PCNRITEM)WinSendMsg(cmp->hwndCalling,
3051 CM_QUERYRECORDEMPHASIS,
3052 MPFROMLONG(CMA_FIRST),
3053 MPFROMSHORT(CRA_CURSORED));
3054 if (!pciS)
3055 Runtime_Error(pszSrcFile, __LINE__, NULL);
3056 else {
3057 // Find matching record
3058 if (cmp->hwndCalling == GetHwndLeft(hwnd)) {
3059 hwndCnrS = GetHwndLeft(hwnd);
3060 hwndCnrD = GetHwndRight(hwnd);
3061 }
3062 else {
3063 hwndCnrS = GetHwndRight(hwnd);
3064 hwndCnrD = GetHwndLeft(hwnd);
3065 }
3066
3067 pciD = FindMatchingItem(pciS, hwndCnrS, hwndCnrD);
3068
3069 if (!pciD)
3070 Runtime_Error(pszSrcFile, __LINE__, NULL);
3071 else if (!pciS->pszFileName)
3072 Runtime_Error(pszSrcFile, __LINE__, NULL);
3073 else {
3074 if (!unlinkf(pciS->pszFileName)) {
3075 WinSendMsg(hwndCnrS, CM_SETRECORDEMPHASIS, MPFROMP(pciS),
3076 MPFROM2SHORT(FALSE, CRA_SELECTED));
3077
3078 if (!*pciD->pszFileName) {
3079 // Other side is blank - remove from both sides
3080 RemoveCnrItems(hwndCnrS, pciS, 1, CMA_FREE | CMA_INVALIDATE);
3081 if (pciD->rc.flRecordAttr & CRA_SELECTED)
3082 WinSendMsg(hwndCnrD, CM_SETRECORDEMPHASIS, MPFROMP(pciD),
3083 MPFROM2SHORT(FALSE, CRA_SELECTED));
3084 RemoveCnrItems(hwndCnrD, pciD, 1, CMA_FREE | CMA_INVALIDATE);
3085 }
3086 else {
3087 // Other side is not blank - just blank this side
3088 FreeCnrItemData(pciS);
3089 pciS->pszFileName = NullStr;
3090 pciS->pszDisplayName = pciS->pszFileName;
3091 pciS->rc.pszIcon = pciS->pszFileName;
3092 pciS->flags = 0; // Just on one side
3093 WinSendMsg(hwndCnrS, CM_INVALIDATERECORD, MPFROMP(&pciS),
3094 MPFROM2SHORT(1, CMA_ERASE | CMA_TEXTCHANGED));
3095 pciD->flags = 0; // Just on one side
3096 if (pciD->pszSubject != NullStr) {
3097 xfree(pciD->pszSubject, pszSrcFile, __LINE__);
3098 pciD->pszSubject = NullStr;
3099 }
3100 }
3101 if (hwndCnrS == GetHwndLeft(hwnd))
3102 cmp->totalleft--;
3103 else
3104 cmp->totalright--;
3105 // Force displayed counts to update
3106 WinPostMsg(hwnd, WM_TIMER, MPFROMLONG(ID_COMP_TIMER), 0);
3107 }
3108 }
3109 }
3110 }
3111 break; // IDM_DELETE
3112
3113 case COMP_FILTER:
3114 case IDM_FILTER:
3115 cmp = INSTDATA(hwnd);
3116 if (cmp) {
3117 BOOL empty = FALSE;
3118 PCNRITEM pci;
3119 CHAR *p;
3120 BOOL temp;
3121
3122 if (!*cmp->dcd.mask.szMask) {
3123 empty = TRUE;
3124 temp = fSelectedAlways;
3125 fSelectedAlways = TRUE;
3126 pci = (PCNRITEM)CurrentRecord(hwnd);
3127 fSelectedAlways = temp;
3128 // 01 Aug 07 SHL
3129 if (pci && ~pci->attrFile & FILE_DIRECTORY) {
3130 p = strrchr(pci->pszFileName, '\\');
3131 if (p) {
3132 p++;
3133 strcpy(cmp->dcd.mask.szMask, p);
3134 }
3135 }
3136 }
3137 cmp->dcd.mask.fNoAttribs = TRUE;
3138 cmp->dcd.mask.attrFile = ALLATTRS;
3139 cmp->dcd.mask.antiattr = 0;
3140 if (WinDlgBox(HWND_DESKTOP, hwnd, PickMaskDlgProc,
3141 FM3ModHandle, MSK_FRAME, MPFROMP(&cmp->dcd.mask))) {
3142 cmp->dcd.mask.attrFile = ALLATTRS;
3143 cmp->dcd.mask.antiattr = 0;
3144 WinSendMsg(hwnd, UM_FILTER, MPVOID, MPVOID);
3145 }
3146 else if (empty) {
3147 *cmp->dcd.mask.szMask = 0;
3148 cmp->dcd.mask.attrFile = ALLATTRS;
3149 cmp->dcd.mask.antiattr = 0;
3150 }
3151 }
3152 break;
3153
3154 case IDM_SHOWSUBJECT:
3155 case IDM_SHOWEAS:
3156 case IDM_SHOWSIZE:
3157 case IDM_SHOWLWDATE:
3158 case IDM_SHOWLWTIME:
3159 case IDM_SHOWLADATE:
3160 case IDM_SHOWLATIME:
3161 case IDM_SHOWCRDATE:
3162 case IDM_SHOWCRTIME:
3163 case IDM_SHOWATTR:
3164 cmp = INSTDATA(hwnd);
3165 if (cmp) {
3166 DIRCNRDATA dcd1;
3167 BOOL tempsubj;
3168
3169 dcd1 = cmp->dcd;
3170 AdjustDetailsSwitches(GetHwndLeft(hwnd),
3171 (HWND)0, SHORT1FROMMP(mp1),
3172 cmp->leftdir, PCSZ_DIRCMP, &cmp->dcd.ds, TRUE);
3173 tempsubj = cmp->dcd.ds.detailssubject;
3174 cmp->dcd = dcd1;
3175 cmp->dcd.ds.detailssubject = FALSE;
3176 AdjustDetailsSwitches(GetHwndRight(hwnd),
3177 cmp->dcd.hwndLastMenu, SHORT1FROMMP(mp1),
3178 cmp->rightdir, PCSZ_DIRCMP, &cmp->dcd.ds, TRUE);
3179 cmp->dcd.ds.detailssubject = tempsubj;
3180 WriteDetailsSwitches(PCSZ_DIRCMP, &cmp->dcd.ds, TRUE);
3181 }
3182 break;
3183
3184 case IDM_LOADLISTFILE:
3185 cmp = INSTDATA(hwnd);
3186 if (cmp) {
3187 CHAR fullname[CCHMAXPATH];
3188
3189 strcpy(fullname, PCSZ_STARDOTPMD);
3190 if (insert_filename(HWND_DESKTOP, fullname, TRUE, FALSE) &&
3191 *fullname && !strchr(fullname, '*') && !strchr(fullname, '?')) {
3192 strcpy(cmp->rightlist, fullname);
3193 PostMsg(hwnd, UM_SETUP, MPVOID, MPVOID);
3194 PostMsg(hwnd, UM_SETDIR, MPVOID, MPVOID);
3195 }
3196 }
3197 break;
3198
3199 case IDM_SAVELISTFILE:
3200 cmp = INSTDATA(hwnd);
3201 if (cmp) {
3202 SNAPSTUFF *sf;
3203 CHAR fullname[CCHMAXPATH];
3204
3205 strcpy(fullname, PCSZ_STARDOTPMD);
3206 if (export_filename(HWND_DESKTOP, fullname, 1) && *fullname &&
3207 !strchr(fullname, '*') && !strchr(fullname, '?')) {
3208 sf = xmallocz(sizeof(SNAPSTUFF), pszSrcFile, __LINE__);
3209 if (sf) {
3210 strcpy(sf->filename, fullname);
3211 if (GetHwndLeft(hwnd) == cmp->hwndCalling)
3212 strcpy(sf->dirname, cmp->leftdir);
3213 else
3214 strcpy(sf->dirname, cmp->rightdir);
3215 sf->recurse = WinQueryButtonCheckstate(hwnd, COMP_INCLUDESUBDIRS);
3216
3217 if (xbeginthread(StartSnapThread,
3218 65536,
3219 sf,
3220 pszSrcFile,
3221 __LINE__) == -1)
3222 {
3223 free(sf);
3224 }
3225 }
3226 }
3227 }
3228 break;
3229
3230 case COMP_SETDIRS:
3231 cmp = INSTDATA(hwnd);
3232 if (cmp) {
3233 WALK2 wa;
3234 memset(&wa, 0, sizeof(wa));
3235 wa.size = sizeof(wa);
3236 strcpy(wa.szCurrentPath1, cmp->leftdir);
3237 strcpy(wa.szCurrentPath2, cmp->rightdir);
3238 wa.includesubdirs = WinQueryButtonCheckstate(hwnd,
3239 COMP_INCLUDESUBDIRS);
3240 if (WinDlgBox(HWND_DESKTOP,
3241 hwnd,
3242 WalkTwoCmpDlgProc,
3243 FM3ModHandle,
3244 WALK2_FRAME,
3245 MPFROMP(&wa)) &&
3246 !IsFile(wa.szCurrentPath1) &&
3247 !IsFile(wa.szCurrentPath2)) {
3248 strcpy(cmp->leftdir, wa.szCurrentPath1);
3249 strcpy(cmp->rightdir, wa.szCurrentPath2);
3250 cmp->includesubdirs = wa.includesubdirs;
3251 if (!cmp->includesubdirs)
3252 WinCheckButton(hwnd, COMP_INCLUDESUBDIRS, FALSE);
3253 cmp->listfile = wa.listfile;
3254 if (cmp->listfile) {
3255 CHAR fullname[CCHMAXPATH];
3256
3257 strcpy(fullname, PCSZ_STARDOTPMD);
3258 if (insert_filename(HWND_DESKTOP, fullname, TRUE, FALSE) &&
3259 *fullname && !strchr(fullname, '*') && !strchr(fullname, '?'))
3260 strcpy(cmp->rightlist, fullname);
3261 }
3262 else
3263 *cmp->rightlist = 0;
3264 PostMsg(hwnd, UM_SETUP, MPVOID, MPVOID);
3265 PostMsg(hwnd, UM_SETDIR, MPVOID, MPVOID);
3266 }
3267 }
3268 break;
3269
3270 case COMP_COPYLEFT:
3271 case COMP_MOVELEFT:
3272 case COMP_COPYRIGHT:
3273 case COMP_MOVERIGHT:
3274 case COMP_DELETELEFT:
3275 case COMP_DELETERIGHT:
3276 cmp = INSTDATA(hwnd);
3277 if (cmp) {
3278 COMPARE *forthread;
3279
3280 cmp->filling = TRUE;
3281 forthread = xmalloc(sizeof(COMPARE), pszSrcFile, __LINE__);
3282 if (forthread) {
3283 *forthread = *cmp;
3284 forthread->cmp = cmp;
3285 forthread->action = SHORT1FROMMP(mp1);
3286 if (xbeginthread(ActionCnrThread,
3287 122880,
3288 forthread,
3289 pszSrcFile,
3290 __LINE__) == -1)
3291 {
3292 free(forthread);
3293 }
3294 else {
3295 WinEnableWindowUpdate(GetHwndLeft(hwnd), FALSE);
3296 WinEnableWindowUpdate(GetHwndRight(hwnd), FALSE);
3297 switch (SHORT1FROMMP(mp1)) {
3298 case COMP_DELETELEFT:
3299 case COMP_DELETERIGHT:
3300 WinSetDlgItemText(hwnd, COMP_NOTE,
3301 (CHAR *) GetPString(IDS_COMPHOLDDELETINGTEXT));
3302 break;
3303 case COMP_MOVELEFT:
3304 case COMP_MOVERIGHT:
3305 WinSetDlgItemText(hwnd, COMP_NOTE,
3306 (CHAR *) GetPString(IDS_COMPHOLDMOVINGTEXT));
3307 break;
3308 case COMP_COPYLEFT:
3309 case COMP_COPYRIGHT:
3310 WinSetDlgItemText(hwnd, COMP_NOTE,
3311 (CHAR *) GetPString(IDS_COMPHOLDCOPYINGTEXT));
3312 break;
3313 default:
3314 Runtime_Error(pszSrcFile, __LINE__, "mp1 %u unexpected", SHORT1FROMMP(mp1));
3315 }
3316 SetButtonEnables(cmp, FALSE);
3317 }
3318 }
3319 }
3320 break;
3321
3322 case DID_OK:
3323 {
3324 SWP swp;
3325 ULONG size = sizeof(SWP);
3326 USHORT ids[] = {COMP_FRAME, COMP_LEFTDIR, COMP_RIGHTDIR, COMP_COLLECT,
3327 COMP_VIEW, COMP_NOTE, COMP_TOTALLEFT, COMP_SELLEFT, COMP_TOTALRIGHT,
3328 COMP_SELRIGHT, COMP_CNRMENU, COMP_DIRMENU, COMP_MENU,
3329 COMP_INCLUDESUBDIRS, COMP_SETDIRS, COMP_COPYLEFT, COMP_MOVELEFT,
3330 COMP_DELETELEFT, COMP_COPYRIGHT, COMP_MOVERIGHT, COMP_DELETERIGHT,
3331 COMP_TOTALLEFTHDR, COMP_SELLEFTHDR, COMP_TOTALRIGHTHDR,
3332 COMP_SELRIGHTHDR, COMP_FILTER, COMP_HIDENOTSELECTED, 0};
3333 UINT x;
3334 CHAR s[24];
3335 WinQueryWindowPos(hwnd, &swp);
3336 PrfWriteProfileData(fmprof, FM3Str, "CompDir.Position", (PVOID) &swp,
3337 size);
3338 for (x = 0; ids[x]; x++) {
3339 sprintf(s, "CompDir%i", ids[x]);
3340 SavePresParams(WinWindowFromID(hwnd, ids[x]), s);
3341 }
3342 }
3343 WinDismissDlg(hwnd, 0);
3344 break;
3345 case DID_CANCEL:
3346 cmp = INSTDATA(hwnd);
3347 if (!cmp)
3348 Runtime_Error(pszSrcFile, __LINE__, NULL);
3349 else {
3350 cmp->stop = TRUE; // In case thread running
3351 if (cmp->filling)
3352 break; // UM_CONTAINER_FILLED will dismiss
3353 }
3354 {
3355 SWP swp;
3356 ULONG size = sizeof(SWP);
3357 WinQueryWindowPos(hwnd, &swp);
3358 PrfWriteProfileData(fmprof, FM3Str, "CompDir.Position", (PVOID) &swp,
3359 size);
3360 }
3361 WinDismissDlg(hwnd, 1);
3362 break;
3363
3364 case IDM_HELP:
3365 if (hwndHelp)
3366 WinSendMsg(hwndHelp, HM_DISPLAY_HELP,
3367 MPFROM2SHORT(HELP_COMPARE, 0), MPFROMSHORT(HM_RESOURCEID));
3368 break;
3369
3370 case IDM_DESELECTALL:
3371 case IDM_SELECTNEWER:
3372 case IDM_SELECTOLDER:
3373 case IDM_SELECTBIGGER:
3374 case IDM_SELECTSMALLER:
3375 case IDM_SELECTEAS:
3376 case IDM_DESELECTNEWER:
3377 case IDM_DESELECTOLDER:
3378 case IDM_DESELECTBIGGER:
3379 case IDM_DESELECTSMALLER:
3380 case IDM_DESELECTONE:
3381 case IDM_DESELECTBOTH:
3382 case IDM_DESELECTEAS:
3383 case IDM_SELECTBOTH:
3384 case IDM_SELECTONE:
3385 case IDM_SELECTSAMECONTENT:
3386 case IDM_SELECTIDENTICAL: // Name, size and time
3387 case IDM_SELECTSAME: // Name and size
3388 case IDM_INVERT:
3389
3390
3391 cmp = INSTDATA(hwnd);
3392 if (!cmp)
3393 Runtime_Error(pszSrcFile, __LINE__, NULL);
3394 else {
3395 COMPARE *forthread;
3396
3397 cmp->filling = TRUE;
3398 forthread = xmalloc(sizeof(COMPARE), pszSrcFile, __LINE__);
3399 if (forthread) {
3400 *forthread = *cmp;
3401 forthread->cmp = cmp;
3402 forthread->action = SHORT1FROMMP(mp1);
3403 SetShiftState();
3404 forthread->shiftstate = shiftstate; // For and'ed actions
3405
3406 if (xbeginthread(SelectCnrsThread,
3407 65536,
3408 forthread,
3409 pszSrcFile,
3410 __LINE__) == -1)
3411 {
3412 free(forthread);
3413 }
3414 else {
3415 WinEnableWindowUpdate(GetHwndLeft(hwnd), FALSE);
3416 WinEnableWindowUpdate(GetHwndRight(hwnd), FALSE);
3417 switch (SHORT1FROMMP(mp1)) {
3418 case IDM_DESELECTALL:
3419 case IDM_DESELECTNEWER:
3420 case IDM_DESELECTOLDER:
3421 case IDM_DESELECTBIGGER:
3422 case IDM_DESELECTSMALLER:
3423 case IDM_DESELECTONE:
3424 case IDM_DESELECTBOTH:
3425 WinSetDlgItemText(hwnd, COMP_NOTE,
3426 (CHAR *) GetPString(IDS_COMPHOLDDESELTEXT));
3427 break;
3428 case IDM_INVERT:
3429 WinSetDlgItemText(hwnd, COMP_NOTE,
3430 (CHAR *) GetPString(IDS_COMPHOLDINVERTTEXT));
3431 break;
3432 default:
3433 WinSetDlgItemText(hwnd, COMP_NOTE,
3434 (CHAR *) GetPString(IDS_COMPHOLDSELTEXT));
3435 break;
3436 }
3437 SetButtonEnables(cmp, FALSE);
3438 }
3439 }
3440 }
3441 break;
3442
3443 case COMP_COLLECT:
3444 cmp = INSTDATA(hwnd);
3445 if (!cmp)
3446 Runtime_Error(pszSrcFile, __LINE__, NULL);
3447 else {
3448 CHAR **listl;
3449 CHAR **listr = NULL;
3450 if (!Collector) {
3451 SWP swp;
3452 HWND hwndC;
3453 if (!fAutoTile &&
3454 !ParentIsDesktop(hwnd, cmp->hwndParent) &&
3455 !fExternalCollector &&
3456 !strcmp(realappname, FM3Str)) {
3457 GetNextWindowPos(cmp->hwndParent, &swp, NULL, NULL);
3458 }
3459 hwndC = StartCollector(fExternalCollector ||
3460 strcmp(realappname, FM3Str) ?
3461 HWND_DESKTOP :
3462 cmp->hwndParent,
3463 4);
3464 if (hwndC) {
3465 if (!fAutoTile &&
3466 !ParentIsDesktop(hwnd, cmp->hwndParent) &&
3467 !fExternalCollector &&
3468 !strcmp(realappname, FM3Str)) {
3469 WinSetWindowPos(hwndC, HWND_TOP,
3470 swp.x, swp.y, swp.cx, swp.cy,
3471 SWP_MOVE | SWP_SIZE | SWP_SHOW | SWP_ZORDER);
3472 }
3473 else if (!ParentIsDesktop(hwnd, cmp->hwndParent) &&
3474 fAutoTile &&
3475 !strcmp(realappname, FM3Str)) {
3476 TileChildren(cmp->hwndParent, TRUE);
3477 }
3478 DosSleep(1); // 12 Jan 08 SHL Let screen update
3479 PostMsg(hwnd, WM_COMMAND, MPFROM2SHORT(COMP_COLLECT, 0), MPVOID);
3480 break;
3481 }
3482 }
3483 else
3484 StartCollector(cmp->hwndParent, 4);
3485
3486 temp = fSelectedAlways;
3487 fSelectedAlways = TRUE;
3488 listl = BuildList(GetHwndLeft(hwnd));
3489 if (!*cmp->rightlist)
3490 listr = BuildList(GetHwndRight(hwnd));
3491 fSelectedAlways = temp;
3492
3493 if (listl || listr) {
3494 if (Collector) {
3495 // 07 Aug 07 SHL Avoid collected from empty list
3496 if (listl && listl[0] && *listl[0]) {
3497 if (PostMsg(Collector, WM_COMMAND,
3498 MPFROM2SHORT(IDM_COLLECTOR, 0), MPFROMP(listl)))
3499 listl = NULL; // Collector will free
3500 }
3501 if (listr && listr[0] && *listr[0]) {
3502 if (PostMsg(Collector, WM_COMMAND,
3503 MPFROM2SHORT(IDM_COLLECTOR, 0), MPFROMP(listr)))
3504 listr = NULL; // Collector will free
3505 }
3506 WinSetWindowPos(WinQueryWindow(WinQueryWindow(Collector,
3507 QW_PARENT),
3508 QW_PARENT),
3509 HWND_TOP, 0, 0, 0, 0,
3510 SWP_ACTIVATE);
3511 }
3512 FreeList(listl);
3513 FreeList(listr);
3514 }
3515 }
3516 break;
3517 } // switch mp1
3518 return 0;
3519
3520 case WM_CLOSE:
3521 cmp = INSTDATA(hwnd);
3522 if (!cmp)
3523 Runtime_Error(pszSrcFile, __LINE__, NULL);
3524 else {
3525 cmp->stop = TRUE; // In case thread running
3526 if (cmp->filling)
3527 break; // UM_CONTAINER_FILLED will dismiss
3528 }
3529 WinDismissDlg(hwnd, 0);
3530 return 0;
3531
3532 case WM_DESTROY:
3533 cmp = INSTDATA(hwnd);
3534 if (cmp) {
3535 // 17 Jan 08 SHL fixme to know if stop really needed?
3536 WinStopTimer(WinQueryAnchorBlock(hwnd), hwnd, ID_COMP_TIMER);
3537 if (cmp->dcd.hwndLastMenu)
3538 WinDestroyWindow(cmp->dcd.hwndLastMenu);
3539 if (cmp->dcd.hwndObject) {
3540 WinSetWindowPtr(cmp->dcd.hwndObject, QWL_USER, (PVOID)NULL);
3541 if (!PostMsg(cmp->dcd.hwndObject, WM_CLOSE, MPVOID, MPVOID))
3542 WinSendMsg(cmp->dcd.hwndObject, WM_CLOSE, MPVOID, MPVOID);
3543 }
3544 DosRequestMutexSem(hmtxFiltering, SEM_INDEFINITE_WAIT);
3545 free(cmp);
3546 cmp = NULL;
3547 DosReleaseMutexSem(hmtxFiltering);
3548 }
3549 EmptyCnr(GetHwndLeft(hwnd));
3550 EmptyCnr(GetHwndRight(hwnd));
3551 DosPostEventSem(CompactSem);
3552 break;
3553 }
3554 return WinDefDlgProc(hwnd, msg, mp1, mp2);
3555}
3556
3557#undef GetHwndLeft
3558#undef GetHwndRight
3559
3560#pragma alloc_text(COMPAREDIR,FillCnrsThread,FillDirList,CompNames,BldFullPathName)
3561#pragma alloc_text(COMPAREDIR1,CompareDlgProc)
3562#pragma alloc_text(COMPAREDIR2,SelectCnrsThread,ActionCnrThread)
3563#pragma alloc_text(COMPAREFILE,CFileDlgProc,CompareFilesThread)
3564#pragma alloc_text(SNAPSHOT,SnapShot,StartSnapThread)
3565#pragma alloc_text(COMPSELECT,CompSelect,CompSelectSetSelects,CompSelectClearSelects)
3566
Note: See TracBrowser for help on using the repository browser.