source: trunk/dll/dirsize.c@ 783

Last change on this file since 783 was 783, checked in by Steven Levine, 18 years ago

Rework DosFindFirst/Next loops to optimize memory allocation and code paths
Adjust FilesToGet limits
Update configuration notebook scanning page
Start updating #pragma alloc_text positioning for OpenWatcom compatibility

  • 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: dirsize.c 783 2007-08-14 04:09:54Z stevenhl $
5
6 Directory sizes
7
8 Copyright (c) 1993-98 M. Kimes
9 Copyright (c) 2001, 2007 Steven H. Levine
10
11 16 Oct 02 SHL Handle large partitions
12 12 Feb 03 SHL Use CBLIST_TO_EASIZE
13 21 Nov 03 SHL Avoid VAC \ after // bug (wierd)
14 21 Nov 03 SHL Correct minor typos
15 21 Nov 03 SHL Total drives >4GB better
16 24 May 05 SHL Rework for CNRITEM.szSubject
17 25 May 05 SHL Use ULONGLONG and CommaFmtULL
18 26 May 05 SHL More large file formatting updates
19 06 Jun 05 SHL Drop obsoletes
20 19 Jun 05 SHL More 64-bit math fixes
21 08 Aug 05 SHL Avoid Expand/Collapse hangs while working
22 17 Jul 06 SHL Use Runtime_Error
23 19 Oct 06 SHL Correct . and .. detect
24 18 Feb 07 GKY Add new drive type icons
25 22 Mar 07 GKY Use QWL_USER
26 23 Jul 07 SHL Sync with naming standards
27 03 Aug 07 GKY Enlarged and made setable everywhere Findbuf (speed file loading)
28 03 Aug 07 SHL DirSizeProc; correct sizing and positioning to be deterministic
29 06 Aug 07 GKY Reduce DosSleep times (ticket 148)
30 13 Aug 07 SHL ProcessDir: remove unneeded reallocs. Sanitize code
31 13 Aug 07 SHL Move #pragma alloc_text to end for OpenWatcom compat
32
33***********************************************************************/
34
35#define INCL_DOS
36#define INCL_WIN
37#define INCL_GPI
38#define INCL_LONGLONG
39#define INCL_DOSERRORS
40#include <os2.h>
41
42#include <stdio.h>
43#include <stdlib.h>
44#include <string.h>
45#include <ctype.h>
46#include <process.h> // _beginthread
47
48#include "fm3dll.h"
49#include "fm3dlg.h"
50#include "fm3str.h"
51
52typedef struct
53{
54 CHAR *pszFileName;
55 HWND hwndCnr;
56 CHAR *pchStopFlag;
57 DIRCNRDATA *pDCD;
58} DIRSIZE;
59
60typedef struct
61{
62 CHAR szDirName[CCHMAXPATH];
63 CHAR chStopFlag;
64 BOOL dying;
65 BOOL working;
66 HPOINTER hptr;
67} tState;
68
69static PSZ pszSrcFile = __FILE__;
70
71static SHORT APIENTRY SortSizeCnr(PMINIRECORDCORE p1,
72 PMINIRECORDCORE p2,
73 PVOID SortFlags)
74{
75 ULONGLONG size1;
76 ULONGLONG size2;
77
78 size1 = ((PCNRITEM) p1)->cbFile + ((PCNRITEM) p1)->easize;
79 size2 = ((PCNRITEM) p2)->cbFile + ((PCNRITEM) p2)->easize;
80 return (size1 < size2) ? 1 : (size1 == size2) ? 0 : -1;
81}
82
83static BOOL ProcessDir(HWND hwndCnr,
84 CHAR *pszFileName,
85 PCNRITEM pciParent,
86 CHAR *pchStopFlag,
87 BOOL top,
88 PULONGLONG pullTotalBytes)
89{
90 CHAR maskstr[CCHMAXPATH];
91 CHAR szBuf[CCHMAXPATH];
92 CHAR *pEndMask;
93 register char *p;
94 register char *sp;
95 register char *pp;
96 ULONG ulFindCnt;
97 ULONGLONG ullCurDirBytes = 0;
98 ULONGLONG ullSubDirBytes = 0;
99 ULONGLONG ull;
100 HDIR hdir;
101 PFILEFINDBUF4 pffbArray;
102 APIRET rc;
103 RECORDINSERT ri;
104 PCNRITEM pci;
105 ULONG ulBufBytes;
106
107 *pullTotalBytes = 0; // In case we fail
108
109 ulBufBytes = sizeof(FILEFINDBUF4) * FilesToGet;
110 pffbArray = xmalloc(ulBufBytes, pszSrcFile, __LINE__);
111 if (!pffbArray)
112 return FALSE; // Error already reported
113
114 strcpy(maskstr, pszFileName);
115 if (maskstr[strlen(maskstr) - 1] != '\\')
116 strcat(maskstr, "\\");
117 pEndMask = &maskstr[strlen(maskstr)]; // Point after last backslash
118 strcat(maskstr, "*");
119
120 hdir = HDIR_CREATE;
121 ulFindCnt = 1;
122 // memset(pffbArray, 0, sizeof(FILEFINDBUF4)); // 11 Aug 07 SHL bypass memset
123 DosError(FERR_DISABLEHARDERR);
124 // Check directory exists
125 rc = DosFindFirst(pszFileName, &hdir,
126 FILE_NORMAL | FILE_READONLY | FILE_ARCHIVED |
127 FILE_SYSTEM | FILE_HIDDEN | MUST_HAVE_DIRECTORY,
128 pffbArray, ulBufBytes, &ulFindCnt, FIL_QUERYEASIZE);
129
130 if (!rc)
131 DosFindClose(hdir);
132
133 /*
134 * the "|| strlen(pszFileName) < 4 below works around an OS/2 bug
135 * that prevents FAT root directories from being found when
136 * requesting EASIZE. sheesh.
137 */
138 if ((!rc && (pffbArray->attrFile & FILE_DIRECTORY)) || strlen(pszFileName) < 4) {
139 if (*pchStopFlag) {
140 free(pffbArray);
141 return FALSE;
142 }
143 pci = WinSendMsg(hwndCnr, CM_ALLOCRECORD, MPFROMLONG(EXTRA_RECORD_BYTES),
144 MPFROMLONG(1));
145 if (!pci) {
146 Win_Error(hwndCnr, HWND_DESKTOP, pszSrcFile, __LINE__, "CM_ALLOCRECORD");
147 free(pffbArray);
148 return FALSE;
149 }
150 if (!rc) {
151 ullCurDirBytes = pffbArray->cbFile;
152 ullCurDirBytes += CBLIST_TO_EASIZE(pffbArray->cbList);
153 }
154 else
155 DosError(FERR_DISABLEHARDERR);
156 pci->rc.hptrIcon = hptrDir;
157 pci->attrFile = 0;
158 pci->pszDispAttr = NullStr;
159 pci->pszSubject = NullStr;
160 } // if got something
161 else {
162 // No match
163 free(pffbArray);
164 Dos_Error(MB_ENTER, rc, HWND_DESKTOP, pszSrcFile, __LINE__,
165 GetPString(IDS_CANTFINDDIRTEXT), pszFileName);
166 return FALSE;
167 }
168
169 if (strlen(pszFileName) < 4 || top)
170 pci->pszFileName = xstrdup(pszFileName, pszSrcFile, __LINE__);
171 else {
172 p = strrchr(pszFileName, '\\');
173 if (!p)
174 p = pszFileName;
175 else
176 p++; // After last backslash
177 // Handle quoted names
178 // fixme to understand this - why lose path prefix?
179 sp = strchr(pszFileName, ' ') != NULL ? "\"" : NullStr;
180 pp = szBuf;
181 if (*sp)
182 *pp++ = *sp; // Need quotes
183 strcpy(pp, p);
184 if (*sp)
185 strcat(pp, sp);
186 pci->pszFileName = xstrdup(szBuf, pszSrcFile, __LINE__);
187 }
188 // fixme to understand this - appears to be indirectly saving length, but why?
189 pci->pszDisplayName = pci->pszFileName + strlen(pci->pszFileName);
190 pci->pszLongName = pci->pszFileName; // fixme to be sure?
191 pci->rc.pszIcon = pci->pszFileName;
192 pci->rc.flRecordAttr |= CRA_RECORDREADONLY;
193 if (fForceUpper)
194 strupr(pci->pszFileName);
195 else if (fForceLower)
196 strlwr(pci->pszFileName);
197 pci->pszDisplayName = pci->pszFileName + strlen(pci->pszFileName);
198 memset(&ri, 0, sizeof(RECORDINSERT));
199 ri.cb = sizeof(RECORDINSERT);
200 ri.pRecordOrder = (PRECORDCORE) CMA_END;
201 ri.pRecordParent = (PRECORDCORE) pciParent;
202 ri.zOrder = (USHORT) CMA_TOP;
203 ri.cRecordsInsert = 1;
204 ri.fInvalidateRecord = TRUE;
205 if (!WinSendMsg(hwndCnr, CM_INSERTRECORD, MPFROMP(pci), MPFROMP(&ri))) {
206 free(pffbArray);
207 return FALSE;
208 }
209
210 // Find files and directories in this directory
211 hdir = HDIR_CREATE;
212 // 13 Aug 07 SHL fixme to know if need to support fRemoteBug here like objcnr.c?
213 ulFindCnt = FilesToGet;
214 rc = DosFindFirst(maskstr, &hdir,
215 FILE_NORMAL | FILE_READONLY | FILE_ARCHIVED |
216 FILE_SYSTEM | FILE_HIDDEN | FILE_DIRECTORY,
217 pffbArray, ulBufBytes, &ulFindCnt, FIL_QUERYEASIZE);
218 if (!rc) {
219 PFILEFINDBUF4 pffbFile;
220 ULONG x;
221
222 while (!rc) {
223
224#if 0 // 13 Aug 07 SHL fixme to be gone
225 {
226 static ULONG ulMaxCnt = 1;
227 if (ulFindCnt > ulMaxCnt) {
228 ulMaxCnt = ulFindCnt;
229 DbgMsg(pszSrcFile, __LINE__, "ulMaxCnt %u/%u", ulMaxCnt, FilesToGet);
230 }
231 }
232#endif
233
234 priority_normal();
235 pffbFile = pffbArray;
236 for (x = 0; x < ulFindCnt; x++) {
237 // Total size skipping . and ..
238 if ((~pffbFile->attrFile & FILE_DIRECTORY) ||
239 (pffbFile->achName[0] != '.' ||
240 (pffbFile->achName[1] &&
241 (pffbFile->achName[1] != '.' || pffbFile->achName[2])))) {
242 ullCurDirBytes += pffbFile->cbFile;
243 ullCurDirBytes += CBLIST_TO_EASIZE(pffbFile->cbList) & 0x3ff;
244
245 if (*pchStopFlag)
246 break;
247 if (~pffbFile->attrFile & FILE_DIRECTORY)
248 pci->attrFile++; // Bump file count
249 else {
250 // Recurse into subdir
251 strcpy(pEndMask, pffbFile->achName); // Append dirname to base dirname
252 ProcessDir(hwndCnr, maskstr, pci, pchStopFlag, FALSE, &ull);
253 ullSubDirBytes += ull;
254 }
255 }
256 if (!pffbFile->oNextEntryOffset)
257 break;
258 pffbFile = (PFILEFINDBUF4)((PBYTE)pffbFile + pffbFile->oNextEntryOffset);
259
260#if 0 // 13 Aug 07 SHL fixme to be gone
261 {
262 static ULONG ulMaxBytes = 65535;
263 ULONG ul = (PBYTE)pffbFile - (PBYTE)pffbArray;
264 if (ul > ulMaxBytes) {
265 ulMaxBytes = ul;
266 DbgMsg(pszSrcFile, __LINE__, "ulFindCnt %u/%u ulMaxBytes %u/%u",
267 ulFindCnt, FilesToGet, ulMaxBytes, ulBufBytes);
268 }
269 }
270#endif
271
272 } // for matches
273 if (*pchStopFlag)
274 break;
275 DosSleep(0);
276 ulFindCnt = FilesToGet;
277 DosError(FERR_DISABLEHARDERR);
278 rc = DosFindNext(hdir, pffbArray, ulBufBytes, &ulFindCnt);
279 } // while more found
280
281 DosFindClose(hdir);
282 priority_normal();
283 } // if got files or directories
284
285 if (rc && rc != ERROR_NO_MORE_FILES) {
286 Dos_Error(MB_ENTER, rc, HWND_DESKTOP, pszSrcFile, __LINE__,
287 GetPString(IDS_CANTFINDDIRTEXT), pszFileName);
288 }
289
290 free(pffbArray);
291
292 pci->cbFile = ullCurDirBytes;
293 pci->easize = ullSubDirBytes; // hack cough
294 WinSendMsg(hwndCnr, CM_INVALIDATERECORD, MPFROMP(&pci),
295 MPFROM2SHORT(1, CMA_ERASE | CMA_TEXTCHANGED));
296
297 *pullTotalBytes = ullCurDirBytes + ullSubDirBytes;
298 return TRUE;
299}
300
301static VOID FillInRecSizes(HWND hwndCnr, PCNRITEM pciParent,
302 ULONGLONG ullTotalBytes, CHAR * pchStopFlag,
303 BOOL isroot)
304{
305 PCNRITEM pci = pciParent;
306 SHORT attrib = CMA_FIRSTCHILD;
307
308 if (pci) {
309
310 float fltPct = 0.0;
311 USHORT c;
312 CHAR szCurDir[80];
313 CHAR szSubDir[80];
314 CHAR szAllDir[80];
315 CHAR szBar[80];
316
317 // cbFile = currect directory usage in bytes
318 // easize = subdirectory usage in bytes
319 CommaFmtULL(szCurDir, sizeof(szCurDir), pci->cbFile, 'K');
320 *szBar = 0;
321
322 if (ullTotalBytes) {
323 register UINT cBar;
324
325 if (isroot) {
326 FSALLOCATE fsa;
327 APIRET rc;
328
329 memset(&fsa, 0, sizeof(fsa));
330 rc = DosQueryFSInfo(toupper(*pci->pszFileName) - '@', FSIL_ALLOC, &fsa,
331 sizeof(FSALLOCATE));
332 if (!rc) {
333 fltPct = (ullTotalBytes * 100.0) /
334 ((float)fsa.cUnit * (fsa.cSectorUnit * fsa.cbSector));
335 }
336 // Need unique buffer 23 Jul 07 SHL
337 pci->pszLongName = xmalloc(2, pszSrcFile, __LINE__);
338 pci->pszLongName[0] = 0; // Make null string
339 pci->pszLongName[1] = 1; // Flag root - hack cough
340 }
341 else
342 fltPct = (((float)pci->cbFile + pci->easize) * 100.0) / ullTotalBytes;
343
344 cBar = (UINT) fltPct / 2;
345 if (cBar)
346 memset(szBar, '#', cBar);
347 if (cBar * 2 != (UINT) fltPct) {
348 szBar[cBar] = '=';
349 cBar++;
350 }
351 if (cBar < 50)
352 memset(szBar + cBar, ' ', 50 - cBar);
353 szBar[50] = 0;
354 }
355
356 pci->flags = (ULONG) fltPct;
357 CommaFmtULL(szSubDir, sizeof(szSubDir), pci->easize, 'K');
358 CommaFmtULL(szAllDir, sizeof(szAllDir), pci->cbFile + pci->easize, 'K');
359 c = pci->pszDisplayName - pci->pszFileName;
360 pci->pszFileName = xrealloc(pci->pszFileName,
361 CCHMAXPATH,
362 pszSrcFile,
363 __LINE__); // 23 Jul 07 SHL
364 sprintf(pci->pszFileName + c,
365 " %s + %s = %s (%.02lf%%%s)\r%s",
366 szCurDir,
367 szSubDir,
368 szAllDir,
369 fltPct,
370 isroot ? GetPString(IDS_OFDRIVETEXT) : NullStr,
371 szBar);
372 pci->pszFileName = xrealloc(pci->pszFileName,
373 strlen(pci->pszFileName) + 1,
374 pszSrcFile,
375 __LINE__); // 23 Jul 07 SHL
376 pci->pszDisplayName = pci->pszFileName + c;
377 WinSendMsg(hwndCnr,
378 CM_INVALIDATERECORD, MPFROMP(&pci), MPFROM2SHORT(1, 0));
379 isroot = FALSE;
380 }
381 else
382 attrib = CMA_FIRST;
383 pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(pci),
384 MPFROM2SHORT(attrib, CMA_ITEMORDER));
385 while (pci && (INT) pci != -1) {
386 if (*pchStopFlag)
387 break;
388 FillInRecSizes(hwndCnr, pci, ullTotalBytes, pchStopFlag, isroot);
389 isroot = FALSE;
390 pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(pci),
391 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
392 }
393}
394
395static VOID PrintToFile(HWND hwndCnr, ULONG indent, PCNRITEM pciParent,
396 FILE * fp)
397{
398 PCNRITEM pci;
399 CHAR *p;
400
401 if (!pciParent) {
402 pciParent = WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(NULL),
403 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
404 indent = 0;
405 }
406 if (pciParent) {
407 p = strchr(pciParent->pszFileName, '\r');
408 if (p)
409 *p = 0;
410 fprintf(fp, "%*.*s%s %lu %s%s\n",
411 indent * 2, indent * 2, " ",
412 pciParent->pszFileName,
413 pciParent->attrFile,
414 GetPString(IDS_FILETEXT), &"s"[pciParent->attrFile == 1]);
415 if (p)
416 *p = '\r';
417 if (pciParent->rc.flRecordAttr & CRA_EXPANDED) {
418 pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(pciParent),
419 MPFROM2SHORT(CMA_FIRSTCHILD,
420 CMA_ITEMORDER));
421 while (pci && (INT) pci != -1) {
422 DosSleep(1);
423 PrintToFile(hwndCnr, indent + 1, pci, fp);
424 pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(pci),
425 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
426 }
427 }
428 }
429}
430
431static VOID FillCnrThread(VOID *args)
432{
433 HAB hab;
434 HMQ hmq;
435 DIRSIZE *dirsize = (DIRSIZE *)args;
436 HWND hwndCnr;
437 ULONGLONG ull;
438
439 if (!dirsize) {
440 Runtime_Error(pszSrcFile, __LINE__, "no data");
441 return;
442 }
443
444 hwndCnr = dirsize->hwndCnr;
445
446 DosError(FERR_DISABLEHARDERR);
447
448 // priority_normal();
449 hab = WinInitialize(0);
450 if (hab) {
451 hmq = WinCreateMsgQueue(hab, 0);
452 if (hmq) {
453 WinCancelShutdown(hmq, TRUE);
454 ProcessDir(hwndCnr, dirsize->pszFileName,
455 (PCNRITEM) NULL, dirsize->pchStopFlag, TRUE, &ull);
456 DosPostEventSem(CompactSem);
457 WinEnableWindowUpdate(hwndCnr, FALSE);
458 FillInRecSizes(hwndCnr, NULL, ull, dirsize->pchStopFlag, TRUE);
459 WinEnableWindowUpdate(hwndCnr, TRUE);
460 WinSendMsg(hwndCnr, CM_INVALIDATERECORD, MPVOID,
461 MPFROM2SHORT(0, CMA_ERASE | CMA_TEXTCHANGED));
462 WinDestroyMsgQueue(hmq);
463 }
464 WinTerminate(hab);
465 }
466 PostMsg(WinQueryWindow(hwndCnr, QW_PARENT),
467 UM_CONTAINER_FILLED, MPVOID, MPVOID);
468 free(dirsize);
469}
470
471MRESULT EXPENTRY DirSizeProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
472{
473 tState *pState;
474 PCNRITEM pci;
475 CHAR szBytes[44];
476 CHAR sz[66];
477
478 switch (msg) {
479 case WM_INITDLG:
480 if (!mp2) {
481 WinDismissDlg(hwnd, 0);
482 break;
483 }
484 pState = xmallocz(sizeof(tState), pszSrcFile, __LINE__);
485 if (!pState) {
486 WinDismissDlg(hwnd, 0);
487 break;
488 }
489 strcpy(pState->szDirName, (CHAR *) mp2);
490 WinSetWindowPtr(hwnd, QWL_USER, (PVOID) pState);
491 pState->hptr = WinLoadPointer(HWND_DESKTOP, FM3ModHandle, DIRSIZE_ICON);
492 WinDefDlgProc(hwnd, WM_SETICON, MPFROMLONG(pState->hptr), MPVOID);
493 {
494 CHAR s[CCHMAXPATH + 81];
495
496 sprintf(s, GetPString(IDS_DIRSIZETITLETEXT), pState->szDirName);
497 WinSetWindowText(hwnd, s);
498 }
499 {
500 DIRSIZE *dirsize;
501
502 dirsize = xmalloc(sizeof(DIRSIZE), pszSrcFile, __LINE__);
503 if (!dirsize) {
504 WinDismissDlg(hwnd, 0);
505 break;
506 }
507 dirsize->pchStopFlag = (CHAR *)&pState->chStopFlag;
508 dirsize->pszFileName = pState->szDirName;
509 dirsize->hwndCnr = WinWindowFromID(hwnd, DSZ_CNR);
510 if (_beginthread(FillCnrThread, NULL, 122880L * 5, (PVOID)dirsize) ==
511 -1) {
512 Runtime_Error(pszSrcFile, __LINE__,
513 GetPString(IDS_COULDNTSTARTTHREADTEXT));
514 free(dirsize);
515 WinDismissDlg(hwnd, 0);
516 break;
517 }
518 pState->working = TRUE;
519 WinEnableWindow(WinWindowFromID(hwnd, DSZ_COLLAPSE), FALSE);
520 WinEnableWindow(WinWindowFromID(hwnd, DSZ_EXPAND), FALSE);
521 WinEnableWindow(WinWindowFromID(hwnd, DSZ_PRINT), FALSE);
522 }
523 PostMsg(hwnd, UM_SETUP, MPVOID, MPVOID);
524 break;
525
526 case UM_SETUP:
527 {
528 CNRINFO cnri;
529 FSALLOCATE fsa;
530 APIRET rc;
531
532 memset(&cnri, 0, sizeof(CNRINFO));
533 cnri.cb = sizeof(CNRINFO);
534 WinSendDlgItemMsg(hwnd, DSZ_CNR, CM_QUERYCNRINFO,
535 MPFROMP(&cnri), MPFROMLONG(sizeof(CNRINFO)));
536 cnri.cyLineSpacing = 0;
537 cnri.cxTreeIndent = 12;
538 cnri.flWindowAttr = CV_TREE | CV_FLOW | CA_TREELINE | CA_OWNERDRAW;
539 WinSendDlgItemMsg(hwnd, DSZ_CNR, CM_SETCNRINFO, MPFROMP(&cnri),
540 MPFROMLONG(CMA_FLWINDOWATTR | CMA_TREEICON |
541 CMA_LINESPACING | CMA_CXTREEINDENT));
542 pState = INSTDATA(hwnd);
543 if (pState && isalpha(*pState->szDirName)) {
544 memset(&fsa, 0, sizeof(fsa));
545 rc =
546 DosQueryFSInfo(toupper(*pState->szDirName) - '@', FSIL_ALLOC, &fsa,
547 sizeof(FSALLOCATE));
548 if (!rc) {
549
550 CHAR s[132], tf[80], tb[80], tu[80];
551
552 CommaFmtULL(tf, sizeof(tf),
553 (ULONGLONG) fsa.cUnitAvail *
554 (fsa.cSectorUnit * fsa.cbSector), 'M');
555 CommaFmtULL(tb, sizeof(tb),
556 (ULONGLONG) fsa.cUnit *
557 (fsa.cSectorUnit * fsa.cbSector), 'M');
558 CommaFmtULL(tu, sizeof(tu),
559 (ULONGLONG) (fsa.cUnit - fsa.cUnitAvail) *
560 (fsa.cSectorUnit * fsa.cbSector), 'M');
561 sprintf(s, GetPString(IDS_FREESPACETEXT), tf, tb, tu);
562 WinSetDlgItemText(hwnd, DSZ_FREESPACE, s);
563 }
564 else
565 WinSetDlgItemText(hwnd,
566 DSZ_FREESPACE, GetPString(IDS_FREESPACEUTEXT));
567 }
568 }
569 return 0;
570
571 case UM_CONTAINER_FILLED:
572 pState = INSTDATA(hwnd);
573 if (!pState || pState->dying) {
574 if (pState)
575 pState->working = FALSE;
576 WinDismissDlg(hwnd, 0);
577 return 0;
578 }
579 pState->working = FALSE;
580 WinEnableWindow(WinWindowFromID(hwnd, DSZ_COLLAPSE), TRUE);
581 WinEnableWindow(WinWindowFromID(hwnd, DSZ_EXPAND), TRUE);
582 WinEnableWindow(WinWindowFromID(hwnd, DSZ_PRINT), TRUE);
583
584 pci = WinSendDlgItemMsg(hwnd, DSZ_CNR, CM_QUERYRECORD, MPVOID,
585 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
586 if (pci && (INT) pci != -1)
587 WinSendDlgItemMsg(hwnd, DSZ_CNR, CM_EXPANDTREE, MPFROMP(pci), MPVOID);
588 *sz = 0;
589 pci = WinSendDlgItemMsg(hwnd, DSZ_CNR, CM_QUERYRECORDEMPHASIS,
590 MPFROMLONG(CMA_FIRST), MPFROMSHORT(CRA_CURSORED));
591 if (pci && (INT) pci != -1) {
592 commafmt(szBytes, sizeof(szBytes), pci->attrFile);
593 sprintf(sz,
594 "%s %s%s",
595 szBytes, GetPString(IDS_FILETEXT), &"s"[pci->attrFile == 1]);
596 }
597 WinSetDlgItemText(hwnd, DSZ_NUMFILES, sz);
598
599 WinSendDlgItemMsg(hwnd, DSZ_CNR, CM_SORTRECORD, MPFROMP(SortSizeCnr),
600 MPVOID);
601 DosBeep(500, 25); // Wake up user
602 return 0;
603
604 case WM_ADJUSTWINDOWPOS:
605 PostMsg(hwnd, UM_STRETCH, MPVOID, MPVOID);
606 break;
607
608 case UM_STRETCH:
609 {
610 SWP swpC, swp;
611
612 WinQueryWindowPos(hwnd, &swp);
613 if (!(swp.fl & (SWP_HIDE | SWP_MINIMIZE))) {
614 WinQueryWindowPos(WinWindowFromID(hwnd, DSZ_CNR), &swpC);
615 WinSetWindowPos(WinWindowFromID(hwnd, DSZ_CNR), HWND_TOP,
616 SysVal(SV_CXSIZEBORDER),
617 swpC.y,
618 swp.cx - (SysVal(SV_CXSIZEBORDER) * 2),
619 (swp.cy - swpC.y) - (SysVal(SV_CYTITLEBAR) +
620 SysVal(SV_CYSIZEBORDER)),
621 SWP_MOVE | SWP_SIZE);
622 }
623 }
624 return 0;
625
626 case WM_DRAWITEM:
627 if (mp2) {
628
629 OWNERITEM *oi = mp2;
630 CNRDRAWITEMINFO *cnd;
631 PCNRITEM pci;
632
633 if (oi->idItem == CMA_TEXT) {
634
635 cnd = (CNRDRAWITEMINFO *)oi->hItem;
636
637 if (cnd) {
638 pci = (PCNRITEM)cnd->pRecord;
639
640 if (pci) {
641 POINTL aptl[TXTBOX_COUNT];
642 POINTL ptl;
643 PSZ p;
644 LONG clr;
645 LONG x;
646 LONG yBottom;
647 INT boxHeight;
648 p = strchr(pci->pszFileName, '\r');
649 if (p) {
650 // draw text
651 if (!pci->cbFile) // no size
652 GpiSetColor(oi->hps, CLR_DARKGRAY);
653 else if (!pci->easize) // no size below
654 GpiSetColor(oi->hps, CLR_DARKBLUE);
655 else
656 GpiSetColor(oi->hps, CLR_BLACK);
657 GpiSetBackMix(oi->hps, BM_LEAVEALONE);
658 GpiSetMix(oi->hps, FM_OVERPAINT);
659
660 *p = 0; // Make 1 line high
661
662 // Calculate nominal graph box height based on font size
663 GpiQueryTextBox(oi->hps, strlen(pci->pszFileName),
664 pci->pszFileName, TXTBOX_COUNT, aptl);
665 boxHeight = aptl[TXTBOX_TOPRIGHT].y - aptl[TXTBOX_BOTTOMRIGHT].y;
666 boxHeight -= 6;
667
668 // Calculate nominal baseline of graph box
669 // rclItem.yBottom is at center of icon because it is
670 yBottom = oi->rclItem.yBottom - boxHeight + 3;
671
672 // Place text above graph box with a bit of whitespace between
673 ptl.x = oi->rclItem.xLeft;
674 ptl.y = yBottom + boxHeight + 8; // 03 Aug 07 SHL
675 // GpiMove(oi->hps, &ptl);
676 GpiCharStringAt(oi->hps, &ptl, strlen(pci->pszFileName),
677 pci->pszFileName);
678
679 *p = '\r'; // Restore
680
681 // draw the graph box
682 // GpiQueryTextBox(oi->hps, 1, "#", TXTBOX_COUNT, aptl); // 03 Aug 07 SHL
683 // draw black outline
684 GpiSetColor(oi->hps, CLR_BLACK);
685 ptl.x = oi->rclItem.xLeft;
686 ptl.y = yBottom + 2;
687 GpiMove(oi->hps, &ptl);
688 ptl.x = oi->rclItem.xLeft + 101;
689 ptl.y = yBottom + boxHeight;
690 GpiBox(oi->hps, DRO_OUTLINE, &ptl, 0, 0);
691 // fill with gray
692 GpiSetColor(oi->hps, CLR_PALEGRAY);
693 ptl.x = oi->rclItem.xLeft + 1;
694 ptl.y = yBottom + 3;
695 GpiMove(oi->hps, &ptl);
696 ptl.x = oi->rclItem.xLeft + 100;
697 ptl.y = yBottom + boxHeight - 1;
698 GpiBox(oi->hps, DRO_OUTLINEFILL, &ptl, 0, 0);
699
700 // draw shadow at bottom & right sides
701 GpiSetColor(oi->hps, CLR_DARKGRAY);
702 ptl.x = oi->rclItem.xLeft + 1;
703 ptl.y = yBottom + 3;
704 GpiMove(oi->hps, &ptl);
705 ptl.x = oi->rclItem.xLeft + 100;
706 GpiLine(oi->hps, &ptl);
707 ptl.y = yBottom + boxHeight - 1;
708 GpiLine(oi->hps, &ptl);
709
710 // draw highlight at top and left sides
711 GpiSetColor(oi->hps, CLR_WHITE);
712 ptl.x = oi->rclItem.xLeft + 1;
713 GpiLine(oi->hps, &ptl);
714 ptl.y = yBottom + 3;
715 GpiLine(oi->hps, &ptl);
716
717 // draw shadow of box
718 GpiSetColor(oi->hps, CLR_DARKGRAY);
719 ptl.x = oi->rclItem.xLeft + 2;
720 ptl.y = yBottom + boxHeight;
721 GpiMove(oi->hps, &ptl);
722 ptl.x = oi->rclItem.xLeft + 103;
723 GpiLine(oi->hps, &ptl);
724 ptl.y = yBottom + boxHeight - 2;
725 GpiLine(oi->hps, &ptl);
726 ptl.x--;
727 GpiMove(oi->hps, &ptl);
728 ptl.y = yBottom + 1;
729 GpiLine(oi->hps, &ptl);
730 ptl.x = oi->rclItem.xLeft + 2;
731 GpiLine(oi->hps, &ptl);
732
733 // fill box with graph bar, flags is integer %
734 if (pci->flags) {
735 if (*(pci->pszLongName + 1) == 1) // is root record
736 GpiSetColor(oi->hps, CLR_DARKGREEN);
737 else
738 GpiSetColor(oi->hps, CLR_RED);
739 ptl.x = oi->rclItem.xLeft + 1;
740 ptl.y = yBottom + 3;
741 GpiMove(oi->hps, &ptl);
742 ptl.x = oi->rclItem.xLeft + pci->flags;
743 ptl.y = yBottom + boxHeight - 1;
744 GpiBox(oi->hps, DRO_OUTLINEFILL, &ptl, 0, 0);
745
746 // draw highlights and shadows on graph
747 if (*(pci->pszLongName + 1) == 1)
748 GpiSetColor(oi->hps, CLR_GREEN);
749 else
750 GpiSetColor(oi->hps, CLR_PALEGRAY);
751 if (pci->flags > 5) {
752 ptl.x = oi->rclItem.xLeft + 1;
753 ptl.y = yBottom + 3;
754 GpiMove(oi->hps, &ptl);
755 ptl.y = yBottom + boxHeight - 1;
756 GpiLine(oi->hps, &ptl);
757 }
758 else {
759 ptl.y = yBottom + boxHeight - 1;
760 GpiMove(oi->hps, &ptl);
761 }
762 ptl.x = oi->rclItem.xLeft + pci->flags;
763 GpiLine(oi->hps, &ptl);
764 if (*(pci->pszLongName + 1) != 1) {
765 GpiSetColor(oi->hps, CLR_DARKRED);
766 ptl.x = oi->rclItem.xLeft + 2;
767 ptl.y = yBottom + 3;
768 GpiMove(oi->hps, &ptl);
769 ptl.x = oi->rclItem.xLeft + pci->flags;
770 GpiLine(oi->hps, &ptl);
771 }
772 }
773
774 // draw hash marks in box
775 GpiSetColor(oi->hps, CLR_WHITE);
776 clr = CLR_WHITE;
777 for (x = 1; x < 10; x++) {
778 if (clr == CLR_WHITE && x * 10 > pci->flags) {
779 clr = CLR_BLACK;
780 GpiSetColor(oi->hps, CLR_BLACK);
781 }
782 ptl.x = oi->rclItem.xLeft + 1 + x * 10;
783 ptl.y = yBottom + boxHeight - 1;
784 GpiMove(oi->hps, &ptl);
785 switch (x) {
786 case 1:
787 case 3:
788 case 7:
789 case 9:
790 ptl.y -= 1;
791 break;
792 case 5:
793 ptl.y -= 4;
794 break;
795 case 2:
796 case 4:
797 case 6:
798 case 8:
799 ptl.y -= 2;
800 break;
801 }
802 GpiLine(oi->hps, &ptl);
803 } // for x
804 return MRFROMLONG(TRUE);
805 }
806 }
807 }
808 }
809 }
810 return FALSE; // Let PM draw
811
812 case WM_CONTROL:
813 switch (SHORT2FROMMP(mp1)) {
814 case CN_ENTER:
815 if (mp2) {
816 PCNRITEM pci = (PCNRITEM)((PNOTIFYRECORDENTER)mp2)->pRecord;
817 CHAR szFileName[CCHMAXPATH]; // 23 Jul 07 SHL
818 CHAR szTemp[CCHMAXPATH];
819
820 if (pci) {
821 *szFileName = 0;
822 while (pci && (INT) pci != -1) {
823 memset(szTemp, 0, sizeof(szTemp));
824 strncpy(szTemp, pci->pszFileName,
825 pci->pszDisplayName - pci->pszFileName);
826 strrev(szTemp);
827 if (*szFileName && *szTemp != '\\')
828 strcat(szFileName, "\\");
829 strcat(szFileName, szTemp);
830 pci = WinSendDlgItemMsg(hwnd, DSZ_CNR, CM_QUERYRECORD,
831 MPFROMP(pci),
832 MPFROM2SHORT(CMA_PARENT, CMA_ITEMORDER));
833 }
834 strrev(szFileName);
835 if (!fVTreeOpensWPS)
836 OpenDirCnr((HWND)0,
837 hwndMain ? hwndMain : HWND_DESKTOP,
838 hwnd,
839 FALSE,
840 szFileName);
841 else {
842
843 ULONG size = sizeof(ULONG);
844 ULONG flWindowAttr = CV_ICON;
845 CHAR s[33];
846
847 strcpy(s, "ICON");
848 PrfQueryProfileData(fmprof, appname, "DirflWindowAttr",
849 (PVOID) & flWindowAttr, &size);
850 if (flWindowAttr & CV_DETAIL) {
851 if (IsRoot(szFileName))
852 strcpy(s, "TREE");
853 else
854 strcpy(s, "DETAILS");
855 }
856 OpenObject(szFileName, s, hwnd);
857 }
858 }
859 }
860 break;
861 case CN_EMPHASIS:
862 pState = INSTDATA(hwnd);
863 if (pState && !pState->working && mp2) {
864
865 PNOTIFYRECORDEMPHASIS pre = mp2;
866
867 pci = (PCNRITEM) ((pre) ? pre->pRecord : NULL);
868 if (pci && (pre->fEmphasisMask & CRA_SELECTED) &&
869 (pci->rc.flRecordAttr & CRA_SELECTED)) {
870 commafmt(szBytes, sizeof(szBytes), pci->attrFile);
871 sprintf(sz,
872 "%s %s%s",
873 szBytes,
874 GetPString(IDS_FILETEXT), &"s"[pci->attrFile == 1]);
875 WinSetDlgItemText(hwnd, DSZ_NUMFILES, sz);
876 }
877 }
878 break;
879 }
880 return 0;
881
882 case WM_COMMAND:
883 switch (SHORT1FROMMP(mp1)) {
884 case IDM_HELP:
885 if (hwndHelp)
886 WinSendMsg(hwndHelp, HM_DISPLAY_HELP,
887 MPFROM2SHORT(HELP_DIRSIZE, 0), MPFROMSHORT(HM_RESOURCEID));
888 break;
889
890 case DSZ_PRINT:
891 // Save button
892 pState = INSTDATA(hwnd);
893 if (!pState)
894 Runtime_Error2(pszSrcFile, __LINE__, IDS_NODATATEXT);
895 else {
896
897 CHAR szFileName[CCHMAXPATH];
898 FILE *fp;
899
900 save_dir2(szFileName);
901 sprintf(&szFileName[strlen(szFileName)], "\\%csizes.Rpt",
902 (pState) ? toupper(*pState->szDirName) : '+');
903 if (export_filename(hwnd, szFileName, FALSE) && *szFileName) {
904 if (stricmp(szFileName, "PRN") &&
905 strnicmp(szFileName, "\\DEV\\LPT", 8) &&
906 !strchr(szFileName, '.'))
907 strcat(szFileName, ".RPT");
908 fp = fopen(szFileName, "a+");
909 if (!fp) {
910 saymsg(MB_CANCEL,
911 hwnd,
912 GetPString(IDS_ERRORTEXT),
913 GetPString(IDS_COMPCANTOPENTEXT), szFileName);
914 }
915 else {
916 WinSetPointer(HWND_DESKTOP, hptrBusy);
917 PrintToFile(WinWindowFromID(hwnd, DSZ_CNR), 0, NULL, fp);
918 fclose(fp);
919 WinSetPointer(HWND_DESKTOP, hptrArrow);
920 }
921 }
922 }
923 break;
924
925 case DSZ_EXPAND:
926 case DSZ_COLLAPSE:
927 pState = INSTDATA(hwnd);
928 if (pState) {
929 pci = (PCNRITEM) WinSendDlgItemMsg(hwnd, DSZ_CNR,
930 CM_QUERYRECORDEMPHASIS,
931 MPFROMLONG(CMA_FIRST),
932 MPFROMSHORT(CRA_CURSORED));
933 if (pci) {
934 WinEnableWindow(WinWindowFromID(hwnd, DID_OK), FALSE);
935 WinEnableWindow(WinWindowFromID(hwnd, IDM_HELP), FALSE);
936 WinEnableWindow(WinWindowFromID(hwnd, DSZ_COLLAPSE), FALSE);
937 WinEnableWindow(WinWindowFromID(hwnd, DSZ_EXPAND), FALSE);
938 WinEnableWindow(WinWindowFromID(hwnd, DSZ_PRINT), FALSE);
939 WinEnableWindow(WinWindowFromID(hwnd, DID_CANCEL), FALSE);
940 // fixme to use thread - too slow on large trees
941 ExpandAll(WinWindowFromID(hwnd, DSZ_CNR),
942 (SHORT1FROMMP(mp1) == DSZ_EXPAND), pci);
943 WinEnableWindow(WinWindowFromID(hwnd, DID_OK), TRUE);
944 WinEnableWindow(WinWindowFromID(hwnd, IDM_HELP), TRUE);
945 WinEnableWindow(WinWindowFromID(hwnd, DSZ_COLLAPSE), TRUE);
946 WinEnableWindow(WinWindowFromID(hwnd, DSZ_EXPAND), TRUE);
947 WinEnableWindow(WinWindowFromID(hwnd, DSZ_PRINT), TRUE);
948 WinEnableWindow(WinWindowFromID(hwnd, DID_CANCEL), TRUE);
949 }
950 }
951 break;
952
953 case DID_OK:
954 case DID_CANCEL:
955 pState = INSTDATA(hwnd);
956 if (!pState)
957 Runtime_Error2(pszSrcFile, __LINE__, IDS_NODATATEXT);
958 else {
959 if (pState->working) {
960 pState->dying = TRUE;
961 pState->chStopFlag = (BYTE)0xff;
962 DosBeep(1000, 100); // Complain?
963 }
964 else
965 WinDismissDlg(hwnd, 0);
966 }
967 break;
968 } // switch mp1
969 return 0;
970
971 case WM_CLOSE:
972 pState = INSTDATA(hwnd);
973 if (pState)
974 pState->chStopFlag = (BYTE)0xff;
975 DosSleep(1);
976 break;
977
978 case WM_DESTROY:
979 pState = INSTDATA(hwnd);
980 if (pState) {
981 pState->chStopFlag = (BYTE)0xff;
982 if (pState->hptr)
983 WinDestroyPointer(pState->hptr);
984 DosSleep(16); //05 Aug 07 GKY 33
985 free(pState); // Let's hope no one is still looking
986 }
987 DosPostEventSem(CompactSem);
988 break;
989 }
990 return WinDefDlgProc(hwnd, msg, mp1, mp2);
991}
992
993#pragma alloc_text(DIRSIZE,ProcessDir,FillCnrThread,DirSizeProc)
994#pragma alloc_text(DIRSIZE2,PrintToFile,FillInRecSizes,SortSizeCnr)
995
Note: See TracBrowser for help on using the repository browser.