source: trunk/dll/dirsize.c@ 758

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

DirSizeProc; correct sizing and positioning to be deterministic

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