source: trunk/dll/dirsize.c @ 739

Last change on this file since 739 was 739, checked in by Steven Levine, 13 years ago

More ticket #24 updates

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