source: trunk/dll/makelist.c@ 1570

Last change on this file since 1570 was 1570, checked in by Gregg Young, 14 years ago

Added IdleIfNeeded to place load and free loops to idle priority when dealing with large numbers of items. Used SleepIfNeeded more places for a similar purpose.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.1 KB
Line 
1
2/***********************************************************************
3
4 $Id: makelist.c 1570 2011-06-12 22:09:19Z gyoung $
5
6 Make file lists
7
8 Copyright (c) 1993-98 M. Kimes
9 Copyright (c) 2003, 2008 Steven H.Levine
10
11 12 Feb 03 SHL AddToFileList: standardize EA math
12 22 Jul 06 SHL Use Runtime_Error
13 22 Jul 06 SHL AddToList optimize
14 06 Apr 07 GKY Work around PM DragInfo and DrgFreeDISH limits
15 20 Aug 07 GKY Move #pragma alloc_text to end for OpenWatcom compat
16 29 Feb 08 GKY Use xfree where appropriate
17 17 Jul 08 SHL Add SetListOwner for Fortify support
18 12 Jun 11 GKY Added IdleIfNeeded to the freelist loop to improve system
19 responsiveness when freeing lists with large numbers of items
20
21***********************************************************************/
22
23#include <stdlib.h>
24#include <string.h>
25
26#define INCL_DOS
27#define INCL_WIN
28#define INCL_LONGLONG
29
30#include "fm3dll.h" // 05 Jan 08 SHL fixme to be gone
31#include "fm3str.h"
32#include "makelist.h"
33#include "errutil.h" // Dos_Error...
34#include "strutil.h" // GetPString
35#include "dircnrs.h"
36#include "misc.h" // CurrentRecord
37#include "newview.h" // Data declarations
38#include "wrappers.h" // xfree
39#include "fortify.h" // 06 May 08 SHL
40#include "tmrsvcs.h" // ITIMER_DESC
41
42static PSZ pszSrcFile = __FILE__;
43
44VOID SortList(LISTINFO *li)
45{
46 /* bubble-sort entries by size, descending */
47
48 UINT x;
49 CHAR *s;
50 ULONG l;
51 BOOL swapped;
52
53 if (li && li->list && li->list[0] && li->cbFile) {
54 do {
55 swapped = FALSE;
56 for (x = 0; li->list[x] && li->list[x + 1]; x++) {
57 if (li->cbFile[x] < li->cbFile[x + 1]) {
58 s = li->list[x];
59 li->list[x] = li->list[x + 1];
60 li->list[x + 1] = s;
61 l = li->cbFile[x];
62 li->cbFile[x] = li->cbFile[x + 1];
63 li->cbFile[x + 1] = l;
64 if (li->ulitemID) {
65 l = li->ulitemID[x];
66 li->ulitemID[x] = li->ulitemID[x + 1];
67 li->ulitemID[x + 1] = l;
68 }
69 swapped = TRUE;
70 }
71 }
72 } while (swapped);
73 }
74}
75
76VOID FreeListInfo(LISTINFO *li)
77{
78 if (li) {
79 xfree(li->ulitemID, pszSrcFile, __LINE__);
80 xfree(li->cbFile, pszSrcFile, __LINE__);
81 if (li->list)
82 FreeList(li->list);
83 free(li);
84 }
85}
86
87VOID FreeList(CHAR **list)
88{
89 UINT x;
90 ITIMER_DESC itdSleep = { 0 };
91
92 if (list) {
93 InitITimer(&itdSleep, 500);
94 for (x = 0; list[x]; x++) {
95#ifdef __DEBUG_ALLOC__
96 _heap_check();
97#endif
98 free(list[x]);
99 if (!IdleIfNeeded(&itdSleep, 30)) {
100 for (x = x + 1; list[x]; x++) {
101 free(list[x]);
102 }
103 break;
104 }
105 }
106#ifdef __DEBUG_ALLOC__
107 _heap_check();
108#endif
109 free(list);
110 priority_normal();
111 DosPostEventSem(CompactSem);
112 }
113}
114
115INT AddToFileList(CHAR *string, FILEFINDBUF4L *ffb4, FILELIST ***list,
116 UINT *pnumfiles, UINT *pnumalloced)
117{
118 FILELIST *pfl;
119
120 if (string && ffb4) {
121 // Ensure room for NULL entry
122 if (((*pnumfiles) + 3) > *pnumalloced) {
123 FILELIST **pflArray;
124
125 // Use plain realloc for speed
126 // 06 Aug 07 SHL fixme to know why + 6
127# ifdef FORTIFY
128 Fortify_EnterScope();
129# endif
130 pflArray = realloc(*list, (*pnumalloced + 6) * sizeof(FILELIST *));
131 if (!pflArray) {
132 Runtime_Error(pszSrcFile, __LINE__, GetPString(IDS_OUTOFMEMORY));
133 return 1;
134 }
135 (*pnumalloced) += 6;
136 *list = pflArray;
137 }
138 // Use plain malloc for speed
139 pfl = malloc(sizeof(FILELIST) + strlen(string));
140 if (!pfl) {
141 Runtime_Error(pszSrcFile, __LINE__, GetPString(IDS_OUTOFMEMORY));
142 return 2;
143 }
144 pfl->attrFile = ffb4->attrFile;
145 pfl->date = ffb4->fdateLastWrite;
146 pfl->time = ffb4->ftimeLastWrite;
147 pfl->ladate = ffb4->fdateLastAccess;
148 pfl->latime = ffb4->ftimeLastAccess;
149 pfl->crdate = ffb4->fdateCreation;
150 pfl->crtime = ffb4->ftimeCreation;
151 pfl->cbFile = ffb4->cbFile;
152 pfl->easize = CBLIST_TO_EASIZE(ffb4->cbList);
153 strcpy(pfl->fname, string);
154 (*list)[*pnumfiles] = pfl;
155 (*pnumfiles)++;
156 // Ensure list always ends with two NULL entries
157 // 06 Aug 07 SHL fixme to know why
158 (*list)[*pnumfiles] = NULL;
159 (*list)[(*pnumfiles) + 1] = NULL;
160#ifdef __DEBUG_ALLOC__
161 _heap_check();
162#endif
163 }
164 return 0;
165}
166
167/**
168 * Add string to string list
169 * Enlarges as needed
170 * Ensures 2 NULL end markers exist
171 */
172
173INT AddToList(CHAR *string, CHAR ***list, UINT *pnumfiles, UINT *pnumalloced)
174{
175 CHAR **ppsz;
176 PSZ psz;
177
178 if (string) {
179 if (((*pnumfiles) + 3) > *pnumalloced) {
180 // Use plain realloc for speed
181# ifdef FORTIFY
182 Fortify_EnterScope();
183# endif
184 ppsz = realloc(*list, (*pnumalloced + 6) * sizeof(CHAR *));
185 if (!ppsz) {
186 Runtime_Error(pszSrcFile, __LINE__, "realloc");
187 return 1;
188 }
189 (*pnumalloced) += 6;
190 *list = ppsz;
191 }
192 // Use plain malloc for speed
193 psz = malloc(strlen(string) + 1);
194 if (!psz) {
195 Runtime_Error(pszSrcFile, __LINE__, GetPString(IDS_OUTOFMEMORY));
196 return 2;
197 }
198 (*list)[*pnumfiles] = psz;
199 strcpy((*list)[*pnumfiles], string); // Add entry
200 (*pnumfiles)++;
201 (*list)[*pnumfiles] = NULL; // Add end marker
202 (*list)[(*pnumfiles) + 1] = NULL; // Add 2nd end marker - fixme to know why?
203#ifdef __DEBUG_ALLOC__
204 _heap_check();
205#endif
206 }
207 return 0;
208}
209
210CHAR **BuildList(HWND hwndCnr)
211{
212 PCNRITEM pci;
213 CHAR **list = NULL, **test;
214 UINT numfiles = 0, numalloc = 0;
215 INT error = 0, attribute = CRA_CURSORED;
216
217 pci = (PCNRITEM) CurrentRecord(hwndCnr);
218 if (pci && (INT) pci != -1 && !(pci->flags & RECFLAGS_ENV)) {
219 if (pci->rc.flRecordAttr & CRA_SELECTED) {
220 attribute = CRA_SELECTED;
221 pci = WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS, MPFROMLONG(CMA_FIRST),
222 MPFROMSHORT(attribute));
223 }
224 }
225 while (pci && (INT) pci != -1 && !error) {
226 if (!(pci->rc.flRecordAttr & CRA_FILTERED))
227 error = AddToList(pci->pszFileName, &list, &numfiles, &numalloc);
228 pci = WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS, MPFROMP(pci),
229 MPFROMSHORT(attribute));
230 }
231 if (numalloc > numfiles + 1) {
232 // Use plain realloc for speed
233
234# ifdef FORTIFY
235 Fortify_EnterScope();
236# endif
237 test = realloc(list, sizeof(CHAR *) * (numfiles + 1));
238 if (!test)
239 Runtime_Error(pszSrcFile, __LINE__, GetPString(IDS_OUTOFMEMORY));
240 else
241 list = test;
242 } // while
243 return list;
244}
245
246CHAR **BuildArcList(HWND hwndCnr)
247{
248 PARCITEM pai;
249 CHAR **list = NULL;
250 UINT numfiles = 0, numalloc = 0;
251 INT error = 0, attribute = CRA_CURSORED;
252
253 pai = (PARCITEM) CurrentRecord(hwndCnr);
254 if (pai && (INT) pai != -1) {
255 if (pai->rc.flRecordAttr & CRA_SELECTED) {
256 attribute = CRA_SELECTED;
257 pai = WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS, MPFROMLONG(CMA_FIRST),
258 MPFROMSHORT(attribute));
259 }
260 }
261 while (pai && (INT) pai != -1 && !error) {
262 if (!(pai->rc.flRecordAttr & CRA_FILTERED))
263 error = AddToList(pai->pszFileName, &list, &numfiles, &numalloc);
264 pai = WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS, MPFROMP(pai),
265 MPFROMSHORT(attribute));
266 }
267 return list;
268}
269
270CHAR **RemoveFromList(CHAR **list, CHAR *item)
271{
272 UINT x, y;
273
274 if (list && list[0] && item) {
275 for (x = 0; list[x]; x++) {
276 if (item == list[x]) {
277 free(list[x]);
278 list[x] = NULL;
279 for (y = x;; y++) {
280 if (y != x && !list[y])
281 break;
282 list[y] = list[y + 1];
283 }
284 if (!list[0]) {
285 FreeList(list);
286 list = NULL;
287 }
288# ifdef FORTIFY
289 Fortify_LeaveScope();
290# endif
291 break;
292 }
293 }
294 }
295 return list;
296}
297
298CHAR **CombineLists(CHAR **prime, CHAR **add)
299{
300 UINT x;
301 UINT numalloc, numfiles = 0;
302
303 if (add && add[0]) {
304 if (prime) {
305 for (x = 0; prime[x]; x++)
306 numfiles++;
307 }
308 numalloc = numfiles;
309 for (x = 0; add[x]; x++) {
310 if (*add[x])
311 AddToList(add[x], &prime, &numfiles, &numalloc);
312 }
313 FreeList(add);
314 }
315 return prime;
316}
317
318#ifdef FORTIFY
319
320VOID SetListOwner(LISTINFO *li)
321{
322 if (li) {
323 CHAR **list = li->list;
324 if (list) {
325 UINT x;
326 for (x = 0; list[x]; x++)
327 Fortify_BecomeOwner(list[x]);
328 }
329 Fortify_BecomeOwner(li);
330 }
331}
332
333#endif // FORTIFY
334
335#pragma alloc_text(MAKELIST,AddToList,AddToFileList,BuildList,FreeListInfo,FreeList)
336#pragma alloc_text(MAKELIST,SortList,BuildArcList,RemoveFromList,CombineLists)
337#ifdef FORTIFY
338#pragma alloc_text(MAKELIST,SetListOwner)
339#endif // FORTIFY
Note: See TracBrowser for help on using the repository browser.