source: trunk/dll/dirsize.c@ 779

Last change on this file since 779 was 779, checked in by Gregg Young, 18 years ago

Change set 778 done correctly (I hope)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 26.8 KB
Line 
1
2/***********************************************************************
3
4 $Id: dirsize.c 779 2007-08-11 22:15:47Z gyoung $
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
31
32***********************************************************************/
33
34#define INCL_DOS
35#define INCL_WIN
36#define INCL_GPI
37#define INCL_LONGLONG
38#include <os2.h>
39
40#include <stdio.h>
41#include <stdlib.h>
42#include <string.h>
43#include <ctype.h>
44#include <process.h> // _beginthread
45
46#include "fm3dll.h"
47#include "fm3dlg.h"
48#include "fm3str.h"
49
50typedef struct
51{
52 CHAR *pszFileName;
53 HWND hwndCnr;
54 CHAR *pchStopFlag;
55 DIRCNRDATA *pDCD;
56} DIRSIZE;
57
58typedef struct
59{
60 CHAR szDirName[CCHMAXPATH];
61 CHAR chStopFlag;
62 BOOL dying;
63 BOOL working;
64 HPOINTER hptr;
65} tState;
66
67static PSZ pszSrcFile = __FILE__;
68
69#pragma alloc_text(DIRSIZE,ProcessDir,FillCnrThread,DirSizeProc)
70#pragma alloc_text(DIRSIZE2,PrintToFile,FillInRecSizes,SortSizeCnr)
71
72static SHORT APIENTRY SortSizeCnr(PMINIRECORDCORE p1, 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 nm;
97 ULONGLONG ullCurDirBytes = 0;
98 ULONGLONG ullSubDirBytes = 0;
99 ULONGLONG ull;
100 HDIR hdir;
101 FILEFINDBUF4 *pffb;
102 APIRET rc;
103 RECORDINSERT ri;
104 PCNRITEM pci;
105
106 // fixme to report errors
107 *pullTotalBytes = 0; // In case we fail
108
109 pffb = xmalloc(sizeof(FILEFINDBUF4), pszSrcFile, __LINE__);
110 if (!pffb)
111 return FALSE;
112 strcpy(maskstr, pszFileName);
113 if (maskstr[strlen(maskstr) - 1] != '\\')
114 strcat(maskstr, "\\");
115 pEndMask = &maskstr[strlen(maskstr)]; // Point after last backslash
116 strcat(maskstr, "*");
117 //printf("%s\n",maskstr);
118
119 hdir = HDIR_CREATE;
120 nm = 1;
121 memset(pffb, 0, sizeof(FILEFINDBUF4));
122 DosError(FERR_DISABLEHARDERR);
123 //printf("FIND1\n");
124 rc = DosFindFirst(pszFileName, &hdir,
125 FILE_NORMAL | FILE_READONLY | FILE_ARCHIVED |
126 FILE_SYSTEM | FILE_HIDDEN | MUST_HAVE_DIRECTORY,
127 pffb, sizeof(FILEFINDBUF4), &nm, FIL_QUERYEASIZE);
128
129 if (!rc)
130 DosFindClose(hdir);
131
132 /*
133 * the "|| strlen(pszFileName) < 4 below works around an OS/2 bug
134 * that prevents FAT root directories from being found when
135 * requesting EASIZE. sheesh.
136 */
137 if ((!rc && (pffb->attrFile & FILE_DIRECTORY)) || strlen(pszFileName) < 4) {
138 if (*pchStopFlag) {
139 free(pffb);
140 return FALSE;
141 }
142 pci = WinSendMsg(hwndCnr, CM_ALLOCRECORD, MPFROMLONG(EXTRA_RECORD_BYTES),
143 MPFROMLONG(1));
144 if (!pci) {
145 free(pffb);
146 return FALSE;
147 }
148 if (!rc) {
149 ullCurDirBytes = pffb->cbFile;
150 ullCurDirBytes += CBLIST_TO_EASIZE(pffb->cbList);
151 }
152 else
153 DosError(FERR_DISABLEHARDERR);
154 pci->rc.hptrIcon = hptrDir;
155 pci->attrFile = 0;
156 pci->pszDispAttr = NullStr;
157 pci->pszSubject = NullStr;
158 }
159 else {
160 free(pffb);
161 Dos_Error(MB_ENTER,
162 rc,
163 HWND_DESKTOP,
164 pszSrcFile,
165 __LINE__, 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 know why - it 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(pffb);
207 return FALSE;
208 }
209 hdir = HDIR_CREATE;
210 nm = FilesToGet;
211 pffb =
212 xrealloc(pffb, (nm + 1) * sizeof(FILEFINDBUF4), pszSrcFile, __LINE__);
213 rc = DosFindFirst(maskstr, &hdir,
214 FILE_NORMAL | FILE_READONLY | FILE_ARCHIVED |
215 FILE_SYSTEM | FILE_HIDDEN | FILE_DIRECTORY,
216 pffb, (nm + 1) * sizeof(FILEFINDBUF4), &nm, FIL_QUERYEASIZE);
217 if (!rc) {
218 register PBYTE fb = (PBYTE) pffb;
219 FILEFINDBUF4 *pffbFile, *pffbTemp;
220 ULONG x;
221 UINT y = 1;
222
223 while (!rc) {
224 priority_normal();
225 //printf("Found %lu\n",nm);
226 for (x = 0; x < nm; x++) {
227 pffbFile = (FILEFINDBUF4 *) fb;
228 //printf("%s\n",pffbFile->achName);
229 //fflush(stdout);
230 // Total size skipping . and ..
231 if ((~pffbFile->attrFile & FILE_DIRECTORY) ||
232 (pffbFile->achName[0] != '.' ||
233 (pffbFile->achName[1] &&
234 (pffbFile->achName[1] != '.' || pffbFile->achName[2])))) {
235 ullCurDirBytes += pffbFile->cbFile;
236 ullCurDirBytes += CBLIST_TO_EASIZE(pffbFile->cbList) & 0x3ff;
237
238 if (!(pffbFile->attrFile & FILE_DIRECTORY))
239 pci->attrFile++; // Bump file count
240 if (*pchStopFlag)
241 break;
242 if (pffbFile->attrFile & FILE_DIRECTORY) {
243 // Recurse into subdir
244 strcpy(pEndMask, pffbFile->achName); // Append dirname to base dirname
245 if (!*pchStopFlag) {
246 ProcessDir(hwndCnr, maskstr, pci, pchStopFlag, FALSE, &ull);
247 ullSubDirBytes += ull;
248 }
249 }
250 }
251 if (!pffbFile->oNextEntryOffset)
252 break;
253 fb += pffbFile->oNextEntryOffset;
254 } // for matches
255 if (*pchStopFlag)
256 break;
257 DosSleep(1);
258 pffbTemp = pffb;
259 nm = FilesToGet; /* FilesToGet */
260 y++;
261 pffb = xrealloc(pffb, y * (nm + 1) * sizeof(FILEFINDBUF4), pszSrcFile, __LINE__);
262 if (!pffb) { //Error already sent
263 free(pffbTemp);
264 break;
265 }
266 DosError(FERR_DISABLEHARDERR);
267 rc = DosFindNext(hdir, pffb, y * (nm + 1) * sizeof(FILEFINDBUF4), &nm);
268 } // while more found
269 DosFindClose(hdir);
270 priority_normal();
271 }
272
273 free(pffb);
274
275 pci->cbFile = ullCurDirBytes;
276 pci->easize = ullSubDirBytes; // hack cough
277 WinSendMsg(hwndCnr, CM_INVALIDATERECORD, MPFROMP(&pci),
278 MPFROM2SHORT(1, CMA_ERASE | CMA_TEXTCHANGED));
279
280 *pullTotalBytes = ullCurDirBytes + ullSubDirBytes;
281 return TRUE;
282}
283
284static VOID FillInRecSizes(HWND hwndCnr, PCNRITEM pciParent,
285 ULONGLONG ullTotalBytes, CHAR * pchStopFlag,
286 BOOL isroot)
287{
288 PCNRITEM pci = pciParent;
289 SHORT attrib = CMA_FIRSTCHILD;
290
291 if (pci) {
292
293 float fltPct = 0.0;
294 USHORT c;
295 CHAR szCurDir[80];
296 CHAR szSubDir[80];
297 CHAR szAllDir[80];
298 CHAR szBar[80];
299
300 // cbFile = currect directory usage in bytes
301 // easize = subdirectory usage in bytes
302 CommaFmtULL(szCurDir, sizeof(szCurDir), pci->cbFile, 'K');
303 *szBar = 0;
304
305 if (ullTotalBytes) {
306 register UINT cBar;
307
308 if (isroot) {
309 FSALLOCATE fsa;
310 APIRET rc;
311
312 memset(&fsa, 0, sizeof(fsa));
313 rc = DosQueryFSInfo(toupper(*pci->pszFileName) - '@', FSIL_ALLOC, &fsa,
314 sizeof(FSALLOCATE));
315 if (!rc) {
316 fltPct = (ullTotalBytes * 100.0) /
317 ((float)fsa.cUnit * (fsa.cSectorUnit * fsa.cbSector));
318 }
319 // Need unique buffer 23 Jul 07 SHL
320 pci->pszLongName = xmalloc(2, pszSrcFile, __LINE__);
321 pci->pszLongName[0] = 0; // Make null string
322 pci->pszLongName[1] = 1; // Flag root - hack cough
323 }
324 else
325 fltPct = (((float)pci->cbFile + pci->easize) * 100.0) / ullTotalBytes;
326
327 cBar = (UINT) fltPct / 2;
328 if (cBar)
329 memset(szBar, '#', cBar);
330 if (cBar * 2 != (UINT) fltPct) {
331 szBar[cBar] = '=';
332 cBar++;
333 }
334 if (cBar < 50)
335 memset(szBar + cBar, ' ', 50 - cBar);
336 szBar[50] = 0;
337 }
338
339 pci->flags = (ULONG) fltPct;
340 CommaFmtULL(szSubDir, sizeof(szSubDir), pci->easize, 'K');
341 CommaFmtULL(szAllDir, sizeof(szAllDir), pci->cbFile + pci->easize, 'K');
342 c = pci->pszDisplayName - pci->pszFileName;
343 pci->pszFileName = xrealloc(pci->pszFileName,
344 CCHMAXPATH,
345 pszSrcFile,
346 __LINE__); // 23 Jul 07 SHL
347 sprintf(pci->pszFileName + c,
348 " %s + %s = %s (%.02lf%%%s)\r%s",
349 szCurDir,
350 szSubDir,
351 szAllDir,
352 fltPct,
353 isroot ? GetPString(IDS_OFDRIVETEXT) : NullStr,
354 szBar);
355 pci->pszFileName = xrealloc(pci->pszFileName,
356 strlen(pci->pszFileName) + 1,
357 pszSrcFile,
358 __LINE__); // 23 Jul 07 SHL
359 pci->pszDisplayName = pci->pszFileName + c;
360 WinSendMsg(hwndCnr,
361 CM_INVALIDATERECORD, MPFROMP(&pci), MPFROM2SHORT(1, 0));
362 isroot = FALSE;
363 }
364 else
365 attrib = CMA_FIRST;
366 pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(pci),
367 MPFROM2SHORT(attrib, CMA_ITEMORDER));
368 while (pci && (INT) pci != -1) {
369 if (*pchStopFlag)
370 break;
371 FillInRecSizes(hwndCnr, pci, ullTotalBytes, pchStopFlag, isroot);
372 isroot = FALSE;
373 pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(pci),
374 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
375 }
376}
377
378static VOID PrintToFile(HWND hwndCnr, ULONG indent, PCNRITEM pciParent,
379 FILE * fp)
380{
381 PCNRITEM pci;
382 CHAR *p;
383
384 if (!pciParent) {
385 pciParent = WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(NULL),
386 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
387 indent = 0;
388 }
389 if (pciParent) {
390 p = strchr(pciParent->pszFileName, '\r');
391 if (p)
392 *p = 0;
393 fprintf(fp, "%*.*s%s %lu %s%s\n",
394 indent * 2, indent * 2, " ",
395 pciParent->pszFileName,
396 pciParent->attrFile,
397 GetPString(IDS_FILETEXT), &"s"[pciParent->attrFile == 1]);
398 if (p)
399 *p = '\r';
400 if (pciParent->rc.flRecordAttr & CRA_EXPANDED) {
401 pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(pciParent),
402 MPFROM2SHORT(CMA_FIRSTCHILD,
403 CMA_ITEMORDER));
404 while (pci && (INT) pci != -1) {
405 DosSleep(1);
406 PrintToFile(hwndCnr, indent + 1, pci, fp);
407 pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(pci),
408 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
409 }
410 }
411 }
412}
413
414static VOID FillCnrThread(VOID * args)
415{
416 HAB hab;
417 HMQ hmq;
418 DIRSIZE *dirsize = (DIRSIZE *) args;
419 HWND hwndCnr;
420 ULONGLONG ull;
421
422 if (!dirsize)
423 return;
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}
Note: See TracBrowser for help on using the repository browser.