source: trunk/dll/comp.c@ 1470

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

Remember last filter mask selection
Use Ctrl-click to select state or commonly used directory quicklist entry without activating.
Use Ctrl-click to select walk dialog user list entry without activating.
Avoid drivebar MB2 exception
Remember last seek and scan mask selection across runs
Avoid traps when changing tree container display style
Restore missing drives to drive list dropdown
Minor documentation updates

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