source: trunk/dll/select.c@ 1812

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

Fixed compare selection replaced pszFileNames with pszDisplayNames Ticket [550]

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