source: trunk/dll/comp.c@ 1670

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

Add ability to change and save PresParam to compare dialog (Ticket 443) Fix loading of a list file in the right compare container (Ticket 489) Allow for selection of include subdirectories or a list file on initial startup of compare dirs (Ticket 145)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 97.8 KB
Line 
1
2/***********************************************************************
3
4 $Id: comp.c 1670 2012-08-13 01:33:25Z 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 Runtime_Error(pszSrcFile, __LINE__, "can not open %s (%d)",
1573 cmp->rightlist, errno);*/
1574 if (fp) {
1575 while (!feof(fp)) {
1576 // First get name of directory
1577 if (!xfgets_bstripcr(str, sizeof(str), fp, pszSrcFile, __LINE__))
1578 break; // EOF
1579 p = str;
1580 if (*p == '\"') {
1581 // Quoted
1582 p++;
1583 if (*p && *p != '\"') {
1584 p = strchr(p, '\"');
1585 if (p) {
1586 *p = 0;
1587 if (*(str + 1)) {
1588 strcpy(cmp->rightdir, str + 1);
1589 if (fForceUpper)
1590 strupr(cmp->rightdir);
1591 else if (fForceLower)
1592 strlwr(cmp->rightdir);
1593 p = cmp->rightdir + (strlen(cmp->rightdir) - 1);
1594 if (p - cmp->rightdir > 3 && *p == '\\')
1595 *p = 0; // Chop trailing slash
1596 break;
1597 }
1598 }
1599 }
1600 }
1601 } // while !EOF
1602
1603 memset(&cnri, 0, sizeof(cnri));
1604 cnri.cb = sizeof(cnri);
1605 cnri.pszCnrTitle = cmp->rightdir;
1606 if (!WinSendMsg(hwndRight, CM_SETCNRINFO,
1607 MPFROMP(&cnri), MPFROMLONG(CMA_CNRTITLE))) {
1608 Win_Error(hwndRight, cmp->hwnd, pszSrcFile, __LINE__, "CM_SETCNRINFO");
1609 }
1610
1611 if (*cmp->rightdir) {
1612 lenr = strlen(cmp->rightdir);
1613 if (cmp->rightdir[strlen(cmp->rightdir) - 1] != '\\')
1614 lenr++;
1615 while (!feof(fp)) {
1616 if (!xfgets_bstripcr
1617 (str, sizeof(str), fp, pszSrcFile, __LINE__))
1618 break;
1619 p = str;
1620 if (*p == '\"') {
1621 p++;
1622 if (*p && *p != '\"') {
1623 p = strchr(p, '\"');
1624 if (p) {
1625 *p = 0;
1626 p++;
1627 if (*p == ',') {
1628 p++;
1629 if (!cmp->includesubdirs && atol(p) > lenr)
1630 continue;
1631 p = strchr(p, ',');
1632 if (p) {
1633 p++;
1634 // 27 Sep 07 SHL fixme to do ULONGLONG conversion
1635 fb4.cbFile = atol(p);
1636 p = strchr(p, ',');
1637 if (p) {
1638 p++;
1639 fb4.fdateLastWrite.year = atol(p) - 1980;
1640 p = strchr(p, '/');
1641 if (p) {
1642 p++;
1643 fb4.fdateLastWrite.month = atol(p);
1644 p = strchr(p, '/');
1645 if (p) {
1646 p++;
1647 fb4.fdateLastWrite.day = atol(p);
1648 p = strchr(p, ',');
1649 if (p) {
1650 p++;
1651 fb4.ftimeLastWrite.hours = atol(p);
1652 p = strchr(p, ':');
1653 if (p) {
1654 p++;
1655 fb4.ftimeLastWrite.minutes = atol(p);
1656 p = strchr(p, ':');
1657 if (p) {
1658 p++;
1659 fb4.ftimeLastWrite.twosecs = atol(p);
1660 p = strchr(p, ',');
1661 if (p) {
1662 p++;
1663 fb4.attrFile = atol(p);
1664 p = strchr(p, ',');
1665 if (p) {
1666 p++;
1667 fb4.cbList = atol(p) * 2;
1668 if (fForceUpper)
1669 strupr(str + 1);
1670 else if (fForceLower)
1671 strlwr(str + 1);
1672 if (AddToFileList((str + 1) + lenr,
1673 &fb4,
1674 &filesr,
1675 &cmp->cmp->totalright,
1676 &numallocr))
1677 break;
1678 }
1679 }
1680 }
1681 }
1682 }
1683 }
1684 }
1685 }
1686 }
1687 }
1688 }
1689 }
1690 }
1691 } // while
1692 } // if have rightdir
1693 fclose(fp);
1694 }
1695 FillDirList(cmp->rightdir, lenr, cmp->includesubdirs,
1696 &filesr, &cmp->cmp->totalright, &numallocr);
1697 } // if snapshot file
1698
1699 if (filesr)
1700 qsort(filesr, cmp->cmp->totalright, sizeof(CHAR *), CompNames);
1701
1702 // We now have two lists of files, both sorted.
1703 // Count total number of container entries required on each side
1704 l = 0;
1705 r = 0;
1706 ulRecsNeeded = 0;
1707 while ((filesl && filesl[l]) || (filesr && filesr[r])) {
1708
1709 if (cmp->stop)
1710 break; // Cancel requested
1711
1712 if (filesl && filesl[l]) {
1713 if (filesr && filesr[r])
1714 x = stricmp(filesl[l]->fname, filesr[r]->fname);
1715 else
1716 x = -1; // Left side list longer
1717 }
1718 else
1719 x = +1; // Right side list longer
1720
1721 if (x <= 0)
1722 l++; // On left side
1723 if (x >= 0)
1724 r++; // On right side
1725
1726 ulRecsNeeded++; // Count how many entries req'd
1727
1728 } // while counting
1729
1730 if (cmp->stop)
1731 ulRecsNeeded = 0;
1732
1733 // Insert records into the containers
1734
1735 if (ulRecsNeeded) {
1736
1737 PCNRITEM pcilFirst;
1738 PCNRITEM pcirFirst;
1739 PCNRITEM pcil = NULL;
1740 PCNRITEM pcir = NULL;
1741 INT ret;
1742 ULONG ulRecsAllocated = 0;
1743 ULONG insertedl;
1744 ULONG insertedr;
1745
1746 l = 0;
1747 r = 0;
1748
1749 // Use send to get message on screen quickly
1750 WinSendMsg(cmp->hwnd, UM_CONTAINERHWND, MPVOID, MPVOID);
1751
1752 cmp->cmp->totalleft = 0;
1753 cmp->cmp->totalright = 0;
1754
1755 while ((filesl && filesl[l]) || (filesr && filesr[r])) {
1756
1757 ULONG ulRecsToInsert; // limited to USHRT_MAX
1758
1759 if (cmp->stop)
1760 break;
1761
1762 // Check alloc needed
1763 if (!pcil || !pcir) {
1764 if (pcil != pcir) {
1765 // 2011-05-29 SHL fixme to GetPString
1766 Runtime_Error(pszSrcFile, __LINE__, "pcil and pcir out of sync");
1767 cmp->stop = TRUE;
1768 break;
1769 }
1770 ulRecsToInsert = ulRecsNeeded - ulRecsAllocated;
1771 if (ulRecsToInsert > USHRT_MAX)
1772 ulRecsToInsert = USHRT_MAX;
1773
1774 pcilFirst = WinSendMsg(hwndLeft,
1775 CM_ALLOCRECORD,
1776 MPFROMLONG(EXTRA_RECORD_BYTES),
1777 MPFROMLONG(ulRecsToInsert));
1778 if (!pcilFirst) {
1779 Win_Error(hwndLeft, cmp->hwnd, pszSrcFile, __LINE__, PCSZ_CM_ALLOCRECORD);
1780 cmp->stop = TRUE;
1781 break;
1782 }
1783 pcirFirst = WinSendMsg(hwndRight, CM_ALLOCRECORD,
1784 MPFROMLONG(EXTRA_RECORD_BYTES),
1785 MPFROMLONG(ulRecsToInsert));
1786 if (!pcirFirst) {
1787 Win_Error(hwndRight, cmp->hwnd, pszSrcFile, __LINE__, PCSZ_CM_ALLOCRECORD);
1788 FreeCnrItemList(hwndLeft, pcilFirst);
1789 pcilFirst = NULL;
1790 cmp->stop = TRUE;
1791 break;
1792 }
1793 pcil = pcilFirst;
1794 pcir = pcirFirst;
1795 insertedl = 0;
1796 insertedr = 0;
1797 ulRecsAllocated += ulRecsToInsert;
1798 } // if need alloc
1799
1800 pcir->hwndCnr = hwndRight;
1801 pcir->rc.hptrIcon = (HPOINTER)0;
1802 pcil->hwndCnr = hwndLeft;
1803 pcil->rc.hptrIcon = (HPOINTER)0;
1804
1805 if (filesl && filesl[l]) {
1806 if (filesr && filesr[r])
1807 x = stricmp(filesl[l]->fname, filesr[r]->fname);
1808 else
1809 x = -1; // Left side list longer
1810 }
1811 else
1812 x = +1; // Right side list longer
1813
1814 if (x <= 0) {
1815 // File appears on left side
1816 cmp->cmp->totalleft++;
1817 insertedl++;
1818 BldFullPathName(szBuf, cmp->leftdir, filesl[l]->fname);
1819 pcil->pszFileName = xstrdup(szBuf, pszSrcFile, __LINE__);
1820 pcil->pszDisplayName = pcil->pszFileName + lenl;
1821 pcil->attrFile = filesl[l]->attrFile;
1822 pcil->pszDispAttr = FileAttrToString(pcil->attrFile);
1823 pcil->cbFile = filesl[l]->cbFile;
1824 // 12 Jan 08 SHL fixme to use cached size here too
1825 CommaFmtULL(szBuf, sizeof(szBuf), pcil->cbFile, ' ');
1826 pcil->pszFmtFileSize = xstrdup(szBuf, pszSrcFile, __LINE__);
1827 pcil->easize = filesl[l]->easize;
1828 pcil->date.day = filesl[l]->date.day;
1829 pcil->date.month = filesl[l]->date.month;
1830 pcil->date.year = filesl[l]->date.year + 1980;
1831 pcil->time.seconds = filesl[l]->time.twosecs * 2;
1832 pcil->time.minutes = filesl[l]->time.minutes;
1833 pcil->time.hours = filesl[l]->time.hours;
1834 pcil->ladate.day = filesl[l]->ladate.day;
1835 pcil->ladate.month = filesl[l]->ladate.month;
1836 pcil->ladate.year = filesl[l]->ladate.year + 1980;
1837 pcil->latime.seconds = filesl[l]->latime.twosecs * 2;
1838 pcil->latime.minutes = filesl[l]->latime.minutes;
1839 pcil->latime.hours = filesl[l]->latime.hours;
1840 pcil->crdate.day = filesl[l]->crdate.day;
1841 pcil->crdate.month = filesl[l]->crdate.month;
1842 pcil->crdate.year = filesl[l]->crdate.year + 1980;
1843 pcil->crtime.seconds = filesl[l]->crtime.twosecs * 2;
1844 pcil->crtime.minutes = filesl[l]->crtime.minutes;
1845 pcil->crtime.hours = filesl[l]->crtime.hours;
1846 if (*cmp->dcd.mask.szMask) {
1847 if (!Filter((PMINIRECORDCORE)pcil, (PVOID)&cmp->dcd.mask)) {
1848 pcil->rc.flRecordAttr |= CRA_FILTERED;
1849 pcir->rc.flRecordAttr |= CRA_FILTERED;
1850 }
1851 }
1852 } // if on left
1853
1854 if (x >= 0) {
1855 // File appears on right side
1856 cmp->cmp->totalright++;
1857 insertedr++;
1858 BldFullPathName(szBuf, cmp->rightdir, filesr[r]->fname);
1859 pcir->pszFileName = xstrdup(szBuf, pszSrcFile, __LINE__); // 31 Jul 07 SHL
1860 pcir->pszDisplayName = pcir->pszFileName + lenr;
1861 pcir->attrFile = filesr[r]->attrFile;
1862 // pcir->rc.hptrIcon = hptrFile;
1863 pcir->pszDispAttr = FileAttrToString(pcir->attrFile);
1864 pcir->cbFile = filesr[r]->cbFile;
1865 // 12 Jan 08 SHL fixme to used cached size here too
1866 CommaFmtULL(szBuf, sizeof(szBuf), pcir->cbFile, ' ');
1867 pcir->pszFmtFileSize = xstrdup(szBuf, pszSrcFile, __LINE__);
1868 pcir->easize = filesr[r]->easize;
1869 pcir->date.day = filesr[r]->date.day;
1870 pcir->date.month = filesr[r]->date.month;
1871 pcir->date.year = filesr[r]->date.year + 1980;
1872 pcir->time.seconds = filesr[r]->time.twosecs * 2;
1873 pcir->time.minutes = filesr[r]->time.minutes;
1874 pcir->time.hours = filesr[r]->time.hours;
1875 pcir->ladate.day = filesr[r]->ladate.day;
1876 pcir->ladate.month = filesr[r]->ladate.month;
1877 pcir->ladate.year = filesr[r]->ladate.year + 1980;
1878 pcir->latime.seconds = filesr[r]->latime.twosecs * 2;
1879 pcir->latime.minutes = filesr[r]->latime.minutes;
1880 pcir->latime.hours = filesr[r]->latime.hours;
1881 pcir->crdate.day = filesr[r]->crdate.day;
1882 pcir->crdate.month = filesr[r]->crdate.month;
1883 pcir->crdate.year = filesr[r]->crdate.year + 1980;
1884 pcir->crtime.seconds = filesr[r]->crtime.twosecs * 2;
1885 pcir->crtime.minutes = filesr[r]->crtime.minutes;
1886 pcir->crtime.hours = filesr[r]->crtime.hours;
1887 // Bypass check if already filtered on left side
1888 if (~pcir->rc.flRecordAttr & CRA_FILTERED &&
1889 *cmp->dcd.mask.szMask) {
1890 if (!Filter((PMINIRECORDCORE)pcir, (PVOID)&cmp->dcd.mask)) {
1891 pcil->rc.flRecordAttr |= CRA_FILTERED;
1892 pcir->rc.flRecordAttr |= CRA_FILTERED;
1893 }
1894 }
1895 } // if on right
1896
1897 if (x == 0) {
1898 // File appears on both sides
1899 pcil->flags |= CNRITEM_EXISTS;
1900 pcir->flags |= CNRITEM_EXISTS;
1901 pch = szBuf;
1902 // Subject field holds status messages
1903 *pch = 0;
1904 if (pcil->cbFile + pcil->easize > pcir->cbFile + pcir->easize) {
1905 pcil->flags |= CNRITEM_LARGER;
1906 pcir->flags |= CNRITEM_SMALLER;
1907 strcpy(pch, GetPString(IDS_LARGERTEXT));
1908 pch += 6;
1909 }
1910 else if (pcil->cbFile + pcil->easize <
1911 pcir->cbFile + pcir->easize) {
1912 pcil->flags |= CNRITEM_SMALLER;
1913 pcir->flags |= CNRITEM_LARGER;
1914 strcpy(pch, GetPString(IDS_SMALLERTEXT));
1915 pch += 7;
1916 }
1917 ret = TestCDates(&pcir->date, &pcir->time,
1918 &pcil->date, &pcil->time);
1919 if (ret == 1) {
1920 pcil->flags |= CNRITEM_NEWER;
1921 pcir->flags |= CNRITEM_OLDER;
1922 if (pch != szBuf) {
1923 strcpy(pch, ", ");
1924 pch += 2;
1925 }
1926 strcpy(pch, GetPString(IDS_NEWERTEXT));
1927 pch += 5;
1928 }
1929 else if (ret == -1) {
1930 pcil->flags |= CNRITEM_OLDER;
1931 pcir->flags |= CNRITEM_NEWER;
1932 if (pch != szBuf) {
1933 strcpy(pch, ", ");
1934 pch += 2;
1935 }
1936 strcpy(pch, GetPString(IDS_OLDERTEXT));
1937 pch += 5;
1938 }
1939 pcil->pszSubject = *szBuf ?
1940 xstrdup(szBuf, pszSrcFile, __LINE__) :
1941 NullStr;
1942
1943 } // if on both sides
1944
1945 if (x <= 0)
1946 free(filesl[l++]); // Done with item on left
1947
1948 if (x >= 0)
1949 free(filesr[r++]); // Done with item on right
1950
1951 // Ensure empty buffers point somewhere
1952 if (!pcil->pszFileName) {
1953 pcil->pszFileName = NullStr;
1954 pcil->pszDisplayName = pcil->pszFileName;
1955 }
1956
1957 if (!pcir->pszFileName) {
1958 pcir->pszFileName = NullStr;
1959 pcir->pszDisplayName = pcir->pszFileName;
1960 }
1961
1962 pcil->rc.pszIcon = pcil->pszDisplayName;
1963 pcir->rc.pszIcon = pcir->pszDisplayName;
1964
1965 pcil->pszLongName = NullStr;
1966 pcir->pszLongName = NullStr;
1967
1968 if (!pcil->pszSubject)
1969 if (!pcir->pszSubject)
1970 pcir->pszSubject = NullStr;
1971
1972 if (!pcil->pszDispAttr)
1973 pcil->pszDispAttr = NullStr;
1974 if (!pcir->pszDispAttr)
1975 pcir->pszDispAttr = NullStr;
1976
1977 // Avoid hogging systems
1978 SleepIfNeeded(&itdSleep, 0);
1979
1980 pcil = (PCNRITEM)pcil->rc.preccNextRecord;
1981 pcir = (PCNRITEM)pcir->rc.preccNextRecord;
1982
1983 if (pcil == NULL || pcir == NULL) {
1984 RECORDINSERT ri;
1985 if (pcil != pcir) {
1986 Runtime_Error(pszSrcFile, __LINE__, "pcil and pcir out of sync");
1987 cmp->stop = TRUE;
1988 break;
1989 }
1990 // Say inserting
1991 WinSendMsg(cmp->hwnd, UM_CONTAINERDIR, MPVOID, MPVOID);
1992
1993 // Insert left side
1994 memset(&ri, 0, sizeof(RECORDINSERT));
1995 ri.cb = sizeof(RECORDINSERT);
1996 ri.pRecordOrder = (PRECORDCORE)CMA_END;
1997 ri.pRecordParent = (PRECORDCORE)NULL;
1998 ri.zOrder = (ULONG)CMA_TOP;
1999 ri.cRecordsInsert = ulRecsToInsert;
2000 ri.fInvalidateRecord = FALSE;
2001
2002 if (!WinSendMsg(hwndLeft, CM_INSERTRECORD,
2003 MPFROMP(pcilFirst), MPFROMP(&ri))) {
2004 Win_Error(hwndLeft, cmp->hwnd, pszSrcFile, __LINE__, "CM_INSERTRECORD");
2005 FreeCnrItemList(hwndLeft, pcilFirst);
2006 cmp->cmp->totalleft -= insertedl;
2007 }
2008 pcilFirst = NULL;
2009
2010 // Insert right side
2011 memset(&ri, 0, sizeof(RECORDINSERT));
2012 ri.cb = sizeof(RECORDINSERT);
2013 ri.pRecordOrder = (PRECORDCORE)CMA_END;
2014 ri.pRecordParent = (PRECORDCORE)NULL;
2015 ri.zOrder = (ULONG)CMA_TOP;
2016 ri.cRecordsInsert = ulRecsToInsert;
2017 ri.fInvalidateRecord = FALSE;
2018
2019 if (!WinSendMsg(hwndRight, CM_INSERTRECORD,
2020 MPFROMP(pcirFirst), MPFROMP(&ri))) {
2021 Win_Error(hwndRight, cmp->hwnd, pszSrcFile, __LINE__, "CM_INSERTRECORD");
2022 // 2011-05-29 SHL fixme?
2023 RemoveCnrItems(hwndLeft, NULL, 0, CMA_FREE | CMA_INVALIDATE);
2024 FreeCnrItemList(hwndRight, pcirFirst);
2025 cmp->cmp->totalright -= insertedr;
2026 }
2027 pcirFirst = NULL;
2028 } // if need insert
2029
2030 } // while filling left or right
2031
2032 // If stopped early clean up
2033
2034 if (cmp->stop) {
2035 // Free up container records that we did not insert in container
2036 if (pcilFirst)
2037 FreeCnrItemList(hwndLeft, pcilFirst);
2038
2039 // Free up items we did not insert in container
2040 if (filesl) {
2041 for(; filesl[l]; l++) {
2042 free(filesl[l]);
2043 }
2044 }
2045
2046 if (pcirFirst)
2047 FreeCnrItemList(hwndRight, pcirFirst);
2048
2049 if (filesr) {
2050 for (; filesr[r]; r++) {
2051 free(filesr[r]);
2052 }
2053 }
2054 } // if insufficient resources
2055
2056 xfree(filesl, pszSrcFile, __LINE__); // Free header - have already freed elements
2057 filesl = NULL;
2058 xfree(filesr, pszSrcFile, __LINE__);
2059 filesr = NULL;
2060
2061 } // if ulRecsNeeded
2062
2063 Deselect(hwndLeft);
2064 Deselect(hwndRight);
2065
2066 // Request window update
2067 if (!PostMsg(cmp->hwnd, UM_CONTAINER_FILLED, MPVOID, MPVOID))
2068 WinSendMsg(cmp->hwnd, UM_CONTAINER_FILLED, MPVOID, MPVOID);
2069 notified = TRUE;
2070
2071 if (filesl)
2072 FreeList((CHAR **)filesl); // Must have failed to create container
2073 if (filesr)
2074 FreeList((CHAR **)filesr);
2075
2076 WinDestroyMsgQueue(hmq);
2077 } // if have queue
2078 if (!notified)
2079 PostMsg(cmp->hwnd, UM_CONTAINER_FILLED, MPVOID, MPVOID);
2080 DecrThreadUsage();
2081 WinTerminate(hab);
2082 }
2083 free(cmp);
2084 DosPostEventSem(CompactSem);
2085
2086# ifdef FORTIFY
2087 Fortify_LeaveScope();
2088# endif
2089
2090}
2091
2092/**
2093 * Find matching item in other container
2094 * @return PCNRITEM or NULL
2095 */
2096
2097static PCNRITEM FindMatchingItem(PCNRITEM pciFindS, HWND hwndCnrS, HWND hwndCnrD);
2098
2099static PCNRITEM FindMatchingItem(PCNRITEM pciFindS, HWND hwndCnrS, HWND hwndCnrD)
2100{
2101
2102 PCNRITEM pciS;
2103 PCNRITEM pciD;
2104
2105 pciS = WinSendMsg(hwndCnrS, CM_QUERYRECORD, MPVOID,
2106 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
2107 pciD = WinSendMsg(hwndCnrD, CM_QUERYRECORD, MPVOID,
2108 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
2109 while (pciS && (INT)pciS != -1 && pciD && (INT)pciD != -1) {
2110
2111 if (pciS == pciFindS)
2112 break;
2113
2114 pciS = WinSendMsg(hwndCnrS, CM_QUERYRECORD, MPFROMP(pciS),
2115 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
2116 pciD = WinSendMsg(hwndCnrD, CM_QUERYRECORD, MPFROMP(pciD),
2117 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
2118 } // while
2119
2120 if (pciS != pciFindS)
2121 pciD = NULL;
2122
2123 return pciD;
2124}
2125
2126/**
2127 * Set button/window enables
2128 */
2129
2130static VOID SetButtonEnables(COMPARE* cmp, BOOL fEnable);
2131
2132static VOID SetButtonEnables(COMPARE* cmp, BOOL fEnable)
2133{
2134 HWND hwnd = cmp->hwnd;
2135 HWND hwndLeft = GetHwndLeft(hwnd);
2136 HWND hwndRight = GetHwndRight(hwnd);
2137
2138 if (!fEnable) {
2139 /* Disable before */
2140 WinEnableWindowUpdate(hwndLeft, fEnable);
2141 WinEnableWindowUpdate(hwndRight, fEnable);
2142 }
2143 WinEnableWindow(hwndLeft, fEnable);
2144 WinEnableWindow(hwndRight, fEnable);
2145 if (fEnable) {
2146 /* Enable after */
2147 WinEnableWindowUpdate(hwndLeft, fEnable);
2148 WinEnableWindowUpdate(hwndRight, fEnable);
2149 }
2150
2151 WinEnableWindow(WinWindowFromID(hwnd, DID_OK), fEnable);
2152 // WinEnableWindow(WinWindowFromID(hwnd, DID_CANCEL), fEnable);
2153 WinEnableWindow(WinWindowFromID(hwnd, COMP_COLLECT), fEnable);
2154 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTBOTH), fEnable);
2155 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTONE), fEnable);
2156 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTNEWER), fEnable);
2157 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTOLDER), fEnable);
2158 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTBIGGER), fEnable);
2159 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTSMALLER), fEnable);
2160 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTBOTH), fEnable);
2161 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTONE), fEnable);
2162 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTNEWER), fEnable);
2163 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTOLDER), fEnable);
2164 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTBIGGER), fEnable);
2165 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTSMALLER), fEnable);
2166 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTALL), fEnable);
2167 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTSAMECONTENT), fEnable);
2168 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTIDENTICAL), fEnable);
2169 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTSAME), fEnable);
2170 WinEnableWindow(WinWindowFromID(hwnd, IDM_INVERT), fEnable);
2171 WinEnableWindow(WinWindowFromID(hwnd, COMP_SETDIRS), fEnable);
2172 WinEnableWindow(WinWindowFromID(hwnd, COMP_DELETELEFT), fEnable);
2173 WinEnableWindow(WinWindowFromID(hwnd, COMP_FILTER), fEnable);
2174 if (!fEnable || !*cmp->rightlist ) {
2175 WinEnableWindow(WinWindowFromID(hwnd, COMP_COPYLEFT), fEnable);
2176 WinEnableWindow(WinWindowFromID(hwnd, COMP_MOVELEFT), fEnable);
2177 WinEnableWindow(WinWindowFromID(hwnd, COMP_DELETERIGHT), fEnable);
2178 WinEnableWindow(WinWindowFromID(hwnd, COMP_COPYRIGHT), fEnable);
2179 WinEnableWindow(WinWindowFromID(hwnd, COMP_MOVERIGHT), fEnable);
2180 }
2181 WinEnableWindow(WinWindowFromID(hwnd, COMP_INCLUDESUBDIRS), fEnable);
2182 WinEnableWindow(WinWindowFromID(hwnd, COMP_HIDENOTSELECTED), fEnable);
2183}
2184
2185/**
2186 * Compare directories dialog procedure
2187 */
2188
2189MRESULT EXPENTRY CompareDlgProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
2190{
2191 COMPARE *cmp;
2192 BOOL temp;
2193 CHAR szPathName[CCHMAXPATH];
2194 CHAR s[81];
2195
2196 static HPOINTER hptr;
2197
2198 switch (msg) {
2199 case WM_INITDLG:
2200 cmp = (COMPARE *)mp2;
2201 if (!cmp) {
2202 Runtime_Error(pszSrcFile, __LINE__, NULL);
2203 WinDismissDlg(hwnd, 0);
2204 }
2205 else {
2206 if (!hptr)
2207 hptr = WinLoadPointer(HWND_DESKTOP, FM3ModHandle, COMPARE_ICON);
2208 WinDefDlgProc(hwnd, WM_SETICON, MPFROMLONG(hptr), MPVOID);
2209 cmp->hwnd = hwnd;
2210 WinSetWindowPtr(hwnd, QWL_USER, (PVOID)cmp);
2211 {
2212 SWP swp;
2213 ULONG size = sizeof(SWP);
2214
2215 PrfQueryProfileData(fmprof, FM3Str, "CompDir.Position", (PVOID) &swp, &size);
2216 swp.fl &= ~SWP_SIZE; // 04 Feb 09 SHL ignore saved size
2217 WinSetWindowPos(hwnd,
2218 HWND_TOP,
2219 swp.x,
2220 swp.y,
2221 swp.cx,
2222 swp.cy,
2223 swp.fl);
2224 }
2225 SetCnrCols(GetHwndLeft(hwnd), TRUE);
2226 SetCnrCols(GetHwndRight(hwnd), TRUE);
2227 if (cmp->listfile) {
2228 CHAR fullname[CCHMAXPATH];
2229
2230 strcpy(fullname, PCSZ_STARDOTPMD);
2231 if (insert_filename(HWND_DESKTOP, fullname, TRUE, FALSE) &&
2232 *fullname && !strchr(fullname, '*') && !strchr(fullname, '?'))
2233 strcpy(cmp->rightlist, fullname);
2234 }
2235 WinSendMsg(hwnd, UM_SETUP, MPVOID, MPVOID);
2236 WinSendMsg(hwnd, UM_SETDIR, MPVOID, MPVOID);
2237 PostMsg(hwnd, UM_STRETCH, MPVOID, MPVOID);
2238 {
2239 USHORT ids[] = {COMP_FRAME, COMP_LEFTDIR, COMP_RIGHTDIR, COMP_COLLECT,
2240 COMP_VIEW, COMP_NOTE, COMP_TOTALLEFT, COMP_SELLEFT, COMP_TOTALRIGHT,
2241 COMP_SELRIGHT, COMP_CNRMENU, COMP_DIRMENU, COMP_MENU,
2242 COMP_INCLUDESUBDIRS, COMP_SETDIRS, COMP_COPYLEFT, COMP_MOVELEFT,
2243 COMP_DELETELEFT, COMP_COPYRIGHT, COMP_MOVERIGHT, COMP_DELETERIGHT,
2244 COMP_TOTALLEFTHDR, COMP_SELLEFTHDR, COMP_TOTALRIGHTHDR,
2245 COMP_SELRIGHTHDR, COMP_FILTER, COMP_HIDENOTSELECTED, 0};
2246 UINT x;
2247 CHAR s[24];
2248
2249 for (x = 0; ids[x]; x++) {
2250 //fixme to allow user to change presparams 1-10-09 GKY
2251 sprintf(s, "CompDir%i", ids[x]);
2252 RestorePresParams(WinWindowFromID(hwnd, ids[x]), s);
2253 /*SetPresParams(WinWindowFromID(hwnd, ids[x]),
2254 &RGBGREY,
2255 &RGBBLACK, &RGBBLACK, FNT_8HELVETICA);*/
2256 }
2257 }
2258 WinStartTimer(WinQueryAnchorBlock(hwnd), hwnd, ID_COMP_TIMER, 500);
2259 }
2260 break;
2261
2262 case UM_STRETCH:
2263 {
2264 SWP swp, swpC;
2265 LONG titl, szbx, szby, sz;
2266 HWND hwndActive;
2267
2268 WinQueryWindowPos(hwnd, &swp);
2269 if (!(swp.fl & (SWP_HIDE | SWP_MINIMIZE))) {
2270 hwndActive = WinQueryFocus(HWND_DESKTOP);
2271 szbx = SysVal(SV_CXSIZEBORDER);
2272 szby = SysVal(SV_CYSIZEBORDER);
2273 titl = SysVal(SV_CYTITLEBAR);
2274 titl += 26;
2275 swp.cx -= (szbx * 2);
2276 sz = (swp.cx / 8);
2277 WinQueryWindowPos(WinWindowFromID(hwnd, COMP_LEFTDIR), &swpC);
2278 WinSetWindowPos(WinWindowFromID(hwnd, COMP_LEFTDIR), HWND_TOP,
2279 szbx + 6,
2280 swpC.y,
2281 (swp.cx / 2) - (szbx + 6),
2282 ((swp.cy - swpC.y) - titl) - szby,
2283 SWP_MOVE | SWP_SIZE);
2284 WinSetWindowPos(WinWindowFromID(hwnd, COMP_RIGHTDIR), HWND_TOP,
2285 (swp.cx / 2) + (szbx + 6),
2286 swpC.y,
2287 (swp.cx / 2) - (szbx + 6),
2288 ((swp.cy - swpC.y) - titl) - szby,
2289 SWP_MOVE | SWP_SIZE);
2290 WinSetWindowPos(WinWindowFromID(hwnd, COMP_TOTALLEFTHDR), HWND_TOP,
2291 szbx + 6,
2292 ((swp.cy - titl) - szby) + 4,
2293 sz - (szbx + 6), 20, SWP_MOVE | SWP_SIZE);
2294 WinSetWindowPos(WinWindowFromID(hwnd, COMP_TOTALLEFT), HWND_TOP,
2295 sz + (szbx + 6),
2296 ((swp.cy - titl) - szby) + 4,
2297 sz - (szbx + 6), 20, SWP_MOVE | SWP_SIZE);
2298 WinSetWindowPos(WinWindowFromID(hwnd, COMP_SELLEFTHDR), HWND_TOP,
2299 (sz * 2) + (szbx + 6),
2300 ((swp.cy - titl) - szby) + 4,
2301 sz - (szbx + 6), 20, SWP_MOVE | SWP_SIZE);
2302 WinSetWindowPos(WinWindowFromID(hwnd, COMP_SELLEFT), HWND_TOP,
2303 (sz * 3) + (szbx + 6),
2304 ((swp.cy - titl) - szby) + 4,
2305 sz - (szbx + 6), 20, SWP_MOVE | SWP_SIZE);
2306 WinSetWindowPos(WinWindowFromID(hwnd, COMP_TOTALRIGHTHDR), HWND_TOP,
2307 (sz * 4) + (szbx + 6),
2308 ((swp.cy - titl) - szby) + 4,
2309 sz - (szbx + 6), 20, SWP_MOVE | SWP_SIZE);
2310 WinSetWindowPos(WinWindowFromID(hwnd, COMP_TOTALRIGHT), HWND_TOP,
2311 (sz * 5) + (szbx + 6),
2312 ((swp.cy - titl) - szby) + 4,
2313 sz - (szbx + 6), 20, SWP_MOVE | SWP_SIZE);
2314 WinSetWindowPos(WinWindowFromID(hwnd, COMP_SELRIGHTHDR), HWND_TOP,
2315 (sz * 6) + (szbx + 6),
2316 ((swp.cy - titl) - szby) + 4,
2317 sz - (szbx + 6), 20, SWP_MOVE | SWP_SIZE);
2318 WinSetWindowPos(WinWindowFromID(hwnd, COMP_SELRIGHT), HWND_TOP,
2319 (sz * 7) + (szbx + 6),
2320 ((swp.cy - titl) - szby) + 4,
2321 sz - (szbx + 6), 20, SWP_MOVE | SWP_SIZE);
2322 PaintRecessedWindow(WinWindowFromID(hwnd, COMP_TOTALLEFT),
2323 (HPS)0, FALSE, FALSE);
2324 PaintRecessedWindow(WinWindowFromID(hwnd, COMP_SELLEFT),
2325 (HPS)0, FALSE, FALSE);
2326 PaintRecessedWindow(WinWindowFromID(hwnd, COMP_TOTALRIGHT),
2327 (HPS)0, FALSE, FALSE);
2328 PaintRecessedWindow(WinWindowFromID(hwnd, COMP_SELRIGHT),
2329 (HPS)0, FALSE, FALSE);
2330 PaintRecessedWindow(GetHwndLeft(hwnd), (HPS)0,
2331 (hwndActive == GetHwndLeft(hwnd)), TRUE);
2332 PaintRecessedWindow(GetHwndRight(hwnd), (HPS)0,
2333 (hwndActive == GetHwndRight(hwnd)), TRUE);
2334 }
2335 }
2336 return 0;
2337
2338 case WM_ADJUSTWINDOWPOS:
2339 PostMsg(hwnd, UM_STRETCH, MPVOID, MPVOID);
2340 break;
2341
2342 case UM_SETUP:
2343 {
2344 CNRINFO cnri;
2345 BOOL tempsubj;
2346
2347 cmp = INSTDATA(hwnd);
2348 if (!cmp)
2349 Runtime_Error(pszSrcFile, __LINE__, NULL);
2350 else {
2351 cmp->dcd.size = sizeof(DIRCNRDATA);
2352 cmp->dcd.type = DIR_FRAME;
2353 cmp->dcd.hwndFrame = hwnd;
2354 cmp->dcd.hwndClient = hwnd;
2355 cmp->dcd.mask.attrFile = (FILE_DIRECTORY | FILE_ARCHIVED |
2356 FILE_READONLY | FILE_SYSTEM | FILE_HIDDEN);
2357 LoadDetailsSwitches(PCSZ_DIRCMP, &cmp->dcd.ds, FALSE);
2358 cmp->dcd.ds.detailslongname = FALSE;
2359 cmp->dcd.ds.detailsicon = FALSE; // TRUE;
2360 }
2361 memset(&cnri, 0, sizeof(CNRINFO));
2362 cnri.cb = sizeof(CNRINFO);
2363 WinSendDlgItemMsg(hwnd, COMP_LEFTDIR, CM_QUERYCNRINFO,
2364 MPFROMP(&cnri), MPFROMLONG(sizeof(CNRINFO)));
2365 cnri.flWindowAttr |= (CA_OWNERDRAW | CV_MINI);
2366 cnri.xVertSplitbar = DIR_SPLITBAR_OFFSET - 68;
2367 WinSendDlgItemMsg(hwnd, COMP_LEFTDIR, CM_SETCNRINFO, MPFROMP(&cnri),
2368 MPFROMLONG(CMA_FLWINDOWATTR | CMA_XVERTSPLITBAR));
2369 memset(&cnri, 0, sizeof(CNRINFO));
2370 cnri.cb = sizeof(CNRINFO);
2371 WinSendDlgItemMsg(hwnd, COMP_RIGHTDIR, CM_QUERYCNRINFO,
2372 MPFROMP(&cnri), MPFROMLONG(sizeof(CNRINFO)));
2373 cnri.flWindowAttr |= (CA_OWNERDRAW | CV_MINI);
2374 cnri.xVertSplitbar = DIR_SPLITBAR_OFFSET - 54;
2375 WinSendDlgItemMsg(hwnd, COMP_RIGHTDIR, CM_SETCNRINFO, MPFROMP(&cnri),
2376 MPFROMLONG(CMA_FLWINDOWATTR | CMA_XVERTSPLITBAR));
2377 AdjustCnrColRO(GetHwndLeft(hwnd), GetPString(IDS_FILENAMECOLTEXT), TRUE, FALSE);
2378 AdjustCnrColRO(GetHwndLeft(hwnd), GetPString(IDS_LONGNAMECOLTEXT), TRUE, FALSE);
2379 AdjustCnrColRO(GetHwndRight(hwnd), GetPString(IDS_FILENAMECOLTEXT), TRUE, FALSE);
2380 AdjustCnrColRO(GetHwndRight(hwnd), GetPString(IDS_LONGNAMECOLTEXT), TRUE, FALSE);
2381 AdjustCnrColsForPref(GetHwndLeft(hwnd), cmp->leftdir, &cmp->dcd.ds, TRUE);
2382 tempsubj = cmp->dcd.ds.detailssubject;
2383 cmp->dcd.ds.detailssubject = FALSE;
2384 AdjustCnrColsForPref(GetHwndRight(hwnd), cmp->rightdir, &cmp->dcd.ds, TRUE);
2385 if (*cmp->rightlist) {
2386 AdjustCnrColVis(GetHwndRight(hwnd), GetPString(IDS_LADATECOLTEXT), FALSE,
2387 FALSE);
2388 AdjustCnrColVis(GetHwndRight(hwnd), GetPString(IDS_LATIMECOLTEXT), FALSE,
2389 FALSE);
2390 AdjustCnrColVis(GetHwndRight(hwnd), GetPString(IDS_CRDATECOLTEXT), FALSE,
2391 FALSE);
2392 AdjustCnrColVis(GetHwndRight(hwnd), GetPString(IDS_CRTIMECOLTEXT), FALSE,
2393 FALSE);
2394 }
2395 cmp->dcd.ds.detailssubject = tempsubj;
2396 }
2397 return 0;
2398
2399 case WM_DRAWITEM:
2400 if (mp2) {
2401 POWNERITEM pown = (POWNERITEM)mp2;
2402 PCNRDRAWITEMINFO pcown;
2403 PCNRITEM pci;
2404
2405 pcown = (PCNRDRAWITEMINFO)pown->hItem;
2406 if (pcown) {
2407 pci = (PCNRITEM)pcown->pRecord;
2408 // 01 Aug 07 SHL if field null or blank, we draw
2409 // fixme to document why - probably to optimize and bypass draw?
2410 if (pci && (INT)pci != -1 && !*pci->pszFileName)
2411 return MRFROMLONG(TRUE);
2412 }
2413 }
2414 return 0;
2415
2416 case UM_CONTAINERHWND:
2417 // Building list
2418 WinSetDlgItemText(hwnd, COMP_NOTE, (CHAR *) GetPString(IDS_COMPHOLDBLDLISTTEXT));
2419 return 0;
2420
2421 case UM_CONTAINERDIR:
2422 // Filling container
2423 WinSetDlgItemText(hwnd, COMP_NOTE, (CHAR *) GetPString(IDS_COMPHOLDFILLCNRTEXT));
2424 return 0;
2425
2426 case WM_TIMER:
2427 // Show current totals
2428 cmp = INSTDATA(hwnd);
2429 if (!cmp) {
2430 Runtime_Error(pszSrcFile, __LINE__, "pCompare NULL");
2431 WinDismissDlg(hwnd, 0);
2432 }
2433 else {
2434 if (cmp->uOldTotalLeft != cmp->totalleft) {
2435 cmp->uOldTotalLeft = cmp->totalleft;
2436 sprintf(s, " %d", cmp->totalleft);
2437 WinSetDlgItemText(hwnd, COMP_TOTALLEFT, s);
2438 }
2439 if (cmp->uOldTotalRight != cmp->totalright) {
2440 cmp->uOldTotalRight = cmp->totalright;
2441 sprintf(s, " %d", cmp->totalright);
2442 WinSetDlgItemText(hwnd, COMP_TOTALRIGHT, s);
2443 }
2444 if (cmp->uOldSelLeft != cmp->selleft) {
2445 cmp->uOldSelLeft = cmp->selleft;
2446 sprintf(s, " %d", cmp->selleft);
2447 WinSetDlgItemText(hwnd, COMP_SELLEFT, s);
2448 }
2449 if (cmp->uOldSelRight != cmp->selright) {
2450 cmp->uOldSelRight = cmp->selright;
2451 sprintf(s, " %d", cmp->selright);
2452 WinSetDlgItemText(hwnd, COMP_SELRIGHT, s);
2453 }
2454 }
2455 break;
2456
2457 case UM_CONTAINER_FILLED:
2458 cmp = INSTDATA(hwnd);
2459 if (!cmp) {
2460 Runtime_Error(pszSrcFile, __LINE__, "pCompare NULL");
2461 WinDismissDlg(hwnd, 0);
2462 }
2463 else if (cmp->stop) {
2464 // Delayed cancel
2465 WinDismissDlg(hwnd, 1);
2466 }
2467 else {
2468 cmp->filling = FALSE;
2469 SetButtonEnables(cmp, TRUE);
2470 WinPostMsg(hwnd, WM_TIMER, MPFROMLONG(ID_COMP_TIMER), 0); // Force counts to update
2471 if (*cmp->dcd.mask.szMask) {
2472 sprintf(s, GetPString(IDS_COMPREADYFILTEREDTEXT), cmp->dcd.mask.szMask);
2473 WinSetDlgItemText(hwnd, COMP_NOTE, s);
2474 }
2475 else
2476 WinSetDlgItemText(hwnd, COMP_NOTE, (CHAR *) GetPString(IDS_COMPREADYTEXT));
2477 }
2478 break;
2479
2480 case WM_INITMENU:
2481 cmp = INSTDATA(hwnd);
2482 if (cmp) {
2483 switch (SHORT1FROMMP(mp1)) {
2484 case IDM_COMMANDSMENU:
2485 SetupCommandMenu(cmp->dcd.hwndLastMenu, hwnd);
2486 break;
2487 }
2488 }
2489 break;
2490
2491 case WM_MENUEND:
2492 cmp = INSTDATA(hwnd);
2493 if (cmp) {
2494 if ((HWND)mp2 == cmp->dcd.hwndLastMenu) {
2495 MarkAll(GetHwndLeft(hwnd), TRUE, FALSE, TRUE);
2496 MarkAll(GetHwndRight(hwnd), TRUE, FALSE, TRUE);
2497 WinDestroyWindow(cmp->dcd.hwndLastMenu);
2498 cmp->dcd.hwndLastMenu = (HWND)0;
2499 }
2500 }
2501 break;
2502
2503 case WM_CONTROL:
2504 switch (SHORT1FROMMP(mp1)) {
2505 case COMP_INCLUDESUBDIRS:
2506 switch (SHORT2FROMMP(mp1)) {
2507 case BN_CLICKED:
2508 cmp = INSTDATA(hwnd);
2509 if (cmp)
2510 *cmp->rightlist = 0;
2511 PostMsg(hwnd, UM_SETUP, MPVOID, MPVOID);
2512 PostMsg(hwnd, UM_SETDIR, MPVOID, MPVOID);
2513 break;
2514 }
2515 break;
2516 case COMP_HIDENOTSELECTED:
2517 switch (SHORT2FROMMP(mp1)) {
2518 case BN_CLICKED:
2519 WinSendMsg(hwnd, UM_HIDENOTSELECTED, MPVOID, MPVOID);
2520 break;
2521 }
2522 break;
2523
2524 case COMP_LEFTDIR:
2525 case COMP_RIGHTDIR:
2526 switch (SHORT2FROMMP(mp1)) {
2527 case CN_KILLFOCUS:
2528 PaintRecessedWindow(WinWindowFromID(hwnd, SHORT1FROMMP(mp1)),
2529 (HPS)0, FALSE, TRUE);
2530 break;
2531
2532 case CN_SETFOCUS:
2533 PaintRecessedWindow(WinWindowFromID(hwnd, SHORT1FROMMP(mp1)),
2534 (HPS)0, TRUE, TRUE);
2535 break;
2536
2537 case CN_ENTER:
2538 if (mp2) {
2539
2540 PCNRITEM pci = (PCNRITEM)((PNOTIFYRECORDENTER)mp2)->pRecord;
2541 HWND hwndCnr = WinWindowFromID(hwnd, SHORT1FROMMP(mp1));
2542
2543 SetShiftState();
2544 if (pci) {
2545 if (pci->rc.flRecordAttr & CRA_INUSE || !pci || !*pci->pszFileName)
2546 break;
2547 WinSendMsg(hwndCnr, CM_SETRECORDEMPHASIS, MPFROMP(pci),
2548 MPFROM2SHORT(TRUE, CRA_INUSE));
2549 if (pci->attrFile & FILE_DIRECTORY) {
2550 if ((shiftstate & (KC_CTRL | KC_SHIFT)) == (KC_CTRL | KC_SHIFT))
2551 OpenObject(pci->pszFileName, Settings, hwnd);
2552 else
2553 OpenObject(pci->pszFileName, Default, hwnd);
2554 }
2555 else
2556 DefaultViewKeys(hwnd, hwnd, HWND_DESKTOP, NULL,
2557 pci->pszFileName);
2558 WinSendMsg(hwndCnr, CM_SETRECORDEMPHASIS,
2559 MPFROMP(pci),
2560 MPFROM2SHORT(FALSE,
2561 CRA_INUSE | (fUnHilite ? CRA_SELECTED : 0)));
2562 }
2563 }
2564 break;
2565
2566 case CN_CONTEXTMENU:
2567 cmp = INSTDATA(hwnd);
2568 if (cmp) {
2569 PCNRITEM pci = (PCNRITEM)mp2;
2570 USHORT id = COMP_CNRMENU; // Assume container menu
2571
2572 if (cmp->dcd.hwndLastMenu)
2573 WinDestroyWindow(cmp->dcd.hwndLastMenu);
2574 cmp->dcd.hwndLastMenu = (HWND)0;
2575 cmp->hwndCalling = WinWindowFromID(hwnd, SHORT1FROMMP(mp1));
2576 if (pci) {
2577 if (!pci || !*pci->pszFileName || *cmp->rightlist)
2578 break;
2579 id = COMP_MENU; // Want container item menu
2580 WinSendMsg(cmp->hwndCalling, CM_SETRECORDEMPHASIS,
2581 MPFROMP(pci), MPFROM2SHORT(TRUE, CRA_CURSORED));
2582 }
2583 cmp->dcd.hwndLastMenu = WinLoadMenu(HWND_DESKTOP, FM3ModHandle, id);
2584 if (cmp->dcd.hwndLastMenu) {
2585 switch (id) {
2586 case COMP_CNRMENU:
2587 if (SHORT1FROMMP(mp1) == COMP_RIGHTDIR)
2588 WinSendMsg(cmp->dcd.hwndLastMenu, MM_DELETEITEM,
2589 MPFROM2SHORT(IDM_SHOWSUBJECT, FALSE), MPVOID);
2590 SetDetailsSwitches(cmp->dcd.hwndLastMenu, &cmp->dcd.ds);
2591 if (SHORT1FROMMP(mp1) == COMP_LEFTDIR)
2592 WinSendMsg(cmp->dcd.hwndLastMenu, MM_DELETEITEM,
2593 MPFROM2SHORT(IDM_LOADLISTFILE, 0), MPVOID);
2594 else if (*cmp->rightlist)
2595 WinSendMsg(cmp->dcd.hwndLastMenu, MM_DELETEITEM,
2596 MPFROM2SHORT(IDM_SAVELISTFILE, 0), MPVOID);
2597 break;
2598 case COMP_MENU:
2599 // Can't compare what's not there
2600 if (~pci->flags & CNRITEM_EXISTS) {
2601 WinSendMsg(cmp->dcd.hwndLastMenu, MM_DELETEITEM,
2602 MPFROM2SHORT(IDM_COMPARE, 0), MPVOID);
2603 }
2604 break;
2605 } // switch
2606 PopupMenu(hwnd, hwnd, cmp->dcd.hwndLastMenu);
2607 }
2608 }
2609 break;
2610
2611 case CN_INITDRAG:
2612 cmp = INSTDATA(hwnd);
2613 if (*cmp->rightlist && SHORT1FROMMP(mp1) == COMP_RIGHTDIR)
2614 break;
2615 DoFileDrag(WinWindowFromID(hwnd, SHORT1FROMMP(mp1)),
2616 (HWND)0, mp2, NULL, NULL, TRUE);
2617 break;
2618
2619 case CN_BEGINEDIT:
2620 case CN_REALLOCPSZ:
2621 // fixme to be gone - field edits not allowed?
2622 Runtime_Error(pszSrcFile, __LINE__,
2623 "CN_BEGINEDIT/CN_REALLOCPSZ unexpected");
2624 break;
2625
2626 case CN_EMPHASIS:
2627 {
2628 PNOTIFYRECORDEMPHASIS pnre = mp2;
2629 BOOL fSelected;
2630 if (pnre->fEmphasisMask & CRA_SELECTED) {
2631 // Select toggled
2632 PCNRITEM pci = (PCNRITEM)pnre->pRecord;
2633 if (pci) {
2634 if (!*pci->pszFileName) {
2635 // User clicked on empty slot - just clear
2636 if (pci->rc.flRecordAttr & CRA_SELECTED)
2637 WinSendDlgItemMsg(hwnd, SHORT1FROMMP(mp1),
2638 CM_SETRECORDEMPHASIS,
2639 MPFROMP(pci),
2640 MPFROM2SHORT(FALSE, CRA_SELECTED));
2641 }
2642 else {
2643 BOOL fUpdateHideButton = FALSE;
2644 cmp = INSTDATA(hwnd);
2645 if (SHORT1FROMMP(mp1) == COMP_LEFTDIR) {
2646 fSelected = pci->rc.flRecordAttr & CRA_SELECTED;
2647 cmp->selleft += fSelected ? 1 : -1;
2648 if (!fSelected)
2649 fUpdateHideButton = TRUE;
2650 }
2651 else if (SHORT1FROMMP(mp1) == COMP_RIGHTDIR) {
2652 fSelected = pci->rc.flRecordAttr & CRA_SELECTED;
2653 cmp->selright += fSelected ? 1 : -1;
2654 if (!fSelected)
2655 fUpdateHideButton = TRUE;
2656 }
2657 else {
2658 Runtime_Error(pszSrcFile, __LINE__,
2659 "mp1 %u unexpected", SHORT1FROMMP(mp1));
2660 }
2661 if (fUpdateHideButton) {
2662 ULONG state = WinQueryButtonCheckstate(hwnd,COMP_HIDENOTSELECTED);
2663 if (state == 1) {
2664 WinCheckButton(hwnd, COMP_HIDENOTSELECTED, 2);
2665 }
2666 }
2667 }
2668 }
2669 }
2670 }
2671 break;
2672
2673 case CN_SCROLL:
2674 cmp = INSTDATA(hwnd);
2675 if (!cmp->forcescroll) {
2676
2677 PNOTIFYSCROLL pns = mp2;
2678
2679 if (pns->fScroll & CMA_VERTICAL) {
2680 cmp->forcescroll = TRUE;
2681 // Scroll other window to match
2682 WinSendDlgItemMsg(hwnd,
2683 SHORT1FROMMP(mp1) == COMP_LEFTDIR ?
2684 COMP_RIGHTDIR : COMP_LEFTDIR,
2685 CM_SCROLLWINDOW,
2686 MPFROMSHORT(CMA_VERTICAL),
2687 MPFROMLONG(pns->lScrollInc));
2688 cmp->forcescroll = FALSE;
2689 }
2690 }
2691 break;
2692 } // switch COMP_LEFTDIR mp1
2693 break; // COMP_LEFTDIR / COMP_RIGHTDIR
2694 } // switch WM_CONTROL mp1
2695 return 0; // WM_CONTROL
2696
2697 case UM_SETDIR:
2698 cmp = INSTDATA(hwnd);
2699 if (cmp) {
2700 COMPARE *forthread;
2701 CNRINFO cnri;
2702 if (cmp->includesubdirs)
2703 WinCheckButton(hwnd, COMP_INCLUDESUBDIRS, TRUE);
2704 cmp->includesubdirs = WinQueryButtonCheckstate(hwnd,
2705 COMP_INCLUDESUBDIRS);
2706 memset(&cnri, 0, sizeof(CNRINFO));
2707 cnri.cb = sizeof(CNRINFO);
2708 cnri.pszCnrTitle = cmp->leftdir;
2709 cnri.flWindowAttr = CV_DETAIL | CV_MINI |
2710 CA_CONTAINERTITLE | CA_TITLESEPARATOR |
2711 CA_DETAILSVIEWTITLES | CA_OWNERDRAW;
2712 WinSendDlgItemMsg(hwnd, COMP_LEFTDIR, CM_SETCNRINFO, MPFROMP(&cnri),
2713 MPFROMLONG(CMA_CNRTITLE | CMA_FLWINDOWATTR));
2714 cnri.pszCnrTitle = cmp->rightdir;
2715 WinSendDlgItemMsg(hwnd, COMP_RIGHTDIR, CM_SETCNRINFO, MPFROMP(&cnri),
2716 MPFROMLONG(CMA_CNRTITLE | CMA_FLWINDOWATTR));
2717 WinCheckButton(hwnd, COMP_HIDENOTSELECTED, 0);
2718 cmp->filling = TRUE;
2719# ifdef FORTIFY
2720 Fortify_EnterScope();
2721# endif
2722 forthread = xmalloc(sizeof(COMPARE), pszSrcFile, __LINE__);
2723 if (!forthread)
2724 WinDismissDlg(hwnd, 0);
2725 else {
2726 *forthread = *cmp;
2727 forthread->cmp = cmp;
2728 if (xbeginthread(FillCnrsThread,
2729 122880,
2730 forthread,
2731 pszSrcFile,
2732 __LINE__) == -1)
2733 {
2734 WinDismissDlg(hwnd, 0);
2735 free(forthread);
2736# ifdef FORTIFY
2737 Fortify_LeaveScope();
2738# endif
2739 }
2740 else {
2741 WinSetDlgItemText(hwnd, COMP_NOTE,
2742 (CHAR *) GetPString(IDS_COMPHOLDREADDISKTEXT));
2743 SetButtonEnables(cmp, FALSE);
2744 cmp->includesubdirs = FALSE;
2745 cmp->selleft = 0;
2746 cmp->selright = 0;
2747 }
2748 }
2749 }
2750 return 0;
2751
2752 case UM_FILTER:
2753 cmp = INSTDATA(hwnd);
2754 if (cmp) {
2755 if (mp1)
2756 SetMask((CHAR *)mp1, &cmp->dcd.mask);
2757
2758 WinSetDlgItemText(hwnd, COMP_NOTE,
2759 (CHAR *) GetPString(IDS_COMPHOLDFILTERINGTEXT));
2760 // cmp->dcd.suspendview = 1; // 12 Jan 08 SHL appears not to be used here
2761 priority_idle(); // Don't hog resources
2762 WinSendMsg(GetHwndLeft(hwnd), CM_FILTER, MPFROMP(Filter),
2763 MPFROMP(&cmp->dcd.mask));
2764 WinSendMsg(GetHwndRight(hwnd), CM_FILTER, MPFROMP(Filter),
2765 MPFROMP(&cmp->dcd.mask));
2766 priority_normal();
2767 // cmp->dcd.suspendview = 0; // 12 Jan 08 SHL appears not to be used here
2768 if (*cmp->dcd.mask.szMask) {
2769 sprintf(s,
2770 GetPString(IDS_COMPREADYFILTEREDTEXT),
2771 cmp->dcd.mask.szMask);
2772 WinSetDlgItemText(hwnd, COMP_NOTE, s);
2773 }
2774 else
2775 WinSetDlgItemText(hwnd, COMP_NOTE, (CHAR *) GetPString(IDS_COMPREADYTEXT));
2776 }
2777 return 0;
2778
2779 case UM_HIDENOTSELECTED:
2780 cmp = INSTDATA(hwnd);
2781 if (cmp) {
2782 ULONG wasHidden = WinQueryButtonCheckstate(hwnd,
2783 COMP_HIDENOTSELECTED);
2784 ULONG nowHidden = wasHidden != 1 && (cmp->selleft || cmp->selright);
2785
2786 // cmp->dcd.suspendview = 1; // 12 Jan 08 SHL appears not to be used here
2787 // 26 Sep 09 SHL Unhide if nothing selected
2788 if (nowHidden) {
2789 // Hide items not selected on both sides
2790 BOOL needRefresh = FALSE;
2791 HWND hwndl = WinWindowFromID(cmp->hwnd, COMP_LEFTDIR);
2792 HWND hwndr = WinWindowFromID(cmp->hwnd, COMP_RIGHTDIR);
2793 PCNRITEM pcil = WinSendMsg(hwndl, CM_QUERYRECORD, MPVOID,
2794 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
2795 PCNRITEM pcir = WinSendMsg(hwndr, CM_QUERYRECORD, MPVOID,
2796 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
2797
2798 while (pcil && (INT)pcil != -1 && pcir && (INT)pcir != -1) {
2799 if (~pcil->rc.flRecordAttr & CRA_SELECTED &&
2800 ~pcir->rc.flRecordAttr & CRA_SELECTED) {
2801 if (~pcil->rc.flRecordAttr & CRA_FILTERED) {
2802 needRefresh = TRUE;
2803 pcil->rc.flRecordAttr |= CRA_FILTERED;
2804 }
2805 if (~pcir->rc.flRecordAttr & CRA_FILTERED) {
2806 pcir->rc.flRecordAttr |= CRA_FILTERED;
2807 needRefresh = TRUE;
2808 }
2809 }
2810 pcil = WinSendMsg(hwndl, CM_QUERYRECORD, MPFROMP(pcil),
2811 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
2812 pcir = WinSendMsg(hwndr, CM_QUERYRECORD, MPFROMP(pcir),
2813 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
2814 } // while
2815 if (needRefresh) {
2816 WinSendMsg(hwndl, CM_INVALIDATERECORD,
2817 MPVOID, MPFROM2SHORT(0, CMA_REPOSITION));
2818 WinSendMsg(hwndr, CM_INVALIDATERECORD,
2819 MPVOID, MPFROM2SHORT(0, CMA_REPOSITION));
2820 }
2821 }
2822 else {
2823 // Unhide
2824 WinSendMsg(GetHwndLeft(hwnd), CM_FILTER, MPFROMP(Filter),
2825 MPFROMP(&cmp->dcd.mask));
2826 WinSendMsg(GetHwndRight(hwnd), CM_FILTER, MPFROMP(Filter),
2827 MPFROMP(&cmp->dcd.mask));
2828 }
2829 // cmp->dcd.suspendview = 0; // 12 Jan 08 SHL appears not to be used here
2830 if (*cmp->dcd.mask.szMask) {
2831 sprintf(s,
2832 GetPString(IDS_COMPREADYFILTEREDTEXT),
2833 cmp->dcd.mask.szMask);
2834 WinSetDlgItemText(hwnd, COMP_NOTE, s);
2835 }
2836 else
2837 WinSetDlgItemText(hwnd, COMP_NOTE, (CHAR *) GetPString(IDS_COMPREADYTEXT));
2838 WinCheckButton(hwnd, COMP_HIDENOTSELECTED, nowHidden);
2839 }
2840 return 0;
2841
2842 case WM_COMMAND:
2843 // 29 Apr 09 SHL fixme to support more context menu items - IDM_VIEW, IDM_EDIT etc.
2844 switch (SHORT1FROMMP(mp1)) {
2845 case IDM_COMPARE:
2846 cmp = INSTDATA(hwnd);
2847 if (cmp) {
2848 PCNRITEM pci;
2849 pci = (PCNRITEM)WinSendMsg(cmp->hwndCalling,
2850 CM_QUERYRECORDEMPHASIS,
2851 MPFROMLONG(CMA_FIRST),
2852 MPFROMSHORT(CRA_CURSORED));
2853 if (pci && *pci->pszFileName) {
2854 if (cmp->hwndCalling == GetHwndLeft(hwnd))
2855 strcpy(szPathName, cmp->rightdir);
2856 else
2857 strcpy(szPathName, cmp->leftdir);
2858 AddBackslashToPath(szPathName);
2859 strcat(szPathName, pci->pszDisplayName);
2860 if (*compare) {
2861 CHAR *fakelist[3];
2862 fakelist[0] = pci->pszFileName;
2863 fakelist[1] = szPathName;
2864 fakelist[2] = NULL;
2865 ExecOnList(hwnd, compare, WINDOWED | SEPARATEKEEP,
2866 NULL, NULL, fakelist, NULL,
2867 pszSrcFile, __LINE__);
2868 }
2869 else {
2870 FCOMPARE fc;
2871 memset(&fc, 0, sizeof(fc));
2872 fc.size = sizeof(fc);
2873 fc.hwndParent = hwnd;
2874 strcpy(fc.file1, pci->pszFileName);
2875 strcpy(fc.file2, szPathName);
2876 WinDlgBox(HWND_DESKTOP, hwnd,
2877 CFileDlgProc, FM3ModHandle, FCMP_FRAME, (PVOID)&fc);
2878 }
2879 }
2880 }
2881 break;
2882
2883 case IDM_DELETE:
2884 cmp = INSTDATA(hwnd);
2885 if (!cmp)
2886 Runtime_Error(pszSrcFile, __LINE__, NULL);
2887 else {
2888 PCNRITEM pciS;
2889 PCNRITEM pciD;
2890 HWND hwndCnrS;
2891 HWND hwndCnrD;
2892 pciS = (PCNRITEM)WinSendMsg(cmp->hwndCalling,
2893 CM_QUERYRECORDEMPHASIS,
2894 MPFROMLONG(CMA_FIRST),
2895 MPFROMSHORT(CRA_CURSORED));
2896 if (!pciS)
2897 Runtime_Error(pszSrcFile, __LINE__, NULL);
2898 else {
2899 // Find matching record
2900 if (cmp->hwndCalling == GetHwndLeft(hwnd)) {
2901 hwndCnrS = GetHwndLeft(hwnd);
2902 hwndCnrD = GetHwndRight(hwnd);
2903 }
2904 else {
2905 hwndCnrS = GetHwndRight(hwnd);
2906 hwndCnrD = GetHwndLeft(hwnd);
2907 }
2908
2909 pciD = FindMatchingItem(pciS, hwndCnrS, hwndCnrD);
2910
2911 if (!pciD)
2912 Runtime_Error(pszSrcFile, __LINE__, NULL);
2913 else if (!pciS->pszFileName)
2914 Runtime_Error(pszSrcFile, __LINE__, NULL);
2915 else {
2916 if (!unlinkf(pciS->pszFileName)) {
2917 WinSendMsg(hwndCnrS, CM_SETRECORDEMPHASIS, MPFROMP(pciS),
2918 MPFROM2SHORT(FALSE, CRA_SELECTED));
2919
2920 if (!*pciD->pszFileName) {
2921 // Other side is blank - remove from both sides
2922 RemoveCnrItems(hwndCnrS, pciS, 1, CMA_FREE | CMA_INVALIDATE);
2923 if (pciD->rc.flRecordAttr & CRA_SELECTED)
2924 WinSendMsg(hwndCnrD, CM_SETRECORDEMPHASIS, MPFROMP(pciD),
2925 MPFROM2SHORT(FALSE, CRA_SELECTED));
2926 RemoveCnrItems(hwndCnrD, pciD, 1, CMA_FREE | CMA_INVALIDATE);
2927 }
2928 else {
2929 // Other side is not blank - just blank this side
2930 FreeCnrItemData(pciS);
2931 pciS->pszFileName = NullStr;
2932 pciS->pszDisplayName = pciS->pszFileName;
2933 pciS->rc.pszIcon = pciS->pszFileName;
2934 pciS->flags = 0; // Just on one side
2935 WinSendMsg(hwndCnrS, CM_INVALIDATERECORD, MPFROMP(&pciS),
2936 MPFROM2SHORT(1, CMA_ERASE | CMA_TEXTCHANGED));
2937 pciD->flags = 0; // Just on one side
2938 if (pciD->pszSubject != NullStr) {
2939 xfree(pciD->pszSubject, pszSrcFile, __LINE__);
2940 pciD->pszSubject = NullStr;
2941 }
2942 }
2943 if (hwndCnrS == GetHwndLeft(hwnd))
2944 cmp->totalleft--;
2945 else
2946 cmp->totalright--;
2947 // Force displayed counts to update
2948 WinPostMsg(hwnd, WM_TIMER, MPFROMLONG(ID_COMP_TIMER), 0);
2949 }
2950 }
2951 }
2952 }
2953 break; // IDM_DELETE
2954
2955 case COMP_FILTER:
2956 case IDM_FILTER:
2957 cmp = INSTDATA(hwnd);
2958 if (cmp) {
2959 BOOL empty = FALSE;
2960 PCNRITEM pci;
2961 CHAR *p;
2962 BOOL temp;
2963
2964 if (!*cmp->dcd.mask.szMask) {
2965 empty = TRUE;
2966 temp = fSelectedAlways;
2967 fSelectedAlways = TRUE;
2968 pci = (PCNRITEM)CurrentRecord(hwnd);
2969 fSelectedAlways = temp;
2970 // 01 Aug 07 SHL
2971 if (pci && ~pci->attrFile & FILE_DIRECTORY) {
2972 p = strrchr(pci->pszFileName, '\\');
2973 if (p) {
2974 p++;
2975 strcpy(cmp->dcd.mask.szMask, p);
2976 }
2977 }
2978 }
2979 cmp->dcd.mask.fNoAttribs = TRUE;
2980 cmp->dcd.mask.attrFile = ALLATTRS;
2981 cmp->dcd.mask.antiattr = 0;
2982 if (WinDlgBox(HWND_DESKTOP, hwnd, PickMaskDlgProc,
2983 FM3ModHandle, MSK_FRAME, MPFROMP(&cmp->dcd.mask))) {
2984 cmp->dcd.mask.attrFile = ALLATTRS;
2985 cmp->dcd.mask.antiattr = 0;
2986 WinSendMsg(hwnd, UM_FILTER, MPVOID, MPVOID);
2987 }
2988 else if (empty) {
2989 *cmp->dcd.mask.szMask = 0;
2990 cmp->dcd.mask.attrFile = ALLATTRS;
2991 cmp->dcd.mask.antiattr = 0;
2992 }
2993 }
2994 break;
2995
2996 case IDM_SHOWSUBJECT:
2997 case IDM_SHOWEAS:
2998 case IDM_SHOWSIZE:
2999 case IDM_SHOWLWDATE:
3000 case IDM_SHOWLWTIME:
3001 case IDM_SHOWLADATE:
3002 case IDM_SHOWLATIME:
3003 case IDM_SHOWCRDATE:
3004 case IDM_SHOWCRTIME:
3005 case IDM_SHOWATTR:
3006 cmp = INSTDATA(hwnd);
3007 if (cmp) {
3008 DIRCNRDATA dcd1;
3009 BOOL tempsubj;
3010
3011 dcd1 = cmp->dcd;
3012 AdjustDetailsSwitches(GetHwndLeft(hwnd),
3013 (HWND)0, SHORT1FROMMP(mp1),
3014 cmp->leftdir, PCSZ_DIRCMP, &cmp->dcd.ds, TRUE);
3015 tempsubj = cmp->dcd.ds.detailssubject;
3016 cmp->dcd = dcd1;
3017 cmp->dcd.ds.detailssubject = FALSE;
3018 AdjustDetailsSwitches(GetHwndRight(hwnd),
3019 cmp->dcd.hwndLastMenu, SHORT1FROMMP(mp1),
3020 cmp->rightdir, PCSZ_DIRCMP, &cmp->dcd.ds, TRUE);
3021 cmp->dcd.ds.detailssubject = tempsubj;
3022 WriteDetailsSwitches(PCSZ_DIRCMP, &cmp->dcd.ds, TRUE);
3023 }
3024 break;
3025
3026 case IDM_LOADLISTFILE:
3027 cmp = INSTDATA(hwnd);
3028 if (cmp) {
3029 CHAR fullname[CCHMAXPATH];
3030
3031 strcpy(fullname, PCSZ_STARDOTPMD);
3032 if (insert_filename(HWND_DESKTOP, fullname, TRUE, FALSE) &&
3033 *fullname && !strchr(fullname, '*') && !strchr(fullname, '?')) {
3034 strcpy(cmp->rightlist, fullname);
3035 PostMsg(hwnd, UM_SETUP, MPVOID, MPVOID);
3036 PostMsg(hwnd, UM_SETDIR, MPVOID, MPVOID);
3037 }
3038 }
3039 break;
3040
3041 case IDM_SAVELISTFILE:
3042 cmp = INSTDATA(hwnd);
3043 if (cmp) {
3044 SNAPSTUFF *sf;
3045 CHAR fullname[CCHMAXPATH];
3046
3047 strcpy(fullname, PCSZ_STARDOTPMD);
3048 if (export_filename(HWND_DESKTOP, fullname, 1) && *fullname &&
3049 !strchr(fullname, '*') && !strchr(fullname, '?')) {
3050 sf = xmallocz(sizeof(SNAPSTUFF), pszSrcFile, __LINE__);
3051 if (sf) {
3052 strcpy(sf->filename, fullname);
3053 if (GetHwndLeft(hwnd) == cmp->hwndCalling)
3054 strcpy(sf->dirname, cmp->leftdir);
3055 else
3056 strcpy(sf->dirname, cmp->rightdir);
3057 sf->recurse = cmp->includesubdirs;
3058 if (xbeginthread(StartSnapThread,
3059 65536,
3060 sf,
3061 pszSrcFile,
3062 __LINE__) == -1)
3063 {
3064 free(sf);
3065 }
3066 }
3067 }
3068 }
3069 break;
3070
3071 case COMP_SETDIRS:
3072 cmp = INSTDATA(hwnd);
3073 if (cmp) {
3074 WALK2 wa;
3075 memset(&wa, 0, sizeof(wa));
3076 wa.size = sizeof(wa);
3077 strcpy(wa.szCurrentPath1, cmp->leftdir);
3078 strcpy(wa.szCurrentPath2, cmp->rightdir);
3079 wa.includesubdirs = WinQueryButtonCheckstate(hwnd,
3080 COMP_INCLUDESUBDIRS);
3081 if (WinDlgBox(HWND_DESKTOP,
3082 hwnd,
3083 WalkTwoCmpDlgProc,
3084 FM3ModHandle,
3085 WALK2_FRAME,
3086 MPFROMP(&wa)) &&
3087 !IsFile(wa.szCurrentPath1) &&
3088 !IsFile(wa.szCurrentPath2)) {
3089 strcpy(cmp->leftdir, wa.szCurrentPath1);
3090 strcpy(cmp->rightdir, wa.szCurrentPath2);
3091 cmp->includesubdirs = wa.includesubdirs;
3092 if (!cmp->includesubdirs)
3093 WinCheckButton(hwnd, COMP_INCLUDESUBDIRS, FALSE);
3094 cmp->listfile = wa.listfile;
3095 if (cmp->listfile) {
3096 CHAR fullname[CCHMAXPATH];
3097
3098 strcpy(fullname, PCSZ_STARDOTPMD);
3099 if (insert_filename(HWND_DESKTOP, fullname, TRUE, FALSE) &&
3100 *fullname && !strchr(fullname, '*') && !strchr(fullname, '?'))
3101 strcpy(cmp->rightlist, fullname);
3102 }
3103 else
3104 *cmp->rightlist = 0;
3105 PostMsg(hwnd, UM_SETUP, MPVOID, MPVOID);
3106 PostMsg(hwnd, UM_SETDIR, MPVOID, MPVOID);
3107 }
3108 }
3109 break;
3110
3111 case COMP_COPYLEFT:
3112 case COMP_MOVELEFT:
3113 case COMP_COPYRIGHT:
3114 case COMP_MOVERIGHT:
3115 case COMP_DELETELEFT:
3116 case COMP_DELETERIGHT:
3117 cmp = INSTDATA(hwnd);
3118 if (cmp) {
3119 COMPARE *forthread;
3120
3121 cmp->filling = TRUE;
3122 forthread = xmalloc(sizeof(COMPARE), pszSrcFile, __LINE__);
3123 if (forthread) {
3124 *forthread = *cmp;
3125 forthread->cmp = cmp;
3126 forthread->action = SHORT1FROMMP(mp1);
3127 if (xbeginthread(ActionCnrThread,
3128 122880,
3129 forthread,
3130 pszSrcFile,
3131 __LINE__) == -1)
3132 {
3133 free(forthread);
3134 }
3135 else {
3136 WinEnableWindowUpdate(GetHwndLeft(hwnd), FALSE);
3137 WinEnableWindowUpdate(GetHwndRight(hwnd), FALSE);
3138 switch (SHORT1FROMMP(mp1)) {
3139 case COMP_DELETELEFT:
3140 case COMP_DELETERIGHT:
3141 WinSetDlgItemText(hwnd, COMP_NOTE,
3142 (CHAR *) GetPString(IDS_COMPHOLDDELETINGTEXT));
3143 break;
3144 case COMP_MOVELEFT:
3145 case COMP_MOVERIGHT:
3146 WinSetDlgItemText(hwnd, COMP_NOTE,
3147 (CHAR *) GetPString(IDS_COMPHOLDMOVINGTEXT));
3148 break;
3149 case COMP_COPYLEFT:
3150 case COMP_COPYRIGHT:
3151 WinSetDlgItemText(hwnd, COMP_NOTE,
3152 (CHAR *) GetPString(IDS_COMPHOLDCOPYINGTEXT));
3153 break;
3154 default:
3155 Runtime_Error(pszSrcFile, __LINE__, "mp1 %u unexpected", SHORT1FROMMP(mp1));
3156 }
3157 SetButtonEnables(cmp, FALSE);
3158 }
3159 }
3160 }
3161 break;
3162
3163 case DID_OK:
3164 {
3165 SWP swp;
3166 ULONG size = sizeof(SWP);
3167 USHORT ids[] = {COMP_FRAME, COMP_LEFTDIR, COMP_RIGHTDIR, COMP_COLLECT,
3168 COMP_VIEW, COMP_NOTE, COMP_TOTALLEFT, COMP_SELLEFT, COMP_TOTALRIGHT,
3169 COMP_SELRIGHT, COMP_CNRMENU, COMP_DIRMENU, COMP_MENU,
3170 COMP_INCLUDESUBDIRS, COMP_SETDIRS, COMP_COPYLEFT, COMP_MOVELEFT,
3171 COMP_DELETELEFT, COMP_COPYRIGHT, COMP_MOVERIGHT, COMP_DELETERIGHT,
3172 COMP_TOTALLEFTHDR, COMP_SELLEFTHDR, COMP_TOTALRIGHTHDR,
3173 COMP_SELRIGHTHDR, COMP_FILTER, COMP_HIDENOTSELECTED, 0};
3174 UINT x;
3175 CHAR s[24];
3176 WinQueryWindowPos(hwnd, &swp);
3177 PrfWriteProfileData(fmprof, FM3Str, "CompDir.Position", (PVOID) &swp,
3178 size);
3179 for (x = 0; ids[x]; x++) {
3180 //fixme to allow user to change presparams 1-10-09 GKY
3181 sprintf(s, "CompDir%i", ids[x]);
3182 SavePresParams(WinWindowFromID(hwnd, ids[x]), s);
3183 }
3184 }
3185 WinDismissDlg(hwnd, 0);
3186 break;
3187 case DID_CANCEL:
3188 cmp = INSTDATA(hwnd);
3189 if (!cmp)
3190 Runtime_Error(pszSrcFile, __LINE__, NULL);
3191 else {
3192 cmp->stop = TRUE; // In case thread running
3193 if (cmp->filling)
3194 break; // UM_CONTAINER_FILLED will dismiss
3195 }
3196 {
3197 SWP swp;
3198 ULONG size = sizeof(SWP);
3199 WinQueryWindowPos(hwnd, &swp);
3200 PrfWriteProfileData(fmprof, FM3Str, "CompDir.Position", (PVOID) &swp,
3201 size);
3202 }
3203 WinDismissDlg(hwnd, 1);
3204 break;
3205
3206 case IDM_HELP:
3207 if (hwndHelp)
3208 WinSendMsg(hwndHelp, HM_DISPLAY_HELP,
3209 MPFROM2SHORT(HELP_COMPARE, 0), MPFROMSHORT(HM_RESOURCEID));
3210 break;
3211
3212 case IDM_DESELECTALL:
3213 case IDM_SELECTNEWER:
3214 case IDM_SELECTOLDER:
3215 case IDM_SELECTBIGGER:
3216 case IDM_SELECTSMALLER:
3217 case IDM_DESELECTNEWER:
3218 case IDM_DESELECTOLDER:
3219 case IDM_DESELECTBIGGER:
3220 case IDM_DESELECTSMALLER:
3221 case IDM_DESELECTONE:
3222 case IDM_DESELECTBOTH:
3223 case IDM_SELECTBOTH:
3224 case IDM_SELECTONE:
3225 case IDM_SELECTSAMECONTENT:
3226 case IDM_SELECTIDENTICAL: // Name, size and time
3227 case IDM_SELECTSAME: // Name and size
3228 case IDM_INVERT:
3229 cmp = INSTDATA(hwnd);
3230 if (!cmp)
3231 Runtime_Error(pszSrcFile, __LINE__, NULL);
3232 else {
3233 COMPARE *forthread;
3234
3235 cmp->filling = TRUE;
3236 forthread = xmalloc(sizeof(COMPARE), pszSrcFile, __LINE__);
3237 if (forthread) {
3238 *forthread = *cmp;
3239 forthread->cmp = cmp;
3240 forthread->action = SHORT1FROMMP(mp1);
3241 SetShiftState();
3242 forthread->shiftstate = shiftstate; // For and'ed actions
3243
3244 if (xbeginthread(SelectCnrsThread,
3245 65536,
3246 forthread,
3247 pszSrcFile,
3248 __LINE__) == -1)
3249 {
3250 free(forthread);
3251 }
3252 else {
3253 WinEnableWindowUpdate(GetHwndLeft(hwnd), FALSE);
3254 WinEnableWindowUpdate(GetHwndRight(hwnd), FALSE);
3255 switch (SHORT1FROMMP(mp1)) {
3256 case IDM_DESELECTALL:
3257 case IDM_DESELECTNEWER:
3258 case IDM_DESELECTOLDER:
3259 case IDM_DESELECTBIGGER:
3260 case IDM_DESELECTSMALLER:
3261 case IDM_DESELECTONE:
3262 case IDM_DESELECTBOTH:
3263 WinSetDlgItemText(hwnd, COMP_NOTE,
3264 (CHAR *) GetPString(IDS_COMPHOLDDESELTEXT));
3265 break;
3266 case IDM_INVERT:
3267 WinSetDlgItemText(hwnd, COMP_NOTE,
3268 (CHAR *) GetPString(IDS_COMPHOLDINVERTTEXT));
3269 break;
3270 default:
3271 WinSetDlgItemText(hwnd, COMP_NOTE,
3272 (CHAR *) GetPString(IDS_COMPHOLDSELTEXT));
3273 break;
3274 }
3275 SetButtonEnables(cmp, FALSE);
3276 }
3277 }
3278 }
3279 break;
3280
3281 case COMP_COLLECT:
3282 cmp = INSTDATA(hwnd);
3283 if (!cmp)
3284 Runtime_Error(pszSrcFile, __LINE__, NULL);
3285 else {
3286 CHAR **listl;
3287 CHAR **listr = NULL;
3288 if (!Collector) {
3289 SWP swp;
3290 HWND hwndC;
3291 if (!fAutoTile &&
3292 !ParentIsDesktop(hwnd, cmp->hwndParent) &&
3293 !fExternalCollector &&
3294 !strcmp(realappname, FM3Str)) {
3295 GetNextWindowPos(cmp->hwndParent, &swp, NULL, NULL);
3296 }
3297 hwndC = StartCollector(fExternalCollector ||
3298 strcmp(realappname, FM3Str) ?
3299 HWND_DESKTOP :
3300 cmp->hwndParent,
3301 4);
3302 if (hwndC) {
3303 if (!fAutoTile &&
3304 !ParentIsDesktop(hwnd, cmp->hwndParent) &&
3305 !fExternalCollector &&
3306 !strcmp(realappname, FM3Str)) {
3307 WinSetWindowPos(hwndC, HWND_TOP,
3308 swp.x, swp.y, swp.cx, swp.cy,
3309 SWP_MOVE | SWP_SIZE | SWP_SHOW | SWP_ZORDER);
3310 }
3311 else if (!ParentIsDesktop(hwnd, cmp->hwndParent) &&
3312 fAutoTile &&
3313 !strcmp(realappname, FM3Str)) {
3314 TileChildren(cmp->hwndParent, TRUE);
3315 }
3316 DosSleep(1); // 12 Jan 08 SHL Let screen update
3317 PostMsg(hwnd, WM_COMMAND, MPFROM2SHORT(COMP_COLLECT, 0), MPVOID);
3318 break;
3319 }
3320 }
3321 else
3322 StartCollector(cmp->hwndParent, 4);
3323
3324 temp = fSelectedAlways;
3325 fSelectedAlways = TRUE;
3326 listl = BuildList(GetHwndLeft(hwnd));
3327 if (!*cmp->rightlist)
3328 listr = BuildList(GetHwndRight(hwnd));
3329 fSelectedAlways = temp;
3330
3331 if (listl || listr) {
3332 if (Collector) {
3333 // 07 Aug 07 SHL Avoid collected from empty list
3334 if (listl && listl[0] && *listl[0]) {
3335 if (PostMsg(Collector, WM_COMMAND,
3336 MPFROM2SHORT(IDM_COLLECTOR, 0), MPFROMP(listl)))
3337 listl = NULL; // Collector will free
3338 }
3339 if (listr && listr[0] && *listr[0]) {
3340 if (PostMsg(Collector, WM_COMMAND,
3341 MPFROM2SHORT(IDM_COLLECTOR, 0), MPFROMP(listr)))
3342 listr = NULL; // Collector will free
3343 }
3344 WinSetWindowPos(WinQueryWindow(WinQueryWindow(Collector,
3345 QW_PARENT),
3346 QW_PARENT),
3347 HWND_TOP, 0, 0, 0, 0,
3348 SWP_ACTIVATE);
3349 }
3350 FreeList(listl);
3351 FreeList(listr);
3352 }
3353 }
3354 break;
3355 } // switch mp1
3356 return 0;
3357
3358 case WM_CLOSE:
3359 cmp = INSTDATA(hwnd);
3360 if (!cmp)
3361 Runtime_Error(pszSrcFile, __LINE__, NULL);
3362 else {
3363 cmp->stop = TRUE; // In case thread running
3364 if (cmp->filling)
3365 break; // UM_CONTAINER_FILLED will dismiss
3366 }
3367 WinDismissDlg(hwnd, 0);
3368 return 0;
3369
3370 case WM_DESTROY:
3371 cmp = INSTDATA(hwnd);
3372 if (cmp) {
3373 // 17 Jan 08 SHL fixme to know if stop really needed?
3374 WinStopTimer(WinQueryAnchorBlock(hwnd), hwnd, ID_COMP_TIMER);
3375 if (cmp->dcd.hwndLastMenu)
3376 WinDestroyWindow(cmp->dcd.hwndLastMenu);
3377 if (cmp->dcd.hwndObject) {
3378 WinSetWindowPtr(cmp->dcd.hwndObject, QWL_USER, (PVOID)NULL);
3379 if (!PostMsg(cmp->dcd.hwndObject, WM_CLOSE, MPVOID, MPVOID))
3380 WinSendMsg(cmp->dcd.hwndObject, WM_CLOSE, MPVOID, MPVOID);
3381 }
3382 free(cmp);
3383 }
3384 EmptyCnr(GetHwndLeft(hwnd));
3385 EmptyCnr(GetHwndRight(hwnd));
3386 DosPostEventSem(CompactSem);
3387 break;
3388 }
3389 return WinDefDlgProc(hwnd, msg, mp1, mp2);
3390}
3391
3392#undef GetHwndLeft
3393#undef GetHwndRight
3394
3395#pragma alloc_text(COMPAREDIR,FillCnrsThread,FillDirList,CompNames,BldFullPathName)
3396#pragma alloc_text(COMPAREDIR1,CompareDlgProc)
3397#pragma alloc_text(COMPAREDIR2,SelectCnrsThread,ActionCnrThread)
3398#pragma alloc_text(COMPAREFILE,CFileDlgProc,CompareFilesThread)
3399#pragma alloc_text(SNAPSHOT,SnapShot,StartSnapThread)
3400#pragma alloc_text(COMPSELECT,CompSelect,CompSelectSetSelects,CompSelectClearSelects)
3401
Note: See TracBrowser for help on using the repository browser.