source: trunk/dll/comp.c@ 1545

Last change on this file since 1545 was 1545, checked in by Gregg Young, 15 years ago

Added ForwardslashToBackslash function to streamline code.

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