source: trunk/dll/comp.c@ 551

Last change on this file since 551 was 551, checked in by Gregg Young, 18 years ago

Indentation cleanup

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 77.7 KB
Line 
1
2/***********************************************************************
3
4 $Id: comp.c 551 2007-02-28 01:33:51Z gyoung $
5
6 Compare directories
7
8 Copyright (c) 1993-02 M. Kimes
9 Copyright (c) 2003, 2006 Steven H. Levine
10
11 16 Oct 02 MK Baseline
12 04 Nov 03 SHL Force window refresh after subdir toggle
13 01 Aug 04 SHL Rework lstrip/rstrip usage
14 24 May 05 SHL Rework Win_Error usage
15 24 May 05 SHL Rework for CNRITEM.szSubject
16 25 May 05 SHL Rework with ULONGLONG
17 06 Jun 05 SHL Drop unused
18 12 Jul 06 SHL Renames and comments
19 13 Jul 06 SHL Use Runtime_Error
20 26 Jul 06 SHL Drop unreachable CN_... code
21 29 Jul 06 SHL Use xfgets_bstripcr
22 15 Aug 06 SHL Turn off hide not selected on dir change
23 19 Oct 06 SHL Correct . and .. detect
24 03 Nov 06 SHL Count thread usage
25
26***********************************************************************/
27
28#define INCL_DOS
29#define INCL_WIN
30#define INCL_GPI
31#define INCL_LONGLONG
32#include <os2.h>
33
34#include <stdio.h>
35#include <stdlib.h>
36#include <string.h>
37#include <ctype.h>
38#include <share.h>
39#include <io.h>
40
41#include "fm3dll.h"
42#include "fm3dlg.h"
43#include "fm3str.h"
44
45#pragma alloc_text(COMPAREDIR,FillCnrsThread,FillDirList,CompNames)
46#pragma alloc_text(COMPAREDIR1,CompareDlgProc)
47#pragma alloc_text(COMPAREDIR2,SelectCnrsThread,ActionCnrThread)
48#pragma alloc_text(COMPAREFILE,CFileDlgProc,CompareFilesThread)
49#pragma alloc_text(SNAPSHOT,SnapShot,StartSnap)
50
51typedef struct
52{
53 CHAR filename[CCHMAXPATH];
54 CHAR dirname[CCHMAXPATH];
55 BOOL recurse;
56}
57SNAPSTUFF;
58
59static PSZ pszSrcFile = __FILE__;
60
61//=== SnapShot() Write directory tree to file and recurse if requested ===
62
63static VOID SnapShot(char *path, FILE * fp, BOOL recurse)
64{
65 FILEFINDBUF4 *fb;
66 char *mask, *enddir;
67 HDIR hdir = HDIR_CREATE;
68 ULONG nm = 1L;
69
70 fb = xmalloc(sizeof(FILEFINDBUF4), pszSrcFile, __LINE__);
71 if (fb) {
72 mask = xmalloc(CCHMAXPATH, pszSrcFile, __LINE__);
73 if (mask) {
74 sprintf(mask,
75 "%s%s*",
76 path, (path[strlen(path) - 1] != '\\') ? "\\" : NullStr);
77 enddir = strrchr(mask, '\\');
78 enddir++;
79 if (!DosFindFirst(mask,
80 &hdir,
81 FILE_NORMAL | FILE_DIRECTORY |
82 FILE_ARCHIVED | FILE_READONLY | FILE_HIDDEN |
83 FILE_SYSTEM,
84 fb, sizeof(FILEFINDBUF4), &nm, FIL_QUERYEASIZE)) {
85 do {
86 strcpy(enddir, fb->achName);
87 if (!(fb->attrFile & FILE_DIRECTORY))
88 fprintf(fp,
89 "\"%s\",%u,%lu,%04u/%02u/%02u,%02u:%02u:%02u,%lu,%lu,N\n",
90 mask,
91 enddir - mask,
92 fb->cbFile,
93 (fb->fdateLastWrite.year + 1980),
94 fb->fdateLastWrite.month,
95 fb->fdateLastWrite.day,
96 fb->ftimeLastWrite.hours,
97 fb->ftimeLastWrite.minutes,
98 fb->ftimeLastWrite.twosecs,
99 fb->attrFile, (fb->cbList > 4L) ? (fb->cbList / 2L) : 0L);
100 // Skip . and ..
101 else if (recurse &&
102 (fb->achName[0] != '.' ||
103 (fb->achName[1] &&
104 (fb->achName[1] != '.' || fb->achName[2])))) {
105 SnapShot(mask, fp, recurse);
106 }
107 nm = 1L;
108 } while (!DosFindNext(hdir, fb, sizeof(FILEFINDBUF4), &nm));
109 DosFindClose(hdir);
110 }
111 free(mask);
112 }
113 free(fb);
114 }
115}
116
117//=== StartSnap() Write directory tree to snapshot file ===
118
119static VOID StartSnap(VOID * dummy)
120{
121 SNAPSTUFF *sf = (SNAPSTUFF *) dummy;
122 FILE *fp;
123 CHAR *p;
124
125 if (sf) {
126 if (*sf->dirname && *sf->filename) {
127 priority_normal();
128 p = sf->dirname;
129 while (*p) {
130 if (*p == '/')
131 *p = '\\';
132 p++;
133 }
134 if (*(p - 1) != '\\') {
135 *p = '\\';
136 p++;
137 }
138 fp = xfopen(sf->filename, "w", pszSrcFile, __LINE__);
139 if (fp) {
140 fprintf(fp, "\"%s\"\n", sf->dirname);
141 SnapShot(sf->dirname, fp, sf->recurse);
142 fclose(fp);
143 }
144 }
145 free(sf);
146 }
147}
148
149//=== CompareFilesThread() Compare files and update container select flags ===
150
151static VOID CompareFilesThread(VOID * args)
152{
153 FCOMPARE fc;
154 HAB hab2;
155 HMQ hmq2;
156 FILE *fp1, *fp2;
157 ULONG len1, len2, offset = 0L;
158 LONG numread1, numread2;
159 CHAR s[1024], ss[1024], *p1, *p2;
160
161 if (args) {
162 fc = *(FCOMPARE *) args;
163 hab2 = WinInitialize(0);
164 if (hab2) {
165 hmq2 = WinCreateMsgQueue(hab2, 0);
166 if (hmq2) {
167 WinCancelShutdown(hmq2, TRUE);
168 IncrThreadUsage();
169 if (!IsFile(fc.file1) || IsRoot(fc.file1)) {
170 p1 = strrchr(fc.file2, '\\');
171 if (p1) {
172 if (fc.file1[strlen(fc.file1) - 1] == '\\')
173 p1++;
174 strcat(fc.file1, p1);
175 }
176 }
177 else if (!IsFile(fc.file2) || IsRoot(fc.file2)) {
178 p1 = strrchr(fc.file1, '\\');
179 if (p1) {
180 if (fc.file2[strlen(fc.file2) - 1] == '\\')
181 p1++;
182 strcat(fc.file2, p1);
183 }
184 }
185 sprintf(s, GetPString(IDS_COMPCOMPARETEXT), fc.file1);
186 AddToListboxBottom(fc.hwndList, s);
187 sprintf(s, GetPString(IDS_COMPTOTEXT), fc.file2);
188 AddToListboxBottom(fc.hwndList, s);
189 fp1 = _fsopen(fc.file1, "rb", SH_DENYNO);
190 if (!fp1) {
191 sprintf(s, GetPString(IDS_COMPCANTOPENTEXT), fc.file1);
192 AddToListboxBottom(fc.hwndList, s);
193 WinSetWindowText(fc.hwndHelp, GetPString(IDS_ERRORTEXT));
194 }
195 else {
196 fp2 = _fsopen(fc.file2, "rb", SH_DENYNO);
197 if (!fp2) {
198 sprintf(s, GetPString(IDS_COMPCANTOPENTEXT), fc.file2);
199 AddToListboxBottom(fc.hwndList, s);
200 WinSetWindowText(fc.hwndHelp, GetPString(IDS_ERRORTEXT));
201 }
202 else {
203 len1 = filelength(fileno(fp1));
204 len2 = filelength(fileno(fp2));
205 if (len1 != len2) {
206 strcpy(s, GetPString(IDS_COMPDIFSIZESTEXT));
207 AddToListboxBottom(fc.hwndList, s);
208 sprintf(s, GetPString(IDS_COMPVSBYTESTEXT), len1, len2);
209 AddToListboxBottom(fc.hwndList, s);
210 WinSetWindowText(fc.hwndHelp,
211 GetPString(IDS_COMPDONTMATCHTEXT));
212 }
213 else {
214 WinSetWindowText(fc.hwndHelp,
215 GetPString(IDS_COMPCOMPARINGTEXT));
216 while (WinIsWindow(hab2, fc.hwndList)) {
217 numread1 = fread(s, 1, 1024, fp1);
218 numread2 = fread(ss, 1, 1024, fp2);
219 if (numread1 != numread2 || feof(fp1) != feof(fp2)) {
220 sprintf(s, GetPString(IDS_COMPREADERRORTEXT),
221 offset, offset);
222 AddToListboxBottom(fc.hwndList, s);
223 WinSetWindowText(fc.hwndHelp, GetPString(IDS_ERRORTEXT));
224 break;
225 }
226 else if (!numread1 && feof(fp1) && feof(fp2)) {
227 AddToListboxBottom(fc.hwndList,
228 GetPString(IDS_COMPFILESMATCHTEXT));
229 if (!stricmp(fc.file1, fc.file2))
230 AddToListboxBottom(fc.hwndList,
231 GetPString(IDS_COMPWONDERWHYTEXT));
232 WinSetWindowText(fc.hwndHelp,
233 GetPString(IDS_COMPCOMPLETETEXT));
234 break;
235 }
236 else if (numread1 <= 0 || numread2 <= 0) {
237 if (offset == len1)
238 break;
239 else {
240 sprintf(s, GetPString(IDS_COMPMATCHREADERRORTEXT),
241 offset, offset);
242 WinSetWindowText(fc.hwndHelp,
243 GetPString(IDS_COMPODDERRORTEXT));
244 AddToListboxBottom(fc.hwndList, s);
245 break;
246 }
247 }
248 else if (memcmp(s, ss, numread1)) {
249 p1 = s;
250 p2 = ss;
251 while (p1 < s + numread1) {
252 if (*p1 != *p2) {
253 sprintf(s, GetPString(IDS_COMPMISMATCHERRORTEXT),
254 offset + (p1 - s), offset + (p1 - s));
255 AddToListboxBottom(fc.hwndList, s);
256 WinSetWindowText(fc.hwndHelp,
257 GetPString(IDS_COMPDONTMATCHTEXT));
258 break;
259 }
260 p1++;
261 p2++;
262 }
263 break;
264 }
265 offset += numread1;
266 }
267 }
268 fclose(fp2);
269 }
270 fclose(fp1);
271 }
272 DecrThreadUsage();
273 WinDestroyMsgQueue(hmq2);
274 }
275 WinTerminate(hab2);
276 }
277 }
278}
279
280//=== CFileDlgProc() Select directories to compare dialog procedure ===
281
282MRESULT EXPENTRY CFileDlgProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
283{
284 FCOMPARE *fc;
285
286 switch (msg) {
287 case WM_INITDLG:
288 if (!mp2)
289 WinDismissDlg(hwnd, 0);
290 else {
291 WinSetWindowPtr(hwnd, 0, mp2);
292 fc = (FCOMPARE *) mp2;
293 fc->hwndReport = hwnd;
294 fc->hwndList = WinWindowFromID(hwnd, FCMP_LISTBOX);
295 fc->hwndHelp = WinWindowFromID(hwnd, FCMP_HELP);
296 if (!*fc->file1 || !fc->file2) {
297 WinDismissDlg(hwnd, 0);
298 break;
299 }
300 MakeFullName(fc->file1);
301 MakeFullName(fc->file2);
302 if (!stricmp(fc->file1, fc->file2)) {
303 saymsg(MB_CANCEL, hwnd,
304 GetPString(IDS_COMPSILLYALERTTEXT),
305 GetPString(IDS_COMPTOITSELFTEXT));
306 WinDismissDlg(hwnd, 0);
307 break;
308 }
309 if (_beginthread(CompareFilesThread, NULL, 65536, (PVOID) fc) == -1) {
310 Runtime_Error(pszSrcFile, __LINE__,
311 GetPString(IDS_COULDNTSTARTTHREADTEXT));
312 WinDismissDlg(hwnd, 0);
313 }
314 }
315 break;
316
317 case WM_ADJUSTWINDOWPOS:
318 PostMsg(hwnd, UM_SETDIR, MPVOID, MPVOID);
319 break;
320
321 case UM_SETDIR:
322 PaintRecessedWindow(WinWindowFromID(hwnd, FCMP_HELP),
323 (HPS) 0, FALSE, TRUE);
324 return 0;
325
326 case WM_COMMAND:
327 switch (SHORT1FROMMP(mp1)) {
328 case DID_OK:
329 WinDismissDlg(hwnd, 0);
330 break;
331 case DID_CANCEL:
332 WinDismissDlg(hwnd, 1);
333 break;
334 }
335 return 0;
336
337 case WM_DESTROY:
338 DosSleep(100L);
339 break;
340 }
341 return WinDefDlgProc(hwnd, msg, mp1, mp2);
342}
343
344//=== ActionCnrThread() Do requested action on container contents ===
345
346static VOID ActionCnrThread(VOID * args)
347{
348 COMPARE *cmp = (COMPARE *) args;
349 HAB hab;
350 HMQ hmq;
351 HWND hwndCnrS, hwndCnrD;
352 PCNRITEM pci, pciO, pcin, pciOn;
353 CHAR newname[CCHMAXPATH], dirname[CCHMAXPATH], *p;
354 APIRET rc;
355
356 if (!cmp)
357 return;
358
359 DosError(FERR_DISABLEHARDERR);
360
361 hab = WinInitialize(0);
362 if (hab) {
363 hmq = WinCreateMsgQueue(hab, 0);
364 if (hmq) {
365 WinCancelShutdown(hmq, TRUE);
366 IncrThreadUsage();
367 priority_normal();
368 switch (cmp->action) {
369 case COMP_DELETELEFT:
370 hwndCnrS = WinWindowFromID(cmp->hwnd, COMP_LEFTDIR);
371 hwndCnrD = WinWindowFromID(cmp->hwnd, COMP_RIGHTDIR);
372 cmp->action = IDM_DELETE;
373 break;
374 case COMP_DELETERIGHT:
375 hwndCnrS = WinWindowFromID(cmp->hwnd, COMP_RIGHTDIR);
376 hwndCnrD = WinWindowFromID(cmp->hwnd, COMP_LEFTDIR);
377 cmp->action = IDM_DELETE;
378 break;
379 case COMP_MOVELEFT:
380 cmp->action = IDM_MOVE;
381 hwndCnrS = WinWindowFromID(cmp->hwnd, COMP_LEFTDIR);
382 hwndCnrD = WinWindowFromID(cmp->hwnd, COMP_RIGHTDIR);
383 break;
384 case COMP_MOVERIGHT:
385 cmp->action = IDM_MOVE;
386 hwndCnrS = WinWindowFromID(cmp->hwnd, COMP_RIGHTDIR);
387 hwndCnrD = WinWindowFromID(cmp->hwnd, COMP_LEFTDIR);
388 break;
389 case COMP_COPYLEFT:
390 cmp->action = IDM_COPY;
391 hwndCnrS = WinWindowFromID(cmp->hwnd, COMP_LEFTDIR);
392 hwndCnrD = WinWindowFromID(cmp->hwnd, COMP_RIGHTDIR);
393 break;
394 case COMP_COPYRIGHT:
395 cmp->action = IDM_COPY;
396 hwndCnrS = WinWindowFromID(cmp->hwnd, COMP_RIGHTDIR);
397 hwndCnrD = WinWindowFromID(cmp->hwnd, COMP_LEFTDIR);
398 break;
399 default:
400 Runtime_Error(pszSrcFile, __LINE__, "bad case %u", cmp->action);
401 goto Abort;
402 }
403
404 pci = WinSendMsg(hwndCnrS, CM_QUERYRECORD, MPVOID,
405 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
406 pciO = WinSendMsg(hwndCnrD, CM_QUERYRECORD, MPVOID,
407 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
408 while (pci && (INT) pci != -1 && pciO && (INT) pciO != -1) {
409
410 pcin = WinSendMsg(hwndCnrS, CM_QUERYRECORD, MPFROMP(pci),
411 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
412 pciOn = WinSendMsg(hwndCnrD, CM_QUERYRECORD, MPFROMP(pciO),
413 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
414 if (*pci->szFileName && (pci->rc.flRecordAttr & CRA_SELECTED)) {
415 switch (cmp->action) {
416 case IDM_DELETE:
417 if (!unlinkf("%s", pci->szFileName)) {
418 WinSendMsg(hwndCnrS, CM_SETRECORDEMPHASIS, MPFROMP(pci),
419 MPFROM2SHORT(FALSE, CRA_SELECTED));
420 if (!*pciO->szFileName) {
421 WinSendMsg(hwndCnrS, CM_REMOVERECORD, MPFROMP(&pci),
422 MPFROM2SHORT(1, CMA_FREE | CMA_INVALIDATE));
423 if (pciO->rc.flRecordAttr & CRA_SELECTED)
424 WinSendMsg(hwndCnrD, CM_SETRECORDEMPHASIS, MPFROMP(pciO),
425 MPFROM2SHORT(FALSE, CRA_SELECTED));
426 WinSendMsg(hwndCnrD, CM_REMOVERECORD, MPFROMP(&pciO),
427 MPFROM2SHORT(1, CMA_FREE | CMA_INVALIDATE));
428 }
429 else {
430 *pci->szFileName = 0;
431 pci->pszFileName = pci->szFileName;
432 pci->flags = 0;
433 WinSendMsg(hwndCnrS, CM_INVALIDATERECORD, MPFROMP(&pci),
434 MPFROM2SHORT(1, CMA_ERASE | CMA_TEXTCHANGED));
435 }
436 if (hwndCnrS == WinWindowFromID(cmp->hwnd, COMP_LEFTDIR))
437 cmp->cmp->totalleft--;
438 else
439 cmp->cmp->totalright--;
440 DosSleep(0L);
441 }
442 break;
443
444 case IDM_MOVE:
445 if (hwndCnrS == WinWindowFromID(cmp->hwnd, COMP_RIGHTDIR))
446 sprintf(newname, "%s%s%s", cmp->leftdir,
447 cmp->leftdir[strlen(cmp->leftdir) - 1] ==
448 '\\' ? NullStr : "\\", pci->pszFileName);
449 else
450 sprintf(newname, "%s%s%s", cmp->rightdir,
451 cmp->rightdir[strlen(cmp->rightdir) - 1] ==
452 '\\' ? NullStr : "\\", pci->pszFileName);
453 /* make directory if required */
454 strcpy(dirname, newname);
455 p = strrchr(dirname, '\\');
456 if (p) {
457 if (p > dirname + 2)
458 p++;
459 *p = 0;
460 if (IsFile(dirname) == -1)
461 MassMkdir(hwndMain, dirname);
462 }
463 rc = docopyf(MOVE, pci->szFileName, "%s", newname);
464 if (!rc && stricmp(pci->szFileName, newname)) {
465 WinSendMsg(hwndCnrS, CM_SETRECORDEMPHASIS, MPFROMP(pci),
466 MPFROM2SHORT(FALSE, CRA_SELECTED));
467 if (pciO->rc.flRecordAttr & CRA_SELECTED)
468 WinSendMsg(hwndCnrD, CM_SETRECORDEMPHASIS, MPFROMP(pciO),
469 MPFROM2SHORT(FALSE, CRA_SELECTED));
470 strcpy(pciO->szFileName, newname);
471 if (hwndCnrS == WinWindowFromID(cmp->hwnd, COMP_RIGHTDIR)) {
472 pciO->pszFileName = pciO->szFileName + strlen(cmp->leftdir);
473 if (cmp->leftdir[strlen(cmp->leftdir) - 1] != '\\')
474 pciO->pszFileName++;
475 }
476 else {
477 pciO->pszFileName = pciO->szFileName + strlen(cmp->rightdir);
478 if (cmp->rightdir[strlen(cmp->rightdir) - 1] != '\\')
479 pciO->pszFileName++;
480 }
481 strcpy(pciO->szDispAttr, pci->szDispAttr);
482 pciO->attrFile = pci->attrFile;
483 pciO->flags = 0;
484 pciO->date = pci->date;
485 pciO->time = pci->time;
486 pciO->ladate = pci->ladate;
487 pciO->latime = pci->latime;
488 pciO->crdate = pci->crdate;
489 pciO->crtime = pci->crtime;
490 pciO->cbFile = pci->cbFile;
491 pciO->easize = pci->easize;
492 *pciO->szSubject = 0;
493 *pci->szFileName = 0;
494 pci->pszFileName = pci->szFileName;
495 pci->flags = 0;
496 WinSendMsg(hwndCnrS, CM_INVALIDATERECORD, MPFROMP(&pci),
497 MPFROM2SHORT(1, CMA_ERASE | CMA_TEXTCHANGED));
498 WinSendMsg(hwndCnrD, CM_INVALIDATERECORD, MPFROMP(&pciO),
499 MPFROM2SHORT(1, CMA_ERASE | CMA_TEXTCHANGED));
500 }
501 else if (rc) {
502 rc = Dos_Error(MB_ENTERCANCEL,
503 rc,
504 HWND_DESKTOP,
505 pszSrcFile,
506 __LINE__,
507 GetPString(IDS_COMPMOVEFAILEDTEXT),
508 pci->szFileName, newname);
509 if (rc == MBID_CANCEL) /* cause loop to break */
510 pcin = NULL;
511 }
512 break;
513
514 case IDM_COPY:
515 if (hwndCnrS == WinWindowFromID(cmp->hwnd, COMP_RIGHTDIR))
516 sprintf(newname, "%s%s%s", cmp->leftdir,
517 cmp->leftdir[strlen(cmp->leftdir) - 1] ==
518 '\\' ? NullStr : "\\", pci->pszFileName);
519 else
520 sprintf(newname, "%s%s%s", cmp->rightdir,
521 cmp->rightdir[strlen(cmp->rightdir) - 1] ==
522 '\\' ? NullStr : "\\", pci->pszFileName);
523 /* make directory if required */
524 strcpy(dirname, newname);
525 p = strrchr(dirname, '\\');
526 if (p) {
527 if (p > dirname + 2)
528 p++;
529 *p = 0;
530 if (IsFile(dirname) == -1)
531 MassMkdir(hwndMain, dirname);
532 }
533 rc = docopyf(COPY, pci->szFileName, "%s", newname);
534 if (rc) {
535 rc = Dos_Error(MB_ENTERCANCEL,
536 rc,
537 HWND_DESKTOP,
538 pszSrcFile,
539 __LINE__,
540 GetPString(IDS_COMPCOPYFAILEDTEXT),
541 pci->szFileName, newname);
542 if (rc == MBID_CANCEL)
543 pcin = NULL; /* cause loop to break */
544 }
545 else {
546 WinSendMsg(hwndCnrS, CM_SETRECORDEMPHASIS, MPFROMP(pci),
547 MPFROM2SHORT(FALSE, CRA_SELECTED));
548 if (pciO->rc.flRecordAttr & CRA_SELECTED)
549 WinSendMsg(hwndCnrD, CM_SETRECORDEMPHASIS, MPFROMP(pciO),
550 MPFROM2SHORT(FALSE, CRA_SELECTED));
551 strcpy(pciO->szFileName, newname);
552 if (hwndCnrS == WinWindowFromID(cmp->hwnd, COMP_RIGHTDIR)) {
553 pciO->pszFileName = pciO->szFileName + strlen(cmp->leftdir);
554 if (cmp->leftdir[strlen(cmp->leftdir) - 1] != '\\')
555 pciO->pszFileName++;
556 }
557 else {
558 pciO->pszFileName = pciO->szFileName + strlen(cmp->rightdir);
559 if (cmp->rightdir[strlen(cmp->rightdir) - 1] != '\\')
560 pciO->pszFileName++;
561 }
562 strcpy(pciO->szDispAttr, pci->szDispAttr);
563 pciO->attrFile = pci->attrFile;
564 pciO->flags = CNRITEM_EXISTS;
565 pciO->date = pci->date;
566 pciO->time = pci->time;
567 pciO->ladate = pci->ladate;
568 pciO->latime = pci->latime;
569 pciO->crdate = pci->crdate;
570 pciO->crtime = pci->crtime;
571 pciO->cbFile = pci->cbFile;
572 pciO->easize = pci->easize;
573 *pci->szSubject = 0;
574 pci->flags = CNRITEM_EXISTS;
575 WinSendMsg(hwndCnrS, CM_INVALIDATERECORD, MPFROMP(&pci),
576 MPFROM2SHORT(1, CMA_ERASE | CMA_TEXTCHANGED));
577 WinSendMsg(hwndCnrD, CM_INVALIDATERECORD, MPFROMP(&pciO),
578 MPFROM2SHORT(1, CMA_ERASE | CMA_TEXTCHANGED));
579 }
580 break;
581
582 default:
583 break;
584 } // switch
585 }
586 pci = pcin;
587 pciO = pciOn;
588 } // while
589 Abort:
590 WinDestroyMsgQueue(hmq);
591 }
592 DecrThreadUsage();
593 WinTerminate(hab);
594 }
595 PostMsg(cmp->hwnd, UM_CONTAINER_FILLED, MPFROMLONG(1L), MPVOID);
596 PostMsg(cmp->hwnd, WM_COMMAND, MPFROM2SHORT(IDM_DESELECTALL, 0), MPVOID);
597 free(cmp);
598}
599
600//=== SelectCnrsThread() Update container selection flags thread ===
601
602static VOID SelectCnrsThread(VOID * args)
603{
604 COMPARE *cmp = (COMPARE *) args;
605 HAB hab;
606 HMQ hmq;
607
608 if (!cmp)
609 return;
610
611 DosError(FERR_DISABLEHARDERR);
612
613 hab = WinInitialize(0);
614 if (hab) {
615 hmq = WinCreateMsgQueue(hab, 0);
616 if (hmq) {
617 WinCancelShutdown(hmq, TRUE);
618 IncrThreadUsage();
619 priority_normal();
620 switch (cmp->action) {
621 case IDM_INVERT:
622 InvertAll(WinWindowFromID(cmp->hwnd, COMP_LEFTDIR));
623 InvertAll(WinWindowFromID(cmp->hwnd, COMP_RIGHTDIR));
624 break;
625
626 case IDM_DESELECTALL:
627 Deselect(WinWindowFromID(cmp->hwnd, COMP_LEFTDIR));
628 Deselect(WinWindowFromID(cmp->hwnd, COMP_RIGHTDIR));
629 break;
630
631 default:
632 SpecialSelect(WinWindowFromID(cmp->hwnd, COMP_LEFTDIR),
633 WinWindowFromID(cmp->hwnd, COMP_RIGHTDIR),
634 cmp->action, cmp->reset);
635 break;
636 }
637 if (!PostMsg(cmp->hwnd, UM_CONTAINER_FILLED, MPFROMLONG(1L), MPVOID))
638 WinSendMsg(cmp->hwnd, UM_CONTAINER_FILLED, MPFROMLONG(1L), MPVOID);
639 WinDestroyMsgQueue(hmq);
640 }
641 DecrThreadUsage();
642 WinTerminate(hab);
643 }
644 free(cmp);
645}
646
647static VOID FillDirList(CHAR * str, INT skiplen, BOOL recurse,
648 FILELIST *** list, INT * numfiles, INT * numalloc)
649{
650
651 register BYTE *fb;
652 register CHAR *enddir;
653 register ULONG x;
654 CHAR *maskstr;
655 FILEFINDBUF4 *ffb4, *pffb;
656 HDIR hDir;
657 ULONG nm, fl = 0, ulM = 64;
658 APIRET rc;
659
660 if (!str || !*str)
661 return;
662 if (!recurse)
663 ulM = 128;
664 maskstr = xmalloc(CCHMAXPATH, pszSrcFile, __LINE__);
665 if (!maskstr)
666 return;
667 ffb4 = xmalloc(sizeof(FILEFINDBUF4) * ulM, pszSrcFile, __LINE__);
668 if (!ffb4) {
669 free(maskstr);
670 return;
671 }
672 x = strlen(str);
673 memcpy(maskstr, str, x + 1);
674 enddir = maskstr + x;
675 if (*(enddir - 1) != '\\') {
676 *enddir = '\\';
677 enddir++;
678 *enddir = 0;
679 }
680 *enddir = '*';
681 *(enddir + 1) = 0;
682 hDir = HDIR_CREATE;
683 nm = ulM;
684 if (recurse)
685 fl = FILE_DIRECTORY;
686 DosError(FERR_DISABLEHARDERR);
687 rc = DosFindFirst(maskstr, &hDir,
688 (FILE_NORMAL | FILE_READONLY | FILE_ARCHIVED |
689 FILE_SYSTEM | FILE_HIDDEN) | fl,
690 ffb4, sizeof(FILEFINDBUF4) * nm, &nm, FIL_QUERYEASIZE);
691 if (!rc) {
692 while (!rc) {
693 fb = (BYTE *) ffb4;
694 x = 0;
695 while (x < nm) {
696 pffb = (FILEFINDBUF4 *) fb;
697 if (pffb->attrFile & FILE_DIRECTORY) {
698 // Skip . and ..
699 if (recurse &&
700 (pffb->achName[0] != '.' ||
701 (pffb->achName[1] &&
702 (pffb->achName[1] != '.' || pffb->achName[2])))) {
703 if (fForceUpper)
704 strupr(pffb->achName);
705 else if (fForceLower)
706 strlwr(pffb->achName);
707 memcpy(enddir, pffb->achName, pffb->cchName + 1);
708 FillDirList(maskstr, skiplen, recurse, list, numfiles, numalloc);
709 }
710 }
711 else {
712 if (fForceUpper)
713 strupr(pffb->achName);
714 else if (fForceLower)
715 strlwr(pffb->achName);
716 memcpy(enddir, pffb->achName, pffb->cchName + 1);
717 if (AddToFileList
718 (maskstr + skiplen, pffb, list, numfiles, numalloc))
719 goto Abort;
720 }
721 fb += pffb->oNextEntryOffset;
722 x++;
723 }
724 nm = ulM;
725 DosError(FERR_DISABLEHARDERR);
726 rc = DosFindNext(hDir, ffb4, sizeof(FILEFINDBUF4) * nm, &nm);
727 }
728 Abort:
729 DosFindClose(hDir);
730 DosSleep(0L);
731 }
732 free(maskstr);
733 free(ffb4);
734}
735
736//=== CompNames() Compare names for qsort ===
737
738static int CompNames(const void *n1, const void *n2)
739{
740 FILELIST *fl1 = *(FILELIST **) n1;
741 FILELIST *fl2 = *(FILELIST **) n2;
742
743 return stricmp(fl1->fname, fl2->fname);
744}
745
746//=== FillCnrsThread() Fill left and right containers ===
747
748static VOID FillCnrsThread(VOID * args)
749{
750 COMPARE *cmp = (COMPARE *) args;
751 HAB hab;
752 HMQ hmq;
753 BOOL notified = FALSE;
754 static CHAR attrstring[] = "RHS\0DA";
755 HWND hwndLeft, hwndRight;
756
757 if (!cmp)
758 _endthread();
759
760 DosError(FERR_DISABLEHARDERR);
761
762 hab = WinInitialize(0);
763 if (!hab)
764 Win_Error(NULLHANDLE, NULLHANDLE, pszSrcFile, __LINE__, "WinInitialize");
765 else {
766 hmq = WinCreateMsgQueue(hab, 0);
767 if (!hmq)
768 Win_Error(NULLHANDLE, NULLHANDLE, pszSrcFile, __LINE__,
769 "WinCreateMsgQueue");
770 else {
771 INT x;
772 INT l;
773 INT r;
774 INT y;
775 ULONG cntr;
776 FILELIST **filesl = NULL;
777 FILELIST **filesr = NULL;
778 INT numfilesl = 0;
779 INT numfilesr = 0;
780 INT numallocl = 0;
781 INT numallocr = 0;
782 INT lenl; // Directory prefix length
783 INT lenr;
784 UINT recsNeeded; // fixme to check ovf
785 PCNRITEM pcilFirst;
786 PCNRITEM pcirFirst;
787 PCNRITEM pcil;
788 PCNRITEM pcir;
789 PCNRITEM pcit;
790 RECORDINSERT ri;
791 CHAR *pch;
792
793 WinCancelShutdown(hmq, TRUE);
794 IncrThreadUsage();
795 hwndLeft = WinWindowFromID(cmp->hwnd, COMP_LEFTDIR);
796 hwndRight = WinWindowFromID(cmp->hwnd, COMP_RIGHTDIR);
797 lenl = strlen(cmp->leftdir);
798 if (cmp->leftdir[strlen(cmp->leftdir) - 1] != '\\')
799 lenl++;
800 lenr = strlen(cmp->rightdir);
801 if (cmp->rightdir[strlen(cmp->rightdir) - 1] != '\\')
802 lenr++;
803 priority_normal();
804 /* clear containers */
805 WinSendMsg(hwndRight, CM_REMOVERECORD,
806 MPVOID, MPFROM2SHORT(0, CMA_FREE | CMA_INVALIDATE));
807 WinSendMsg(hwndLeft, CM_REMOVERECORD,
808 MPVOID, MPFROM2SHORT(0, CMA_FREE | CMA_INVALIDATE));
809 cmp->cmp->totalleft = cmp->cmp->totalright = 0;
810
811 /* build list of all files in left directory */
812 if (fForceLower)
813 strlwr(cmp->leftdir);
814 else if (fForceUpper)
815 strupr(cmp->leftdir);
816 FillDirList(cmp->leftdir, lenl, cmp->includesubdirs,
817 &filesl, &numfilesl, &numallocl);
818
819 if (filesl)
820 qsort(filesl, numfilesl, sizeof(CHAR *), CompNames);
821 /* build list of all files in right directory */
822 if (!*cmp->rightlist) {
823 if (fForceLower)
824 strlwr(cmp->rightdir);
825 else if (fForceUpper)
826 strupr(cmp->rightdir);
827 FillDirList(cmp->rightdir, lenr, cmp->includesubdirs,
828 &filesr, &numfilesr, &numallocr);
829 }
830 else {
831 /* use snapshot file */
832 FILE *fp;
833 FILEFINDBUF4 fb4;
834 CHAR str[CCHMAXPATH * 2], *p;
835
836 memset(&fb4, 0, sizeof(fb4));
837 fp = fopen(cmp->rightlist, "r");
838 if (!fp)
839 Runtime_Error(pszSrcFile, __LINE__, "can not open %s (%d)",
840 cmp->rightlist, errno);
841 else {
842 while (!feof(fp)) {
843 /* first get name of directory */
844 if (!xfgets_bstripcr(str, sizeof(str), fp, pszSrcFile, __LINE__))
845 break; // EOF
846 p = str;
847 if (*p == '\"') {
848 /* Quoted */
849 p++;
850 if (*p && *p != '\"') {
851 p = strchr(p, '\"');
852 if (p) {
853 *p = 0;
854 if (*(str + 1)) {
855 strcpy(cmp->rightdir, str + 1);
856 if (fForceUpper)
857 strupr(cmp->rightdir);
858 else if (fForceLower)
859 strlwr(cmp->rightdir);
860 p = cmp->rightdir + (strlen(cmp->rightdir) - 1);
861 if (p - cmp->rightdir > 3 && *p == '\\')
862 *p = 0; // Chop trailing slash
863 break;
864 }
865 }
866 }
867 }
868 } // while !EOF
869 {
870 CNRINFO cnri;
871
872 memset(&cnri, 0, sizeof(cnri));
873 cnri.cb = sizeof(cnri);
874 cnri.pszCnrTitle = cmp->rightdir;
875 WinSendMsg(hwndRight, CM_SETCNRINFO,
876 MPFROMP(&cnri), MPFROMLONG(CMA_CNRTITLE));
877 }
878 if (*cmp->rightdir) {
879 lenr = strlen(cmp->rightdir) +
880 (cmp->rightdir[strlen(cmp->rightdir) - 1] != '\\');
881 while (!feof(fp)) {
882 if (!xfgets_bstripcr
883 (str, sizeof(str), fp, pszSrcFile, __LINE__))
884 break;
885 p = str;
886 if (*p == '\"') {
887 p++;
888 if (*p && *p != '\"') {
889 p = strchr(p, '\"');
890 if (p) {
891 *p = 0;
892 p++;
893 if (*p == ',') {
894 p++;
895 if (!cmp->includesubdirs && atol(p) > lenr)
896 continue;
897 p = strchr(p, ',');
898 if (p) {
899 p++;
900 fb4.cbFile = atol(p);
901 p = strchr(p, ',');
902 if (p) {
903 p++;
904 fb4.fdateLastWrite.year = atol(p) - 1980;
905 p = strchr(p, '/');
906 if (p) {
907 p++;
908 fb4.fdateLastWrite.month = atol(p);
909 p = strchr(p, '/');
910 if (p) {
911 p++;
912 fb4.fdateLastWrite.day = atol(p);
913 p = strchr(p, ',');
914 if (p) {
915 p++;
916 fb4.ftimeLastWrite.hours = atol(p);
917 p = strchr(p, ':');
918 if (p) {
919 p++;
920 fb4.ftimeLastWrite.minutes = atol(p);
921 p = strchr(p, ':');
922 if (p) {
923 p++;
924 fb4.ftimeLastWrite.twosecs = atol(p);
925 p = strchr(p, ',');
926 if (p) {
927 p++;
928 fb4.attrFile = atol(p);
929 p = strchr(p, ',');
930 if (p) {
931 p++;
932 fb4.cbList = atol(p) * 2;
933 if (fForceUpper)
934 strupr(str + 1);
935 else if (fForceLower)
936 strlwr(str + 1);
937 if (AddToFileList((str + 1) + lenr,
938 &fb4,
939 &filesr,
940 &numfilesr,
941 &numallocr))
942 break;
943 }
944 }
945 }
946 }
947 }
948 }
949 }
950 }
951 }
952 }
953 }
954 }
955 }
956 } // while
957 } // if have rightdir
958 fclose(fp);
959 }
960 } // if snapshot file
961
962 if (filesr)
963 qsort(filesr, numfilesr, sizeof(CHAR *), CompNames);
964
965 /* we now have two lists of files, both sorted. */
966 /* first, count total number of container entries required */
967 l = r = 0;
968 recsNeeded = 0;
969 while ((filesl && filesl[l]) || (filesr && filesr[r])) {
970 if ((filesl && filesl[l]) && (filesr && filesr[r])) {
971 x = stricmp(filesl[l]->fname, filesr[r]->fname);
972 if (!x) {
973 l++; // In both
974 r++;
975 }
976 else if (x < 0)
977 l++; // In left only
978 else
979 r++; // In right only
980 }
981 else if (filesl && filesl[l])
982 l++; // In left only
983 else /* filesr && filesr[r] */
984 r++; // In right only
985 recsNeeded++; /* keep count of how many entries req'd */
986 }
987 WinSendMsg(cmp->hwnd, UM_CONTAINERHWND, MPVOID, MPVOID);
988 /* now insert records into the containers */
989 cntr = 0;
990 l = r = 0;
991 if (recsNeeded) {
992 pcilFirst = WinSendMsg(hwndLeft,
993 CM_ALLOCRECORD,
994 MPFROMLONG(EXTRA_RECORD_BYTES2),
995 MPFROMLONG(recsNeeded));
996 if (!pcilFirst) {
997 Runtime_Error(pszSrcFile, __LINE__, "CM_ALLOCRECORD %u failed",
998 recsNeeded);
999 recsNeeded = 0;
1000 }
1001 }
1002 if (recsNeeded) {
1003 pcirFirst = WinSendMsg(hwndRight, CM_ALLOCRECORD,
1004 MPFROMLONG(EXTRA_RECORD_BYTES2),
1005 MPFROMLONG(recsNeeded));
1006 if (!pcirFirst) {
1007 Runtime_Error(pszSrcFile, __LINE__, "CM_ALLOCRECORD %u failed",
1008 recsNeeded);
1009 recsNeeded = 0;
1010 pcil = pcilFirst;
1011 while (pcil) {
1012 pcit = (PCNRITEM) pcil->rc.preccNextRecord;
1013 WinSendMsg(hwndLeft, CM_FREERECORD,
1014 MPFROMP(&pcil), MPFROMSHORT(1));
1015 pcil = pcit;
1016 }
1017 }
1018 }
1019 if (recsNeeded) {
1020 pcil = pcilFirst;
1021 pcir = pcirFirst;
1022 while ((filesl && filesl[l]) || (filesr && filesr[r])) {
1023 pcir->hwndCnr = hwndRight;
1024 pcir->pszFileName = pcir->szFileName;
1025 pcir->rc.pszIcon = pcir->pszFileName;
1026 pcir->rc.hptrIcon = (HPOINTER) 0;
1027 pcir->pszSubject = pcir->szSubject;
1028 pcir->pszLongname = pcir->szLongname;
1029 pcir->pszDispAttr = pcir->szDispAttr;
1030 pcil->hwndCnr = hwndLeft;
1031 pcil->pszFileName = pcil->szFileName;
1032 pcil->rc.pszIcon = pcil->pszFileName;
1033 pcil->rc.hptrIcon = (HPOINTER) 0;
1034 pcil->pszDispAttr = pcil->szDispAttr;
1035 pcil->pszSubject = pcil->szSubject;
1036 pcil->pszLongname = pcil->szLongname;
1037 if ((filesl && filesl[l]) && (filesr && filesr[r])) {
1038 x = stricmp(filesl[l]->fname, filesr[r]->fname);
1039 if (!x) {
1040 // Same
1041 sprintf(pcil->szFileName, "%s%s%s", cmp->leftdir,
1042 (cmp->leftdir[strlen(cmp->leftdir) - 1] == '\\') ?
1043 NullStr : "\\", filesl[l]->fname);
1044 // pcil->rc.hptrIcon = hptrFile;
1045 pcil->pszFileName = pcil->szFileName + lenl;
1046 pcil->attrFile = filesl[l]->attrFile;
1047 y = 0;
1048 for (x = 0; x < 6; x++) {
1049 if (attrstring[x])
1050 pcil->szDispAttr[y++] =
1051 (CHAR) ((pcil->
1052 attrFile & (1 << x)) ? attrstring[x] : '-');
1053 }
1054 pcil->szDispAttr[5] = 0;
1055 pcil->cbFile = filesl[l]->cbFile;
1056 pcil->easize = filesl[l]->easize;
1057 pcil->date.day = filesl[l]->date.day;
1058 pcil->date.month = filesl[l]->date.month;
1059 pcil->date.year = filesl[l]->date.year + 1980;
1060 pcil->time.seconds = filesl[l]->time.twosecs * 2;
1061 pcil->time.minutes = filesl[l]->time.minutes;
1062 pcil->time.hours = filesl[l]->time.hours;
1063 pcil->ladate.day = filesl[l]->ladate.day;
1064 pcil->ladate.month = filesl[l]->ladate.month;
1065 pcil->ladate.year = filesl[l]->ladate.year + 1980;
1066 pcil->latime.seconds = filesl[l]->latime.twosecs * 2;
1067 pcil->latime.minutes = filesl[l]->latime.minutes;
1068 pcil->latime.hours = filesl[l]->latime.hours;
1069 pcil->crdate.day = filesl[l]->crdate.day;
1070 pcil->crdate.month = filesl[l]->crdate.month;
1071 pcil->crdate.year = filesl[l]->crdate.year + 1980;
1072 pcil->crtime.seconds = filesl[l]->crtime.twosecs * 2;
1073 pcil->crtime.minutes = filesl[l]->crtime.minutes;
1074 pcil->crtime.hours = filesl[l]->crtime.hours;
1075 if (*cmp->dcd.mask.szMask) {
1076 if (!Filter((PMINIRECORDCORE) pcil, (PVOID) & cmp->dcd.mask)) {
1077 pcil->rc.flRecordAttr |= CRA_FILTERED;
1078 pcir->rc.flRecordAttr |= CRA_FILTERED;
1079 }
1080 }
1081 sprintf(pcir->szFileName, "%s%s%s", cmp->rightdir,
1082 (cmp->rightdir[strlen(cmp->rightdir) - 1] == '\\') ?
1083 NullStr : "\\", filesr[r]->fname);
1084 pcir->pszFileName = pcir->szFileName + lenr;
1085 pcir->attrFile = filesr[r]->attrFile;
1086 // pcir->rc.hptrIcon = hptrFile;
1087 y = 0;
1088 for (x = 0; x < 6; x++)
1089 if (attrstring[x])
1090 pcir->szDispAttr[y++] =
1091 (CHAR) ((pcir->
1092 attrFile & (1 << x)) ? attrstring[x] : '-');
1093 pcir->szDispAttr[5] = 0;
1094 pcir->cbFile = filesr[r]->cbFile;
1095 pcir->easize = filesr[r]->easize;
1096 pcir->date.day = filesr[r]->date.day;
1097 pcir->date.month = filesr[r]->date.month;
1098 pcir->date.year = filesr[r]->date.year + 1980;
1099 pcir->time.seconds = filesr[r]->time.twosecs * 2;
1100 pcir->time.minutes = filesr[r]->time.minutes;
1101 pcir->time.hours = filesr[r]->time.hours;
1102 pcir->ladate.day = filesr[r]->ladate.day;
1103 pcir->ladate.month = filesr[r]->ladate.month;
1104 pcir->ladate.year = filesr[r]->ladate.year + 1980;
1105 pcir->latime.seconds = filesr[r]->latime.twosecs * 2;
1106 pcir->latime.minutes = filesr[r]->latime.minutes;
1107 pcir->latime.hours = filesr[r]->latime.hours;
1108 pcir->crdate.day = filesr[r]->crdate.day;
1109 pcir->crdate.month = filesr[r]->crdate.month;
1110 pcir->crdate.year = filesr[r]->crdate.year + 1980;
1111 pcir->crtime.seconds = filesr[r]->crtime.twosecs * 2;
1112 pcir->crtime.minutes = filesr[r]->crtime.minutes;
1113 pcir->crtime.hours = filesr[r]->crtime.hours;
1114 pcil->flags |= CNRITEM_EXISTS;
1115 pcir->flags |= CNRITEM_EXISTS;
1116 pch = pcil->szSubject;
1117 if (pcil->cbFile + pcil->easize > pcir->cbFile + pcir->easize) {
1118 pcil->flags |= CNRITEM_LARGER;
1119 pcir->flags |= CNRITEM_SMALLER;
1120 strcpy(pch, GetPString(IDS_LARGERTEXT));
1121 pch += 6;
1122 }
1123 else if (pcil->cbFile + pcil->easize <
1124 pcir->cbFile + pcir->easize) {
1125 pcil->flags |= CNRITEM_SMALLER;
1126 pcir->flags |= CNRITEM_LARGER;
1127 strcpy(pch, GetPString(IDS_SMALLERTEXT));
1128 pch += 7;
1129 }
1130 if ((pcil->date.year > pcir->date.year) ? TRUE :
1131 (pcil->date.year < pcir->date.year) ? FALSE :
1132 (pcil->date.month > pcir->date.month) ? TRUE :
1133 (pcil->date.month < pcir->date.month) ? FALSE :
1134 (pcil->date.day > pcir->date.day) ? TRUE :
1135 (pcil->date.day < pcir->date.day) ? FALSE :
1136 (pcil->time.hours > pcir->time.hours) ? TRUE :
1137 (pcil->time.hours < pcir->time.hours) ? FALSE :
1138 (pcil->time.minutes > pcir->time.minutes) ? TRUE :
1139 (pcil->time.minutes < pcir->time.minutes) ? FALSE :
1140 (pcil->time.seconds > pcir->time.seconds) ? TRUE :
1141 (pcil->time.seconds < pcir->time.seconds) ? FALSE : FALSE) {
1142 pcil->flags |= CNRITEM_NEWER;
1143 pcir->flags |= CNRITEM_OLDER;
1144 if (pch != pcil->szSubject) {
1145 strcpy(pch, ", ");
1146 pch += 2;
1147 }
1148 strcpy(pch, GetPString(IDS_NEWERTEXT));
1149 pch += 5;
1150 }
1151 else if ((pcil->date.year < pcir->date.year) ? TRUE :
1152 (pcil->date.year > pcir->date.year) ? FALSE :
1153 (pcil->date.month < pcir->date.month) ? TRUE :
1154 (pcil->date.month > pcir->date.month) ? FALSE :
1155 (pcil->date.day < pcir->date.day) ? TRUE :
1156 (pcil->date.day > pcir->date.day) ? FALSE :
1157 (pcil->time.hours < pcir->time.hours) ? TRUE :
1158 (pcil->time.hours > pcir->time.hours) ? FALSE :
1159 (pcil->time.minutes < pcir->time.minutes) ? TRUE :
1160 (pcil->time.minutes > pcir->time.minutes) ? FALSE :
1161 (pcil->time.seconds < pcir->time.seconds) ? TRUE :
1162 (pcil->time.seconds > pcir->time.seconds) ? FALSE :
1163 FALSE) {
1164 pcil->flags |= CNRITEM_OLDER;
1165 pcir->flags |= CNRITEM_NEWER;
1166 if (pch != pcil->szSubject) {
1167 strcpy(pch, ", ");
1168 pch += 2;
1169 }
1170 strcpy(pch, GetPString(IDS_OLDERTEXT));
1171 pch += 5;
1172 }
1173 *pch = 0;
1174 r++;
1175 l++;
1176 }
1177 else if (x < 0) {
1178 // Just on left
1179 sprintf(pcil->szFileName, "%s%s%s", cmp->leftdir,
1180 (cmp->leftdir[strlen(cmp->leftdir) - 1] == '\\') ?
1181 NullStr : "\\", filesl[l]->fname);
1182 pcil->pszFileName = pcil->szFileName + lenl;
1183 pcil->attrFile = filesl[l]->attrFile;
1184 // pcil->rc.hptrIcon = hptrFile;
1185 y = 0;
1186 for (x = 0; x < 6; x++)
1187 if (attrstring[x])
1188 pcil->szDispAttr[y++] =
1189 (CHAR) ((pcil->
1190 attrFile & (1 << x)) ? attrstring[x] : '-');
1191 pcil->szDispAttr[5] = 0;
1192 pcil->cbFile = filesl[l]->cbFile;
1193 pcil->easize = filesl[l]->easize;
1194 pcil->date.day = filesl[l]->date.day;
1195 pcil->date.month = filesl[l]->date.month;
1196 pcil->date.year = filesl[l]->date.year + 1980;
1197 pcil->time.seconds = filesl[l]->time.twosecs * 2;
1198 pcil->time.minutes = filesl[l]->time.minutes;
1199 pcil->time.hours = filesl[l]->time.hours;
1200 pcil->ladate.day = filesl[l]->ladate.day;
1201 pcil->ladate.month = filesl[l]->ladate.month;
1202 pcil->ladate.year = filesl[l]->ladate.year + 1980;
1203 pcil->latime.seconds = filesl[l]->latime.twosecs * 2;
1204 pcil->latime.minutes = filesl[l]->latime.minutes;
1205 pcil->latime.hours = filesl[l]->latime.hours;
1206 pcil->crdate.day = filesl[l]->crdate.day;
1207 pcil->crdate.month = filesl[l]->crdate.month;
1208 pcil->crdate.year = filesl[l]->crdate.year + 1980;
1209 pcil->crtime.seconds = filesl[l]->crtime.twosecs * 2;
1210 pcil->crtime.minutes = filesl[l]->crtime.minutes;
1211 pcil->crtime.hours = filesl[l]->crtime.hours;
1212 if (*cmp->dcd.mask.szMask) {
1213 if (!Filter((PMINIRECORDCORE) pcil, (PVOID) & cmp->dcd.mask)) {
1214 pcil->rc.flRecordAttr |= CRA_FILTERED;
1215 pcir->rc.flRecordAttr |= CRA_FILTERED;
1216 }
1217 }
1218 free(filesl[l]);
1219 l++;
1220 }
1221 else {
1222 // Just on right
1223 sprintf(pcir->szFileName, "%s%s%s", cmp->rightdir,
1224 (cmp->rightdir[strlen(cmp->rightdir) - 1] == '\\') ?
1225 NullStr : "\\", filesr[r]->fname);
1226 pcir->pszFileName = pcir->szFileName + lenr;
1227 pcir->attrFile = filesr[r]->attrFile;
1228 // pcir->rc.hptrIcon = hptrFile;
1229 y = 0;
1230 for (x = 0; x < 6; x++) {
1231 if (attrstring[x])
1232 pcir->szDispAttr[y++] =
1233 (CHAR) ((pcir->
1234 attrFile & (1 << x)) ? attrstring[x] : '-');
1235 }
1236 pcir->szDispAttr[5] = 0;
1237 pcir->cbFile = filesr[r]->cbFile;
1238 pcir->easize = filesr[r]->easize;
1239 pcir->date.day = filesr[r]->date.day;
1240 pcir->date.month = filesr[r]->date.month;
1241 pcir->date.year = filesr[r]->date.year + 1980;
1242 pcir->time.seconds = filesr[r]->time.twosecs * 2;
1243 pcir->time.minutes = filesr[r]->time.minutes;
1244 pcir->time.hours = filesr[r]->time.hours;
1245 pcir->ladate.day = filesr[r]->ladate.day;
1246 pcir->ladate.month = filesr[r]->ladate.month;
1247 pcir->ladate.year = filesr[r]->ladate.year + 1980;
1248 pcir->latime.seconds = filesr[r]->latime.twosecs * 2;
1249 pcir->latime.minutes = filesr[r]->latime.minutes;
1250 pcir->latime.hours = filesr[r]->latime.hours;
1251 pcir->crdate.day = filesr[r]->crdate.day;
1252 pcir->crdate.month = filesr[r]->crdate.month;
1253 pcir->crdate.year = filesr[r]->crdate.year + 1980;
1254 pcir->crtime.seconds = filesr[r]->crtime.twosecs * 2;
1255 pcir->crtime.minutes = filesr[r]->crtime.minutes;
1256 pcir->crtime.hours = filesr[r]->crtime.hours;
1257 if (*cmp->dcd.mask.szMask) {
1258 if (!Filter((PMINIRECORDCORE) pcir, (PVOID) & cmp->dcd.mask)) {
1259 pcir->rc.flRecordAttr |= CRA_FILTERED;
1260 pcil->rc.flRecordAttr |= CRA_FILTERED;
1261 }
1262 }
1263 free(filesr[r]);
1264 r++;
1265 }
1266 }
1267 else if (filesl && filesl[l]) {
1268 // Just on left
1269 sprintf(pcil->szFileName, "%s%s%s", cmp->leftdir,
1270 (cmp->leftdir[strlen(cmp->leftdir) - 1] == '\\') ?
1271 NullStr : "\\", filesl[l]->fname);
1272 pcil->pszFileName = pcil->szFileName + lenl;
1273 pcil->attrFile = filesl[l]->attrFile;
1274 // pcil->rc.hptrIcon = hptrFile;
1275 y = 0;
1276 for (x = 0; x < 6; x++)
1277 if (attrstring[x])
1278 pcil->szDispAttr[y++] = (CHAR) ((pcil->attrFile & (1 << x)) ?
1279 attrstring[x] : '-');
1280 pcil->szDispAttr[5] = 0;
1281 pcil->cbFile = filesl[l]->cbFile;
1282 pcil->easize = filesl[l]->easize;
1283 pcil->date.day = filesl[l]->date.day;
1284 pcil->date.month = filesl[l]->date.month;
1285 pcil->date.year = filesl[l]->date.year + 1980;
1286 pcil->time.seconds = filesl[l]->time.twosecs * 2;
1287 pcil->time.minutes = filesl[l]->time.minutes;
1288 pcil->time.hours = filesl[l]->time.hours;
1289 pcil->ladate.day = filesl[l]->ladate.day;
1290 pcil->ladate.month = filesl[l]->ladate.month;
1291 pcil->ladate.year = filesl[l]->ladate.year + 1980;
1292 pcil->latime.seconds = filesl[l]->latime.twosecs * 2;
1293 pcil->latime.minutes = filesl[l]->latime.minutes;
1294 pcil->latime.hours = filesl[l]->latime.hours;
1295 pcil->crdate.day = filesl[l]->crdate.day;
1296 pcil->crdate.month = filesl[l]->crdate.month;
1297 pcil->crdate.year = filesl[l]->crdate.year + 1980;
1298 pcil->crtime.seconds = filesl[l]->crtime.twosecs * 2;
1299 pcil->crtime.minutes = filesl[l]->crtime.minutes;
1300 pcil->crtime.hours = filesl[l]->crtime.hours;
1301 if (*cmp->dcd.mask.szMask) {
1302 if (!Filter((PMINIRECORDCORE) pcil, (PVOID) & cmp->dcd.mask)) {
1303 pcil->rc.flRecordAttr |= CRA_FILTERED;
1304 pcir->rc.flRecordAttr |= CRA_FILTERED;
1305 }
1306 }
1307 free(filesl[l]);
1308 l++;
1309 }
1310 else {
1311 /* filesr && filesr[r] */
1312 // Just on right
1313 sprintf(pcir->szFileName, "%s%s%s", cmp->rightdir,
1314 (cmp->rightdir[strlen(cmp->rightdir) - 1] == '\\') ?
1315 NullStr : "\\", filesr[r]->fname);
1316 pcir->pszFileName = pcir->szFileName + lenr;
1317 pcir->attrFile = filesr[r]->attrFile;
1318 // pcir->rc.hptrIcon = hptrFile;
1319 y = 0;
1320 for (x = 0; x < 6; x++) {
1321 if (attrstring[x])
1322 pcir->szDispAttr[y++] = (CHAR) ((pcir->attrFile & (1 << x)) ?
1323 attrstring[x] : '-');
1324 }
1325 pcir->szDispAttr[5] = 0;
1326 pcir->cbFile = filesr[r]->cbFile;
1327 pcir->easize = filesr[r]->easize;
1328 pcir->date.day = filesr[r]->date.day;
1329 pcir->date.month = filesr[r]->date.month;
1330 pcir->date.year = filesr[r]->date.year + 1980;
1331 pcir->time.seconds = filesr[r]->time.twosecs * 2;
1332 pcir->time.minutes = filesr[r]->time.minutes;
1333 pcir->time.hours = filesr[r]->time.hours;
1334 pcir->ladate.day = filesr[r]->ladate.day;
1335 pcir->ladate.month = filesr[r]->ladate.month;
1336 pcir->ladate.year = filesr[r]->ladate.year + 1980;
1337 pcir->latime.seconds = filesr[r]->latime.twosecs * 2;
1338 pcir->latime.minutes = filesr[r]->latime.minutes;
1339 pcir->latime.hours = filesr[r]->latime.hours;
1340 pcir->crdate.day = filesr[r]->crdate.day;
1341 pcir->crdate.month = filesr[r]->crdate.month;
1342 pcir->crdate.year = filesr[r]->crdate.year + 1980;
1343 pcir->crtime.seconds = filesr[r]->crtime.twosecs * 2;
1344 pcir->crtime.minutes = filesr[r]->crtime.minutes;
1345 pcir->crtime.hours = filesr[r]->crtime.hours;
1346 if (*cmp->dcd.mask.szMask) {
1347 if (!Filter((PMINIRECORDCORE) pcir, (PVOID) & cmp->dcd.mask)) {
1348 pcir->rc.flRecordAttr |= CRA_FILTERED;
1349 pcil->rc.flRecordAttr |= CRA_FILTERED;
1350 }
1351 }
1352 free(filesr[r]);
1353 r++;
1354 }
1355 if (!(cntr % 500))
1356 DosSleep(1L);
1357 else if (!(cntr % 50))
1358 DosSleep(0L);
1359 cntr++;
1360 pcil = (PCNRITEM) pcil->rc.preccNextRecord;
1361 pcir = (PCNRITEM) pcir->rc.preccNextRecord;
1362 } // while
1363 if (filesl)
1364 free(filesl); // Free header - have already freed elements
1365 filesl = NULL;
1366 if (filesr)
1367 free(filesr);
1368 filesr = NULL;
1369 /* insert 'em */
1370 WinSendMsg(cmp->hwnd, UM_CONTAINERDIR, MPVOID, MPVOID);
1371 memset(&ri, 0, sizeof(RECORDINSERT));
1372 ri.cb = sizeof(RECORDINSERT);
1373 ri.pRecordOrder = (PRECORDCORE) CMA_END;
1374 ri.pRecordParent = (PRECORDCORE) NULL;
1375 ri.zOrder = (ULONG) CMA_TOP;
1376 ri.cRecordsInsert = recsNeeded;
1377 ri.fInvalidateRecord = FALSE;
1378 if (!WinSendMsg(hwndLeft, CM_INSERTRECORD,
1379 MPFROMP(pcilFirst), MPFROMP(&ri))) {
1380 pcil = pcilFirst;
1381 while (pcil) {
1382 pcit = (PCNRITEM) pcil->rc.preccNextRecord;
1383 WinSendMsg(hwndLeft, CM_FREERECORD,
1384 MPFROMP(&pcil), MPFROMSHORT(1));
1385 pcil = pcit;
1386 }
1387 numfilesl = 0;
1388 }
1389 memset(&ri, 0, sizeof(RECORDINSERT));
1390 ri.cb = sizeof(RECORDINSERT);
1391 ri.pRecordOrder = (PRECORDCORE) CMA_END;
1392 ri.pRecordParent = (PRECORDCORE) NULL;
1393 ri.zOrder = (ULONG) CMA_TOP;
1394 ri.cRecordsInsert = recsNeeded;
1395 ri.fInvalidateRecord = FALSE;
1396 if (!WinSendMsg(hwndRight, CM_INSERTRECORD,
1397 MPFROMP(pcirFirst), MPFROMP(&ri))) {
1398 WinSendMsg(hwndLeft, CM_REMOVERECORD,
1399 MPVOID, MPFROM2SHORT(0, CMA_FREE | CMA_INVALIDATE));
1400 pcir = pcirFirst;
1401 while (pcir) {
1402 pcit = (PCNRITEM) pcir->rc.preccNextRecord;
1403 WinSendMsg(hwndRight, CM_FREERECORD,
1404 MPFROMP(&pcir), MPFROMSHORT(1));
1405 pcir = pcit;
1406 }
1407 numfilesr = 0;
1408 }
1409 cmp->cmp->totalleft = numfilesl;
1410 cmp->cmp->totalright = numfilesr;
1411 } // if recsNeeded
1412 Deselect(hwndLeft);
1413 Deselect(hwndRight);
1414 if (!PostMsg(cmp->hwnd, UM_CONTAINER_FILLED, MPVOID, MPVOID))
1415 WinSendMsg(cmp->hwnd, UM_CONTAINER_FILLED, MPVOID, MPVOID);
1416 notified = TRUE;
1417 if (filesl)
1418 FreeList((CHAR **) filesl); // Must have failed to create container
1419 if (filesr)
1420 FreeList((CHAR **) filesr);
1421 WinDestroyMsgQueue(hmq);
1422 }
1423 DecrThreadUsage();
1424 WinTerminate(hab);
1425 }
1426 if (!notified)
1427 PostMsg(cmp->hwnd, UM_CONTAINER_FILLED, MPVOID, MPVOID);
1428 free(cmp);
1429 DosPostEventSem(CompactSem);
1430}
1431
1432#define hwndLeft (WinWindowFromID(hwnd,COMP_LEFTDIR))
1433#define hwndRight (WinWindowFromID(hwnd,COMP_RIGHTDIR))
1434
1435//=== CompareDlgProc() Compare directories dialog procedure ===
1436
1437MRESULT EXPENTRY CompareDlgProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
1438{
1439 COMPARE *cmp;
1440
1441 static HPOINTER hptr = (HPOINTER) 0;
1442
1443 switch (msg) {
1444 case WM_INITDLG:
1445 cmp = (COMPARE *) mp2;
1446 if (!cmp) {
1447 Runtime_Error2(pszSrcFile, __LINE__, IDS_NODATATEXT);
1448 WinDismissDlg(hwnd, 0);
1449 }
1450 else {
1451 if (!hptr)
1452 hptr = WinLoadPointer(HWND_DESKTOP, FM3ModHandle, COMPARE_ICON);
1453 WinDefDlgProc(hwnd, WM_SETICON, MPFROMLONG(hptr), MPVOID);
1454 cmp->hwnd = hwnd;
1455 WinSetWindowPtr(hwnd, QWL_USER, (PVOID) cmp);
1456 SetCnrCols(hwndLeft, TRUE);
1457 SetCnrCols(hwndRight, TRUE);
1458 WinSendMsg(hwnd, UM_SETUP, MPVOID, MPVOID);
1459 WinSendMsg(hwnd, UM_SETDIR, MPVOID, MPVOID);
1460 PostMsg(hwnd, UM_STRETCH, MPVOID, MPVOID);
1461 {
1462 USHORT ids[] = { COMP_LEFTDIR, COMP_RIGHTDIR, COMP_TOTALLEFT,
1463 COMP_TOTALRIGHT, COMP_SELLEFT, COMP_SELRIGHT,
1464 0
1465 };
1466 register INT x;
1467
1468 for (x = 0; ids[x]; x++)
1469 SetPresParams(WinWindowFromID(hwnd, ids[x]),
1470 &RGBGREY,
1471 &RGBBLACK, &RGBBLACK, GetPString(IDS_8HELVTEXT));
1472 }
1473 }
1474 break;
1475
1476 case UM_STRETCH:
1477 {
1478 SWP swp, swpC;
1479 LONG titl, szbx, szby, sz;
1480 HWND hwndActive;
1481
1482 WinQueryWindowPos(hwnd, &swp);
1483 if (!(swp.fl & (SWP_HIDE | SWP_MINIMIZE))) {
1484 hwndActive = WinQueryFocus(HWND_DESKTOP);
1485 szbx = SysVal(SV_CXSIZEBORDER);
1486 szby = SysVal(SV_CYSIZEBORDER);
1487 titl = SysVal(SV_CYTITLEBAR);
1488 titl += 26;
1489 swp.cx -= (szbx * 2);
1490 sz = (swp.cx / 8);
1491 WinQueryWindowPos(WinWindowFromID(hwnd, COMP_LEFTDIR), &swpC);
1492 WinSetWindowPos(WinWindowFromID(hwnd, COMP_LEFTDIR), HWND_TOP,
1493 szbx + 6,
1494 swpC.y,
1495 (swp.cx / 2) - (szbx + 6),
1496 ((swp.cy - swpC.y) - titl) - szby,
1497 SWP_MOVE | SWP_SIZE);
1498 WinSetWindowPos(WinWindowFromID(hwnd, COMP_RIGHTDIR), HWND_TOP,
1499 (swp.cx / 2) + (szbx + 6),
1500 swpC.y,
1501 (swp.cx / 2) - (szbx + 6),
1502 ((swp.cy - swpC.y) - titl) - szby,
1503 SWP_MOVE | SWP_SIZE);
1504 WinSetWindowPos(WinWindowFromID(hwnd, COMP_TOTALLEFTHDR), HWND_TOP,
1505 szbx + 6,
1506 ((swp.cy - titl) - szby) + 4,
1507 sz - (szbx + 6), 20, SWP_MOVE | SWP_SIZE);
1508 WinSetWindowPos(WinWindowFromID(hwnd, COMP_TOTALLEFT), HWND_TOP,
1509 sz + (szbx + 6),
1510 ((swp.cy - titl) - szby) + 4,
1511 sz - (szbx + 6), 20, SWP_MOVE | SWP_SIZE);
1512 WinSetWindowPos(WinWindowFromID(hwnd, COMP_SELLEFTHDR), HWND_TOP,
1513 (sz * 2) + (szbx + 6),
1514 ((swp.cy - titl) - szby) + 4,
1515 sz - (szbx + 6), 20, SWP_MOVE | SWP_SIZE);
1516 WinSetWindowPos(WinWindowFromID(hwnd, COMP_SELLEFT), HWND_TOP,
1517 (sz * 3) + (szbx + 6),
1518 ((swp.cy - titl) - szby) + 4,
1519 sz - (szbx + 6), 20, SWP_MOVE | SWP_SIZE);
1520 WinSetWindowPos(WinWindowFromID(hwnd, COMP_TOTALRIGHTHDR), HWND_TOP,
1521 (sz * 4) + (szbx + 6),
1522 ((swp.cy - titl) - szby) + 4,
1523 sz - (szbx + 6), 20, SWP_MOVE | SWP_SIZE);
1524 WinSetWindowPos(WinWindowFromID(hwnd, COMP_TOTALRIGHT), HWND_TOP,
1525 (sz * 5) + (szbx + 6),
1526 ((swp.cy - titl) - szby) + 4,
1527 sz - (szbx + 6), 20, SWP_MOVE | SWP_SIZE);
1528 WinSetWindowPos(WinWindowFromID(hwnd, COMP_SELRIGHTHDR), HWND_TOP,
1529 (sz * 6) + (szbx + 6),
1530 ((swp.cy - titl) - szby) + 4,
1531 sz - (szbx + 6), 20, SWP_MOVE | SWP_SIZE);
1532 WinSetWindowPos(WinWindowFromID(hwnd, COMP_SELRIGHT), HWND_TOP,
1533 (sz * 7) + (szbx + 6),
1534 ((swp.cy - titl) - szby) + 4,
1535 sz - (szbx + 6), 20, SWP_MOVE | SWP_SIZE);
1536 PaintRecessedWindow(WinWindowFromID(hwnd, COMP_TOTALLEFT),
1537 (HPS) 0, FALSE, FALSE);
1538 PaintRecessedWindow(WinWindowFromID(hwnd, COMP_SELLEFT),
1539 (HPS) 0, FALSE, FALSE);
1540 PaintRecessedWindow(WinWindowFromID(hwnd, COMP_TOTALRIGHT),
1541 (HPS) 0, FALSE, FALSE);
1542 PaintRecessedWindow(WinWindowFromID(hwnd, COMP_SELRIGHT),
1543 (HPS) 0, FALSE, FALSE);
1544 PaintRecessedWindow(hwndLeft, (HPS) 0,
1545 (hwndActive == hwndLeft), TRUE);
1546 PaintRecessedWindow(hwndRight, (HPS) 0,
1547 (hwndActive == hwndRight), TRUE);
1548 }
1549 }
1550 return 0;
1551
1552 case WM_ADJUSTWINDOWPOS:
1553 PostMsg(hwnd, UM_STRETCH, MPVOID, MPVOID);
1554 break;
1555
1556 case UM_SETUP:
1557 {
1558 CNRINFO cnri;
1559 BOOL tempsubj;
1560
1561 cmp = INSTDATA(hwnd);
1562 if (cmp) {
1563 cmp->dcd.size = sizeof(DIRCNRDATA);
1564 cmp->dcd.type = DIR_FRAME;
1565 cmp->dcd.hwndFrame = hwnd;
1566 cmp->dcd.hwndClient = hwnd;
1567 cmp->dcd.mask.attrFile = (FILE_DIRECTORY | FILE_ARCHIVED |
1568 FILE_READONLY | FILE_SYSTEM | FILE_HIDDEN);
1569 LoadDetailsSwitches("DirCmp", &cmp->dcd);
1570 cmp->dcd.detailslongname = FALSE;
1571 cmp->dcd.detailsicon = FALSE; /* TRUE; */
1572 }
1573 memset(&cnri, 0, sizeof(CNRINFO));
1574 cnri.cb = sizeof(CNRINFO);
1575 WinSendDlgItemMsg(hwnd, COMP_LEFTDIR, CM_QUERYCNRINFO,
1576 MPFROMP(&cnri), MPFROMLONG(sizeof(CNRINFO)));
1577 cnri.flWindowAttr |= (CA_OWNERDRAW | CV_MINI);
1578 cnri.xVertSplitbar = DIR_SPLITBAR_OFFSET - 68;
1579 WinSendDlgItemMsg(hwnd, COMP_LEFTDIR, CM_SETCNRINFO, MPFROMP(&cnri),
1580 MPFROMLONG(CMA_FLWINDOWATTR | CMA_XVERTSPLITBAR));
1581 memset(&cnri, 0, sizeof(CNRINFO));
1582 cnri.cb = sizeof(CNRINFO);
1583 WinSendDlgItemMsg(hwnd, COMP_RIGHTDIR, CM_QUERYCNRINFO,
1584 MPFROMP(&cnri), MPFROMLONG(sizeof(CNRINFO)));
1585 cnri.flWindowAttr |= (CA_OWNERDRAW | CV_MINI);
1586 cnri.xVertSplitbar = DIR_SPLITBAR_OFFSET - 54;
1587 WinSendDlgItemMsg(hwnd, COMP_RIGHTDIR, CM_SETCNRINFO, MPFROMP(&cnri),
1588 MPFROMLONG(CMA_FLWINDOWATTR | CMA_XVERTSPLITBAR));
1589 AdjustCnrColRO(hwndLeft, GetPString(IDS_FILENAMECOLTEXT), TRUE, FALSE);
1590 AdjustCnrColRO(hwndLeft, GetPString(IDS_LONGNAMECOLTEXT), TRUE, FALSE);
1591 AdjustCnrColRO(hwndRight, GetPString(IDS_FILENAMECOLTEXT), TRUE, FALSE);
1592 AdjustCnrColRO(hwndRight, GetPString(IDS_LONGNAMECOLTEXT), TRUE, FALSE);
1593 AdjustCnrColsForPref(hwndLeft, cmp->leftdir, &cmp->dcd, TRUE);
1594 tempsubj = cmp->dcd.detailssubject;
1595 cmp->dcd.detailssubject = FALSE;
1596 AdjustCnrColsForPref(hwndRight, cmp->rightdir, &cmp->dcd, TRUE);
1597 if (*cmp->rightlist) {
1598 AdjustCnrColVis(hwndRight, GetPString(IDS_LADATECOLTEXT), FALSE,
1599 FALSE);
1600 AdjustCnrColVis(hwndRight, GetPString(IDS_LATIMECOLTEXT), FALSE,
1601 FALSE);
1602 AdjustCnrColVis(hwndRight, GetPString(IDS_CRDATECOLTEXT), FALSE,
1603 FALSE);
1604 AdjustCnrColVis(hwndRight, GetPString(IDS_CRTIMECOLTEXT), FALSE,
1605 FALSE);
1606 }
1607 cmp->dcd.detailssubject = tempsubj;
1608 }
1609 return 0;
1610
1611 case WM_DRAWITEM:
1612 if (mp2) {
1613
1614 POWNERITEM pown = (POWNERITEM) mp2;
1615 PCNRDRAWITEMINFO pcown;
1616 PCNRITEM pci;
1617
1618 pcown = (PCNRDRAWITEMINFO) pown->hItem;
1619 if (pcown) {
1620 pci = (PCNRITEM) pcown->pRecord;
1621 if (pci && (INT) pci != -1 && !*pci->szFileName)
1622 return MRFROMLONG(TRUE);
1623 }
1624 }
1625 return 0;
1626
1627 case UM_CONTAINERHWND:
1628 WinSetDlgItemText(hwnd, COMP_NOTE, GetPString(IDS_COMPHOLDBLDLISTTEXT));
1629 return 0;
1630
1631 case UM_CONTAINERDIR:
1632 WinSetDlgItemText(hwnd, COMP_NOTE, GetPString(IDS_COMPHOLDFILLCNRTEXT));
1633 return 0;
1634
1635 case UM_CONTAINER_FILLED:
1636 cmp = INSTDATA(hwnd);
1637 if (!cmp) {
1638 Runtime_Error(pszSrcFile, __LINE__, "pCompare NULL");
1639 WinDismissDlg(hwnd, 0);
1640 }
1641 else {
1642 CHAR s[81];
1643
1644 cmp->filling = FALSE;
1645 WinEnableWindow(hwndLeft, TRUE);
1646 WinEnableWindow(hwndRight, TRUE);
1647 WinEnableWindowUpdate(hwndLeft, TRUE);
1648 WinEnableWindowUpdate(hwndRight, TRUE);
1649 sprintf(s, " %d", cmp->totalleft);
1650 WinSetDlgItemText(hwnd, COMP_TOTALLEFT, s);
1651 sprintf(s, " %d", cmp->totalright);
1652 WinSetDlgItemText(hwnd, COMP_TOTALRIGHT, s);
1653 sprintf(s, " %d", cmp->selleft);
1654 WinSetDlgItemText(hwnd, COMP_SELLEFT, s);
1655 sprintf(s, " %d", cmp->selright);
1656 WinSetDlgItemText(hwnd, COMP_SELRIGHT, s);
1657 WinEnableWindow(WinWindowFromID(hwnd, DID_OK), TRUE);
1658 WinEnableWindow(WinWindowFromID(hwnd, DID_CANCEL), TRUE);
1659 WinEnableWindow(WinWindowFromID(hwnd, COMP_COLLECT), TRUE);
1660 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTBOTH), TRUE);
1661 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTONE), TRUE);
1662 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTNEWER), TRUE);
1663 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTOLDER), TRUE);
1664 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTBIGGER), TRUE);
1665 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTSMALLER), TRUE);
1666 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTBOTH), TRUE);
1667 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTONE), TRUE);
1668 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTNEWER), TRUE);
1669 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTOLDER), TRUE);
1670 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTBIGGER), TRUE);
1671 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTSMALLER), TRUE);
1672 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTALL), TRUE);
1673 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTSAMECONTENT), TRUE);
1674 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTIDENTICAL), TRUE);
1675 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTSAME), TRUE);
1676 WinEnableWindow(WinWindowFromID(hwnd, IDM_INVERT), TRUE);
1677 WinEnableWindow(WinWindowFromID(hwnd, COMP_SETDIRS), TRUE);
1678 WinEnableWindow(WinWindowFromID(hwnd, COMP_DELETELEFT), TRUE);
1679 WinEnableWindow(WinWindowFromID(hwnd, COMP_FILTER), TRUE);
1680 if (!*cmp->rightlist) {
1681 WinEnableWindow(WinWindowFromID(hwnd, COMP_COPYLEFT), TRUE);
1682 WinEnableWindow(WinWindowFromID(hwnd, COMP_MOVELEFT), TRUE);
1683 WinEnableWindow(WinWindowFromID(hwnd, COMP_DELETERIGHT), TRUE);
1684 WinEnableWindow(WinWindowFromID(hwnd, COMP_COPYRIGHT), TRUE);
1685 WinEnableWindow(WinWindowFromID(hwnd, COMP_MOVERIGHT), TRUE);
1686 }
1687 WinEnableWindow(WinWindowFromID(hwnd, COMP_INCLUDESUBDIRS), TRUE);
1688 if (*cmp->dcd.mask.szMask)
1689 WinSetDlgItemText(hwnd, COMP_NOTE,
1690 GetPString(IDS_COMPREADYFILTEREDTEXT));
1691 else
1692 WinSetDlgItemText(hwnd, COMP_NOTE, GetPString(IDS_COMPREADYTEXT));
1693 }
1694 break;
1695
1696 case WM_INITMENU:
1697 cmp = INSTDATA(hwnd);
1698 if (cmp) {
1699 switch (SHORT1FROMMP(mp1)) {
1700 case IDM_COMMANDSMENU:
1701 SetupCommandMenu(cmp->dcd.hwndLastMenu, hwnd);
1702 break;
1703 }
1704 }
1705 break;
1706
1707 case WM_MENUEND:
1708 cmp = INSTDATA(hwnd);
1709 if (cmp) {
1710 if ((HWND) mp2 == cmp->dcd.hwndLastMenu) {
1711 MarkAll(hwndLeft, TRUE, FALSE, TRUE);
1712 MarkAll(hwndRight, TRUE, FALSE, TRUE);
1713 WinDestroyWindow(cmp->dcd.hwndLastMenu);
1714 cmp->dcd.hwndLastMenu = (HWND) 0;
1715 }
1716 }
1717 break;
1718
1719 case WM_CONTROL:
1720 switch (SHORT1FROMMP(mp1)) {
1721 case COMP_INCLUDESUBDIRS:
1722 switch (SHORT2FROMMP(mp1)) {
1723 case BN_CLICKED:
1724 cmp = INSTDATA(hwnd);
1725 if (cmp)
1726 *cmp->rightlist = 0;
1727 PostMsg(hwnd, UM_SETUP, MPVOID, MPVOID);
1728 PostMsg(hwnd, UM_SETDIR, MPVOID, MPVOID);
1729 break;
1730 }
1731 break;
1732 case COMP_HIDENOTSELECTED:
1733 switch (SHORT2FROMMP(mp1)) {
1734 case BN_CLICKED:
1735 WinSendMsg(hwnd, UM_HIDENOTSELECTED, MPVOID, MPVOID);
1736 break;
1737 }
1738 break;
1739
1740 case COMP_LEFTDIR:
1741 case COMP_RIGHTDIR:
1742 switch (SHORT2FROMMP(mp1)) {
1743 case CN_KILLFOCUS:
1744 PaintRecessedWindow(WinWindowFromID(hwnd, SHORT1FROMMP(mp1)),
1745 (HPS) 0, FALSE, TRUE);
1746 break;
1747
1748 case CN_SETFOCUS:
1749 PaintRecessedWindow(WinWindowFromID(hwnd, SHORT1FROMMP(mp1)),
1750 (HPS) 0, TRUE, TRUE);
1751 break;
1752
1753 case CN_ENTER:
1754 if (mp2) {
1755
1756 PCNRITEM pci = (PCNRITEM) ((PNOTIFYRECORDENTER) mp2)->pRecord;
1757 HWND hwndCnr = WinWindowFromID(hwnd, SHORT1FROMMP(mp1));
1758
1759 SetShiftState();
1760 if (pci) {
1761 if ((pci->rc.flRecordAttr & CRA_INUSE) || !*pci->szFileName)
1762 break;
1763 WinSendMsg(hwndCnr, CM_SETRECORDEMPHASIS, MPFROMP(pci),
1764 MPFROM2SHORT(TRUE, CRA_INUSE));
1765 if (pci->attrFile & FILE_DIRECTORY) {
1766 if ((shiftstate & (KC_CTRL | KC_SHIFT)) == (KC_CTRL | KC_SHIFT))
1767 OpenObject(pci->szFileName, Settings, hwnd);
1768 else
1769 OpenObject(pci->szFileName, Default, hwnd);
1770 }
1771 else
1772 DefaultViewKeys(hwnd, hwnd, HWND_DESKTOP, NULL,
1773 pci->szFileName);
1774 WinSendMsg(hwndCnr, CM_SETRECORDEMPHASIS,
1775 MPFROMP(pci),
1776 MPFROM2SHORT(FALSE, CRA_INUSE |
1777 ((fUnHilite) ? CRA_SELECTED : 0)));
1778 }
1779 }
1780 break;
1781
1782 case CN_CONTEXTMENU:
1783 cmp = INSTDATA(hwnd);
1784 if (cmp) {
1785
1786 PCNRITEM pci = (PCNRITEM) mp2;
1787 USHORT id = COMP_CNRMENU;
1788
1789 if (cmp->dcd.hwndLastMenu)
1790 WinDestroyWindow(cmp->dcd.hwndLastMenu);
1791 cmp->dcd.hwndLastMenu = (HWND) 0;
1792 cmp->hwndCalling = WinWindowFromID(hwnd, SHORT1FROMMP(mp1));
1793 if (pci) {
1794 if (!*pci->szFileName || *cmp->rightlist)
1795 break;
1796 id = COMP_MENU;
1797 WinSendMsg(cmp->hwndCalling, CM_SETRECORDEMPHASIS,
1798 MPFROMP(pci), MPFROM2SHORT(TRUE, CRA_CURSORED));
1799 }
1800 cmp->dcd.hwndLastMenu = WinLoadMenu(HWND_DESKTOP, FM3ModHandle, id);
1801 if (cmp->dcd.hwndLastMenu) {
1802 if (id == COMP_CNRMENU) {
1803 if (SHORT1FROMMP(mp1) == COMP_RIGHTDIR)
1804 WinSendMsg(cmp->dcd.hwndLastMenu, MM_DELETEITEM,
1805 MPFROM2SHORT(IDM_SHOWSUBJECT, FALSE), MPVOID);
1806 SetDetailsSwitches(cmp->dcd.hwndLastMenu, &cmp->dcd);
1807 if (SHORT1FROMMP(mp1) == COMP_LEFTDIR)
1808 WinSendMsg(cmp->dcd.hwndLastMenu, MM_DELETEITEM,
1809 MPFROM2SHORT(IDM_LOADLISTFILE, 0), MPVOID);
1810 else if (*cmp->rightlist)
1811 WinSendMsg(cmp->dcd.hwndLastMenu, MM_DELETEITEM,
1812 MPFROM2SHORT(IDM_SAVELISTFILE, 0), MPVOID);
1813 }
1814 PopupMenu(hwnd, hwnd, cmp->dcd.hwndLastMenu);
1815 }
1816 }
1817 break;
1818
1819 case CN_INITDRAG:
1820 cmp = INSTDATA(hwnd);
1821 if (*cmp->rightlist && SHORT1FROMMP(mp1) == COMP_RIGHTDIR)
1822 break;
1823 DoFileDrag(WinWindowFromID(hwnd, SHORT1FROMMP(mp1)),
1824 (HWND) 0, mp2, NULL, NULL, TRUE);
1825 break;
1826
1827 case CN_BEGINEDIT:
1828 case CN_REALLOCPSZ:
1829 // fixme to be gone - field edits not allowed
1830 Runtime_Error(pszSrcFile, __LINE__,
1831 "CN_BEGINEDIT/CN_REALLOCPSZ unexpected");
1832 break;
1833
1834 case CN_EMPHASIS:
1835 {
1836 PNOTIFYRECORDEMPHASIS pre = mp2;
1837 PCNRITEM pci;
1838
1839 if (pre->fEmphasisMask & CRA_SELECTED) {
1840 pci = (PCNRITEM) pre->pRecord;
1841 if (pci) {
1842 if (!*pci->szFileName) {
1843 if (pci->rc.flRecordAttr & CRA_SELECTED)
1844 WinSendDlgItemMsg(hwnd, SHORT1FROMMP(mp1),
1845 CM_SETRECORDEMPHASIS,
1846 MPFROMP(pci),
1847 MPFROM2SHORT(FALSE, CRA_SELECTED));
1848 }
1849 else {
1850
1851 CHAR s[81];
1852
1853 cmp = INSTDATA(hwnd);
1854 if (pci->rc.flRecordAttr & CRA_SELECTED) {
1855 if (SHORT1FROMMP(mp1) == COMP_LEFTDIR)
1856 cmp->selleft++;
1857 else
1858 cmp->selright++;
1859 }
1860 else {
1861 if (SHORT1FROMMP(mp1) == COMP_LEFTDIR) {
1862 if (cmp->selleft)
1863 cmp->selleft--;
1864 }
1865 else {
1866 if (cmp->selright)
1867 cmp->selright--;
1868 }
1869 }
1870 if (SHORT1FROMMP(mp1) == COMP_LEFTDIR) {
1871 if (WinIsWindowEnabled(hwndLeft) || !(cmp->selleft % 50)) {
1872 sprintf(s, " %d", cmp->selleft);
1873 WinSetDlgItemText(hwnd, COMP_SELLEFT, s);
1874 }
1875 }
1876 else {
1877 if (WinIsWindowEnabled(hwndRight) || !(cmp->selright % 50)) {
1878 sprintf(s, " %d", cmp->selright);
1879 WinSetDlgItemText(hwnd, COMP_SELRIGHT, s);
1880 }
1881 }
1882 }
1883 }
1884 }
1885 }
1886 break;
1887
1888 case CN_SCROLL:
1889 cmp = INSTDATA(hwnd);
1890 if (!cmp->forcescroll) {
1891
1892 PNOTIFYSCROLL pns = mp2;
1893
1894 if (pns->fScroll & CMA_VERTICAL) {
1895 cmp->forcescroll = TRUE;
1896 WinSendDlgItemMsg(hwnd, (SHORT1FROMMP(mp1) == COMP_LEFTDIR) ?
1897 COMP_RIGHTDIR : COMP_LEFTDIR,
1898 CM_SCROLLWINDOW, MPFROMSHORT(CMA_VERTICAL),
1899 MPFROMLONG(pns->lScrollInc));
1900 cmp->forcescroll = FALSE;
1901 }
1902 }
1903 break;
1904 }
1905 break; // COMP_RIGHTDIR
1906 }
1907 return 0; // WM_CONTROL
1908
1909 case UM_SETDIR:
1910 cmp = INSTDATA(hwnd);
1911 if (cmp) {
1912
1913 COMPARE *forthread;
1914 CNRINFO cnri;
1915
1916 cmp->includesubdirs = WinQueryButtonCheckstate(hwnd,
1917 COMP_INCLUDESUBDIRS);
1918 memset(&cnri, 0, sizeof(CNRINFO));
1919 cnri.cb = sizeof(CNRINFO);
1920 cnri.pszCnrTitle = cmp->leftdir;
1921 cnri.flWindowAttr = CV_DETAIL | CV_MINI |
1922 CA_CONTAINERTITLE | CA_TITLESEPARATOR |
1923 CA_DETAILSVIEWTITLES | CA_OWNERDRAW;
1924 WinSendDlgItemMsg(hwnd, COMP_LEFTDIR, CM_SETCNRINFO, MPFROMP(&cnri),
1925 MPFROMLONG(CMA_CNRTITLE | CMA_FLWINDOWATTR));
1926 cnri.pszCnrTitle = cmp->rightdir;
1927 WinSendDlgItemMsg(hwnd, COMP_RIGHTDIR, CM_SETCNRINFO, MPFROMP(&cnri),
1928 MPFROMLONG(CMA_CNRTITLE | CMA_FLWINDOWATTR));
1929 WinCheckButton(hwnd, COMP_HIDENOTSELECTED, 0);
1930 cmp->filling = TRUE;
1931 forthread = xmalloc(sizeof(COMPARE), pszSrcFile, __LINE__);
1932 if (!forthread)
1933 WinDismissDlg(hwnd, 0);
1934 else {
1935 *forthread = *cmp;
1936 forthread->cmp = cmp;
1937 if (_beginthread(FillCnrsThread, NULL, 122880, (PVOID) forthread) ==
1938 -1) {
1939 Runtime_Error(pszSrcFile, __LINE__,
1940 GetPString(IDS_COULDNTSTARTTHREADTEXT));
1941 WinDismissDlg(hwnd, 0);
1942 free(forthread);
1943 }
1944 else {
1945 WinEnableWindowUpdate(hwndLeft, FALSE);
1946 WinEnableWindowUpdate(hwndRight, FALSE);
1947 cmp->selleft = cmp->selright = 0;
1948 WinSetDlgItemText(hwnd, COMP_SELLEFT, "0");
1949 WinSetDlgItemText(hwnd, COMP_SELRIGHT, "0");
1950 WinSetDlgItemText(hwnd, COMP_TOTALLEFT, "0");
1951 WinSetDlgItemText(hwnd, COMP_TOTALRIGHT, "0");
1952 WinSetDlgItemText(hwnd, COMP_NOTE,
1953 GetPString(IDS_COMPHOLDREADDISKTEXT));
1954 WinEnableWindow(hwndRight, FALSE);
1955 WinEnableWindow(hwndLeft, FALSE);
1956 WinEnableWindow(WinWindowFromID(hwnd, DID_OK), FALSE);
1957 WinEnableWindow(WinWindowFromID(hwnd, DID_CANCEL), FALSE);
1958 WinEnableWindow(WinWindowFromID(hwnd, COMP_COLLECT), FALSE);
1959 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTBOTH), FALSE);
1960 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTONE), FALSE);
1961 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTNEWER), FALSE);
1962 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTOLDER), FALSE);
1963 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTBIGGER), FALSE);
1964 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTSMALLER), FALSE);
1965 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTBOTH), FALSE);
1966 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTONE), FALSE);
1967 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTNEWER), FALSE);
1968 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTOLDER), FALSE);
1969 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTBIGGER), FALSE);
1970 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTSMALLER), FALSE);
1971 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTALL), FALSE);
1972 WinEnableWindow(WinWindowFromID(hwnd, COMP_INCLUDESUBDIRS), FALSE);
1973 WinEnableWindow(WinWindowFromID(hwnd, COMP_SETDIRS), FALSE);
1974 WinEnableWindow(WinWindowFromID(hwnd, COMP_DELETELEFT), FALSE);
1975 WinEnableWindow(WinWindowFromID(hwnd, COMP_DELETERIGHT), FALSE);
1976 WinEnableWindow(WinWindowFromID(hwnd, COMP_COPYLEFT), FALSE);
1977 WinEnableWindow(WinWindowFromID(hwnd, COMP_MOVELEFT), FALSE);
1978 WinEnableWindow(WinWindowFromID(hwnd, COMP_COPYRIGHT), FALSE);
1979 WinEnableWindow(WinWindowFromID(hwnd, COMP_MOVERIGHT), FALSE);
1980 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTSAMECONTENT),
1981 FALSE);
1982 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTIDENTICAL), FALSE);
1983 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTSAME), FALSE);
1984 WinEnableWindow(WinWindowFromID(hwnd, IDM_INVERT), FALSE);
1985 WinEnableWindow(WinWindowFromID(hwnd, COMP_FILTER), FALSE);
1986 }
1987 }
1988 }
1989 return 0;
1990
1991 case UM_FILTER:
1992 cmp = INSTDATA(hwnd);
1993 if (cmp) {
1994 if (mp1) {
1995 DosEnterCritSec();
1996 SetMask((CHAR *) mp1, &cmp->dcd.mask);
1997 DosExitCritSec();
1998 }
1999 cmp->dcd.suspendview = 1;
2000 WinSendMsg(hwndLeft, CM_FILTER, MPFROMP(Filter),
2001 MPFROMP(&cmp->dcd.mask));
2002 WinSendMsg(hwndRight, CM_FILTER, MPFROMP(Filter),
2003 MPFROMP(&cmp->dcd.mask));
2004 cmp->dcd.suspendview = 0;
2005 if (*cmp->dcd.mask.szMask)
2006 WinSetDlgItemText(hwnd, COMP_NOTE,
2007 GetPString(IDS_COMPREADYFILTEREDTEXT));
2008 else
2009 WinSetDlgItemText(hwnd, COMP_NOTE, GetPString(IDS_COMPREADYTEXT));
2010 }
2011 return 0;
2012
2013 case UM_HIDENOTSELECTED:
2014 cmp = INSTDATA(hwnd);
2015 if (cmp) {
2016 USHORT wantHide = WinQueryButtonCheckstate(hwnd,
2017 COMP_HIDENOTSELECTED);
2018
2019 cmp->dcd.suspendview = 1;
2020 if (wantHide) {
2021 BOOL needRefresh = FALSE;
2022 HWND hwndl = WinWindowFromID(cmp->hwnd, COMP_LEFTDIR);
2023 HWND hwndr = WinWindowFromID(cmp->hwnd, COMP_RIGHTDIR);
2024 PCNRITEM pcil = WinSendMsg(hwndl, CM_QUERYRECORD, MPVOID,
2025 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
2026 PCNRITEM pcir = WinSendMsg(hwndr, CM_QUERYRECORD, MPVOID,
2027 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
2028
2029 while (pcil && (INT) pcil != -1 && pcir && (INT) pcir != -1) {
2030 if (~pcil->rc.flRecordAttr & CRA_SELECTED &&
2031 ~pcir->rc.flRecordAttr & CRA_SELECTED) {
2032 pcil->rc.flRecordAttr |= CRA_FILTERED;
2033 pcir->rc.flRecordAttr |= CRA_FILTERED;
2034 needRefresh = TRUE;
2035 }
2036 pcil = WinSendMsg(hwndl, CM_QUERYRECORD, MPFROMP(pcil),
2037 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
2038 pcir = WinSendMsg(hwndr, CM_QUERYRECORD, MPFROMP(pcir),
2039 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
2040 } // while
2041 if (needRefresh) {
2042 WinSendMsg(hwndl, CM_INVALIDATERECORD,
2043 MPVOID, MPFROM2SHORT(0, CMA_REPOSITION));
2044 WinSendMsg(hwndr, CM_INVALIDATERECORD,
2045 MPVOID, MPFROM2SHORT(0, CMA_REPOSITION));
2046 }
2047 }
2048 else {
2049 WinSendMsg(hwndLeft, CM_FILTER, MPFROMP(Filter),
2050 MPFROMP(&cmp->dcd.mask));
2051 WinSendMsg(hwndRight, CM_FILTER, MPFROMP(Filter),
2052 MPFROMP(&cmp->dcd.mask));
2053 }
2054 cmp->dcd.suspendview = 0;
2055 if (*cmp->dcd.mask.szMask)
2056 WinSetDlgItemText(hwnd, COMP_NOTE,
2057 GetPString(IDS_COMPREADYFILTEREDTEXT));
2058 else
2059 WinSetDlgItemText(hwnd, COMP_NOTE, GetPString(IDS_COMPREADYTEXT));
2060 }
2061 return 0;
2062
2063 case WM_COMMAND:
2064 switch (SHORT1FROMMP(mp1)) {
2065 case IDM_COMPARE:
2066 cmp = INSTDATA(hwnd);
2067 if (cmp) {
2068
2069 PCNRITEM pci;
2070 CHAR ofile[CCHMAXPATH];
2071
2072 pci = (PCNRITEM) WinSendMsg(cmp->hwndCalling,
2073 CM_QUERYRECORDEMPHASIS,
2074 MPFROMLONG(CMA_FIRST),
2075 MPFROMSHORT(CRA_CURSORED));
2076 if (pci) {
2077 if (cmp->hwndCalling == hwndLeft)
2078 strcpy(ofile, cmp->rightdir);
2079 else
2080 strcpy(ofile, cmp->leftdir);
2081 if (ofile[strlen(ofile) - 1] != '\\')
2082 strcat(ofile, "\\");
2083 strcat(ofile, pci->pszFileName);
2084 if (*compare) {
2085
2086 CHAR *fakelist[3];
2087
2088 fakelist[0] = pci->szFileName;
2089 fakelist[1] = ofile;
2090 fakelist[2] = NULL;
2091 ExecOnList(hwnd, compare,
2092 WINDOWED | SEPARATEKEEP, NULL, fakelist, NULL);
2093 }
2094 else {
2095
2096 FCOMPARE fc;
2097
2098 memset(&fc, 0, sizeof(fc));
2099 fc.size = sizeof(fc);
2100 fc.hwndParent = hwnd;
2101 strcpy(fc.file1, pci->szFileName);
2102 strcpy(fc.file2, ofile);
2103 WinDlgBox(HWND_DESKTOP, hwnd,
2104 CFileDlgProc, FM3ModHandle, FCMP_FRAME, (PVOID) & fc);
2105 }
2106 }
2107 }
2108 break;
2109
2110 case COMP_FILTER:
2111 case IDM_FILTER:
2112 cmp = INSTDATA(hwnd);
2113 if (cmp) {
2114
2115 BOOL empty = FALSE;
2116 PCNRITEM pci;
2117 CHAR *p;
2118 BOOL temp;
2119
2120 if (!*cmp->dcd.mask.szMask) {
2121 empty = TRUE;
2122 temp = fSelectedAlways;
2123 fSelectedAlways = TRUE;
2124 pci = (PCNRITEM) CurrentRecord(hwnd);
2125 fSelectedAlways = temp;
2126 if (pci && !(pci->attrFile & FILE_DIRECTORY)) {
2127 p = strrchr(pci->szFileName, '\\');
2128 if (p) {
2129 p++;
2130 strcpy(cmp->dcd.mask.szMask, p);
2131 }
2132 }
2133 }
2134 cmp->dcd.mask.fNoAttribs = TRUE;
2135 cmp->dcd.mask.attrFile = ALLATTRS;
2136 cmp->dcd.mask.antiattr = 0;
2137 if (WinDlgBox(HWND_DESKTOP, hwnd, PickMaskDlgProc,
2138 FM3ModHandle, MSK_FRAME, MPFROMP(&cmp->dcd.mask))) {
2139 cmp->dcd.mask.attrFile = ALLATTRS;
2140 cmp->dcd.mask.antiattr = 0;
2141 WinSendMsg(hwnd, UM_FILTER, MPVOID, MPVOID);
2142 }
2143 else if (empty) {
2144 *cmp->dcd.mask.szMask = 0;
2145 cmp->dcd.mask.attrFile = ALLATTRS;
2146 cmp->dcd.mask.antiattr = 0;
2147 }
2148 }
2149 break;
2150
2151 case IDM_SHOWSUBJECT:
2152 case IDM_SHOWEAS:
2153 case IDM_SHOWSIZE:
2154 case IDM_SHOWLWDATE:
2155 case IDM_SHOWLWTIME:
2156 case IDM_SHOWLADATE:
2157 case IDM_SHOWLATIME:
2158 case IDM_SHOWCRDATE:
2159 case IDM_SHOWCRTIME:
2160 case IDM_SHOWATTR:
2161 cmp = INSTDATA(hwnd);
2162 if (cmp) {
2163
2164 DIRCNRDATA dcd1;
2165 BOOL tempsubj;
2166
2167 dcd1 = cmp->dcd;
2168 AdjustDetailsSwitches(hwndLeft,
2169 (HWND) 0, SHORT1FROMMP(mp1),
2170 cmp->leftdir, "DirCmp", &cmp->dcd, TRUE);
2171 tempsubj = cmp->dcd.detailssubject;
2172 cmp->dcd = dcd1;
2173 cmp->dcd.detailssubject = FALSE;
2174 AdjustDetailsSwitches(hwndRight,
2175 cmp->dcd.hwndLastMenu, SHORT1FROMMP(mp1),
2176 cmp->rightdir, "DirCmp", &cmp->dcd, TRUE);
2177 cmp->dcd.detailssubject = tempsubj;
2178 }
2179 break;
2180
2181 case IDM_LOADLISTFILE:
2182 cmp = INSTDATA(hwnd);
2183 if (cmp) {
2184
2185 CHAR fullname[CCHMAXPATH];
2186
2187 strcpy(fullname, "*.PMD");
2188 if (insert_filename(HWND_DESKTOP, fullname, TRUE, FALSE) &&
2189 *fullname && !strchr(fullname, '*') && !strchr(fullname, '?')) {
2190 strcpy(cmp->rightlist, fullname);
2191 PostMsg(hwnd, UM_SETUP, MPVOID, MPVOID);
2192 PostMsg(hwnd, UM_SETDIR, MPVOID, MPVOID);
2193 }
2194 }
2195 break;
2196
2197 case IDM_SAVELISTFILE:
2198 cmp = INSTDATA(hwnd);
2199 if (cmp) {
2200
2201 SNAPSTUFF *sf;
2202 CHAR fullname[CCHMAXPATH];
2203
2204 strcpy(fullname, "*.PMD");
2205 if (export_filename(HWND_DESKTOP, fullname, 1) && *fullname &&
2206 !strchr(fullname, '*') && !strchr(fullname, '?')) {
2207 sf = xmallocz(sizeof(SNAPSTUFF), pszSrcFile, __LINE__);
2208 if (sf) {
2209 strcpy(sf->filename, fullname);
2210 if (hwndLeft == cmp->hwndCalling)
2211 strcpy(sf->dirname, cmp->leftdir);
2212 else
2213 strcpy(sf->dirname, cmp->rightdir);
2214 sf->recurse = cmp->includesubdirs;
2215 if (_beginthread(StartSnap, NULL, 65536, (PVOID) sf) == -1) {
2216 Runtime_Error(pszSrcFile, __LINE__,
2217 GetPString(IDS_COULDNTSTARTTHREADTEXT));
2218 free(sf);
2219 }
2220 }
2221 }
2222 }
2223 break;
2224
2225 case COMP_SETDIRS:
2226 cmp = INSTDATA(hwnd);
2227 if (cmp) {
2228
2229 WALK2 wa;
2230
2231 memset(&wa, 0, sizeof(wa));
2232 wa.size = sizeof(wa);
2233 strcpy(wa.szCurrentPath1, cmp->leftdir);
2234 strcpy(wa.szCurrentPath2, cmp->rightdir);
2235 if (WinDlgBox(HWND_DESKTOP, hwnd, WalkTwoCmpDlgProc,
2236 FM3ModHandle, WALK2_FRAME,
2237 MPFROMP(&wa)) &&
2238 !IsFile(wa.szCurrentPath1) && !IsFile(wa.szCurrentPath2)) {
2239 strcpy(cmp->leftdir, wa.szCurrentPath1);
2240 strcpy(cmp->rightdir, wa.szCurrentPath2);
2241 *cmp->rightlist = 0;
2242 PostMsg(hwnd, UM_SETUP, MPVOID, MPVOID);
2243 PostMsg(hwnd, UM_SETDIR, MPVOID, MPVOID);
2244 }
2245 }
2246 break;
2247
2248 case COMP_COPYLEFT:
2249 case COMP_MOVELEFT:
2250 case COMP_COPYRIGHT:
2251 case COMP_MOVERIGHT:
2252 case COMP_DELETELEFT:
2253 case COMP_DELETERIGHT:
2254 cmp = INSTDATA(hwnd);
2255 if (cmp) {
2256
2257 COMPARE *forthread;
2258
2259 cmp->filling = TRUE;
2260 forthread = xmalloc(sizeof(COMPARE), pszSrcFile, __LINE__);
2261 if (forthread) {
2262 *forthread = *cmp;
2263 forthread->cmp = cmp;
2264 forthread->action = SHORT1FROMMP(mp1);
2265 if (_beginthread(ActionCnrThread, NULL, 122880, (PVOID) forthread)
2266 == -1) {
2267 Runtime_Error(pszSrcFile, __LINE__,
2268 GetPString(IDS_COULDNTSTARTTHREADTEXT));
2269 free(forthread);
2270 }
2271 else {
2272 WinEnableWindowUpdate(hwndLeft, FALSE);
2273 WinEnableWindowUpdate(hwndRight, FALSE);
2274 switch (SHORT1FROMMP(mp1)) {
2275 case COMP_DELETELEFT:
2276 case COMP_DELETERIGHT:
2277 WinSetDlgItemText(hwnd, COMP_NOTE,
2278 GetPString(IDS_COMPHOLDDELETINGTEXT));
2279 break;
2280 case COMP_MOVELEFT:
2281 case COMP_MOVERIGHT:
2282 WinSetDlgItemText(hwnd, COMP_NOTE,
2283 GetPString(IDS_COMPHOLDMOVINGTEXT));
2284 break;
2285 case COMP_COPYLEFT:
2286 case COMP_COPYRIGHT:
2287 WinSetDlgItemText(hwnd, COMP_NOTE,
2288 GetPString(IDS_COMPHOLDCOPYINGTEXT));
2289 break;
2290 default:
2291 WinSetDlgItemText(hwnd, COMP_NOTE,
2292 GetPString(IDS_COMPHOLDDUNNOTEXT));
2293 break;
2294 }
2295 WinEnableWindow(hwndRight, FALSE);
2296 WinEnableWindow(hwndLeft, FALSE);
2297 WinEnableWindow(WinWindowFromID(hwnd, DID_OK), FALSE);
2298 WinEnableWindow(WinWindowFromID(hwnd, DID_CANCEL), FALSE);
2299 WinEnableWindow(WinWindowFromID(hwnd, COMP_COLLECT), FALSE);
2300 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTBOTH), FALSE);
2301 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTONE), FALSE);
2302 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTNEWER), FALSE);
2303 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTOLDER), FALSE);
2304 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTBIGGER), FALSE);
2305 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTSMALLER), FALSE);
2306 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTBOTH), FALSE);
2307 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTONE), FALSE);
2308 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTNEWER), FALSE);
2309 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTOLDER), FALSE);
2310 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTBIGGER), FALSE);
2311 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTSMALLER),
2312 FALSE);
2313 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTALL), FALSE);
2314 WinEnableWindow(WinWindowFromID(hwnd, COMP_INCLUDESUBDIRS),
2315 FALSE);
2316 WinEnableWindow(WinWindowFromID(hwnd, COMP_SETDIRS), FALSE);
2317 WinEnableWindow(WinWindowFromID(hwnd, COMP_DELETELEFT), FALSE);
2318 WinEnableWindow(WinWindowFromID(hwnd, COMP_DELETERIGHT), FALSE);
2319 WinEnableWindow(WinWindowFromID(hwnd, COMP_COPYLEFT), FALSE);
2320 WinEnableWindow(WinWindowFromID(hwnd, COMP_MOVELEFT), FALSE);
2321 WinEnableWindow(WinWindowFromID(hwnd, COMP_COPYRIGHT), FALSE);
2322 WinEnableWindow(WinWindowFromID(hwnd, COMP_MOVERIGHT), FALSE);
2323 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTSAMECONTENT),
2324 FALSE);
2325 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTIDENTICAL),
2326 FALSE);
2327 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTSAME), FALSE);
2328 WinEnableWindow(WinWindowFromID(hwnd, IDM_INVERT), FALSE);
2329 WinEnableWindow(WinWindowFromID(hwnd, COMP_FILTER), FALSE);
2330 }
2331 }
2332 }
2333 break;
2334
2335 case DID_OK:
2336 WinDismissDlg(hwnd, 0);
2337 break;
2338 case DID_CANCEL:
2339 WinDismissDlg(hwnd, 1);
2340 break;
2341
2342 case IDM_HELP:
2343 if (hwndHelp)
2344 WinSendMsg(hwndHelp, HM_DISPLAY_HELP,
2345 MPFROM2SHORT(HELP_COMPARE, 0), MPFROMSHORT(HM_RESOURCEID));
2346 break;
2347
2348 case IDM_DESELECTALL:
2349 case IDM_SELECTNEWER:
2350 case IDM_SELECTOLDER:
2351 case IDM_SELECTBIGGER:
2352 case IDM_SELECTSMALLER:
2353 case IDM_DESELECTNEWER:
2354 case IDM_DESELECTOLDER:
2355 case IDM_DESELECTBIGGER:
2356 case IDM_DESELECTSMALLER:
2357 case IDM_DESELECTONE:
2358 case IDM_DESELECTBOTH:
2359 case IDM_SELECTBOTH:
2360 case IDM_SELECTONE:
2361 case IDM_SELECTSAMECONTENT:
2362 case IDM_SELECTIDENTICAL: // name, size and time
2363 case IDM_SELECTSAME: // name and size
2364 case IDM_INVERT:
2365 cmp = INSTDATA(hwnd);
2366 if (!cmp)
2367 Runtime_Error2(pszSrcFile, __LINE__, IDS_NODATATEXT);
2368 else {
2369 COMPARE *forthread;
2370
2371 cmp->filling = TRUE;
2372 forthread = xmalloc(sizeof(COMPARE), pszSrcFile, __LINE__);
2373 if (forthread) {
2374 *forthread = *cmp;
2375 forthread->cmp = cmp;
2376 forthread->action = SHORT1FROMMP(mp1);
2377 if (_beginthread(SelectCnrsThread, NULL, 65536, (PVOID) forthread)
2378 == -1) {
2379 Runtime_Error(pszSrcFile, __LINE__,
2380 GetPString(IDS_COULDNTSTARTTHREADTEXT));
2381 free(forthread);
2382 }
2383 else {
2384 WinEnableWindowUpdate(hwndLeft, FALSE);
2385 WinEnableWindowUpdate(hwndRight, FALSE);
2386 switch (SHORT1FROMMP(mp1)) {
2387 case IDM_DESELECTALL:
2388 case IDM_DESELECTNEWER:
2389 case IDM_DESELECTOLDER:
2390 case IDM_DESELECTBIGGER:
2391 case IDM_DESELECTSMALLER:
2392 case IDM_DESELECTONE:
2393 case IDM_DESELECTBOTH:
2394 WinSetDlgItemText(hwnd, COMP_NOTE,
2395 GetPString(IDS_COMPHOLDDESELTEXT));
2396 break;
2397 case IDM_INVERT:
2398 WinSetDlgItemText(hwnd, COMP_NOTE,
2399 GetPString(IDS_COMPHOLDINVERTTEXT));
2400 break;
2401 default:
2402 WinSetDlgItemText(hwnd, COMP_NOTE,
2403 GetPString(IDS_COMPHOLDSELTEXT));
2404 break;
2405 }
2406 WinEnableWindow(hwndRight, FALSE);
2407 WinEnableWindow(hwndLeft, FALSE);
2408 WinEnableWindow(WinWindowFromID(hwnd, DID_OK), FALSE);
2409 WinEnableWindow(WinWindowFromID(hwnd, DID_CANCEL), FALSE);
2410 WinEnableWindow(WinWindowFromID(hwnd, COMP_COLLECT), FALSE);
2411 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTBOTH), FALSE);
2412 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTONE), FALSE);
2413 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTNEWER), FALSE);
2414 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTOLDER), FALSE);
2415 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTBIGGER), FALSE);
2416 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTSMALLER), FALSE);
2417 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTBOTH), FALSE);
2418 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTONE), FALSE);
2419 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTNEWER), FALSE);
2420 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTOLDER), FALSE);
2421 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTBIGGER), FALSE);
2422 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTSMALLER),
2423 FALSE);
2424 WinEnableWindow(WinWindowFromID(hwnd, IDM_DESELECTALL), FALSE);
2425 WinEnableWindow(WinWindowFromID(hwnd, COMP_INCLUDESUBDIRS),
2426 FALSE);
2427 WinEnableWindow(WinWindowFromID(hwnd, COMP_SETDIRS), FALSE);
2428 WinEnableWindow(WinWindowFromID(hwnd, COMP_DELETELEFT), FALSE);
2429 WinEnableWindow(WinWindowFromID(hwnd, COMP_DELETERIGHT), FALSE);
2430 WinEnableWindow(WinWindowFromID(hwnd, COMP_COPYLEFT), FALSE);
2431 WinEnableWindow(WinWindowFromID(hwnd, COMP_MOVELEFT), FALSE);
2432 WinEnableWindow(WinWindowFromID(hwnd, COMP_COPYRIGHT), FALSE);
2433 WinEnableWindow(WinWindowFromID(hwnd, COMP_MOVERIGHT), FALSE);
2434 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTSAMECONTENT),
2435 FALSE);
2436 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTIDENTICAL),
2437 FALSE);
2438 WinEnableWindow(WinWindowFromID(hwnd, IDM_SELECTSAME), FALSE);
2439 WinEnableWindow(WinWindowFromID(hwnd, IDM_INVERT), FALSE);
2440 WinEnableWindow(WinWindowFromID(hwnd, COMP_FILTER), FALSE);
2441 }
2442 }
2443 }
2444 break;
2445
2446 case COMP_COLLECT:
2447 cmp = INSTDATA(hwnd);
2448 if (cmp) {
2449
2450 CHAR **listl, **listr = NULL;
2451
2452 if (!Collector) {
2453
2454 SWP swp;
2455 HWND hwndC;
2456
2457 if (!fAutoTile && !ParentIsDesktop(hwnd, cmp->hwndParent) &&
2458 (!fExternalCollector && !strcmp(realappname, FM3Str)))
2459 GetNextWindowPos(cmp->hwndParent, &swp, NULL, NULL);
2460 hwndC = StartCollector((fExternalCollector ||
2461 strcmp(realappname, FM3Str)) ?
2462 HWND_DESKTOP : cmp->hwndParent, 4);
2463 if (hwndC) {
2464 if (!fAutoTile && !ParentIsDesktop(hwnd, cmp->hwndParent) &&
2465 (!fExternalCollector && !strcmp(realappname, FM3Str)))
2466 WinSetWindowPos(hwndC, HWND_TOP, swp.x, swp.y,
2467 swp.cx, swp.cy, SWP_MOVE | SWP_SIZE |
2468 SWP_SHOW | SWP_ZORDER);
2469 else if (!ParentIsDesktop(hwnd, cmp->hwndParent) && fAutoTile &&
2470 !strcmp(realappname, FM3Str))
2471 TileChildren(cmp->hwndParent, TRUE);
2472 DosSleep(64L);
2473 PostMsg(hwnd, WM_COMMAND, MPFROM2SHORT(COMP_COLLECT, 0), MPVOID);
2474 break;
2475 }
2476 }
2477 else
2478 StartCollector(cmp->hwndParent, 4);
2479 {
2480 BOOL temp;
2481
2482 temp = fSelectedAlways;
2483 fSelectedAlways = TRUE;
2484 listl = BuildList(hwndLeft);
2485 if (!*cmp->rightlist)
2486 listr = BuildList(hwndRight);
2487 fSelectedAlways = temp;
2488 }
2489 if (listl || listr) {
2490 if (Collector) {
2491 if (listl) {
2492 if (!PostMsg(Collector, WM_COMMAND,
2493 MPFROM2SHORT(IDM_COLLECTOR, 0), MPFROMP(listl)))
2494 FreeList(listl);
2495 }
2496 if (listr) {
2497 if (!PostMsg(Collector, WM_COMMAND,
2498 MPFROM2SHORT(IDM_COLLECTOR, 0), MPFROMP(listr)))
2499 FreeList(listr);
2500 }
2501 WinSetWindowPos(WinQueryWindow(WinQueryWindow(Collector,
2502 QW_PARENT),
2503 QW_PARENT), HWND_TOP, 0, 0, 0, 0,
2504 SWP_ACTIVATE);
2505 }
2506 else {
2507 FreeList(listl);
2508 FreeList(listr);
2509 }
2510 }
2511 }
2512 break;
2513 }
2514 return 0;
2515
2516 case WM_CLOSE:
2517 WinDismissDlg(hwnd, 0);
2518 return 0;
2519
2520 case WM_DESTROY:
2521 cmp = INSTDATA(hwnd);
2522 if (cmp) {
2523 if (cmp->dcd.hwndLastMenu)
2524 WinDestroyWindow(cmp->dcd.hwndLastMenu);
2525 if (cmp->dcd.hwndObject) {
2526 WinSetWindowPtr(cmp->dcd.hwndObject, 0, (PVOID) NULL);
2527 if (!PostMsg(cmp->dcd.hwndObject, WM_CLOSE, MPVOID, MPVOID))
2528 WinSendMsg(cmp->dcd.hwndObject, WM_CLOSE, MPVOID, MPVOID);
2529 }
2530 free(cmp);
2531 }
2532 EmptyCnr(hwndLeft);
2533 EmptyCnr(hwndRight);
2534 DosPostEventSem(CompactSem);
2535 break;
2536 }
2537 return WinDefDlgProc(hwnd, msg, mp1, mp2);
2538}
Note: See TracBrowser for help on using the repository browser.