source: trunk/dll/dirsize.c@ 778

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

Free the memory on error

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