source: trunk/dll/select.c @ 751

Last change on this file since 751 was 751, checked in by Steven Levine, 13 years ago

Sync rest of code with CNRITEM mods
Sync code with ARCITEM mods
Get compare dialog working
Still some issues with status display
Still some issues with directory sizes tree display
Heap check diagnostic code mostly enabled

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 42.1 KB
Line 
1
2/***********************************************************************
3
4  $Id: select.c 751 2007-08-02 23:05:48Z stevenhl $
5
6  Container item selection support routines
7
8  Copyright (c) 1993-98 M. Kimes
9  Copyright (c) 2004, 2007 Steven H. Levine
10
11  01 Aug 04 SHL Rework lstrip/rstrip usage
12  25 May 05 SHL Rework for ULONGLONG
13  06 Jun 05 SHL Drop unused code
14  06 Jul 06 SHL Support compare content (IDM_SELECTSAMECONTENT)
15  13 Jul 06 SHL Use Runtime_Error
16  29 Jul 06 SHL Use xfgets_bstripcr
17  15 Aug 06 SHL Rework SetMask args and logic
18  06 Apr 07 GKY Work around PM DragInfo and DrgFreeDISH limits
19  19 Apr 07 SHL Sync with NumItemsToUnhilite mods
20  12 May 07 SHL Use dcd->ulItemsToUnHilite
21  14 Jun 07 SHL SelectAll: make odd expression go away
22  02 Aug 07 SHL Sync with CNRITEM mods
23
24***********************************************************************/
25
26#define INCL_DOS
27#define INCL_WIN
28#define INCL_LONGLONG
29#include <os2.h>
30
31#include <stdio.h>
32#include <stdlib.h>
33#include <string.h>
34#include <share.h>
35#include <io.h>
36
37#include "fm3dll.h"
38#include "fm3str.h"
39
40#pragma alloc_text(SELECT,UnHilite,SelectAll,DeselectAll,MarkAll,SetMask)
41#pragma alloc_text(SELECT,SelectList)
42#pragma alloc_text(SELECT1,Deselect,HideAll,RemoveAll,ExpandAll,InvertAll)
43
44static PSZ pszSrcFile = __FILE__;
45
46VOID UnHilite(HWND hwndCnr, BOOL all, CHAR *** list, ULONG ulItemsToUnHilite)
47{
48  PCNRITEM pci;
49  INT numfiles = 0, numalloc = 0, x = 0;
50  INT attribute = CRA_CURSORED;
51
52  if (all && list && *list) {
53    FreeList(*list);
54    *list = NULL;
55  }
56  pci = (PCNRITEM) CurrentRecord(hwndCnr);
57  if (pci && (INT)pci != -1) {
58    if (pci->rc.flRecordAttr & CRA_SELECTED) {
59      attribute = CRA_SELECTED;
60      pci = WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS, MPFROMLONG(CMA_FIRST),
61                       MPFROMSHORT(attribute));
62    }
63    while (pci && (INT)pci != -1) {
64      WinSendMsg(hwndCnr, CM_SETRECORDEMPHASIS, MPFROMP(pci),
65                 MPFROM2SHORT(FALSE, CRA_SELECTED));
66      if (!all)
67          break;
68      // Count is one extra to ensure non-zero elsewhere
69      // x is 0 based index
70      if (x + 2 == ulItemsToUnHilite)
71        break;
72      if (list)
73        AddToList(pci->pszFileName, list, &numfiles, &numalloc);
74      pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS,
75                                  MPFROMP(pci), MPFROMSHORT(CRA_SELECTED));
76      x++;
77    }
78  }
79}
80
81VOID SelectList(HWND hwndCnr, BOOL partial, BOOL deselect, BOOL clearfirst,
82                PCNRITEM pciParent, PSZ filename, CHAR ** list)
83{
84
85  PCNRITEM pci;
86  register INT x;
87  BOOL foundone = FALSE;
88  ULONG errs = 0L;
89
90  if (clearfirst && !deselect)
91    UnHilite(hwndCnr, TRUE, NULL, 0);
92  if (list && list[0]) {
93    for (x = 0; list[x]; x++) {
94      pci = FindCnrRecord(hwndCnr,
95                          list[x], pciParent, partial, partial, TRUE);
96      if (pci) {
97        WinSendMsg(hwndCnr,
98                   CM_SETRECORDEMPHASIS,
99                   MPFROMP(pci),
100                   MPFROM2SHORT((SHORT) ((deselect) ? FALSE : TRUE),
101                                CRA_SELECTED));
102        foundone = TRUE;
103      }
104    }
105    if (!foundone)
106      Runtime_Error(pszSrcFile, __LINE__, "select failed");
107  }
108  else if (filename && *filename) {
109
110    FILE *fp;
111    CHAR input[1024], *p;
112
113    fp = _fsopen(filename, "r", SH_DENYNO);
114    if (fp) {
115      while (!feof(fp)) {
116        if (!xfgets_bstripcr(input, sizeof(input), fp, pszSrcFile, __LINE__))
117          break;
118        if (*input == '\"') {
119          memmove(input, input + 1, strlen(input) + 1);
120          lstrip(input);
121          p = strchr(input, '\"');
122          if (p)
123            *p = 0;
124          rstrip(input);
125        }
126        else {
127          p = strchr(input, ' ');
128          if (p)
129            *p = 0;
130        }
131        /* input now contains name of file to select */
132        pci = FindCnrRecord(hwndCnr,
133                            input, pciParent, partial, partial, TRUE);
134        if (pci)                        /* found it? */
135          WinSendMsg(hwndCnr,
136                     CM_SETRECORDEMPHASIS,
137                     MPFROMP(pci),
138                     MPFROM2SHORT((SHORT) ((deselect) ? FALSE : TRUE),
139                                  CRA_SELECTED));
140        else
141          errs++;
142        if (errs > 50L) {               /* prevent runaway on bad file */
143
144          APIRET ret;
145
146          ret = saymsg(MB_YESNO,
147                       hwndCnr,
148                       GetPString(IDS_POSSIBLEERRORTEXT),
149                       GetPString(IDS_MAYNOTBELISTTEXT), filename);
150          if (ret == MBID_NO)
151            break;
152          errs = 0L;
153        }
154      }
155      fclose(fp);
156    }
157  }
158}
159
160VOID SelectAll(HWND hwndCnr, BOOL files, BOOL dirs, PSZ maskstr,
161               PSZ text, BOOL is_arc)
162{
163
164  PCNRITEM pci;
165  BOOL markit;
166  PSZ file;
167  PSZ pszToMatch;
168  MASK Mask;
169  INT x;
170  ULONG textlen = 0;
171
172  if (text)
173    textlen = strlen(text);
174  memset(&Mask, 0, sizeof(Mask));
175  if (maskstr)
176    SetMask(maskstr, &Mask);
177  pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORD, MPVOID,
178                              MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
179  while (pci && (INT)pci != -1) {
180
181    markit = FALSE;
182
183    if (~pci->rc.flRecordAttr & CRA_FILTERED) {
184      if (!is_arc) {
185        if (files && ~pci->attrFile & FILE_DIRECTORY)
186          markit = TRUE;
187        if (dirs && pci->attrFile & FILE_DIRECTORY)
188          markit = TRUE;
189      }
190      else
191        markit = TRUE;
192      if (maskstr && *maskstr && markit) {
193        markit = FALSE;
194        // Point a filename part
195        file = strrchr(pci->pszFileName, '\\');
196        if (!file)
197          file = strrchr(pci->pszFileName, ':');
198        if (file)
199          file++;
200        else
201          file = pci->pszFileName;
202        for (x = 0; Mask.pszMasks[x]; x++) {
203          if (*Mask.pszMasks[x]) {
204            if ((strchr(Mask.pszMasks[x], '\\') ||
205                strchr(Mask.pszMasks[x], ':')))
206              pszToMatch = pci->pszFileName;
207            else
208              pszToMatch = file;
209            if (*Mask.pszMasks[x] != '/') {
210              if (wildcard(pszToMatch, Mask.pszMasks[x], FALSE)) {
211                markit = TRUE;
212              }
213            }
214            else {
215              if (wildcard(pszToMatch, Mask.pszMasks[x] + 1, FALSE)) {
216                markit = FALSE;
217                break;
218              }
219            }
220          }
221        } // for
222      }
223    }
224
225    if (markit && text && *text) {
226      if (~pci->attrFile & FILE_DIRECTORY) {
227        PSZ input;
228        markit = FALSE;
229        input = xmalloc(65537, pszSrcFile, __LINE__);
230        if (input) {
231          ULONG pos;
232          LONG len;
233          FILE *inputFile;
234
235          if ((inputFile = _fsopen(pci->pszFileName, "rb", SH_DENYNO)) != NULL) {
236            pos = ftell(inputFile);
237            while (!feof(inputFile)) {
238              if (pos)
239                fseek(inputFile, pos - 256, SEEK_SET);
240              len = fread(input, 1, 65536, inputFile);
241              if (len >= 0) {
242                if (findstring(text, textlen, input, len, FALSE)) {
243                  markit = TRUE;
244                  break;
245                }
246              }
247              else
248                break;
249            }
250            fclose(inputFile);
251          }
252          free(input);
253          DosSleep(1L);
254        }
255      }
256      else
257        markit = FALSE;
258    }
259
260    if (markit)
261      WinSendMsg(hwndCnr, CM_SETRECORDEMPHASIS, MPFROMP(pci),
262                 MPFROM2SHORT(TRUE, CRA_SELECTED));
263    pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(pci),
264                                MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
265  }                                     // while
266}
267
268VOID DeselectAll(HWND hwndCnr, BOOL files, BOOL dirs, PSZ maskstr,
269                 PSZ text, BOOL is_arc)
270{
271  PCNRITEM pci;
272  BOOL unmarkit;
273  PSZ file;
274  PSZ pszToMatch;
275  MASK Mask;
276  register INT x;
277  ULONG textlen = 0;
278
279  if (text)
280    textlen = strlen(text);
281  memset(&Mask, 0, sizeof(Mask));
282  if (maskstr && *maskstr)
283    SetMask(maskstr, &Mask);
284  pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORD, MPVOID,
285                              MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
286  while (pci && (INT)pci != -1) {
287    unmarkit = FALSE;
288    if (~pci->rc.flRecordAttr & CRA_FILTERED) {
289      if (!is_arc) {
290        if (files && ~pci->attrFile & FILE_DIRECTORY)
291          unmarkit = TRUE;
292        if (dirs && (pci->attrFile & FILE_DIRECTORY))
293          unmarkit = TRUE;
294      }
295      else
296        unmarkit = TRUE;
297      if (maskstr && *maskstr && unmarkit) {
298        unmarkit = FALSE;
299        file = strrchr(pci->pszFileName, '\\');
300        if (!file)
301          file = strrchr(pci->pszFileName, ':');
302        if (file)
303          file++;
304        else
305          file = pci->pszFileName;
306        for (x = 0; Mask.pszMasks[x]; x++) {
307          if (*Mask.pszMasks[x]) {
308            if (strchr(Mask.pszMasks[x], '\\') ||
309                strchr(Mask.pszMasks[x], ':'))
310              pszToMatch = pci->pszFileName;
311            else
312              pszToMatch = file;
313            if (*Mask.pszMasks[x] != '/') {
314              if (wildcard(pszToMatch, Mask.pszMasks[x], FALSE))
315                unmarkit = TRUE;
316            }
317            else {
318              if (wildcard(pszToMatch, Mask.pszMasks[x] + 1, FALSE)) {
319                unmarkit = FALSE;
320                break;
321              }
322            }
323          }
324        }
325      }
326    }
327
328    if (unmarkit && text && *text) {
329      if (~pci->attrFile & FILE_DIRECTORY) {
330        PSZ input;
331        unmarkit = FALSE;
332        input = xmalloc(65537, pszSrcFile, __LINE__);
333        if (input) {
334          ULONG pos;
335          LONG len;
336          FILE *inputFile;
337
338          if ((inputFile = _fsopen(pci->pszFileName, "rb", SH_DENYNO)) != NULL) {
339            pos = ftell(inputFile);
340            while (!feof(inputFile)) {
341              if (pos)
342                fseek(inputFile, pos - 256, SEEK_SET);
343              len = fread(input, 1, 65536, inputFile);
344              if (len >= 0) {
345                if (findstring(text, textlen, input, len, FALSE)) {
346                  unmarkit = TRUE;
347                  break;
348                }
349              }
350              else
351                break;
352            }
353            fclose(inputFile);
354          }
355          free(input);
356          DosSleep(1L);
357        }
358      }
359      else
360        unmarkit = FALSE;
361    }
362
363    if (unmarkit)
364      WinSendMsg(hwndCnr, CM_SETRECORDEMPHASIS, pci,
365                 MPFROM2SHORT(FALSE, CRA_SELECTED | CRA_CURSORED |
366                              CRA_INUSE | CRA_SOURCE));
367    pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(pci),
368                                MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
369  }
370}
371
372VOID Deselect(HWND hwndCnr)
373{
374  PCNRITEM pcil;
375
376  pcil = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS,
377                               MPFROMLONG(CMA_FIRST),
378                               MPFROMSHORT(CRA_SELECTED));
379  while (pcil && (INT)pcil != -1) {
380    WinSendMsg(hwndCnr, CM_SETRECORDEMPHASIS, MPFROMP(pcil),
381               MPFROM2SHORT(FALSE, CRA_SELECTED));
382    pcil = WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS, MPFROMP(pcil),
383                      MPFROMSHORT(CRA_SELECTED));
384  }
385}
386
387//=== HideAll() Hide all selected records ===
388
389VOID HideAll(HWND hwndCnr)
390{
391  PCNRITEM pci, pciH;
392  INT attribute = CRA_CURSORED;
393  CNRINFO cnri;
394  BOOL didone = FALSE;
395
396  memset(&cnri, 0, sizeof(CNRINFO));
397  cnri.cb = sizeof(CNRINFO);
398  WinSendMsg(hwndCnr, CM_QUERYCNRINFO, MPFROMP(&cnri),
399             MPFROMLONG(sizeof(CNRINFO)));
400  pci = (PCNRITEM) CurrentRecord(hwndCnr);
401  if (pci && (INT)pci != -1) {
402    if (pci->rc.flRecordAttr & CRA_SELECTED) {
403      attribute = CRA_SELECTED;
404      pci = WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS, MPFROMLONG(CMA_FIRST),
405                       MPFROMSHORT(attribute));
406    }
407  }
408  while (pci && (INT)pci != -1) {
409    pciH = WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS, MPFROMP(pci),
410                      MPFROMSHORT(attribute));
411    WinSendMsg(hwndCnr, CM_SETRECORDEMPHASIS, MPFROMP(pci),
412               MPFROM2SHORT(FALSE, CRA_CURSORED | CRA_SELECTED |
413                            CRA_INUSE | CRA_SOURCE));
414    pci->rc.flRecordAttr |= CRA_FILTERED;
415    didone = TRUE;
416    if (fSyncUpdates) {
417      if (cnri.flWindowAttr & CV_DETAIL)
418        WinSendMsg(hwndCnr, CM_INVALIDATERECORD, MPVOID,
419                   MPFROM2SHORT(0, CMA_REPOSITION | CMA_ERASE));
420      else
421        WinSendMsg(hwndCnr, CM_INVALIDATERECORD, MPFROMP(&pci),
422                   MPFROM2SHORT(1, CMA_REPOSITION | CMA_ERASE));
423    }
424    pci = pciH;
425  }
426  if (didone && !fSyncUpdates)
427    WinSendMsg(hwndCnr, CM_INVALIDATERECORD, MPVOID,
428               MPFROM2SHORT(0, CMA_ERASE | CMA_REPOSITION));
429}
430
431VOID MarkAll(HWND hwndCnr, BOOL quitit, BOOL target, BOOL source)
432{
433  PCNRITEM pci;
434  INT attribute = CRA_CURSORED;
435
436  if (quitit)
437    attribute = target ? CRA_TARGET : source ? CRA_SOURCE : CRA_INUSE;
438  pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS,
439                              MPFROMLONG(CMA_FIRST), MPFROMSHORT(attribute));
440  if (pci && (INT)pci != -1) {
441    if (attribute == CRA_CURSORED) {
442      if (pci->rc.flRecordAttr & CRA_SELECTED) {
443        attribute = CRA_SELECTED;
444        pci =
445          WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS, MPFROMLONG(CMA_FIRST),
446                     MPFROMSHORT(attribute));
447      }
448    }
449  }
450  while (pci && (INT)pci != -1) {
451    WinSendMsg(hwndCnr, CM_SETRECORDEMPHASIS, MPFROMP(pci),
452               MPFROM2SHORT(!quitit,
453                            target ? CRA_TARGET : source ? CRA_SOURCE :
454                             CRA_INUSE));
455    pci =
456      WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS, MPFROMP(pci),
457                 MPFROMSHORT(attribute));
458  }
459}
460
461VOID RemoveAll(HWND hwndCnr, ULONGLONG * pullTotalBytes,
462               ULONG * pulTotalFiles)
463{
464  PCNRITEM pci;
465  INT attribute = CRA_CURSORED;
466  BOOL didone = FALSE;
467
468  pci = (PCNRITEM) CurrentRecord(hwndCnr);
469  if (pci && (INT)pci != -1) {
470    if (pci->rc.flRecordAttr & CRA_SELECTED) {
471      attribute = CRA_SELECTED;
472      pci = WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS, MPFROMLONG(CMA_FIRST),
473                       MPFROMSHORT(attribute));
474    }
475  }
476  while (pci && (INT)pci != -1) {
477    if (~pci->rc.flRecordAttr & CRA_FILTERED) {
478      didone = TRUE;
479      if (pulTotalFiles)
480        *pulTotalFiles -= 1;
481      if (pullTotalBytes)
482        *pullTotalBytes -= (pci->cbFile + pci->easize);
483      WinSendMsg(hwndCnr, CM_SETRECORDEMPHASIS, MPFROMP(pci),
484                 MPFROM2SHORT(0, CRA_SELECTED));
485      if (fSyncUpdates)
486        RemoveCnrItems(hwndCnr, pci, 1, CMA_FREE | CMA_INVALIDATE);
487      else
488        RemoveCnrItems(hwndCnr, pci, 1, CMA_FREE);
489      if (attribute == CRA_CURSORED)
490        break;
491      pci = WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS, MPFROMLONG(CMA_FIRST),
492                       MPFROMSHORT(attribute));
493    }
494    else
495      pci = WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS, MPFROMP(pci),
496                       MPFROMSHORT(attribute));
497  }
498  if (didone && !fSyncUpdates)
499    WinSendMsg(hwndCnr, CM_INVALIDATERECORD, MPVOID,
500               MPFROM2SHORT(0, CMA_REPOSITION));
501}
502
503//== SetMask() Convert mask string to array of pointers to masks ==
504
505VOID SetMask(PSZ maskstr, MASK * mask)
506{
507  UINT x;
508  PSZ p;
509
510  if (maskstr)
511    strcpy(mask->szMask, maskstr);      // Got new mask string
512  // Build array of pointers
513  p = mask->szMaskCopy;
514  strcpy(p, mask->szMask);
515  // Allow up to 25 masks - ignore extras
516  for (x = 0; *p && x < 25; x++) {
517    mask->pszMasks[x] = p;
518    while (*p && *p != ';')
519      p++;                              // Find separator
520    if (*p) {
521      *p = 0;                           // Replace ;
522      p++;
523    }
524  }                                     // for
525  mask->pszMasks[x] = NULL;             // Mark end
526}
527
528VOID ExpandAll(HWND hwndCnr, BOOL expand, PCNRITEM pciParent)
529{
530  PCNRITEM pci;
531
532  if (!pciParent)
533    pciParent = WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(NULL),
534                           MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
535  if (pciParent) {
536    if (expand && ~pciParent->rc.flRecordAttr & CRA_EXPANDED)
537      WinSendMsg(hwndCnr, CM_EXPANDTREE, MPFROMP(pciParent), MPVOID);
538    else if (!expand && (pciParent->rc.flRecordAttr & CRA_EXPANDED))
539      WinSendMsg(hwndCnr, CM_COLLAPSETREE, MPFROMP(pciParent), MPVOID);
540    pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(pciParent),
541                                MPFROM2SHORT(CMA_FIRSTCHILD, CMA_ITEMORDER));
542    if (pci)
543      DosSleep(1L);
544    while (pci && (INT)pci != -1) {
545      ExpandAll(hwndCnr, expand, pci);
546      pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(pci),
547                                  MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
548    }
549  }
550  DosSleep(1);
551}
552
553VOID InvertAll(HWND hwndCnr)
554{
555  PCNRITEM pci;
556
557  pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORD, MPVOID,
558                              MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
559  while (pci && (INT)pci != -1) {
560    if (~pci->rc.flRecordAttr & CRA_FILTERED) {
561      if (~pci->rc.flRecordAttr & CRA_SELECTED)
562        WinSendMsg(hwndCnr, CM_SETRECORDEMPHASIS, MPFROMP(pci),
563                   MPFROM2SHORT(TRUE, CRA_SELECTED));
564      else
565        WinSendMsg(hwndCnr, CM_SETRECORDEMPHASIS, MPFROMP(pci),
566                   MPFROM2SHORT(FALSE, CRA_SELECTED));
567    }
568    pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(pci),
569                                MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
570  }
571}
572
573#pragma alloc_text (SELECT3,SpecialSelect)
574#pragma alloc_text(SELECT4,FreeCnrs,SpecialSelect2,CompSSNames,CompSSNamesB)
575
576VOID SpecialSelect(HWND hwndCnrS, HWND hwndCnrD, INT action, BOOL reset)
577{
578  PCNRITEM pciS, pciD, *pciSa = NULL, *pciDa = NULL;
579  CNRINFO cnri;
580  BOOL slow = FALSE;
581  register INT x, numD, numS;
582
583
584  if (!hwndCnrS || !hwndCnrD)
585    return;
586
587  memset(&cnri, 0, sizeof(CNRINFO));
588  cnri.cb = sizeof(CNRINFO);
589  WinSendMsg(hwndCnrD, CM_QUERYCNRINFO, MPFROMP(&cnri),
590             MPFROMLONG(sizeof(CNRINFO)));
591  numD = (INT) cnri.cRecords;
592  memset(&cnri, 0, sizeof(CNRINFO));
593  cnri.cb = sizeof(CNRINFO);
594  WinSendMsg(hwndCnrS, CM_QUERYCNRINFO, MPFROMP(&cnri),
595             MPFROMLONG(sizeof(CNRINFO)));
596  numS = (INT) cnri.cRecords;
597  if (!numD || numS != numD) {
598    saymsg(MB_ENTER,
599           HWND_DESKTOP,
600           DEBUG_STRING, "numD (%lu) != numS (%lu)", numD, numS);
601    return;
602  }
603  pciDa = xmalloc(sizeof(PCNRITEM) * numD, pszSrcFile, __LINE__);
604  if (!pciDa)
605    return;
606
607  pciSa = xmalloc(sizeof(PCNRITEM) * numS, pszSrcFile, __LINE__);
608  if (!pciSa) {
609    free(pciDa);
610    return;
611  }
612
613Restart:
614
615  memset(pciDa, 0, sizeof(PCNRITEM) * numD);
616  memset(pciSa, 0, sizeof(PCNRITEM) * numS);
617
618  pciD = (PCNRITEM) WinSendMsg(hwndCnrD, CM_QUERYRECORD, MPVOID,
619                               MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
620  x = 0;
621  while (pciD && (INT)pciD != -1 && x < numD) {
622    if (reset)
623      pciD->flags = 0;
624    pciDa[x] = pciD;
625    x++;
626    if (!slow)
627      pciD = (PCNRITEM) pciD->rc.preccNextRecord;
628    else
629      pciD = (PCNRITEM) WinSendMsg(hwndCnrD, CM_QUERYRECORD, MPFROMP(pciD),
630                                   MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
631    if (!(x % 500))
632      DosSleep(1L);
633    else if (!(x % 50))
634      DosSleep(1);
635  }
636  if (numD != x) {
637    if (!slow) {
638      slow = TRUE;
639      goto Restart;
640    }
641    free(pciDa);
642    free(pciSa);
643    saymsg(MB_ENTER,
644           HWND_DESKTOP, DEBUG_STRING, "numD (%lu) != x (%lu)", numD, x);
645    return;
646  }
647
648  pciS = (PCNRITEM) WinSendMsg(hwndCnrS, CM_QUERYRECORD, MPVOID,
649                               MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
650  x = 0;
651  while (pciS && (INT)pciS != -1 && x < numS) {
652    if (reset)
653      pciS->flags = 0;
654    pciSa[x] = pciS;
655    x++;
656    if (!slow)
657      pciS = (PCNRITEM) pciS->rc.preccNextRecord;
658    else
659      pciS = (PCNRITEM) WinSendMsg(hwndCnrS, CM_QUERYRECORD, MPFROMP(pciS),
660                                   MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
661    if (!(x % 500))
662      DosSleep(1L);
663    else if (!(x % 50))
664      DosSleep(1);
665  }
666  if (numS != x) {
667    if (!slow) {
668      slow = TRUE;
669      goto Restart;
670    }
671    free(pciSa);
672    free(pciDa);
673    Runtime_Error(pszSrcFile, __LINE__, "numS (%lu) != x (%lu)", numS, x);
674    return;
675  }
676
677  if (reset) {
678    for (x = 0; x < numS; x++) {
679
680      if (!*pciSa[x]->pszFileName || !*pciDa[x]->pszFileName)
681        continue;
682
683      pciSa[x]->flags |= CNRITEM_EXISTS;
684      pciDa[x]->flags |= CNRITEM_EXISTS;
685      if (pciSa[x]->cbFile + pciSa[x]->easize >
686          pciDa[x]->cbFile + pciDa[x]->easize) {
687        pciSa[x]->flags |= CNRITEM_LARGER;
688        pciDa[x]->flags |= CNRITEM_SMALLER;
689      }
690      else if (pciSa[x]->cbFile + pciSa[x]->easize <
691               pciDa[x]->cbFile + pciDa[x]->easize) {
692        pciSa[x]->flags |= CNRITEM_SMALLER;
693        pciDa[x]->flags |= CNRITEM_LARGER;
694      }
695      if ((pciSa[x]->date.year > pciDa[x]->date.year) ? TRUE :
696          (pciSa[x]->date.year < pciDa[x]->date.year) ? FALSE :
697          (pciSa[x]->date.month > pciDa[x]->date.month) ? TRUE :
698          (pciSa[x]->date.month < pciDa[x]->date.month) ? FALSE :
699          (pciSa[x]->date.day > pciDa[x]->date.day) ? TRUE :
700          (pciSa[x]->date.day < pciDa[x]->date.day) ? FALSE :
701          (pciSa[x]->time.hours > pciDa[x]->time.hours) ? TRUE :
702          (pciSa[x]->time.hours < pciDa[x]->time.hours) ? FALSE :
703          (pciSa[x]->time.minutes > pciDa[x]->time.minutes) ? TRUE :
704          (pciSa[x]->time.minutes < pciDa[x]->time.minutes) ? FALSE :
705          (pciSa[x]->time.seconds > pciDa[x]->time.seconds) ? TRUE :
706          (pciSa[x]->time.seconds < pciDa[x]->time.seconds) ? FALSE : FALSE) {
707        pciSa[x]->flags |= CNRITEM_NEWER;
708        pciDa[x]->flags |= CNRITEM_OLDER;
709      }
710      else if ((pciSa[x]->date.year < pciDa[x]->date.year) ? TRUE :
711               (pciSa[x]->date.year > pciDa[x]->date.year) ? FALSE :
712               (pciSa[x]->date.month < pciDa[x]->date.month) ? TRUE :
713               (pciSa[x]->date.month > pciDa[x]->date.month) ? FALSE :
714               (pciSa[x]->date.day < pciDa[x]->date.day) ? TRUE :
715               (pciSa[x]->date.day > pciDa[x]->date.day) ? FALSE :
716               (pciSa[x]->time.hours < pciDa[x]->time.hours) ? TRUE :
717               (pciSa[x]->time.hours > pciDa[x]->time.hours) ? FALSE :
718               (pciSa[x]->time.minutes < pciDa[x]->time.minutes) ? TRUE :
719               (pciSa[x]->time.minutes > pciDa[x]->time.minutes) ? FALSE :
720               (pciSa[x]->time.seconds < pciDa[x]->time.seconds) ? TRUE :
721               (pciSa[x]->time.seconds > pciDa[x]->time.seconds) ? FALSE :
722               FALSE) {
723        pciSa[x]->flags |= CNRITEM_OLDER;
724        pciDa[x]->flags |= CNRITEM_NEWER;
725      }
726      if (!(x % 500))
727        DosSleep(1L);
728      else if (!(x % 50))
729        DosSleep(1);
730    }
731  }
732
733  switch (action) {
734  case IDM_SELECTIDENTICAL:
735    for (x = 0; x < numS; x++) {
736      if (~pciSa[x]->rc.flRecordAttr & CRA_FILTERED) {
737        if (*pciSa[x]->pszFileName &&
738            pciSa[x]->flags & CNRITEM_EXISTS &&
739            ~pciSa[x]->flags & CNRITEM_SMALLER &&
740            ~pciSa[x]->flags & CNRITEM_LARGER &&
741            ~pciSa[x]->flags & CNRITEM_NEWER &&
742            ~pciSa[x]->flags & CNRITEM_OLDER) {
743          if (~pciSa[x]->rc.flRecordAttr & CRA_SELECTED)
744            WinSendMsg(hwndCnrS, CM_SETRECORDEMPHASIS, MPFROMP(pciSa[x]),
745                       MPFROM2SHORT(TRUE, CRA_SELECTED));
746          if (~pciDa[x]->rc.flRecordAttr & CRA_SELECTED)
747            WinSendMsg(hwndCnrD, CM_SETRECORDEMPHASIS, MPFROMP(pciDa[x]),
748                       MPFROM2SHORT(TRUE, CRA_SELECTED));
749        }
750        if (!(x % 500))
751          DosSleep(1L);
752        else if (!(x % 50))
753          DosSleep(1);
754      }
755    }
756    break;
757
758  case IDM_SELECTSAME:
759    for (x = 0; x < numS; x++) {
760      if (~pciSa[x]->rc.flRecordAttr & CRA_FILTERED &&
761          *pciSa[x]->pszFileName &&
762          pciSa[x]->flags & CNRITEM_EXISTS &&
763          ~pciSa[x]->flags & CNRITEM_SMALLER &&
764          ~pciSa[x]->flags & CNRITEM_LARGER) {
765        if (~pciSa[x]->rc.flRecordAttr & CRA_SELECTED)
766          WinSendMsg(hwndCnrS, CM_SETRECORDEMPHASIS, MPFROMP(pciSa[x]),
767                     MPFROM2SHORT(TRUE, CRA_SELECTED));
768        if (~pciDa[x]->rc.flRecordAttr & CRA_SELECTED)
769          WinSendMsg(hwndCnrD, CM_SETRECORDEMPHASIS, MPFROMP(pciDa[x]),
770                     MPFROM2SHORT(TRUE, CRA_SELECTED));
771      }
772      if (!(x % 500))
773        DosSleep(1L);
774      else if (!(x % 50))
775        DosSleep(1);
776    }
777    break;
778
779  case IDM_SELECTSAMECONTENT:
780    // fixme why?
781    for (x = 0; x < numS; x++) {
782      if (~pciSa[x]->rc.flRecordAttr & CRA_FILTERED &&
783          *pciSa[x]->pszFileName &&
784          *pciDa[x]->pszFileName &&
785          pciSa[x]->flags & CNRITEM_EXISTS &&
786          pciDa[x]->flags & CNRITEM_EXISTS)
787      {
788        FILE *fp1 = NULL;
789        FILE *fp2 = NULL;
790        BOOL gotMatch = FALSE;
791        UINT errLineNo = 0;
792        UINT compErrno = 0;
793        CHAR buf1[1024];
794        CHAR buf2[1024];
795        HAB hab = WinQueryAnchorBlock(hwndCnrS);
796
797        fp1 = _fsopen(pciSa[x]->pszFileName, "rb", SH_DENYNO);
798        if (!fp1) {
799          errLineNo = __LINE__;
800          compErrno = errno;
801        }
802        else {
803          fp2 = _fsopen(pciDa[x]->pszFileName, "rb", SH_DENYNO);
804          if (!fp2) {
805            errLineNo = __LINE__;
806            compErrno = errno;
807          }
808          else {
809            size_t len1 = filelength(fileno(fp1));
810            size_t len2 = filelength(fileno(fp2));
811
812            if (len1 == len2) {
813              setbuf(fp1, NULL);
814              setbuf(fp2, NULL);
815              while (WinIsWindow(hab, hwndCnrS)) {
816                size_t numread1 = fread(buf1, 1, 1024, fp1);
817                size_t numread2 = fread(buf2, 1, 1024, fp2);
818
819                if (!numread1 || !numread2 || numread1 != numread2) {
820                  if (ferror(fp1) || ferror(fp2)) {
821                    errLineNo = __LINE__;
822                    compErrno = errno;
823                  }
824                  else if (feof(fp1) && feof(fp2))
825                    gotMatch = TRUE;
826                  break;
827                }
828                else if (memcmp(buf1, buf2, numread1))
829                  break;
830              } // while
831            } // same len
832          }
833        }
834
835        if (fp1)
836          fclose(fp1);
837
838        if (fp2)
839          fclose(fp2);
840
841        if (errLineNo) {
842          Runtime_Error(pszSrcFile, errLineNo,
843                        "error %d while comparing", compErrno);
844        }
845        if (gotMatch) {
846          if (~pciSa[x]->rc.flRecordAttr & CRA_SELECTED)
847            WinSendMsg(hwndCnrS, CM_SETRECORDEMPHASIS, MPFROMP(pciSa[x]),
848                       MPFROM2SHORT(TRUE, CRA_SELECTED));
849          if (~pciDa[x]->rc.flRecordAttr & CRA_SELECTED)
850            WinSendMsg(hwndCnrD, CM_SETRECORDEMPHASIS, MPFROMP(pciDa[x]),
851                       MPFROM2SHORT(TRUE, CRA_SELECTED));
852        }
853      }
854      if (!(x % 500))
855        DosSleep(1L);
856      else if (!(x % 50))
857        DosSleep(1);
858    }                                   // for records
859    break;
860
861  case IDM_SELECTBOTH:
862    for (x = 0; x < numS; x++) {
863      if (~pciSa[x]->rc.flRecordAttr & CRA_FILTERED &&
864          *pciSa[x]->pszFileName &&
865          pciSa[x]->flags & CNRITEM_EXISTS) {
866        if (~pciSa[x]->rc.flRecordAttr & CRA_SELECTED)
867          WinSendMsg(hwndCnrS, CM_SETRECORDEMPHASIS, MPFROMP(pciSa[x]),
868                     MPFROM2SHORT(TRUE, CRA_SELECTED));
869        if (~pciDa[x]->rc.flRecordAttr & CRA_SELECTED)
870          WinSendMsg(hwndCnrD, CM_SETRECORDEMPHASIS, MPFROMP(pciDa[x]),
871                     MPFROM2SHORT(TRUE, CRA_SELECTED));
872      }
873      if (!(x % 500))
874        DosSleep(1L);
875      else if (!(x % 50))
876        DosSleep(1);
877    }
878    break;
879
880  case IDM_SELECTONE:
881    for (x = 0; x < numS; x++) {
882      if (~pciSa[x]->rc.flRecordAttr & CRA_FILTERED &&
883          *pciSa[x]->pszFileName &&
884          ~pciSa[x]->flags & CNRITEM_EXISTS)
885      {
886        if (~pciSa[x]->rc.flRecordAttr & CRA_SELECTED)
887          WinSendMsg(hwndCnrS, CM_SETRECORDEMPHASIS, MPFROMP(pciSa[x]),
888                     MPFROM2SHORT(TRUE, CRA_SELECTED));
889      }
890      else if (*pciDa[x]->pszFileName &&
891               ~pciDa[x]->flags & CNRITEM_EXISTS) {
892        if (~pciDa[x]->rc.flRecordAttr & CRA_SELECTED)
893          WinSendMsg(hwndCnrD, CM_SETRECORDEMPHASIS, MPFROMP(pciDa[x]),
894                     MPFROM2SHORT(TRUE, CRA_SELECTED));
895      }
896      if (!(x % 500))
897        DosSleep(1L);
898      else if (!(x % 50))
899        DosSleep(1);
900    }
901    break;
902
903  case IDM_SELECTBIGGER:
904    for (x = 0; x < numS; x++) {
905      if (~pciSa[x]->rc.flRecordAttr & CRA_FILTERED &&
906          pciSa[x]->flags & CNRITEM_LARGER) {
907        if (~pciSa[x]->rc.flRecordAttr & CRA_SELECTED)
908          WinSendMsg(hwndCnrS, CM_SETRECORDEMPHASIS, MPFROMP(pciSa[x]),
909                     MPFROM2SHORT(TRUE, CRA_SELECTED));
910      }
911      else if (~pciDa[x]->rc.flRecordAttr & CRA_FILTERED &&
912               *pciDa[x]->pszFileName &&
913               pciDa[x]->flags & CNRITEM_LARGER) {
914        if (~pciDa[x]->rc.flRecordAttr & CRA_SELECTED)
915          WinSendMsg(hwndCnrD, CM_SETRECORDEMPHASIS, MPFROMP(pciDa[x]),
916                     MPFROM2SHORT(TRUE, CRA_SELECTED));
917      }
918      if (!(x % 500))
919        DosSleep(1L);
920      else if (!(x % 50))
921        DosSleep(1);
922    }
923    break;
924
925  case IDM_SELECTSMALLER:
926    for (x = 0; x < numS; x++) {
927      if (~pciSa[x]->rc.flRecordAttr & CRA_FILTERED &&
928          *pciSa[x]->pszFileName &&
929          pciSa[x]->flags & CNRITEM_SMALLER) {
930        if (~pciSa[x]->rc.flRecordAttr & CRA_SELECTED)
931          WinSendMsg(hwndCnrS, CM_SETRECORDEMPHASIS, MPFROMP(pciSa[x]),
932                     MPFROM2SHORT(TRUE, CRA_SELECTED));
933      }
934      else if (~pciDa[x]->rc.flRecordAttr & CRA_FILTERED &&
935               *pciDa[x]->pszFileName &&
936               pciDa[x]->flags & CNRITEM_SMALLER) {
937        if (~pciDa[x]->rc.flRecordAttr & CRA_SELECTED)
938          WinSendMsg(hwndCnrD, CM_SETRECORDEMPHASIS, MPFROMP(pciDa[x]),
939                     MPFROM2SHORT(TRUE, CRA_SELECTED));
940      }
941      if (!(x % 500))
942        DosSleep(1L);
943      else if (!(x % 50))
944        DosSleep(1);
945    }
946    break;
947
948  case IDM_SELECTNEWER:
949    for (x = 0; x < numS; x++) {
950      if (~pciSa[x]->rc.flRecordAttr & CRA_FILTERED &&
951          *pciSa[x]->pszFileName &&
952          pciSa[x]->flags & CNRITEM_NEWER) {
953        if (~pciSa[x]->rc.flRecordAttr & CRA_SELECTED)
954          WinSendMsg(hwndCnrS, CM_SETRECORDEMPHASIS, MPFROMP(pciSa[x]),
955                     MPFROM2SHORT(TRUE, CRA_SELECTED));
956      }
957      else if (~pciDa[x]->rc.flRecordAttr & CRA_FILTERED &&
958               *pciDa[x]->pszFileName &&
959               pciDa[x]->flags & CNRITEM_NEWER) {
960        if (~pciDa[x]->rc.flRecordAttr & CRA_SELECTED)
961          WinSendMsg(hwndCnrD, CM_SETRECORDEMPHASIS, MPFROMP(pciDa[x]),
962                     MPFROM2SHORT(TRUE, CRA_SELECTED));
963      }
964      if (!(x % 500))
965        DosSleep(1L);
966      else if (!(x % 50))
967        DosSleep(1);
968    }
969    break;
970
971  case IDM_SELECTOLDER:
972    for (x = 0; x < numS; x++) {
973      if (~pciSa[x]->rc.flRecordAttr & CRA_FILTERED &&
974          *pciSa[x]->pszFileName &&
975          pciSa[x]->flags & CNRITEM_OLDER) {
976        if (~pciSa[x]->rc.flRecordAttr & CRA_SELECTED)
977          WinSendMsg(hwndCnrS, CM_SETRECORDEMPHASIS, MPFROMP(pciSa[x]),
978                     MPFROM2SHORT(TRUE, CRA_SELECTED));
979      }
980      else if (~pciDa[x]->rc.flRecordAttr & CRA_FILTERED &&
981               *pciDa[x]->pszFileName &&
982               pciDa[x]->flags & CNRITEM_OLDER) {
983        if (~pciDa[x]->rc.flRecordAttr & CRA_SELECTED)
984          WinSendMsg(hwndCnrD, CM_SETRECORDEMPHASIS, MPFROMP(pciDa[x]),
985                     MPFROM2SHORT(TRUE, CRA_SELECTED));
986      }
987      if (!(x % 500))
988        DosSleep(1L);
989      else if (!(x % 50))
990        DosSleep(1);
991    }
992    break;
993
994  case IDM_DESELECTBOTH:
995    for (x = 0; x < numS; x++) {
996      if (~pciSa[x]->rc.flRecordAttr & CRA_FILTERED &&
997          *pciSa[x]->pszFileName &&
998          pciSa[x]->flags & CNRITEM_EXISTS) {
999        if (pciSa[x]->rc.flRecordAttr & CRA_SELECTED)
1000          WinSendMsg(hwndCnrS, CM_SETRECORDEMPHASIS, MPFROMP(pciSa[x]),
1001                     MPFROM2SHORT(FALSE, CRA_SELECTED));
1002        if (pciDa[x]->rc.flRecordAttr & CRA_SELECTED)
1003          WinSendMsg(hwndCnrD, CM_SETRECORDEMPHASIS, MPFROMP(pciDa[x]),
1004                     MPFROM2SHORT(FALSE, CRA_SELECTED));
1005      }
1006      if (!(x % 500))
1007        DosSleep(1L);
1008      else if (!(x % 50))
1009        DosSleep(1);
1010    }
1011    break;
1012
1013  case IDM_DESELECTONE:
1014    for (x = 0; x < numS; x++) {
1015      if (~pciSa[x]->rc.flRecordAttr & CRA_FILTERED &&
1016          *pciSa[x]->pszFileName &&
1017          ~pciSa[x]->flags & CNRITEM_EXISTS) {
1018        if (pciSa[x]->rc.flRecordAttr & CRA_SELECTED)
1019          WinSendMsg(hwndCnrS, CM_SETRECORDEMPHASIS, MPFROMP(pciSa[x]),
1020                     MPFROM2SHORT(FALSE, CRA_SELECTED));
1021      }
1022      else if (*pciDa[x]->pszFileName &&
1023               ~pciDa[x]->flags & CNRITEM_EXISTS) {
1024        if (pciDa[x]->rc.flRecordAttr & CRA_SELECTED)
1025          WinSendMsg(hwndCnrD, CM_SETRECORDEMPHASIS, MPFROMP(pciDa[x]),
1026                     MPFROM2SHORT(FALSE, CRA_SELECTED));
1027      }
1028      if (!(x % 500))
1029        DosSleep(1L);
1030      else if (!(x % 50))
1031        DosSleep(1);
1032    }
1033    break;
1034
1035  case IDM_DESELECTBIGGER:
1036    for (x = 0; x < numS; x++) {
1037      if (~pciSa[x]->rc.flRecordAttr & CRA_FILTERED &&
1038          *pciSa[x]->pszFileName &&
1039          pciSa[x]->flags & CNRITEM_LARGER) {
1040        if (pciSa[x]->rc.flRecordAttr & CRA_SELECTED)
1041          WinSendMsg(hwndCnrS, CM_SETRECORDEMPHASIS, MPFROMP(pciSa[x]),
1042                     MPFROM2SHORT(FALSE, CRA_SELECTED));
1043      }
1044      else if (~pciDa[x]->rc.flRecordAttr & CRA_FILTERED &&
1045               *pciDa[x]->pszFileName &&
1046               pciDa[x]->flags & CNRITEM_LARGER) {
1047        if (pciDa[x]->rc.flRecordAttr & CRA_SELECTED)
1048          WinSendMsg(hwndCnrD, CM_SETRECORDEMPHASIS, MPFROMP(pciDa[x]),
1049                     MPFROM2SHORT(FALSE, CRA_SELECTED));
1050      }
1051      if (!(x % 500))
1052        DosSleep(1L);
1053      else if (!(x % 50))
1054        DosSleep(1);
1055    }
1056    break;
1057
1058  case IDM_DESELECTSMALLER:
1059    for (x = 0; x < numS; x++) {
1060      if (~pciSa[x]->rc.flRecordAttr & CRA_FILTERED &&
1061          *pciSa[x]->pszFileName &&
1062          pciSa[x]->flags & CNRITEM_SMALLER) {
1063        if (pciSa[x]->rc.flRecordAttr & CRA_SELECTED)
1064          WinSendMsg(hwndCnrS, CM_SETRECORDEMPHASIS, MPFROMP(pciSa[x]),
1065                     MPFROM2SHORT(FALSE, CRA_SELECTED));
1066      }
1067      else if (~pciDa[x]->rc.flRecordAttr & CRA_FILTERED &&
1068               *pciDa[x]->pszFileName &&
1069               pciDa[x]->flags & CNRITEM_SMALLER) {
1070        if (pciDa[x]->rc.flRecordAttr & CRA_SELECTED)
1071          WinSendMsg(hwndCnrD, CM_SETRECORDEMPHASIS, MPFROMP(pciDa[x]),
1072                     MPFROM2SHORT(FALSE, CRA_SELECTED));
1073      }
1074      if (!(x % 500))
1075        DosSleep(1L);
1076      else if (!(x % 50))
1077        DosSleep(1);
1078    }
1079    break;
1080
1081  case IDM_DESELECTNEWER:
1082    for (x = 0; x < numS; x++) {
1083      if (~pciSa[x]->rc.flRecordAttr & CRA_FILTERED &&
1084          *pciSa[x]->pszFileName &&
1085          pciSa[x]->flags & CNRITEM_NEWER) {
1086        if (pciSa[x]->rc.flRecordAttr & CRA_SELECTED)
1087          WinSendMsg(hwndCnrS, CM_SETRECORDEMPHASIS, MPFROMP(pciSa[x]),
1088                     MPFROM2SHORT(FALSE, CRA_SELECTED));
1089      }
1090      else if (~pciDa[x]->rc.flRecordAttr & CRA_FILTERED &&
1091               *pciDa[x]->pszFileName &&
1092               pciDa[x]->flags & CNRITEM_NEWER) {
1093        if (pciDa[x]->rc.flRecordAttr & CRA_SELECTED)
1094          WinSendMsg(hwndCnrD, CM_SETRECORDEMPHASIS, MPFROMP(pciDa[x]),
1095                     MPFROM2SHORT(FALSE, CRA_SELECTED));
1096      }
1097      if (!(x % 500))
1098        DosSleep(1L);
1099      else if (!(x % 50))
1100        DosSleep(1);
1101    }
1102    break;
1103
1104  case IDM_DESELECTOLDER:
1105    for (x = 0; x < numS; x++) {
1106      if (~pciSa[x]->rc.flRecordAttr & CRA_FILTERED &&
1107          *pciSa[x]->pszFileName &&
1108          pciSa[x]->flags & CNRITEM_OLDER) {
1109        if (pciSa[x]->rc.flRecordAttr & CRA_SELECTED)
1110          WinSendMsg(hwndCnrS, CM_SETRECORDEMPHASIS, MPFROMP(pciSa[x]),
1111                     MPFROM2SHORT(FALSE, CRA_SELECTED));
1112      }
1113      else if (~pciDa[x]->rc.flRecordAttr & CRA_FILTERED &&
1114               *pciDa[x]->pszFileName &&
1115               pciDa[x]->flags & CNRITEM_OLDER) {
1116        if (pciDa[x]->rc.flRecordAttr & CRA_SELECTED)
1117          WinSendMsg(hwndCnrD, CM_SETRECORDEMPHASIS, MPFROMP(pciDa[x]),
1118                     MPFROM2SHORT(FALSE, CRA_SELECTED));
1119      }
1120      if (!(x % 500))
1121        DosSleep(1L);
1122      else if (!(x % 50))
1123        DosSleep(1);
1124    }
1125    break;
1126
1127  default:
1128    break;
1129  }
1130
1131  if (reset) {
1132    while (numS) {
1133      WinSendMsg(hwndCnrS, CM_INVALIDATERECORD,
1134                 MPFROMP(pciSa), MPFROM2SHORT((min(numS, 65535)), 0));
1135      DosSleep(1);
1136      WinSendMsg(hwndCnrD, CM_INVALIDATERECORD,
1137                 MPFROMP(pciDa), MPFROM2SHORT((min(numD, 65535)), 0));
1138      numS -= min(numS, 65535);
1139      if (numS)
1140        DosSleep(1);
1141    }
1142  }
1143
1144  free(pciSa);
1145  free(pciDa);
1146  DosPostEventSem(CompactSem);
1147}
1148
1149struct SS
1150{
1151  PCNRITEM pci;
1152  BOOL unique, all, smallest, largest, newest, oldest;
1153};
1154
1155struct Cnr
1156{
1157  HWND hwndCnr;
1158  ULONG numfiles;
1159  struct SS *ss;
1160};
1161
1162static int CompSSNamesB(const void *s1, const void *s2)
1163{
1164  struct SS *ss2 = (struct SS *)s2;
1165
1166  return stricmp((PSZ)s1, ss2->pci->pszFileName);
1167}
1168
1169static int CompSSNames(const void *s1, const void *s2)
1170{
1171  struct SS *ss1 = (struct SS *)s1;
1172  struct SS *ss2 = (struct SS *)s2;
1173
1174  return stricmp(ss1->pci->pszFileName, ss2->pci->pszFileName);
1175}
1176
1177VOID FreeCnrs(struct Cnr * Cnrs, INT numw)
1178{
1179  register INT z;
1180
1181  for (z = 0; z < numw; z++) {
1182    if (Cnrs[z].ss)
1183      free(Cnrs[z].ss);
1184  }
1185  free(Cnrs);
1186  DosPostEventSem(CompactSem);
1187}
1188
1189VOID SpecialSelect2(HWND hwndParent, INT action)
1190{
1191  PCNRITEM pci;
1192  HENUM henum;
1193  HWND hwnd;
1194  register INT numwindows = 0, w, x, z, cmp;
1195  struct Cnr *Cnrs = NULL;
1196  struct SS *bsres;
1197
1198  if (!hwndParent)
1199    return;
1200
1201  /* count directory containers, build array of hwnds */
1202  henum = WinBeginEnumWindows(hwndParent);
1203  while ((hwnd = WinGetNextWindow(henum)) != NULLHANDLE) {
1204    if (WinWindowFromID(WinWindowFromID(hwnd, FID_CLIENT), DIR_CNR)) {
1205      Cnrs =
1206        xrealloc(Cnrs, (numwindows + 1) * sizeof(struct Cnr), pszSrcFile,
1207                 __LINE__);
1208      if (!Cnrs) {
1209        Notify(GetPString(IDS_OUTOFMEMORY));
1210        return;
1211      }
1212      memset(&Cnrs[numwindows], 0, sizeof(struct Cnr));
1213      Cnrs[numwindows].hwndCnr = WinWindowFromID(WinWindowFromID(hwnd,
1214                                                                 FID_CLIENT),
1215                                                 DIR_CNR);
1216      numwindows++;
1217    }
1218  }
1219  WinEndEnumWindows(henum);
1220  if (numwindows < 2) {
1221    FreeCnrs(Cnrs, numwindows);
1222    Runtime_Error(pszSrcFile, __LINE__, "expected two windows");
1223    Notify(GetPString(IDS_COMPSEL2ORMORETEXT));
1224    return;
1225  }
1226  if (numwindows > 4) {
1227    WinSendMsg(Cnrs[0].
1228               hwndCnr,
1229               UM_NOTIFY, MPFROMP(GetPString(IDS_BUILDINGLISTSTEXT)), MPVOID);
1230    DosSleep(1);
1231  }
1232
1233  /* count records, build array of pointers to records */
1234  for (z = 0; z < numwindows; z++) {
1235    pci = (PCNRITEM) WinSendMsg(Cnrs[z].hwndCnr,
1236                                CM_QUERYRECORD,
1237                                MPVOID,
1238                                MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
1239    x = 0;
1240    while (pci && (INT)pci != -1) {
1241      if (~pci->rc.flRecordAttr & CRA_FILTERED &&
1242          ~pci->attrFile & FILE_DIRECTORY) {
1243        Cnrs[z].ss =
1244          xrealloc(Cnrs[z].ss, (x + 1) * sizeof(struct SS), pszSrcFile,
1245                   __LINE__);
1246        if (!Cnrs[z].ss) {
1247          FreeCnrs(Cnrs, numwindows);
1248          Notify(GetPString(IDS_OUTOFMEMORY));
1249          return;
1250        }
1251        memset(&Cnrs[z].ss[x], 0, sizeof(struct SS));
1252        Cnrs[z].ss[x].pci = pci;
1253        x++;
1254      }
1255      pci = (PCNRITEM) WinSendMsg(Cnrs[z].hwndCnr,
1256                                  CM_QUERYRECORD,
1257                                  MPFROMP(pci),
1258                                  MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
1259    }
1260    DosSleep(1);
1261    Cnrs[z].numfiles = x;
1262    if (Cnrs[z].numfiles)
1263      qsort(Cnrs[z].ss, Cnrs[z].numfiles, sizeof(struct SS), CompSSNames);
1264  }
1265
1266  for (z = 0; z < numwindows; z++) {
1267    for (x = 0; x < Cnrs[z].numfiles; x++) {
1268      Cnrs[z].ss[x].all = Cnrs[z].ss[x].unique = Cnrs[z].ss[x].newest =
1269        Cnrs[z].ss[x].oldest = Cnrs[z].ss[x].smallest =
1270        Cnrs[z].ss[x].largest = TRUE;
1271      for (w = 0; w < numwindows; w++) {
1272        if (w != z && Cnrs[w].numfiles) {
1273          bsres = (struct SS *)bsearch(Cnrs[z].ss[x].pci->pszFileName,
1274                                       Cnrs[w].ss, Cnrs[w].numfiles,
1275                                       sizeof(struct SS), CompSSNamesB);
1276          if (bsres) {
1277            Cnrs[z].ss[x].unique = FALSE;
1278            if (Cnrs[z].ss[x].pci->cbFile + Cnrs[z].ss[x].pci->easize >
1279                bsres->pci->cbFile + bsres->pci->easize)
1280              Cnrs[z].ss[x].smallest = FALSE;
1281            if (Cnrs[z].ss[x].pci->cbFile + Cnrs[z].ss[x].pci->easize <
1282                bsres->pci->cbFile + bsres->pci->easize)
1283              Cnrs[z].ss[x].largest = FALSE;
1284            cmp =
1285              (Cnrs[z].ss[x].pci->date.year >
1286               bsres->pci->date.year) ? TRUE : (Cnrs[z].ss[x].pci->date.year <
1287                                                bsres->pci->date.
1288                                                year) ? FALSE : (Cnrs[z].
1289                                                                 ss[x].pci->
1290                                                                 date.month >
1291                                                                 bsres->pci->
1292                                                                 date.
1293                                                                 month) ? TRUE
1294              : (Cnrs[z].ss[x].pci->date.month <
1295                 bsres->pci->date.month) ? FALSE : (Cnrs[z].ss[x].pci->date.
1296                                                    day >
1297                                                    bsres->pci->date.
1298                                                    day) ? TRUE : (Cnrs[z].
1299                                                                   ss[x].pci->
1300                                                                   date.day <
1301                                                                   bsres->
1302                                                                   pci->date.
1303                                                                   day) ?
1304              FALSE : (Cnrs[z].ss[x].pci->time.hours >
1305                       bsres->pci->time.hours) ? TRUE : (Cnrs[z].ss[x].pci->
1306                                                         time.hours <
1307                                                         bsres->pci->time.
1308                                                         hours) ? FALSE
1309              : (Cnrs[z].ss[x].pci->time.minutes >
1310                 bsres->pci->time.minutes) ? TRUE : (Cnrs[z].ss[x].pci->time.
1311                                                     minutes <
1312                                                     bsres->pci->time.
1313                                                     minutes) ? FALSE
1314              : (Cnrs[z].ss[x].pci->time.seconds >
1315                 bsres->pci->time.seconds) ? TRUE : (Cnrs[z].ss[x].pci->time.
1316                                                     seconds <
1317                                                     bsres->pci->time.
1318                                                     seconds) ? FALSE : FALSE;
1319            if (!cmp)
1320              Cnrs[z].ss[x].newest = FALSE;
1321            cmp =
1322              (Cnrs[z].ss[x].pci->date.year <
1323               bsres->pci->date.year) ? TRUE : (Cnrs[z].ss[x].pci->date.year >
1324                                                bsres->pci->date.
1325                                                year) ? FALSE : (Cnrs[z].
1326                                                                 ss[x].pci->
1327                                                                 date.month <
1328                                                                 bsres->pci->
1329                                                                 date.
1330                                                                 month) ? TRUE
1331              : (Cnrs[z].ss[x].pci->date.month >
1332                 bsres->pci->date.month) ? FALSE : (Cnrs[z].ss[x].pci->date.
1333                                                    day <
1334                                                    bsres->pci->date.
1335                                                    day) ? TRUE : (Cnrs[z].
1336                                                                   ss[x].pci->
1337                                                                   date.day >
1338                                                                   bsres->
1339                                                                   pci->date.
1340                                                                   day) ?
1341              FALSE : (Cnrs[z].ss[x].pci->time.hours <
1342                       bsres->pci->time.hours) ? TRUE : (Cnrs[z].ss[x].pci->
1343                                                         time.hours >
1344                                                         bsres->pci->time.
1345                                                         hours) ? FALSE
1346              : (Cnrs[z].ss[x].pci->time.minutes <
1347                 bsres->pci->time.minutes) ? TRUE : (Cnrs[z].ss[x].pci->time.
1348                                                     minutes >
1349                                                     bsres->pci->time.
1350                                                     minutes) ? FALSE
1351              : (Cnrs[z].ss[x].pci->time.seconds <
1352                 bsres->pci->time.seconds) ? TRUE : (Cnrs[z].ss[x].pci->time.
1353                                                     seconds >
1354                                                     bsres->pci->time.
1355                                                     seconds) ? FALSE : FALSE;
1356            if (!cmp)
1357              Cnrs[z].ss[x].oldest = FALSE;
1358            cmp = 0;
1359            break;
1360          }
1361          else
1362            Cnrs[z].ss[x].all = FALSE;
1363        }
1364      }
1365      if (Cnrs[z].ss[x].unique)
1366        Cnrs[z].ss[x].oldest = Cnrs[z].ss[x].newest = Cnrs[z].ss[x].all =
1367          Cnrs[z].ss[x].largest = Cnrs[z].ss[x].smallest = FALSE;
1368      DosSleep(1);
1369    }
1370    DosSleep(1L);
1371  }
1372
1373  switch (action) {
1374  case IDM_SELECTBOTH:
1375    for (z = 0; z < numwindows; z++) {
1376      for (x = 0; x < Cnrs[z].numfiles; x++) {
1377        if (Cnrs[z].ss[x].all)
1378          WinSendMsg(Cnrs[z].hwndCnr, CM_SETRECORDEMPHASIS,
1379                     MPFROMP(Cnrs[z].ss[x].pci),
1380                     MPFROM2SHORT(TRUE, CRA_SELECTED));
1381      }
1382      DosSleep(1);
1383    }
1384    break;
1385  case IDM_SELECTMORE:
1386    for (z = 0; z < numwindows; z++) {
1387      for (x = 0; x < Cnrs[z].numfiles; x++) {
1388        if (!Cnrs[z].ss[x].unique)
1389          WinSendMsg(Cnrs[z].hwndCnr, CM_SETRECORDEMPHASIS,
1390                     MPFROMP(Cnrs[z].ss[x].pci),
1391                     MPFROM2SHORT(TRUE, CRA_SELECTED));
1392      }
1393      DosSleep(1);
1394    }
1395    break;
1396  case IDM_SELECTONE:
1397    for (z = 0; z < numwindows; z++) {
1398      for (x = 0; x < Cnrs[z].numfiles; x++) {
1399        if (Cnrs[z].ss[x].unique)
1400          WinSendMsg(Cnrs[z].hwndCnr, CM_SETRECORDEMPHASIS,
1401                     MPFROMP(Cnrs[z].ss[x].pci),
1402                     MPFROM2SHORT(TRUE, CRA_SELECTED));
1403      }
1404      DosSleep(1);
1405    }
1406    break;
1407  case IDM_SELECTNEWER:
1408    for (z = 0; z < numwindows; z++) {
1409      for (x = 0; x < Cnrs[z].numfiles; x++) {
1410        if (Cnrs[z].ss[x].newest)
1411          WinSendMsg(Cnrs[z].hwndCnr, CM_SETRECORDEMPHASIS,
1412                     MPFROMP(Cnrs[z].ss[x].pci),
1413                     MPFROM2SHORT(TRUE, CRA_SELECTED));
1414      }
1415      DosSleep(1);
1416    }
1417    break;
1418  case IDM_SELECTOLDER:
1419    for (z = 0; z < numwindows; z++) {
1420      for (x = 0; x < Cnrs[z].numfiles; x++) {
1421        if (Cnrs[z].ss[x].oldest)
1422          WinSendMsg(Cnrs[z].hwndCnr, CM_SETRECORDEMPHASIS,
1423                     MPFROMP(Cnrs[z].ss[x].pci),
1424                     MPFROM2SHORT(TRUE, CRA_SELECTED));
1425      }
1426      DosSleep(1);
1427    }
1428    break;
1429  case IDM_SELECTBIGGER:
1430    for (z = 0; z < numwindows; z++) {
1431      for (x = 0; x < Cnrs[z].numfiles; x++) {
1432        if (Cnrs[z].ss[x].largest)
1433          WinSendMsg(Cnrs[z].hwndCnr, CM_SETRECORDEMPHASIS,
1434                     MPFROMP(Cnrs[z].ss[x].pci),
1435                     MPFROM2SHORT(TRUE, CRA_SELECTED));
1436      }
1437      DosSleep(1);
1438    }
1439    break;
1440  case IDM_SELECTSMALLER:
1441    for (z = 0; z < numwindows; z++) {
1442      for (x = 0; x < Cnrs[z].numfiles; x++) {
1443        if (Cnrs[z].ss[x].smallest)
1444          WinSendMsg(Cnrs[z].hwndCnr, CM_SETRECORDEMPHASIS,
1445                     MPFROMP(Cnrs[z].ss[x].pci),
1446                     MPFROM2SHORT(TRUE, CRA_SELECTED));
1447      }
1448      DosSleep(1);
1449    }
1450    break;
1451
1452  case IDM_DESELECTBOTH:
1453    for (z = 0; z < numwindows; z++) {
1454      for (x = 0; x < Cnrs[z].numfiles; x++) {
1455        if (Cnrs[z].ss[x].all)
1456          WinSendMsg(Cnrs[z].hwndCnr, CM_SETRECORDEMPHASIS,
1457                     MPFROMP(Cnrs[z].ss[x].pci),
1458                     MPFROM2SHORT(FALSE, CRA_SELECTED));
1459      }
1460      DosSleep(1);
1461    }
1462    break;
1463  case IDM_DESELECTMORE:
1464    for (z = 0; z < numwindows; z++) {
1465      for (x = 0; x < Cnrs[z].numfiles; x++) {
1466        if (!Cnrs[z].ss[x].unique)
1467          WinSendMsg(Cnrs[z].hwndCnr, CM_SETRECORDEMPHASIS,
1468                     MPFROMP(Cnrs[z].ss[x].pci),
1469                     MPFROM2SHORT(FALSE, CRA_SELECTED));
1470      }
1471      DosSleep(1);
1472    }
1473    break;
1474  case IDM_DESELECTONE:
1475    for (z = 0; z < numwindows; z++) {
1476      for (x = 0; x < Cnrs[z].numfiles; x++) {
1477        if (Cnrs[z].ss[x].unique)
1478          WinSendMsg(Cnrs[z].hwndCnr, CM_SETRECORDEMPHASIS,
1479                     MPFROMP(Cnrs[z].ss[x].pci),
1480                     MPFROM2SHORT(FALSE, CRA_SELECTED));
1481      }
1482      DosSleep(1);
1483    }
1484    break;
1485  case IDM_DESELECTNEWER:
1486    for (z = 0; z < numwindows; z++) {
1487      for (x = 0; x < Cnrs[z].numfiles; x++) {
1488        if (Cnrs[z].ss[x].newest)
1489          WinSendMsg(Cnrs[z].hwndCnr, CM_SETRECORDEMPHASIS,
1490                     MPFROMP(Cnrs[z].ss[x].pci),
1491                     MPFROM2SHORT(FALSE, CRA_SELECTED));
1492      }
1493      DosSleep(1);
1494    }
1495    break;
1496  case IDM_DESELECTOLDER:
1497    for (z = 0; z < numwindows; z++) {
1498      for (x = 0; x < Cnrs[z].numfiles; x++) {
1499        if (Cnrs[z].ss[x].oldest)
1500          WinSendMsg(Cnrs[z].hwndCnr, CM_SETRECORDEMPHASIS,
1501                     MPFROMP(Cnrs[z].ss[x].pci),
1502                     MPFROM2SHORT(FALSE, CRA_SELECTED));
1503      }
1504      DosSleep(1);
1505    }
1506    break;
1507  case IDM_DESELECTBIGGER:
1508    for (z = 0; z < numwindows; z++) {
1509      for (x = 0; x < Cnrs[z].numfiles; x++) {
1510        if (Cnrs[z].ss[x].largest)
1511          WinSendMsg(Cnrs[z].hwndCnr, CM_SETRECORDEMPHASIS,
1512                     MPFROMP(Cnrs[z].ss[x].pci),
1513                     MPFROM2SHORT(FALSE, CRA_SELECTED));
1514      }
1515      DosSleep(1);
1516    }
1517    break;
1518  case IDM_DESELECTSMALLER:
1519    for (z = 0; z < numwindows; z++) {
1520      for (x = 0; x < Cnrs[z].numfiles; x++) {
1521        if (Cnrs[z].ss[x].smallest)
1522          WinSendMsg(Cnrs[z].hwndCnr, CM_SETRECORDEMPHASIS,
1523                     MPFROMP(Cnrs[z].ss[x].pci),
1524                     MPFROM2SHORT(FALSE, CRA_SELECTED));
1525      }
1526      DosSleep(1);
1527    }
1528    break;
1529  }
1530
1531  FreeCnrs(Cnrs, numwindows);
1532}
Note: See TracBrowser for help on using the repository browser.