source: trunk/dll/comp.c@ 1682

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

Added optional confirmation dialogs for delete move and copy to compare dir Ticket 277; Added EA compare option to compare dir Ticket 80; Minor code cleanup.

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