source: trunk/dll/select.c@ 1890

Last change on this file since 1890 was 1890, checked in by Steven Levine, 6 years ago

Add PMPRINTF enable support to makefiles.
Correct PMPRINTF debug macro enables in sources.

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