source: trunk/dll/comp.c@ 1655

Last change on this file since 1655 was 1655, checked in by Gregg Young, 14 years ago

Cleanup and added comments

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