source: trunk/dll/comp.c@ 1505

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

Remove unnecessary type casts; minor formating cleanup.

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