source: trunk/dll/dirsize.c @ 758

Last change on this file since 758 was 758, checked in by Steven Levine, 13 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.