source: trunk/dll/dirsize.c@ 907

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

Avoid out of memory traps in Compare Directories
Rework Compare Directories progress display for 2 second update rate
Start refactoring to reduce dependence on fm3dll.h
Add timer services (IsITimerExpired etc.)

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