source: trunk/dll/select.c@ 1873

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

Adjustments to ShowTreeRec to eliminate failures and reduce retries and container noise on tree switches. Remove fInitialDriveScan code. Changes to speed up ExpandAll. WaitFleshWorkListEmpty now gives error message and returns if semaphore request fails more than 5 consecutive times.

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