source: trunk/dll/select.c@ 1838

Last change on this file since 1838 was 1838, checked in by Gregg Young, 10 years ago

Serialize local hard drive scanning to reduce drive thrashing continue to scan all other drive types in separate threads. Ticket [561] Remove unneed SubbyScan code and improve suppression of blank lines and duplicate subdirectory name caused by running Stubby in worker threads.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 25.5 KB
Line 
1
2/***********************************************************************
3
4 $Id: select.c 1838 2015-08-02 22:14:21Z gyoung $
5
6 Container item selection support routines
7
8 Copyright (c) 1993-98 M. Kimes
9 Copyright (c) 2004, 2011 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 04 Aug 07 SHL Use Runtime_Error
24 05 Aug 07 SHL Rework SpecialSelect to use CNRITEM_EXISTS and
25 not use pszFileName since CNRITEM_EXISTS set implies
26 pszFileName not null
27 14 Aug 07 SHL Revert ExpandAll DosSleep to 0
28 20 Aug 07 GKY Move #pragma alloc_text to end for OpenWatcom compat
29 26 Aug 07 GKY DosSleep(1) in loops changed to (0)
30 12 Jan 08 SHL Localize SpecialSelect in comp.c
31 29 Feb 08 GKY Use xfree where appropriate
32 31 May 11 SHL Ensure mask->pszMasks[1] initialize to NULL if not used
33 13 Jun 15 GKY Fixed compare selection replaced pszFileNames with pszDisplayNames
34 02 Aug 15 GKY Remove unneed SubbyScan code and improve suppression of blank lines and
35 duplicate subdirectory name caused by running Stubby in worker threads.
36
37***********************************************************************/
38
39#include <stdlib.h>
40#include <string.h>
41#include <share.h>
42#include <io.h>
43
44#define INCL_DOS
45#define INCL_WIN
46#define INCL_LONGLONG
47
48#include "fm3dll.h"
49#include "fm3dll2.h" // #define's for UM_*, control id's, etc.
50#include "select.h"
51#include "notebook.h" // Data declaration(s)
52#include "newview.h" // Data declarations
53#include "fm3str.h"
54#include "filldir.h" // RemoveCnrItems
55#include "makelist.h" // AddToList
56#include "errutil.h" // Dos_Error...
57#include "strutil.h" // GetPString
58#include "valid.h" // TestCDates
59#include "misc.h" // CurrentRecord
60#include "findrec.h" // FindCnrRecord
61#include "notify.h" // Notify
62#include "literal.h" // wildcard
63#include "wrappers.h" // xrealloc
64#include "strips.h" // bstrip
65#include "stristr.h" // findstring
66#include "fortify.h"
67#if 0
68#define __PMPRINTF__
69#include "PMPRINTF.H"
70#endif
71
72static PSZ pszSrcFile = __FILE__;
73
74VOID UnHilite(HWND hwndCnr, BOOL all, CHAR *** list, ULONG ulItemsToUnHilite)
75{
76 PCNRITEM pci;
77 UINT numfiles = 0, numalloc = 0;
78 UINT x = 0;
79 INT attribute = CRA_CURSORED;
80
81 if (all && list && *list) {
82 FreeList(*list);
83 *list = NULL;
84 }
85 pci = (PCNRITEM) CurrentRecord(hwndCnr);
86 if (pci && (INT)pci != -1) {
87 if (pci->rc.flRecordAttr & CRA_SELECTED) {
88 attribute = CRA_SELECTED;
89 pci = WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS, MPFROMLONG(CMA_FIRST),
90 MPFROMSHORT(attribute));
91 }
92 while (pci && (INT)pci != -1) {
93 WinSendMsg(hwndCnr, CM_SETRECORDEMPHASIS, MPFROMP(pci),
94 MPFROM2SHORT(FALSE, CRA_SELECTED));
95 if (!all)
96 break;
97 // Count is one extra to ensure non-zero elsewhere
98 // x is 0 based index
99 if (x + 2 == ulItemsToUnHilite)
100 break;
101 if (list)
102 AddToList(pci->pszFileName, list, &numfiles, &numalloc);
103 pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS,
104 MPFROMP(pci), MPFROMSHORT(CRA_SELECTED));
105 x++;
106 }
107 }
108}
109
110VOID SelectList(HWND hwndCnr, BOOL partial, BOOL deselect, BOOL clearfirst,
111 PCNRITEM pciParent, PSZ filename, CHAR ** list)
112{
113
114 PCNRITEM pci;
115 register INT x;
116 BOOL foundone = FALSE;
117 ULONG errs = 0;
118
119 if (clearfirst && !deselect)
120 UnHilite(hwndCnr, TRUE, NULL, 0);
121 if (list && list[0]) {
122 for (x = 0; list[x]; x++) {
123 pci = FindCnrRecord(hwndCnr,
124 list[x], pciParent, partial, partial, TRUE);
125 if (pci) {
126 WinSendMsg(hwndCnr,
127 CM_SETRECORDEMPHASIS,
128 MPFROMP(pci),
129 MPFROM2SHORT((SHORT) ((deselect) ? FALSE : TRUE),
130 CRA_SELECTED));
131 foundone = TRUE;
132 }
133 }
134 if (!foundone)
135 Runtime_Error(pszSrcFile, __LINE__, "select failed");
136 }
137 else if (filename && *filename) {
138
139 FILE *fp;
140 CHAR input[1024], *p;
141 CHAR *moder = "r";
142
143 fp = xfsopen(filename, moder, SH_DENYNO, pszSrcFile, __LINE__, TRUE);
144 if (fp) {
145 while (!feof(fp)) {
146 if (!xfgets_bstripcr(input, sizeof(input), fp, pszSrcFile, __LINE__))
147 break;
148 if (*input == '\"') {
149 memmove(input, input + 1, strlen(input) + 1);
150 lstrip(input);
151 p = strchr(input, '\"');
152 if (p)
153 *p = 0;
154 rstrip(input);
155 }
156 else {
157 p = strchr(input, ' ');
158 if (p)
159 *p = 0;
160 }
161 // Input now contains name of file to select
162 pci = FindCnrRecord(hwndCnr,
163 input, pciParent, partial, partial, TRUE);
164 if (pci) // Found it?
165 WinSendMsg(hwndCnr,
166 CM_SETRECORDEMPHASIS,
167 MPFROMP(pci),
168 MPFROM2SHORT((SHORT) ((deselect) ? FALSE : TRUE),
169 CRA_SELECTED));
170 else
171 errs++;
172 if (errs > 50) { // Prevent runaway on bad file
173
174 APIRET ret;
175
176 ret = saymsg(MB_YESNO,
177 hwndCnr,
178 GetPString(IDS_POSSIBLEERRORTEXT),
179 GetPString(IDS_MAYNOTBELISTTEXT), filename);
180 if (ret == MBID_NO)
181 break;
182 errs = 0;
183 }
184 }
185 fclose(fp);
186 }
187 }
188}
189
190VOID SelectAll(HWND hwndCnr, BOOL files, BOOL dirs, PSZ maskstr,
191 PSZ text, BOOL is_arc)
192{
193
194 PCNRITEM pci;
195 BOOL markit;
196 PSZ file;
197 PSZ pszToMatch;
198 MASK Mask;
199 INT x;
200 ULONG textlen = 0;
201
202 if (text)
203 textlen = strlen(text);
204 memset(&Mask, 0, sizeof(Mask));
205 if (maskstr)
206 SetMask(maskstr, &Mask);
207 pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORD, MPVOID,
208 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
209 while (pci && (INT)pci != -1) {
210
211 markit = FALSE;
212
213 if (~pci->rc.flRecordAttr & CRA_FILTERED) {
214 if (!is_arc) {
215 if (files && ~pci->attrFile & FILE_DIRECTORY)
216 markit = TRUE;
217 if (dirs && pci->attrFile & FILE_DIRECTORY)
218 markit = TRUE;
219 }
220 else
221 markit = TRUE;
222 if (maskstr && *maskstr && markit) {
223 markit = FALSE;
224 // Point a filename part
225 file = strrchr(pci->pszFileName, '\\');
226 if (!file)
227 file = strrchr(pci->pszFileName, ':');
228 if (file)
229 file++;
230 else
231 file = pci->pszFileName;
232 for (x = 0; Mask.pszMasks[x]; x++) {
233 if (*Mask.pszMasks[x]) {
234 if ((strchr(Mask.pszMasks[x], '\\') ||
235 strchr(Mask.pszMasks[x], ':')))
236 pszToMatch = pci->pszFileName;
237 else
238 pszToMatch = file;
239 if (*Mask.pszMasks[x] != '/') {
240 if (wildcard(pszToMatch, Mask.pszMasks[x], TRUE)) {
241 markit = TRUE;
242 }
243 }
244 else {
245 if (wildcard(pszToMatch, Mask.pszMasks[x] + 1, TRUE)) {
246 markit = FALSE;
247 break;
248 }
249 }
250 }
251 } // for
252 }
253 }
254
255 if (markit && text && *text) {
256 if (~pci->attrFile & FILE_DIRECTORY) {
257 PSZ input;
258 markit = FALSE;
259 input = xmalloc(65537, pszSrcFile, __LINE__);
260 if (input) {
261 ULONG pos;
262 LONG len;
263 FILE *inputFile;
264 CHAR *moderb = "rb";
265
266 if ((inputFile = xfsopen(pci->pszFileName, moderb, SH_DENYNO,
267 pszSrcFile, __LINE__, TRUE)) != NULL) {
268 pos = ftell(inputFile);
269 while (!feof(inputFile)) {
270 if (pos)
271 fseek(inputFile, pos - 256, SEEK_SET);
272 len = fread(input, 1, 65536, inputFile);
273 if (len >= 0) {
274 if (findstring(text, textlen, input, len, FALSE)) {
275 markit = TRUE;
276 break;
277 }
278 }
279 else
280 break;
281 } // while
282 fclose(inputFile);
283 }
284 free(input);
285 DosSleep(1);
286 }
287 }
288 else
289 markit = FALSE;
290 }
291
292 if (markit)
293 WinSendMsg(hwndCnr, CM_SETRECORDEMPHASIS, MPFROMP(pci),
294 MPFROM2SHORT(TRUE, CRA_SELECTED));
295 pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(pci),
296 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
297 } // while
298}
299
300VOID DeselectAll(HWND hwndCnr, BOOL files, BOOL dirs, PSZ maskstr,
301 PSZ text, BOOL is_arc)
302{
303 PCNRITEM pci;
304 BOOL unmarkit;
305 PSZ file;
306 PSZ pszToMatch;
307 MASK Mask;
308 register INT x;
309 ULONG textlen = 0;
310
311 if (text)
312 textlen = strlen(text);
313 memset(&Mask, 0, sizeof(Mask));
314 if (maskstr && *maskstr)
315 SetMask(maskstr, &Mask);
316 pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORD, MPVOID,
317 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
318 while (pci && (INT)pci != -1) {
319 unmarkit = FALSE;
320 if (~pci->rc.flRecordAttr & CRA_FILTERED) {
321 if (!is_arc) {
322 if (files && ~pci->attrFile & FILE_DIRECTORY)
323 unmarkit = TRUE;
324 if (dirs && (pci->attrFile & FILE_DIRECTORY))
325 unmarkit = TRUE;
326 }
327 else
328 unmarkit = TRUE;
329 if (maskstr && *maskstr && unmarkit) {
330 unmarkit = FALSE;
331 file = strrchr(pci->pszFileName, '\\');
332 if (!file)
333 file = strrchr(pci->pszFileName, ':');
334 if (file)
335 file++;
336 else
337 file = pci->pszFileName;
338 for (x = 0; Mask.pszMasks[x]; x++) {
339 if (*Mask.pszMasks[x]) {
340 if (strchr(Mask.pszMasks[x], '\\') ||
341 strchr(Mask.pszMasks[x], ':'))
342 pszToMatch = pci->pszFileName;
343 else
344 pszToMatch = file;
345 if (*Mask.pszMasks[x] != '/') {
346 if (wildcard(pszToMatch, Mask.pszMasks[x], TRUE))
347 unmarkit = TRUE;
348 }
349 else {
350 if (wildcard(pszToMatch, Mask.pszMasks[x] + 1, TRUE)) {
351 unmarkit = FALSE;
352 break;
353 }
354 }
355 }
356 }
357 }
358 }
359
360 if (unmarkit && text && *text) {
361 if (~pci->attrFile & FILE_DIRECTORY) {
362 PSZ input;
363 unmarkit = FALSE;
364 input = xmalloc(65537, pszSrcFile, __LINE__);
365 if (input) {
366 ULONG pos;
367 LONG len;
368 FILE *inputFile;
369 CHAR *moderb = "rb";
370
371 if ((inputFile = xfsopen(pci->pszFileName, moderb, SH_DENYNO,
372 pszSrcFile, __LINE__, TRUE)) != NULL) {
373 pos = ftell(inputFile);
374 while (!feof(inputFile)) {
375 if (pos)
376 fseek(inputFile, pos - 256, SEEK_SET);
377 len = fread(input, 1, 65536, inputFile);
378 if (len >= 0) {
379 if (findstring(text, textlen, input, len, FALSE)) {
380 unmarkit = TRUE;
381 break;
382 }
383 }
384 else
385 break;
386 } // while
387 fclose(inputFile);
388 }
389 free(input);
390 DosSleep(1);
391 }
392 }
393 else
394 unmarkit = FALSE;
395 }
396
397 if (unmarkit)
398 WinSendMsg(hwndCnr, CM_SETRECORDEMPHASIS, MPFROMP(pci),
399 MPFROM2SHORT(FALSE, CRA_SELECTED | CRA_CURSORED |
400 CRA_INUSE | CRA_SOURCE));
401 pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(pci),
402 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
403 }
404}
405
406VOID Deselect(HWND hwndCnr)
407{
408 PCNRITEM pcil;
409
410 pcil = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS,
411 MPFROMLONG(CMA_FIRST),
412 MPFROMSHORT(CRA_SELECTED));
413 while (pcil && (INT)pcil != -1) {
414 WinSendMsg(hwndCnr, CM_SETRECORDEMPHASIS, MPFROMP(pcil),
415 MPFROM2SHORT(FALSE, CRA_SELECTED));
416 pcil = WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS, MPFROMP(pcil),
417 MPFROMSHORT(CRA_SELECTED));
418 }
419}
420
421//=== HideAll() Hide all selected records ===
422
423VOID HideAll(HWND hwndCnr)
424{
425 PCNRITEM pci, pciH;
426 INT attribute = CRA_CURSORED;
427 CNRINFO cnri;
428 BOOL didone = FALSE;
429
430 memset(&cnri, 0, sizeof(CNRINFO));
431 cnri.cb = sizeof(CNRINFO);
432 WinSendMsg(hwndCnr, CM_QUERYCNRINFO, MPFROMP(&cnri),
433 MPFROMLONG(sizeof(CNRINFO)));
434 pci = (PCNRITEM) CurrentRecord(hwndCnr);
435 if (pci && (INT)pci != -1) {
436 if (pci->rc.flRecordAttr & CRA_SELECTED) {
437 attribute = CRA_SELECTED;
438 pci = WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS, MPFROMLONG(CMA_FIRST),
439 MPFROMSHORT(attribute));
440 }
441 }
442 while (pci && (INT)pci != -1) {
443 pciH = WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS, MPFROMP(pci),
444 MPFROMSHORT(attribute));
445 WinSendMsg(hwndCnr, CM_SETRECORDEMPHASIS, MPFROMP(pci),
446 MPFROM2SHORT(FALSE, CRA_CURSORED | CRA_SELECTED |
447 CRA_INUSE | CRA_SOURCE));
448 pci->rc.flRecordAttr |= CRA_FILTERED;
449 didone = TRUE;
450 if (fSyncUpdates) {
451 if (cnri.flWindowAttr & CV_DETAIL)
452 WinSendMsg(hwndCnr, CM_INVALIDATERECORD, MPVOID,
453 MPFROM2SHORT(0, CMA_REPOSITION | CMA_ERASE));
454 else
455 WinSendMsg(hwndCnr, CM_INVALIDATERECORD, MPFROMP(&pci),
456 MPFROM2SHORT(1, CMA_REPOSITION | CMA_ERASE));
457 }
458 pci = pciH;
459 }
460 if (didone && !fSyncUpdates)
461 WinSendMsg(hwndCnr, CM_INVALIDATERECORD, MPVOID,
462 MPFROM2SHORT(0, CMA_ERASE | CMA_REPOSITION));
463}
464
465VOID MarkAll(HWND hwndCnr, BOOL quitit, BOOL target, BOOL source)
466{
467 PCNRITEM pci;
468 INT attribute = CRA_CURSORED;
469
470 if (quitit)
471 attribute = target ? CRA_TARGET : source ? CRA_SOURCE : CRA_INUSE;
472 pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS,
473 MPFROMLONG(CMA_FIRST), MPFROMSHORT(attribute));
474 if (pci && (INT)pci != -1) {
475 if (attribute == CRA_CURSORED) {
476 if (pci->rc.flRecordAttr & CRA_SELECTED) {
477 attribute = CRA_SELECTED;
478 pci =
479 WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS, MPFROMLONG(CMA_FIRST),
480 MPFROMSHORT(attribute));
481 }
482 }
483 }
484 while (pci && (INT)pci != -1) {
485 WinSendMsg(hwndCnr, CM_SETRECORDEMPHASIS, MPFROMP(pci),
486 MPFROM2SHORT(!quitit,
487 target ? CRA_TARGET : source ? CRA_SOURCE :
488 CRA_INUSE));
489 pci =
490 WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS, MPFROMP(pci),
491 MPFROMSHORT(attribute));
492 }
493}
494
495VOID RemoveAll(HWND hwndCnr, ULONGLONG * pullTotalBytes,
496 ULONG * pulTotalFiles)
497{
498 PCNRITEM pci;
499 INT attribute = CRA_CURSORED;
500 BOOL didone = FALSE;
501
502 pci = (PCNRITEM) CurrentRecord(hwndCnr);
503 if (pci && (INT)pci != -1) {
504 if (pci->rc.flRecordAttr & CRA_SELECTED) {
505 attribute = CRA_SELECTED;
506 pci = WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS, MPFROMLONG(CMA_FIRST),
507 MPFROMSHORT(attribute));
508 }
509 }
510 while (pci && (INT)pci != -1) {
511 if (~pci->rc.flRecordAttr & CRA_FILTERED) {
512 didone = TRUE;
513 if (pulTotalFiles)
514 *pulTotalFiles -= 1;
515 if (pullTotalBytes)
516 *pullTotalBytes -= (pci->cbFile + pci->easize);
517 WinSendMsg(hwndCnr, CM_SETRECORDEMPHASIS, MPFROMP(pci),
518 MPFROM2SHORT(0, CRA_SELECTED));
519 if (fSyncUpdates)
520 RemoveCnrItems(hwndCnr, pci, 1, CMA_FREE | CMA_INVALIDATE);
521 else
522 RemoveCnrItems(hwndCnr, pci, 1, CMA_FREE);
523 if (attribute == CRA_CURSORED)
524 break;
525 pci = WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS, MPFROMLONG(CMA_FIRST),
526 MPFROMSHORT(attribute));
527 }
528 else
529 pci = WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS, MPFROMP(pci),
530 MPFROMSHORT(attribute));
531 }
532 if (didone && !fSyncUpdates)
533 WinSendMsg(hwndCnr, CM_INVALIDATERECORD, MPVOID,
534 MPFROM2SHORT(0, CMA_REPOSITION));
535}
536
537//== SetMask() Convert mask string to array of pointers to masks ==
538
539VOID SetMask(PSZ maskstr, MASK *mask)
540{
541 UINT x;
542 PSZ p;
543
544 DosEnterCritSec();
545 if (maskstr)
546 strcpy(mask->szMask, maskstr); // Got new mask string
547 // Build array of pointers
548 p = mask->szMaskCopy;
549 strcpy(p, mask->szMask);
550 // Allow up to 25 masks - ignore extras
551 for (x = 0; *p && x < 25; x++) {
552 mask->pszMasks[x] = p;
553 while (*p && *p != ';')
554 p++; // Find separator
555 if (*p) {
556 *p = 0; // Replace ; will nul to terminate string
557 p++;
558 }
559 } // for
560 mask->pszMasks[x] = NULL; // Mark end
561 if (!x)
562 mask->pszMasks[1] = NULL; // Need 1 more for multiple mask detect 2011-05-31 SHL
563 DosExitCritSec();
564}
565
566VOID ExpandAll(HWND hwndCnr, BOOL expand, PCNRITEM pciParent)
567{
568 PCNRITEM pci;
569
570 if (!pciParent)
571 pciParent = WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(NULL),
572 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
573 if (pciParent) {
574 if (expand && ~pciParent->rc.flRecordAttr & CRA_EXPANDED)
575 WinSendMsg(hwndCnr, CM_EXPANDTREE, MPFROMP(pciParent), MPVOID);
576 else if (!expand && (pciParent->rc.flRecordAttr & CRA_EXPANDED))
577 WinSendMsg(hwndCnr, CM_COLLAPSETREE, MPFROMP(pciParent), MPVOID);
578 pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(pciParent),
579 MPFROM2SHORT(CMA_FIRSTCHILD, CMA_ITEMORDER));
580 while (pci && (INT)pci != -1) {
581 ExpandAll(hwndCnr, expand, pci);
582 pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(pci),
583 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
584 }
585 }
586 DosSleep(0);
587}
588
589VOID InvertAll(HWND hwndCnr)
590{
591 PCNRITEM pci;
592
593 pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORD, MPVOID,
594 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
595 while (pci && (INT)pci != -1) {
596 if (~pci->rc.flRecordAttr & CRA_FILTERED) {
597 if (~pci->rc.flRecordAttr & CRA_SELECTED)
598 WinSendMsg(hwndCnr, CM_SETRECORDEMPHASIS, MPFROMP(pci),
599 MPFROM2SHORT(TRUE, CRA_SELECTED));
600 else
601 WinSendMsg(hwndCnr, CM_SETRECORDEMPHASIS, MPFROMP(pci),
602 MPFROM2SHORT(FALSE, CRA_SELECTED));
603 }
604 pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(pci),
605 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
606 }
607}
608
609struct SS
610{
611 PCNRITEM pci;
612 BOOL unique, all, smallest, largest, newest, oldest;
613};
614
615struct Cnr
616{
617 HWND hwndCnr;
618 ULONG numfiles;
619 struct SS *ss;
620};
621
622static int CompSSNamesB(const void *s1, const void *s2)
623{
624 struct SS *ss2 = (struct SS *)s2;
625
626 return stricmp((PSZ)s1, ss2->pci->pszDisplayName);
627}
628
629static int CompSSNames(const void *s1, const void *s2)
630{
631 struct SS *ss1 = (struct SS *)s1;
632 struct SS *ss2 = (struct SS *)s2;
633
634 return stricmp(ss1->pci->pszFileName, ss2->pci->pszFileName);
635}
636
637VOID FreeCnrs(struct Cnr * Cnrs, INT numw)
638{
639 register INT z;
640
641 for (z = 0; z < numw; z++) {
642 xfree(Cnrs[z].ss, pszSrcFile, __LINE__);
643 }
644 xfree(Cnrs, pszSrcFile, __LINE__);
645 DosPostEventSem(CompactSem);
646}
647
648/**
649 * Do select actions for single container
650 *
651 */
652
653VOID SpecialSelect2(HWND hwndParent, INT action)
654{
655 PCNRITEM pci;
656 HENUM henum;
657 HWND hwnd;
658 INT numwindows = 0, w, x, z, cmp = 0;
659 struct Cnr *Cnrs = NULL;
660 struct SS *bsres;
661
662 if (!hwndParent)
663 return;
664
665 // Count directory containers, build array of hwnds
666 henum = WinBeginEnumWindows(hwndParent);
667 while ((hwnd = WinGetNextWindow(henum)) != NULLHANDLE) {
668 if (WinWindowFromID(WinWindowFromID(hwnd, FID_CLIENT), DIR_CNR)) {
669 Cnrs =
670 xrealloc(Cnrs, (numwindows + 1) * sizeof(struct Cnr), pszSrcFile,
671 __LINE__);
672 if (!Cnrs) {
673 Notify(GetPString(IDS_OUTOFMEMORY));
674 return;
675 }
676 memset(&Cnrs[numwindows], 0, sizeof(struct Cnr));
677 Cnrs[numwindows].hwndCnr = WinWindowFromID(WinWindowFromID(hwnd,
678 FID_CLIENT),
679 DIR_CNR);
680 numwindows++;
681 }
682 }
683 WinEndEnumWindows(henum);
684 if (numwindows < 2) {
685 FreeCnrs(Cnrs, numwindows);
686 Runtime_Error(pszSrcFile, __LINE__, "expected two windows");
687 Notify(GetPString(IDS_COMPSEL2ORMORETEXT));
688 return;
689 }
690 if (numwindows > 4) {
691 WinSendMsg(Cnrs[0].
692 hwndCnr,
693 UM_NOTIFY, MPFROMP(GetPString(IDS_BUILDINGLISTSTEXT)), MPVOID);
694 DosSleep(0); // Allow other windows to update
695 }
696
697 // Count records, build array of pointers to records
698 for (z = 0; z < numwindows; z++) {
699 pci = (PCNRITEM) WinSendMsg(Cnrs[z].hwndCnr,
700 CM_QUERYRECORD,
701 MPVOID,
702 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
703 x = 0;
704 while (pci && (INT)pci != -1) {
705 if (~pci->rc.flRecordAttr & CRA_FILTERED &&
706 ~pci->attrFile & FILE_DIRECTORY) {
707 Cnrs[z].ss =
708 xrealloc(Cnrs[z].ss, (x + 1) * sizeof(struct SS), pszSrcFile,
709 __LINE__);
710 if (!Cnrs[z].ss) {
711 FreeCnrs(Cnrs, numwindows);
712 Notify(GetPString(IDS_OUTOFMEMORY));
713 return;
714 }
715 memset(&Cnrs[z].ss[x], 0, sizeof(struct SS));
716 Cnrs[z].ss[x].pci = pci;
717 x++;
718 }
719 pci = (PCNRITEM) WinSendMsg(Cnrs[z].hwndCnr,
720 CM_QUERYRECORD,
721 MPFROMP(pci),
722 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
723 }
724 DosSleep(0); // Allow other windows to update
725 Cnrs[z].numfiles = x;
726 if (Cnrs[z].numfiles)
727 qsort(Cnrs[z].ss, Cnrs[z].numfiles, sizeof(struct SS), CompSSNames);
728 }
729
730 for (z = 0; z < numwindows; z++) {
731 for (x = 0; x < Cnrs[z].numfiles; x++) {
732 Cnrs[z].ss[x].all = Cnrs[z].ss[x].unique = Cnrs[z].ss[x].newest =
733 Cnrs[z].ss[x].oldest = Cnrs[z].ss[x].smallest =
734 Cnrs[z].ss[x].largest = TRUE;
735 for (w = 0; w < numwindows; w++) {
736 if (w != z && Cnrs[w].numfiles) {
737 bsres = (struct SS *)bsearch(Cnrs[z].ss[x].pci->pszDisplayName,
738 Cnrs[w].ss, Cnrs[w].numfiles,
739 sizeof(struct SS), CompSSNamesB);
740 if (bsres) {
741 Cnrs[z].ss[x].unique = FALSE;
742 if (Cnrs[z].ss[x].pci->cbFile + Cnrs[z].ss[x].pci->easize >
743 bsres->pci->cbFile + bsres->pci->easize)
744 Cnrs[z].ss[x].smallest = FALSE;
745 if (Cnrs[z].ss[x].pci->cbFile + Cnrs[z].ss[x].pci->easize <
746 bsres->pci->cbFile + bsres->pci->easize)
747 Cnrs[z].ss[x].largest = FALSE;
748 cmp = TestCDates(&bsres->pci->date, &bsres->pci->time,
749 &Cnrs[z].ss[x].pci->date, &Cnrs[z].ss[x].pci->time);
750 if (cmp != 1)
751 Cnrs[z].ss[x].newest = FALSE;
752 if (cmp != -1)
753 Cnrs[z].ss[x].oldest = FALSE;
754 cmp = 0;
755 break;
756 }
757 else
758 Cnrs[z].ss[x].all = FALSE;
759 }
760 }
761 if (Cnrs[z].ss[x].unique)
762 Cnrs[z].ss[x].oldest = Cnrs[z].ss[x].newest = Cnrs[z].ss[x].all =
763 Cnrs[z].ss[x].largest = Cnrs[z].ss[x].smallest = FALSE;
764 DosSleep(1);
765 }
766 DosSleep(1);
767 }
768
769 switch (action) {
770 case IDM_SELECTBOTH:
771 for (z = 0; z < numwindows; z++) {
772 for (x = 0; x < Cnrs[z].numfiles; x++) {
773 if (Cnrs[z].ss[x].all)
774 WinSendMsg(Cnrs[z].hwndCnr, CM_SETRECORDEMPHASIS,
775 MPFROMP(Cnrs[z].ss[x].pci),
776 MPFROM2SHORT(TRUE, CRA_SELECTED));
777 }
778 DosSleep(0); // Allow other windows to update
779 }
780 break;
781 case IDM_SELECTMORE:
782 for (z = 0; z < numwindows; z++) {
783 for (x = 0; x < Cnrs[z].numfiles; x++) {
784 if (!Cnrs[z].ss[x].unique)
785 WinSendMsg(Cnrs[z].hwndCnr, CM_SETRECORDEMPHASIS,
786 MPFROMP(Cnrs[z].ss[x].pci),
787 MPFROM2SHORT(TRUE, CRA_SELECTED));
788 }
789 DosSleep(0); // Allow other windows to update
790 }
791 break;
792 case IDM_SELECTONE:
793 for (z = 0; z < numwindows; z++) {
794 for (x = 0; x < Cnrs[z].numfiles; x++) {
795 if (Cnrs[z].ss[x].unique)
796 WinSendMsg(Cnrs[z].hwndCnr, CM_SETRECORDEMPHASIS,
797 MPFROMP(Cnrs[z].ss[x].pci),
798 MPFROM2SHORT(TRUE, CRA_SELECTED));
799 }
800 DosSleep(0); // Allow other windows to update
801 }
802 break;
803 case IDM_SELECTNEWER:
804 for (z = 0; z < numwindows; z++) {
805 for (x = 0; x < Cnrs[z].numfiles; x++) {
806 if (Cnrs[z].ss[x].newest)
807 WinSendMsg(Cnrs[z].hwndCnr, CM_SETRECORDEMPHASIS,
808 MPFROMP(Cnrs[z].ss[x].pci),
809 MPFROM2SHORT(TRUE, CRA_SELECTED));
810 }
811 DosSleep(0); // Allow other windows to update
812 }
813 break;
814 case IDM_SELECTOLDER:
815 for (z = 0; z < numwindows; z++) {
816 for (x = 0; x < Cnrs[z].numfiles; x++) {
817 if (Cnrs[z].ss[x].oldest)
818 WinSendMsg(Cnrs[z].hwndCnr, CM_SETRECORDEMPHASIS,
819 MPFROMP(Cnrs[z].ss[x].pci),
820 MPFROM2SHORT(TRUE, CRA_SELECTED));
821 }
822 DosSleep(0); // Allow other windows to update
823 }
824 break;
825 case IDM_SELECTBIGGER:
826 for (z = 0; z < numwindows; z++) {
827 for (x = 0; x < Cnrs[z].numfiles; x++) {
828 if (Cnrs[z].ss[x].largest)
829 WinSendMsg(Cnrs[z].hwndCnr, CM_SETRECORDEMPHASIS,
830 MPFROMP(Cnrs[z].ss[x].pci),
831 MPFROM2SHORT(TRUE, CRA_SELECTED));
832 }
833 DosSleep(0); // Allow other windows to update
834 }
835 break;
836 case IDM_SELECTSMALLER:
837 for (z = 0; z < numwindows; z++) {
838 for (x = 0; x < Cnrs[z].numfiles; x++) {
839 if (Cnrs[z].ss[x].smallest)
840 WinSendMsg(Cnrs[z].hwndCnr, CM_SETRECORDEMPHASIS,
841 MPFROMP(Cnrs[z].ss[x].pci),
842 MPFROM2SHORT(TRUE, CRA_SELECTED));
843 }
844 DosSleep(0); // Allow other windows to update
845 }
846 break;
847
848 case IDM_DESELECTBOTH:
849 for (z = 0; z < numwindows; z++) {
850 for (x = 0; x < Cnrs[z].numfiles; x++) {
851 if (Cnrs[z].ss[x].all)
852 WinSendMsg(Cnrs[z].hwndCnr, CM_SETRECORDEMPHASIS,
853 MPFROMP(Cnrs[z].ss[x].pci),
854 MPFROM2SHORT(FALSE, CRA_SELECTED));
855 }
856 DosSleep(0); // Allow other windows to update
857 }
858 break;
859 case IDM_DESELECTMORE:
860 for (z = 0; z < numwindows; z++) {
861 for (x = 0; x < Cnrs[z].numfiles; x++) {
862 if (!Cnrs[z].ss[x].unique)
863 WinSendMsg(Cnrs[z].hwndCnr, CM_SETRECORDEMPHASIS,
864 MPFROMP(Cnrs[z].ss[x].pci),
865 MPFROM2SHORT(FALSE, CRA_SELECTED));
866 }
867 DosSleep(0); // Allow other windows to update
868 }
869 break;
870 case IDM_DESELECTONE:
871 for (z = 0; z < numwindows; z++) {
872 for (x = 0; x < Cnrs[z].numfiles; x++) {
873 if (Cnrs[z].ss[x].unique)
874 WinSendMsg(Cnrs[z].hwndCnr, CM_SETRECORDEMPHASIS,
875 MPFROMP(Cnrs[z].ss[x].pci),
876 MPFROM2SHORT(FALSE, CRA_SELECTED));
877 }
878 DosSleep(0); // Allow other windows to update
879 }
880 break;
881 case IDM_DESELECTNEWER:
882 for (z = 0; z < numwindows; z++) {
883 for (x = 0; x < Cnrs[z].numfiles; x++) {
884 if (Cnrs[z].ss[x].newest)
885 WinSendMsg(Cnrs[z].hwndCnr, CM_SETRECORDEMPHASIS,
886 MPFROMP(Cnrs[z].ss[x].pci),
887 MPFROM2SHORT(FALSE, CRA_SELECTED));
888 }
889 DosSleep(0); // Allow other windows to update
890 }
891 break;
892 case IDM_DESELECTOLDER:
893 for (z = 0; z < numwindows; z++) {
894 for (x = 0; x < Cnrs[z].numfiles; x++) {
895 if (Cnrs[z].ss[x].oldest)
896 WinSendMsg(Cnrs[z].hwndCnr, CM_SETRECORDEMPHASIS,
897 MPFROMP(Cnrs[z].ss[x].pci),
898 MPFROM2SHORT(FALSE, CRA_SELECTED));
899 }
900 DosSleep(0); // Allow other windows to update
901 }
902 break;
903 case IDM_DESELECTBIGGER:
904 for (z = 0; z < numwindows; z++) {
905 for (x = 0; x < Cnrs[z].numfiles; x++) {
906 if (Cnrs[z].ss[x].largest)
907 WinSendMsg(Cnrs[z].hwndCnr, CM_SETRECORDEMPHASIS,
908 MPFROMP(Cnrs[z].ss[x].pci),
909 MPFROM2SHORT(FALSE, CRA_SELECTED));
910 }
911 DosSleep(0); // Allow other windows to update
912 }
913 break;
914 case IDM_DESELECTSMALLER:
915 for (z = 0; z < numwindows; z++) {
916 for (x = 0; x < Cnrs[z].numfiles; x++) {
917 if (Cnrs[z].ss[x].smallest)
918 WinSendMsg(Cnrs[z].hwndCnr, CM_SETRECORDEMPHASIS,
919 MPFROMP(Cnrs[z].ss[x].pci),
920 MPFROM2SHORT(FALSE, CRA_SELECTED));
921 }
922 DosSleep(0); // Allow other windows to update
923 }
924 break;
925 }
926
927 FreeCnrs(Cnrs, numwindows);
928}
929
930#pragma alloc_text(SELECT,UnHilite,SelectAll,DeselectAll,MarkAll,SetMask)
931#pragma alloc_text(SELECT,SelectList)
932#pragma alloc_text(SELECT1,Deselect,HideAll,RemoveAll,ExpandAll,InvertAll)
933#pragma alloc_text(SELECT4,FreeCnrs,SpecialSelect2,CompSSNames,CompSSNamesB)
Note: See TracBrowser for help on using the repository browser.