source: trunk/dll/comp.c@ 1684

Last change on this file since 1684 was 1684, checked in by Steven Levine, 12 years ago

SetButtonEnables: correct enable support for newish buttons

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