source: trunk/dll/comp.c@ 1686

Last change on this file since 1686 was 1686, checked in by Gregg Young, 12 years ago

GKY Improvrd readonly check on delete to allow cancel and don't ask again options; Added saymsg2 for this purpose; Fixes to snapshot file. cs 1685 contained the COMP.C changes

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