source: trunk/dll/comp.c@ 1653

Last change on this file since 1653 was 1653, checked in by Gregg Young, 14 years ago

Added pszFmtFileSize to container information passed from one pane to the other on COPY and MOVE in compare directories. Ticket 479

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