source: trunk/dll/select.c@ 1883

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

Comments for CS [1882]

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