source: trunk/dll/comp.c@ 1683

Last change on this file since 1683 was 1683, checked in by Steven Levine, 12 years ago

ActionCnrThread: need to strdup pszFmtFileSize to avoid aliased pointers

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