source: trunk/dll/comp.c@ 1469

Last change on this file since 1469 was 1469, checked in by Steven Levine, 16 years ago

Enhance compare directories - support AND'ed selections, rework CompSelect for size and speed,
allow fast cancel, drop unused reset logic, more context menu items

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