source: trunk/dll/dirsize.c@ 781

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

ProcessDir: remove unneeded reallocs

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