source: trunk/dll/comp.c@ 1673

Last change on this file since 1673 was 1673, checked in by Gregg Young, 13 years ago

Update to Doxygen comment style Ticket 55. Also some minor code cleanup.

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