source: trunk/dll/dirsize.c@ 780

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

Free memory on error for first xrealloc call

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 26.9 KB
Line 
1
2/***********************************************************************
3
4 $Id: dirsize.c 780 2007-08-11 22:39:33Z 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, *pffbTemp;
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 pffbTemp = pffb;
211 nm = FilesToGet;
212 pffb = xrealloc(pffb, (nm + 1) * sizeof(FILEFINDBUF4), pszSrcFile, __LINE__);
213 if (!pffb) { //Error already sent
214 free(pffbTemp);
215 return FALSE;
216 }
217 rc = DosFindFirst(maskstr, &hdir,
218 FILE_NORMAL | FILE_READONLY | FILE_ARCHIVED |
219 FILE_SYSTEM | FILE_HIDDEN | FILE_DIRECTORY,
220 pffb, (nm + 1) * sizeof(FILEFINDBUF4), &nm, FIL_QUERYEASIZE);
221 if (!rc) {
222 register PBYTE fb = (PBYTE) pffb;
223 FILEFINDBUF4 *pffbFile;
224 ULONG x;
225 UINT y = 1;
226
227 while (!rc) {
228 priority_normal();
229 //printf("Found %lu\n",nm);
230 for (x = 0; x < nm; x++) {
231 pffbFile = (FILEFINDBUF4 *) fb;
232 //printf("%s\n",pffbFile->achName);
233 //fflush(stdout);
234 // Total size skipping . and ..
235 if ((~pffbFile->attrFile & FILE_DIRECTORY) ||
236 (pffbFile->achName[0] != '.' ||
237 (pffbFile->achName[1] &&
238 (pffbFile->achName[1] != '.' || pffbFile->achName[2])))) {
239 ullCurDirBytes += pffbFile->cbFile;
240 ullCurDirBytes += CBLIST_TO_EASIZE(pffbFile->cbList) & 0x3ff;
241
242 if (!(pffbFile->attrFile & FILE_DIRECTORY))
243 pci->attrFile++; // Bump file count
244 if (*pchStopFlag)
245 break;
246 if (pffbFile->attrFile & FILE_DIRECTORY) {
247 // Recurse into subdir
248 strcpy(pEndMask, pffbFile->achName); // Append dirname to base dirname
249 if (!*pchStopFlag) {
250 ProcessDir(hwndCnr, maskstr, pci, pchStopFlag, FALSE, &ull);
251 ullSubDirBytes += ull;
252 }
253 }
254 }
255 if (!pffbFile->oNextEntryOffset)
256 break;
257 fb += pffbFile->oNextEntryOffset;
258 } // for matches
259 if (*pchStopFlag)
260 break;
261 DosSleep(1);
262 pffbTemp = pffb;
263 nm = FilesToGet; /* FilesToGet */
264 y++;
265 pffb = xrealloc(pffb, y * (nm + 1) * sizeof(FILEFINDBUF4), pszSrcFile, __LINE__);
266 if (!pffb) { //Error already sent
267 free(pffbTemp);
268 break;
269 }
270 DosError(FERR_DISABLEHARDERR);
271 rc = DosFindNext(hdir, pffb, y * (nm + 1) * sizeof(FILEFINDBUF4), &nm);
272 } // while more found
273 DosFindClose(hdir);
274 priority_normal();
275 }
276
277 free(pffb);
278
279 pci->cbFile = ullCurDirBytes;
280 pci->easize = ullSubDirBytes; // hack cough
281 WinSendMsg(hwndCnr, CM_INVALIDATERECORD, MPFROMP(&pci),
282 MPFROM2SHORT(1, CMA_ERASE | CMA_TEXTCHANGED));
283
284 *pullTotalBytes = ullCurDirBytes + ullSubDirBytes;
285 return TRUE;
286}
287
288static VOID FillInRecSizes(HWND hwndCnr, PCNRITEM pciParent,
289 ULONGLONG ullTotalBytes, CHAR * pchStopFlag,
290 BOOL isroot)
291{
292 PCNRITEM pci = pciParent;
293 SHORT attrib = CMA_FIRSTCHILD;
294
295 if (pci) {
296
297 float fltPct = 0.0;
298 USHORT c;
299 CHAR szCurDir[80];
300 CHAR szSubDir[80];
301 CHAR szAllDir[80];
302 CHAR szBar[80];
303
304 // cbFile = currect directory usage in bytes
305 // easize = subdirectory usage in bytes
306 CommaFmtULL(szCurDir, sizeof(szCurDir), pci->cbFile, 'K');
307 *szBar = 0;
308
309 if (ullTotalBytes) {
310 register UINT cBar;
311
312 if (isroot) {
313 FSALLOCATE fsa;
314 APIRET rc;
315
316 memset(&fsa, 0, sizeof(fsa));
317 rc = DosQueryFSInfo(toupper(*pci->pszFileName) - '@', FSIL_ALLOC, &fsa,
318 sizeof(FSALLOCATE));
319 if (!rc) {
320 fltPct = (ullTotalBytes * 100.0) /
321 ((float)fsa.cUnit * (fsa.cSectorUnit * fsa.cbSector));
322 }
323 // Need unique buffer 23 Jul 07 SHL
324 pci->pszLongName = xmalloc(2, pszSrcFile, __LINE__);
325 pci->pszLongName[0] = 0; // Make null string
326 pci->pszLongName[1] = 1; // Flag root - hack cough
327 }
328 else
329 fltPct = (((float)pci->cbFile + pci->easize) * 100.0) / ullTotalBytes;
330
331 cBar = (UINT) fltPct / 2;
332 if (cBar)
333 memset(szBar, '#', cBar);
334 if (cBar * 2 != (UINT) fltPct) {
335 szBar[cBar] = '=';
336 cBar++;
337 }
338 if (cBar < 50)
339 memset(szBar + cBar, ' ', 50 - cBar);
340 szBar[50] = 0;
341 }
342
343 pci->flags = (ULONG) fltPct;
344 CommaFmtULL(szSubDir, sizeof(szSubDir), pci->easize, 'K');
345 CommaFmtULL(szAllDir, sizeof(szAllDir), pci->cbFile + pci->easize, 'K');
346 c = pci->pszDisplayName - pci->pszFileName;
347 pci->pszFileName = xrealloc(pci->pszFileName,
348 CCHMAXPATH,
349 pszSrcFile,
350 __LINE__); // 23 Jul 07 SHL
351 sprintf(pci->pszFileName + c,
352 " %s + %s = %s (%.02lf%%%s)\r%s",
353 szCurDir,
354 szSubDir,
355 szAllDir,
356 fltPct,
357 isroot ? GetPString(IDS_OFDRIVETEXT) : NullStr,
358 szBar);
359 pci->pszFileName = xrealloc(pci->pszFileName,
360 strlen(pci->pszFileName) + 1,
361 pszSrcFile,
362 __LINE__); // 23 Jul 07 SHL
363 pci->pszDisplayName = pci->pszFileName + c;
364 WinSendMsg(hwndCnr,
365 CM_INVALIDATERECORD, MPFROMP(&pci), MPFROM2SHORT(1, 0));
366 isroot = FALSE;
367 }
368 else
369 attrib = CMA_FIRST;
370 pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(pci),
371 MPFROM2SHORT(attrib, CMA_ITEMORDER));
372 while (pci && (INT) pci != -1) {
373 if (*pchStopFlag)
374 break;
375 FillInRecSizes(hwndCnr, pci, ullTotalBytes, pchStopFlag, isroot);
376 isroot = FALSE;
377 pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(pci),
378 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
379 }
380}
381
382static VOID PrintToFile(HWND hwndCnr, ULONG indent, PCNRITEM pciParent,
383 FILE * fp)
384{
385 PCNRITEM pci;
386 CHAR *p;
387
388 if (!pciParent) {
389 pciParent = WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(NULL),
390 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
391 indent = 0;
392 }
393 if (pciParent) {
394 p = strchr(pciParent->pszFileName, '\r');
395 if (p)
396 *p = 0;
397 fprintf(fp, "%*.*s%s %lu %s%s\n",
398 indent * 2, indent * 2, " ",
399 pciParent->pszFileName,
400 pciParent->attrFile,
401 GetPString(IDS_FILETEXT), &"s"[pciParent->attrFile == 1]);
402 if (p)
403 *p = '\r';
404 if (pciParent->rc.flRecordAttr & CRA_EXPANDED) {
405 pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(pciParent),
406 MPFROM2SHORT(CMA_FIRSTCHILD,
407 CMA_ITEMORDER));
408 while (pci && (INT) pci != -1) {
409 DosSleep(1);
410 PrintToFile(hwndCnr, indent + 1, pci, fp);
411 pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(pci),
412 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
413 }
414 }
415 }
416}
417
418static VOID FillCnrThread(VOID * args)
419{
420 HAB hab;
421 HMQ hmq;
422 DIRSIZE *dirsize = (DIRSIZE *) args;
423 HWND hwndCnr;
424 ULONGLONG ull;
425
426 if (!dirsize)
427 return;
428 hwndCnr = dirsize->hwndCnr;
429
430 DosError(FERR_DISABLEHARDERR);
431
432 // priority_normal();
433 hab = WinInitialize(0);
434 if (hab) {
435 hmq = WinCreateMsgQueue(hab, 0);
436 if (hmq) {
437 WinCancelShutdown(hmq, TRUE);
438 ProcessDir(hwndCnr, dirsize->pszFileName,
439 (PCNRITEM) NULL, dirsize->pchStopFlag, TRUE, &ull);
440 DosPostEventSem(CompactSem);
441 WinEnableWindowUpdate(hwndCnr, FALSE);
442 FillInRecSizes(hwndCnr, NULL, ull, dirsize->pchStopFlag, TRUE);
443 WinEnableWindowUpdate(hwndCnr, TRUE);
444 WinSendMsg(hwndCnr, CM_INVALIDATERECORD, MPVOID,
445 MPFROM2SHORT(0, CMA_ERASE | CMA_TEXTCHANGED));
446 WinDestroyMsgQueue(hmq);
447 }
448 WinTerminate(hab);
449 }
450 PostMsg(WinQueryWindow(hwndCnr, QW_PARENT),
451 UM_CONTAINER_FILLED, MPVOID, MPVOID);
452 free(dirsize);
453}
454
455MRESULT EXPENTRY DirSizeProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
456{
457 tState *pState;
458 PCNRITEM pci;
459 CHAR szBytes[44];
460 CHAR sz[66];
461
462 switch (msg) {
463 case WM_INITDLG:
464 if (!mp2) {
465 WinDismissDlg(hwnd, 0);
466 break;
467 }
468 pState = xmallocz(sizeof(tState), pszSrcFile, __LINE__);
469 if (!pState) {
470 WinDismissDlg(hwnd, 0);
471 break;
472 }
473 strcpy(pState->szDirName, (CHAR *) mp2);
474 WinSetWindowPtr(hwnd, QWL_USER, (PVOID) pState);
475 pState->hptr = WinLoadPointer(HWND_DESKTOP, FM3ModHandle, DIRSIZE_ICON);
476 WinDefDlgProc(hwnd, WM_SETICON, MPFROMLONG(pState->hptr), MPVOID);
477 {
478 CHAR s[CCHMAXPATH + 81];
479
480 sprintf(s, GetPString(IDS_DIRSIZETITLETEXT), pState->szDirName);
481 WinSetWindowText(hwnd, s);
482 }
483 {
484 DIRSIZE *dirsize;
485
486 dirsize = xmalloc(sizeof(DIRSIZE), pszSrcFile, __LINE__);
487 if (!dirsize) {
488 WinDismissDlg(hwnd, 0);
489 break;
490 }
491 dirsize->pchStopFlag = (CHAR *)&pState->chStopFlag;
492 dirsize->pszFileName = pState->szDirName;
493 dirsize->hwndCnr = WinWindowFromID(hwnd, DSZ_CNR);
494 if (_beginthread(FillCnrThread, NULL, 122880L * 5, (PVOID)dirsize) ==
495 -1) {
496 Runtime_Error(pszSrcFile, __LINE__,
497 GetPString(IDS_COULDNTSTARTTHREADTEXT));
498 free(dirsize);
499 WinDismissDlg(hwnd, 0);
500 break;
501 }
502 pState->working = TRUE;
503 WinEnableWindow(WinWindowFromID(hwnd, DSZ_COLLAPSE), FALSE);
504 WinEnableWindow(WinWindowFromID(hwnd, DSZ_EXPAND), FALSE);
505 WinEnableWindow(WinWindowFromID(hwnd, DSZ_PRINT), FALSE);
506 }
507 PostMsg(hwnd, UM_SETUP, MPVOID, MPVOID);
508 break;
509
510 case UM_SETUP:
511 {
512 CNRINFO cnri;
513 FSALLOCATE fsa;
514 APIRET rc;
515
516 memset(&cnri, 0, sizeof(CNRINFO));
517 cnri.cb = sizeof(CNRINFO);
518 WinSendDlgItemMsg(hwnd, DSZ_CNR, CM_QUERYCNRINFO,
519 MPFROMP(&cnri), MPFROMLONG(sizeof(CNRINFO)));
520 cnri.cyLineSpacing = 0;
521 cnri.cxTreeIndent = 12;
522 cnri.flWindowAttr = CV_TREE | CV_FLOW | CA_TREELINE | CA_OWNERDRAW;
523 WinSendDlgItemMsg(hwnd, DSZ_CNR, CM_SETCNRINFO, MPFROMP(&cnri),
524 MPFROMLONG(CMA_FLWINDOWATTR | CMA_TREEICON |
525 CMA_LINESPACING | CMA_CXTREEINDENT));
526 pState = INSTDATA(hwnd);
527 if (pState && isalpha(*pState->szDirName)) {
528 memset(&fsa, 0, sizeof(fsa));
529 rc =
530 DosQueryFSInfo(toupper(*pState->szDirName) - '@', FSIL_ALLOC, &fsa,
531 sizeof(FSALLOCATE));
532 if (!rc) {
533
534 CHAR s[132], tf[80], tb[80], tu[80];
535
536 CommaFmtULL(tf, sizeof(tf),
537 (ULONGLONG) fsa.cUnitAvail *
538 (fsa.cSectorUnit * fsa.cbSector), 'M');
539 CommaFmtULL(tb, sizeof(tb),
540 (ULONGLONG) fsa.cUnit *
541 (fsa.cSectorUnit * fsa.cbSector), 'M');
542 CommaFmtULL(tu, sizeof(tu),
543 (ULONGLONG) (fsa.cUnit - fsa.cUnitAvail) *
544 (fsa.cSectorUnit * fsa.cbSector), 'M');
545 sprintf(s, GetPString(IDS_FREESPACETEXT), tf, tb, tu);
546 WinSetDlgItemText(hwnd, DSZ_FREESPACE, s);
547 }
548 else
549 WinSetDlgItemText(hwnd,
550 DSZ_FREESPACE, GetPString(IDS_FREESPACEUTEXT));
551 }
552 }
553 return 0;
554
555 case UM_CONTAINER_FILLED:
556 pState = INSTDATA(hwnd);
557 if (!pState || pState->dying) {
558 if (pState)
559 pState->working = FALSE;
560 WinDismissDlg(hwnd, 0);
561 return 0;
562 }
563 pState->working = FALSE;
564 WinEnableWindow(WinWindowFromID(hwnd, DSZ_COLLAPSE), TRUE);
565 WinEnableWindow(WinWindowFromID(hwnd, DSZ_EXPAND), TRUE);
566 WinEnableWindow(WinWindowFromID(hwnd, DSZ_PRINT), TRUE);
567
568 pci = WinSendDlgItemMsg(hwnd, DSZ_CNR, CM_QUERYRECORD, MPVOID,
569 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
570 if (pci && (INT) pci != -1)
571 WinSendDlgItemMsg(hwnd, DSZ_CNR, CM_EXPANDTREE, MPFROMP(pci), MPVOID);
572 *sz = 0;
573 pci = WinSendDlgItemMsg(hwnd, DSZ_CNR, CM_QUERYRECORDEMPHASIS,
574 MPFROMLONG(CMA_FIRST), MPFROMSHORT(CRA_CURSORED));
575 if (pci && (INT) pci != -1) {
576 commafmt(szBytes, sizeof(szBytes), pci->attrFile);
577 sprintf(sz,
578 "%s %s%s",
579 szBytes, GetPString(IDS_FILETEXT), &"s"[pci->attrFile == 1]);
580 }
581 WinSetDlgItemText(hwnd, DSZ_NUMFILES, sz);
582
583 WinSendDlgItemMsg(hwnd, DSZ_CNR, CM_SORTRECORD, MPFROMP(SortSizeCnr),
584 MPVOID);
585 DosBeep(500, 25); // Wake up user
586 return 0;
587
588 case WM_ADJUSTWINDOWPOS:
589 PostMsg(hwnd, UM_STRETCH, MPVOID, MPVOID);
590 break;
591
592 case UM_STRETCH:
593 {
594 SWP swpC, swp;
595
596 WinQueryWindowPos(hwnd, &swp);
597 if (!(swp.fl & (SWP_HIDE | SWP_MINIMIZE))) {
598 WinQueryWindowPos(WinWindowFromID(hwnd, DSZ_CNR), &swpC);
599 WinSetWindowPos(WinWindowFromID(hwnd, DSZ_CNR), HWND_TOP,
600 SysVal(SV_CXSIZEBORDER),
601 swpC.y,
602 swp.cx - (SysVal(SV_CXSIZEBORDER) * 2),
603 (swp.cy - swpC.y) - (SysVal(SV_CYTITLEBAR) +
604 SysVal(SV_CYSIZEBORDER)),
605 SWP_MOVE | SWP_SIZE);
606 }
607 }
608 return 0;
609
610 case WM_DRAWITEM:
611 if (mp2) {
612
613 OWNERITEM *oi = mp2;
614 CNRDRAWITEMINFO *cnd;
615 PCNRITEM pci;
616
617 if (oi->idItem == CMA_TEXT) {
618
619 cnd = (CNRDRAWITEMINFO *)oi->hItem;
620
621 if (cnd) {
622 pci = (PCNRITEM)cnd->pRecord;
623
624 if (pci) {
625 POINTL aptl[TXTBOX_COUNT];
626 POINTL ptl;
627 PSZ p;
628 LONG clr;
629 LONG x;
630 LONG yBottom;
631 INT boxHeight;
632 p = strchr(pci->pszFileName, '\r');
633 if (p) {
634 /* draw text */
635 if (!pci->cbFile) /* no size */
636 GpiSetColor(oi->hps, CLR_DARKGRAY);
637 else if (!pci->easize) /* no size below */
638 GpiSetColor(oi->hps, CLR_DARKBLUE);
639 else
640 GpiSetColor(oi->hps, CLR_BLACK);
641 GpiSetBackMix(oi->hps, BM_LEAVEALONE);
642 GpiSetMix(oi->hps, FM_OVERPAINT);
643
644 *p = 0; // Make 1 line high
645
646 // Calculate nominal graph box height based on font size
647 GpiQueryTextBox(oi->hps, strlen(pci->pszFileName),
648 pci->pszFileName, TXTBOX_COUNT, aptl);
649 boxHeight = aptl[TXTBOX_TOPRIGHT].y - aptl[TXTBOX_BOTTOMRIGHT].y;
650 boxHeight -= 6;
651
652 // Calculate nominal baseline of graph box
653 // rclItem.yBottom is at center of icon because it is
654 yBottom = oi->rclItem.yBottom - boxHeight + 3;
655
656 // Place text above graph box with a bit of whitespace between
657 ptl.x = oi->rclItem.xLeft;
658 ptl.y = yBottom + boxHeight + 8; // 03 Aug 07 SHL
659 // GpiMove(oi->hps, &ptl);
660 GpiCharStringAt(oi->hps, &ptl, strlen(pci->pszFileName),
661 pci->pszFileName);
662
663 *p = '\r'; // Restore
664
665 /* draw the graph box */
666 // GpiQueryTextBox(oi->hps, 1, "#", TXTBOX_COUNT, aptl); // 03 Aug 07 SHL
667 /* draw black outline */
668 GpiSetColor(oi->hps, CLR_BLACK);
669 ptl.x = oi->rclItem.xLeft;
670 ptl.y = yBottom + 2;
671 GpiMove(oi->hps, &ptl);
672 ptl.x = oi->rclItem.xLeft + 101;
673 ptl.y = yBottom + boxHeight;
674 GpiBox(oi->hps, DRO_OUTLINE, &ptl, 0, 0);
675 /* fill with gray */
676 GpiSetColor(oi->hps, CLR_PALEGRAY);
677 ptl.x = oi->rclItem.xLeft + 1;
678 ptl.y = yBottom + 3;
679 GpiMove(oi->hps, &ptl);
680 ptl.x = oi->rclItem.xLeft + 100;
681 ptl.y = yBottom + boxHeight - 1;
682 GpiBox(oi->hps, DRO_OUTLINEFILL, &ptl, 0, 0);
683
684 /* draw shadow at bottom & right sides */
685 GpiSetColor(oi->hps, CLR_DARKGRAY);
686 ptl.x = oi->rclItem.xLeft + 1;
687 ptl.y = yBottom + 3;
688 GpiMove(oi->hps, &ptl);
689 ptl.x = oi->rclItem.xLeft + 100;
690 GpiLine(oi->hps, &ptl);
691 ptl.y = yBottom + boxHeight - 1;
692 GpiLine(oi->hps, &ptl);
693
694 /* draw highlight at top and left sides */
695 GpiSetColor(oi->hps, CLR_WHITE);
696 ptl.x = oi->rclItem.xLeft + 1;
697 GpiLine(oi->hps, &ptl);
698 ptl.y = yBottom + 3;
699 GpiLine(oi->hps, &ptl);
700
701 /* draw shadow of box */
702 GpiSetColor(oi->hps, CLR_DARKGRAY);
703 ptl.x = oi->rclItem.xLeft + 2;
704 ptl.y = yBottom + boxHeight;
705 GpiMove(oi->hps, &ptl);
706 ptl.x = oi->rclItem.xLeft + 103;
707 GpiLine(oi->hps, &ptl);
708 ptl.y = yBottom + boxHeight - 2;
709 GpiLine(oi->hps, &ptl);
710 ptl.x--;
711 GpiMove(oi->hps, &ptl);
712 ptl.y = yBottom + 1;
713 GpiLine(oi->hps, &ptl);
714 ptl.x = oi->rclItem.xLeft + 2;
715 GpiLine(oi->hps, &ptl);
716
717 /* fill box with graph bar, flags is integer % */
718 if (pci->flags) {
719 if (*(pci->pszLongName + 1) == 1) /* is root record */
720 GpiSetColor(oi->hps, CLR_DARKGREEN);
721 else
722 GpiSetColor(oi->hps, CLR_RED);
723 ptl.x = oi->rclItem.xLeft + 1;
724 ptl.y = yBottom + 3;
725 GpiMove(oi->hps, &ptl);
726 ptl.x = oi->rclItem.xLeft + pci->flags;
727 ptl.y = yBottom + boxHeight - 1;
728 GpiBox(oi->hps, DRO_OUTLINEFILL, &ptl, 0, 0);
729
730 /* draw highlights and shadows on graph */
731 if (*(pci->pszLongName + 1) == 1)
732 GpiSetColor(oi->hps, CLR_GREEN);
733 else
734 GpiSetColor(oi->hps, CLR_PALEGRAY);
735 if (pci->flags > 5) {
736 ptl.x = oi->rclItem.xLeft + 1;
737 ptl.y = yBottom + 3;
738 GpiMove(oi->hps, &ptl);
739 ptl.y = yBottom + boxHeight - 1;
740 GpiLine(oi->hps, &ptl);
741 }
742 else {
743 ptl.y = yBottom + boxHeight - 1;
744 GpiMove(oi->hps, &ptl);
745 }
746 ptl.x = oi->rclItem.xLeft + pci->flags;
747 GpiLine(oi->hps, &ptl);
748 if (*(pci->pszLongName + 1) != 1) {
749 GpiSetColor(oi->hps, CLR_DARKRED);
750 ptl.x = oi->rclItem.xLeft + 2;
751 ptl.y = yBottom + 3;
752 GpiMove(oi->hps, &ptl);
753 ptl.x = oi->rclItem.xLeft + pci->flags;
754 GpiLine(oi->hps, &ptl);
755 }
756 }
757
758 /* draw hash marks in box */
759 GpiSetColor(oi->hps, CLR_WHITE);
760 clr = CLR_WHITE;
761 for (x = 1; x < 10; x++) {
762 if (clr == CLR_WHITE && x * 10 > pci->flags) {
763 clr = CLR_BLACK;
764 GpiSetColor(oi->hps, CLR_BLACK);
765 }
766 ptl.x = oi->rclItem.xLeft + 1 + x * 10;
767 ptl.y = yBottom + boxHeight - 1;
768 GpiMove(oi->hps, &ptl);
769 switch (x) {
770 case 1:
771 case 3:
772 case 7:
773 case 9:
774 ptl.y -= 1;
775 break;
776 case 5:
777 ptl.y -= 4;
778 break;
779 case 2:
780 case 4:
781 case 6:
782 case 8:
783 ptl.y -= 2;
784 break;
785 }
786 GpiLine(oi->hps, &ptl);
787 } // for x
788 return MRFROMLONG(TRUE);
789 }
790 }
791 }
792 }
793 }
794 return FALSE; // Let PM draw
795
796 case WM_CONTROL:
797 switch (SHORT2FROMMP(mp1)) {
798 case CN_ENTER:
799 if (mp2) {
800 PCNRITEM pci = (PCNRITEM)((PNOTIFYRECORDENTER)mp2)->pRecord;
801 CHAR szFileName[CCHMAXPATH]; // 23 Jul 07 SHL
802 CHAR szTemp[CCHMAXPATH];
803
804 if (pci) {
805 *szFileName = 0;
806 while (pci && (INT) pci != -1) {
807 memset(szTemp, 0, sizeof(szTemp));
808 strncpy(szTemp, pci->pszFileName,
809 pci->pszDisplayName - pci->pszFileName);
810 strrev(szTemp);
811 if (*szFileName && *szTemp != '\\')
812 strcat(szFileName, "\\");
813 strcat(szFileName, szTemp);
814 pci = WinSendDlgItemMsg(hwnd, DSZ_CNR, CM_QUERYRECORD,
815 MPFROMP(pci),
816 MPFROM2SHORT(CMA_PARENT, CMA_ITEMORDER));
817 }
818 strrev(szFileName);
819 if (!fVTreeOpensWPS)
820 OpenDirCnr((HWND)0,
821 hwndMain ? hwndMain : HWND_DESKTOP,
822 hwnd,
823 FALSE,
824 szFileName);
825 else {
826
827 ULONG size = sizeof(ULONG);
828 ULONG flWindowAttr = CV_ICON;
829 CHAR s[33];
830
831 strcpy(s, "ICON");
832 PrfQueryProfileData(fmprof, appname, "DirflWindowAttr",
833 (PVOID) & flWindowAttr, &size);
834 if (flWindowAttr & CV_DETAIL) {
835 if (IsRoot(szFileName))
836 strcpy(s, "TREE");
837 else
838 strcpy(s, "DETAILS");
839 }
840 OpenObject(szFileName, s, hwnd);
841 }
842 }
843 }
844 break;
845 case CN_EMPHASIS:
846 pState = INSTDATA(hwnd);
847 if (pState && !pState->working && mp2) {
848
849 PNOTIFYRECORDEMPHASIS pre = mp2;
850
851 pci = (PCNRITEM) ((pre) ? pre->pRecord : NULL);
852 if (pci && (pre->fEmphasisMask & CRA_SELECTED) &&
853 (pci->rc.flRecordAttr & CRA_SELECTED)) {
854 commafmt(szBytes, sizeof(szBytes), pci->attrFile);
855 sprintf(sz,
856 "%s %s%s",
857 szBytes,
858 GetPString(IDS_FILETEXT), &"s"[pci->attrFile == 1]);
859 WinSetDlgItemText(hwnd, DSZ_NUMFILES, sz);
860 }
861 }
862 break;
863 }
864 return 0;
865
866 case WM_COMMAND:
867 switch (SHORT1FROMMP(mp1)) {
868 case IDM_HELP:
869 if (hwndHelp)
870 WinSendMsg(hwndHelp, HM_DISPLAY_HELP,
871 MPFROM2SHORT(HELP_DIRSIZE, 0), MPFROMSHORT(HM_RESOURCEID));
872 break;
873
874 case DSZ_PRINT:
875 // Save button
876 pState = INSTDATA(hwnd);
877 if (!pState)
878 Runtime_Error2(pszSrcFile, __LINE__, IDS_NODATATEXT);
879 else {
880
881 CHAR szFileName[CCHMAXPATH];
882 FILE *fp;
883
884 save_dir2(szFileName);
885 sprintf(&szFileName[strlen(szFileName)], "\\%csizes.Rpt",
886 (pState) ? toupper(*pState->szDirName) : '+');
887 if (export_filename(hwnd, szFileName, FALSE) && *szFileName) {
888 if (stricmp(szFileName, "PRN") &&
889 strnicmp(szFileName, "\\DEV\\LPT", 8) &&
890 !strchr(szFileName, '.'))
891 strcat(szFileName, ".RPT");
892 fp = fopen(szFileName, "a+");
893 if (!fp) {
894 saymsg(MB_CANCEL,
895 hwnd,
896 GetPString(IDS_ERRORTEXT),
897 GetPString(IDS_COMPCANTOPENTEXT), szFileName);
898 }
899 else {
900 WinSetPointer(HWND_DESKTOP, hptrBusy);
901 PrintToFile(WinWindowFromID(hwnd, DSZ_CNR), 0, NULL, fp);
902 fclose(fp);
903 WinSetPointer(HWND_DESKTOP, hptrArrow);
904 }
905 }
906 }
907 break;
908
909 case DSZ_EXPAND:
910 case DSZ_COLLAPSE:
911 pState = INSTDATA(hwnd);
912 if (pState) {
913 pci = (PCNRITEM) WinSendDlgItemMsg(hwnd, DSZ_CNR,
914 CM_QUERYRECORDEMPHASIS,
915 MPFROMLONG(CMA_FIRST),
916 MPFROMSHORT(CRA_CURSORED));
917 if (pci) {
918 WinEnableWindow(WinWindowFromID(hwnd, DID_OK), FALSE);
919 WinEnableWindow(WinWindowFromID(hwnd, IDM_HELP), FALSE);
920 WinEnableWindow(WinWindowFromID(hwnd, DSZ_COLLAPSE), FALSE);
921 WinEnableWindow(WinWindowFromID(hwnd, DSZ_EXPAND), FALSE);
922 WinEnableWindow(WinWindowFromID(hwnd, DSZ_PRINT), FALSE);
923 WinEnableWindow(WinWindowFromID(hwnd, DID_CANCEL), FALSE);
924 // fixme to use thread - too slow on large trees
925 ExpandAll(WinWindowFromID(hwnd, DSZ_CNR),
926 (SHORT1FROMMP(mp1) == DSZ_EXPAND), pci);
927 WinEnableWindow(WinWindowFromID(hwnd, DID_OK), TRUE);
928 WinEnableWindow(WinWindowFromID(hwnd, IDM_HELP), TRUE);
929 WinEnableWindow(WinWindowFromID(hwnd, DSZ_COLLAPSE), TRUE);
930 WinEnableWindow(WinWindowFromID(hwnd, DSZ_EXPAND), TRUE);
931 WinEnableWindow(WinWindowFromID(hwnd, DSZ_PRINT), TRUE);
932 WinEnableWindow(WinWindowFromID(hwnd, DID_CANCEL), TRUE);
933 }
934 }
935 break;
936
937 case DID_OK:
938 case DID_CANCEL:
939 pState = INSTDATA(hwnd);
940 if (!pState)
941 Runtime_Error2(pszSrcFile, __LINE__, IDS_NODATATEXT);
942 else {
943 if (pState->working) {
944 pState->dying = TRUE;
945 pState->chStopFlag = (BYTE)0xff;
946 DosBeep(1000, 100); // Complain?
947 }
948 else
949 WinDismissDlg(hwnd, 0);
950 }
951 break;
952 } // switch mp1
953 return 0;
954
955 case WM_CLOSE:
956 pState = INSTDATA(hwnd);
957 if (pState)
958 pState->chStopFlag = (BYTE)0xff;
959 DosSleep(1);
960 break;
961
962 case WM_DESTROY:
963 pState = INSTDATA(hwnd);
964 if (pState) {
965 pState->chStopFlag = (BYTE)0xff;
966 if (pState->hptr)
967 WinDestroyPointer(pState->hptr);
968 DosSleep(16); //05 Aug 07 GKY 33
969 free(pState); // Let's hope no one is still looking
970 }
971 DosPostEventSem(CompactSem);
972 break;
973 }
974 return WinDefDlgProc(hwnd, msg, mp1, mp2);
975}
Note: See TracBrowser for help on using the repository browser.