source: trunk/dll/comp.c@ 1544

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

Changes to fopen and _fsopen to allow FM2 to be loaded in high memory

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