source: trunk/dll/comp.c@ 1563

Last change on this file since 1563 was 1563, checked in by Steven Levine, 14 years ago

Rework collector and compare directories to correctly support more than 65K records.
Collector was trapping.
Compare directories was fixed to avoid the traps, but the implementation was not correctly handling all records.

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