diff options
author | Oliver Schneider <oliver@assarbad.net> | 2015-11-15 22:55:05 +0300 |
---|---|---|
committer | Oliver Schneider <oliver@assarbad.net> | 2015-11-15 22:55:05 +0300 |
commit | 5f42f5d3b026968fd79f2576d545ed899d89bee3 (patch) | |
tree | 5f01a520ed33de5c8ffc019c954ba75b873b089e | |
parent | 88d4fcc77923037e5a9747bc24132983fa909d1d (diff) | |
parent | 57f06afdb61633745ed144a951ad8eb6de2e899c (diff) |
Merging Finnbogi's WiX project
-rw-r--r-- | CONTRIBUTORS.txt | 6 | ||||
-rw-r--r-- | README.md | 2 | ||||
-rw-r--r-- | common/setvcvars.cmd | 85 | ||||
-rw-r--r-- | premake4.lua | 31 | ||||
-rw-r--r-- | windirstat/Controls/treemap.cpp | 256 | ||||
-rw-r--r-- | windirstat/Controls/treemap.h | 25 | ||||
-rw-r--r-- | windirstat/Controls/typeview.cpp | 4 | ||||
-rw-r--r-- | windirstat/Dialogs/SelectDrivesDlg.cpp | 4 | ||||
-rw-r--r-- | windirstat/dirstatdoc.cpp | 4 | ||||
-rw-r--r-- | windirstat/item.cpp | 43 | ||||
-rw-r--r-- | windirstat/item.h | 5 | ||||
-rw-r--r-- | windirstat/stdafx.h | 3 |
12 files changed, 323 insertions, 145 deletions
diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index e114095..65bad28 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -6,6 +6,12 @@ Project creator, initial author Direct contributors
-------------------
+- Falco Peijnenburg
+ * Performance improvments to the treemap rendering
+
+- Morten Asscheman
+ * Performance improvments to the treemap rendering
+
- Oliver Schneider (maintainer)
- Chris Wimmer
@@ -3,7 +3,7 @@ ## Copyright and licenses * Copyright © 2003-2005 Bernhard Seifert (bseifert@users.sourceforge.net) -* Copyright © 2004-2014 WinDirStat team (windirstat.info) +* Copyright © 2004-2015 WinDirStat team (windirstat.info) The application itself is distributed under the terms of the [GPL v2](https://bitbucket.org/windirstat/windirstat/raw/tip/windirstat/res/license.txt), but parts of the source code are also available under more lenient license terms. diff --git a/common/setvcvars.cmd b/common/setvcvars.cmd index 82dce05..7d03038 100644 --- a/common/setvcvars.cmd +++ b/common/setvcvars.cmd @@ -1,18 +1,19 @@ @echo off
@if not "%OS%"=="Windows_NT" @(echo This script requires Windows NT 4.0 or later to run properly! & goto :EOF)
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
-::: 2009-2013, Oliver Schneider (assarbad.net) - PUBLIC DOMAIN/CC0
+::: 2009-2015, Oliver Schneider (assarbad.net) - PUBLIC DOMAIN/CC0
::: Available from: <https://bitbucket.org/assarbad/scripts/>
:::
-::: PURPOSE: This script can be used to run the vcvars32.bat from any of the
-::: existing Visual C++ versions from .NET (2002) through 2013 or
-::: custom given versions (or single version) on the command line.
+::: PURPOSE: This script can be used to run the vcvars32.bat/vcvarsall.bat
+::: from any of the existing Visual C++ versions starting with .NET
+::: (2002) through 2015 or versions (or a single version) given on
+::: the command line.
::: The script will try to find the newest installed VC version by
::: iterating over the space-separated (descending) list of versions
-::: in the variable SUPPORTED_VC below.
+::: in the variable SUPPORTED_VC below, by default.
::: Call it from another script and after that you will have NMAKE,
::: DEVENV.EXE and friends available without having to hardcode
-::: their path into a script or makefile.
+::: their paths into a script or makefile.
:::
::: DISCLAIMER: Disclaimer: This software is provided 'as-is', without any
::: express or implied warranty. In no event will the author be
@@ -20,17 +21,26 @@ ::: software.
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:SCRIPT
-if defined VCVER_FRIENDLY echo This script expects a clean environment. Don't run it several times in the same instance of CMD!&goto :EOF
setlocal & pushd .
+:: Toolsets (potentially) supported
+set SUPPORTED_TSET=amd64 x86 ia64 x86_ia64 x86_amd64 amd64_x86 x86_arm amd64_arm
+if not "%~1" == "" @(
+ if "%~1" == "/?" popd&endlocal&goto :Help
+ if "%~1" == "-?" popd&endlocal&goto :Help
+ if "%~1" == "/h" popd&endlocal&goto :Help
+ if "%~1" == "-h" popd&endlocal&goto :Help
+ if "%~1" == "/help" popd&endlocal&goto :Help
+ if "%~1" == "--help" popd&endlocal&goto :Help
+)
+if defined VCVER_FRIENDLY echo This script expects a clean environment. Don't run it several times in the same instance of CMD! Or use setlocal and endlocal in your own script to limit the effect of this one.&goto :EOF
set MIN_VC=7.0
-set MAX_VC=12.0
+set MAX_VC=14.0
set MIN_NICE=2002
+set MAX_NICE=2015
:: Internal representation of the version number
-set SUPPORTED_VC=12.0 11.0 10.0 9.0 8.0 7.1 7.0
+set SUPPORTED_VC=14.0 12.0 11.0 10.0 9.0 8.0 7.1 7.0
:: Marketing name of the Visual Studio versions
-set SUPPORTED_NICE=2013 2012 2010 2008 2005 2003 2002
-:: Toolsets (potentially) supported
-set SUPPORTED_TSET=amd64 x86 ia64 x86_ia64 x86_amd64 x86_arm
+set SUPPORTED_NICE=2015 2013 2012 2010 2008 2005 2003 2002
set DEFAULT_TSET=x86
reg /? > NUL 2>&1 || echo "REG.EXE is a prerequisite but wasn't found!" && goto :EOF
set SETVCV_ERROR=0
@@ -42,7 +52,7 @@ if not "%~1" == "" @( )
:: Fall back to x86 if not given
if not defined VCTGT_TOOLSET set VCTGT_TOOLSET=%DEFAULT_TSET%
-:: Make the string appear a bit nicer
+:: Make the string appear a bit nicer, i.e. comma-separated
set SUPPORTED_PP=%SUPPORTED_NICE: =, %
:: Allow the version to be overridden on the command line
:: ... else find the VC versions in the order given by SUPPORTED_VC
@@ -82,10 +92,17 @@ goto :EOF setlocal ENABLEEXTENSIONS & set VCVER=%~1
:: We're not interested in overwriting an already existing value
if defined VCVARS_PATH @( endlocal & goto :EOF )
-:: Now let's distinguish the "nice" version numbers (2002, ... 2013) from the internal ones
+:: Now let's distinguish the "nice" version numbers (2002, ... 2015) from the internal ones
+set VCVER=%VCVER:vs=%
if "%VCVER%" geq "%MIN_NICE%" call :NICE_%VCVER% > NUL 2>&1
+:: Figure out the set of supported toolsets
+set VCVERLBL=%VCVER:.=_%
+call :TSET_%VCVERLBL% > NUL 2>&1
:: Jump over those "subs"
goto :NICE_SET
+:NICE_2015
+ set VCVER=14.0
+ goto :EOF
:NICE_2013
set VCVER=12.0
goto :EOF
@@ -107,10 +124,22 @@ goto :NICE_SET :NICE_2002
set VCVER=7.0
goto :EOF
+:TSET_14_0
+:TSET_12_0
+ set SUPPORTED_TSET=x86 amd64 arm x86_amd64 x86_arm amd64_x86 amd64_arm
+ goto :EOF
+:TSET_11_0
+ set SUPPORTED_TSET=x86 amd64 arm x86_amd64 x86_arm
+ goto :EOF
+:TSET_10_0
+:TSET_9_0
+:TSET_8_0
+ set SUPPORTED_TSET=x86 ia64 amd64 x86_amd64 x86_ia64
+ goto :EOF
:NICE_SET
:: This is where we intend to find the installation path in the registry
set _VSINSTALLKEY=HKLM\SOFTWARE\Microsoft\VisualStudio\%VCVER%\Setup\VC
-echo Trying to find Visual C++ %VCVER% ^(%VCTGT_TOOLSET%^)
+echo Trying to locate Visual C++ %VCVER% ^(%VCTGT_TOOLSET%^)
for /f "tokens=2*" %%i in ('reg query "%_VSINSTALLKEY%" /v ProductDir 2^> NUL') do @(
call :SetVar _VCINSTALLDIR "%%j"
)
@@ -122,6 +151,7 @@ if not defined _VCINSTALLDIR @( )
)
set TEMP_TOOLSET=%VCTGT_TOOLSET%
+set TEMP_SUPPORTED=
if defined _VCINSTALLDIR @(
if EXIST "%_VCINSTALLDIR%\vcvarsall.bat" @(
call :SetVar VCVARS_PATH "%_VCINSTALLDIR%\vcvarsall.bat"
@@ -131,7 +161,13 @@ if defined _VCINSTALLDIR @( call :SetVar VCTGT_TOOLSET
)
)
-:
+if not "%VCTGT_TOOLSET%" == "" @(
+ for %%i in (%SUPPORTED_TSET%) do @(
+ if "%VCTGT_TOOLSET%" == "%%i" call :SetVar TEMP_SUPPORTED yes
+ )
+)
+if not "%TEMP_SUPPORTED%" == "yes" @( echo ERROR: Invalid toolset %TEMP_TOOLSET% for version %VCVER% of Visual C++&endlocal&set SETVCV_ERROR=1&goto :EOF )
+set VCTGT_TOOLSET=%TEMP_TOOLSET%
:: Return, in case nothing was found
if not defined VCVARS_PATH @( endlocal&set SETVCV_ERROR=1&goto :EOF )
:: Replace the . in the version by an underscore
@@ -140,6 +176,9 @@ set VCVERLBL=%VCVER:.=_% call :FRIENDLY_%VCVERLBL% > NUL 2>&1
:: Jump over those "subs"
goto :FRIENDLY_SET
+:FRIENDLY_14_0
+ set _VCVER=2015 ^[%TEMP_TOOLSET%^]
+ goto :EOF
:FRIENDLY_12_0
set _VCVER=2013 ^[%TEMP_TOOLSET%^]
goto :EOF
@@ -171,6 +210,20 @@ goto :EOF ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::: / Help subroutine
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+:Help
+echo.
+echo Syntax: setvcvars ^[toolset^] ^[store^] ^[VS versions^]
+echo.
+echo The toolset can be one of %SUPPORTED_TSET% according to the version of Visual Studio.
+echo 'store' is the literal string store for Visual Studio 2015 and newer.
+exit /b 0
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::: \ Help subroutine
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::: / SetVar subroutine
::: Param1 == name of the variable, Param2 == value to be set for the variable
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
diff --git a/premake4.lua b/premake4.lua index 4cd9dcf..98c0313 100644 --- a/premake4.lua +++ b/premake4.lua @@ -25,12 +25,39 @@ if _OPTIONS["release"] then _OPTIONS["release"] = pfx
end
do
+ -- This is mainly to support older premake4 builds
+ if not premake.project.getbasename then
+ print "Magic happens ..."
+ -- override the function to establish the behavior we'd get after patching Premake to have premake.project.getbasename
+ premake.project.getbasename = function(prjname, pattern)
+ return pattern:gsub("%%%%", prjname)
+ end
+ -- obviously we also need to overwrite the following to generate functioning VS solution files
+ premake.vstudio.projectfile = function(prj)
+ local pattern
+ if prj.language == "C#" then
+ pattern = "%%.csproj"
+ else
+ pattern = iif(_ACTION > "vs2008", "%%.vcxproj", "%%.vcproj")
+ end
+
+ local fname = premake.project.getbasename(prj.name, pattern)
+ fname = path.join(prj.location, fname)
+ return fname
+ end
+ -- we simply overwrite the original function on older Premake versions
+ premake.project.getfilename = function(prj, pattern)
+ local fname = premake.project.getbasename(prj.name, pattern)
+ fname = path.join(prj.location, fname)
+ return path.getrelative(os.getcwd(), fname)
+ end
+ end
-- Name the project files after their VS version
local orig_getbasename = premake.project.getbasename
premake.project.getbasename = function(prjname, pattern)
- -- The below is used to insert the .vs(8|9|10|11|12) into the file names for projects and solutions
+ -- The below is used to insert the .vs(8|9|10|11|12|14) into the file names for projects and solutions
if _ACTION then
- name_map = {vs2005 = "vs8", vs2008 = "vs9", vs2010 = "vs10", vs2012 = "vs11", vs2013 = "vs12"}
+ name_map = {vs2005 = "vs8", vs2008 = "vs9", vs2010 = "vs10", vs2012 = "vs11", vs2013 = "vs12", vs2015 = "vs14"}
if name_map[_ACTION] then
pattern = pattern:gsub("%%%%", "%%%%." .. name_map[_ACTION])
else
diff --git a/windirstat/Controls/treemap.cpp b/windirstat/Controls/treemap.cpp index 4df6958..9183e06 100644 --- a/windirstat/Controls/treemap.cpp +++ b/windirstat/Controls/treemap.cpp @@ -29,6 +29,8 @@ #define new DEBUG_NEW #endif +#define BGR(b,g,r) ((COLORREF)(((BYTE)(b)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(r))<<16))) + // I define the "brightness" of an rgb value as (r+b+g)/3/255. // The EqualizeColors() method creates a palette with colors // all having the same brightness of 0.6 @@ -47,8 +49,8 @@ double CColorSpace::GetColorBrightness(COLORREF color) COLORREF CColorSpace::MakeBrightColor(COLORREF color, double brightness) { - ASSERT(brightness >= 0.0); - ASSERT(brightness <= 1.0); + WEAK_ASSERT(brightness >= 0.0); + WEAK_ASSERT(brightness <= 1.0); double dred = (RGB_GET_RVALUE(color) & 0xFF) / 255.0; double dgreen = (RGB_GET_GVALUE(color) & 0xFF) / 255.0; @@ -80,7 +82,7 @@ bool CColorSpace::Is256Colors() void CColorSpace::NormalizeColor(int& red, int& green, int& blue) { - ASSERT(red + green + blue <= 3 * 255); + WEAK_ASSERT(red + green + blue <= 3 * 255); if(red > 255) { @@ -108,14 +110,14 @@ void CColorSpace::DistributeFirst(int& first, int& second, int& third) int h = second - 255; second = 255; third += h; - ASSERT(third <= 255); + WEAK_ASSERT(third <= 255); } else if(third > 255) { int h = third - 255; third = 255; second += h; - ASSERT(second <= 255); + WEAK_ASSERT(second <= 255); } } @@ -222,7 +224,7 @@ CTreemap::CTreemap(Callback *callback) void CTreemap::SetOptions(const Options *options) { - ASSERT(options != NULL); + WEAK_ASSERT(options != NULL); m_options = *options; // Derive normalized vector here for performance @@ -256,7 +258,7 @@ void CTreemap::RecurseCheckTree(Item *item) { if(item->TmiIsLeaf()) { - ASSERT(item->TmiGetChildrenCount() == 0); + WEAK_ASSERT(item->TmiGetChildrenCount() == 0); } else { @@ -268,7 +270,7 @@ void CTreemap::RecurseCheckTree(Item *item) sum += child->TmiGetSize(); RecurseCheckTree(child); } - ASSERT(sum == item->TmiGetSize()); + WEAK_ASSERT(sum == item->TmiGetSize()); } } #endif @@ -314,6 +316,8 @@ void CTreemap::DrawTreemap(CDC *pdc, CRect rc, Item *root, const Options *option return; } + m_renderArea = rc; + if(root->TmiGetSize() > 0) { double surface[4]; @@ -322,7 +326,34 @@ void CTreemap::DrawTreemap(CDC *pdc, CRect rc, Item *root, const Options *option surface[i]= 0; } - RecurseDrawGraph(pdc, root, rc, true, surface, m_options.height, 0); + // Create a temporary CDC that represents only the tree map + CDC dcTreeView; + dcTreeView.CreateCompatibleDC(pdc); + + // This temporary CDC will be filled with this bitmap + CBitmap bmp; + + // That bitmap in turn will be created from this array + CArray<COLORREF, COLORREF> *bitmap = new CArray<COLORREF, COLORREF>; + bitmap->SetSize(rc.Width() * rc.Height()); + + // Recursively draw the tree graph + RecurseDrawGraph(bitmap, root, rc, true, surface, m_options.height, 0); + + // Fill the bitmap with the array + bmp.CreateBitmap(rc.Width(), rc.Height(), 1, 32, &(*bitmap)[0]); + + // Render bitmap to the temporary CDC + dcTreeView.SelectObject(&bmp); + + // And lastly, draw the temporary CDC to the real one + pdc->BitBlt(rc.TopLeft().x, rc.TopLeft().y, rc.Width(), rc.Height(), &dcTreeView, 0, 0, SRCCOPY); + + // Free memory + bmp.DeleteObject(); + dcTreeView.DeleteDC(); + delete bitmap; + #ifdef STRONGDEBUG // slow, but finds bugs! #ifdef _DEBUG @@ -330,7 +361,7 @@ void CTreemap::DrawTreemap(CDC *pdc, CRect rc, Item *root, const Options *option { for(int y = rc.top; y < rc.bottom - m_options.grid; y++) { - ASSERT(FindItemByPoint(root, CPoint(x, y)) != NULL); + WEAK_ASSERT(FindItemByPoint(root, CPoint(x, y)) != NULL); } } #endif @@ -371,7 +402,7 @@ void CTreemap::DrawTreemapDoubleBuffered(CDC *pdc, const CRect& rc, Item *root, CTreemap::Item *CTreemap::FindItemByPoint(Item *item, CPoint point) { - ASSERT(item != NULL); + WEAK_ASSERT(item != NULL); const CRect& rc = item->TmiGetRectangle(); if(!rc.PtInRect(point)) @@ -388,7 +419,7 @@ CTreemap::Item *CTreemap::FindItemByPoint(Item *item, CPoint point) return NULL; } - ASSERT(rc.PtInRect(point)); + WEAK_ASSERT(rc.PtInRect(point)); Item *ret = NULL; @@ -404,14 +435,14 @@ CTreemap::Item *CTreemap::FindItemByPoint(Item *item, CPoint point) } else { - ASSERT(item->TmiGetSize() > 0); - ASSERT(item->TmiGetChildrenCount() > 0); + WEAK_ASSERT(item->TmiGetSize() > 0); + WEAK_ASSERT(item->TmiGetChildrenCount() > 0); for(int i = 0; i < item->TmiGetChildrenCount(); i++) { Item *child = item->TmiGetChild(i); - ASSERT(child->TmiGetSize() > 0); + WEAK_ASSERT(child->TmiGetSize() > 0); #ifdef _DEBUG CRect rcChild(child->TmiGetRectangle()); @@ -425,7 +456,7 @@ CTreemap::Item *CTreemap::FindItemByPoint(Item *item, CPoint point) if(child->TmiGetRectangle().PtInRect(point)) { ret = FindItemByPoint(child, point); - ASSERT(ret != NULL); + WEAK_ASSERT(ret != NULL); #ifdef STRONGDEBUG #ifdef _DEBUG for(i++; i < item->TmiGetChildrenCount(); i++) @@ -440,18 +471,18 @@ CTreemap::Item *CTreemap::FindItemByPoint(Item *item, CPoint point) rcChild = child->TmiGetRectangle(); if(rcChild.left == -1) { - ASSERT(rcChild.top == -1); - ASSERT(rcChild.right == -1); - ASSERT(rcChild.bottom == -1); + WEAK_ASSERT(rcChild.top == -1); + WEAK_ASSERT(rcChild.right == -1); + WEAK_ASSERT(rcChild.bottom == -1); break; } - ASSERT(rcChild.right >= rcChild.left); - ASSERT(rcChild.bottom >= rcChild.top); - ASSERT(rcChild.left >= rc.left); - ASSERT(rcChild.right <= rc.right); - ASSERT(rcChild.top >= rc.top); - ASSERT(rcChild.bottom <= rc.bottom); + WEAK_ASSERT(rcChild.right >= rcChild.left); + WEAK_ASSERT(rcChild.bottom >= rcChild.top); + WEAK_ASSERT(rcChild.left >= rc.left); + WEAK_ASSERT(rcChild.right <= rc.right); + WEAK_ASSERT(rcChild.top >= rc.top); + WEAK_ASSERT(rcChild.bottom <= rc.bottom); } #endif #endif @@ -461,7 +492,7 @@ CTreemap::Item *CTreemap::FindItemByPoint(Item *item, CPoint point) } } - ASSERT(ret != NULL); + WEAK_ASSERT(ret != NULL); if(ret == NULL) { @@ -486,7 +517,31 @@ void CTreemap::DrawColorPreview(CDC *pdc, const CRect& rc, COLORREF color, const AddRidge(rc, surface, m_options.height * m_options.scaleFactor); - RenderRectangle(pdc, rc, surface, color); + m_renderArea = rc; + + // Create a temporary CDC that represents only the tree map + CDC dcTreeView; + dcTreeView.CreateCompatibleDC(pdc); + + // This temporary CDC will be filled with this bitmap + CBitmap bmp; + + // That bitmap in turn will be created from this array + CArray<COLORREF, COLORREF> *bitmap = new CArray<COLORREF, COLORREF>; + bitmap->SetSize(rc.Width() * rc.Height()); + + // Recursively draw the tree graph + RenderRectangle(bitmap, CRect(0, 0, rc.Width(), rc.Height()), surface, color); + + // Fill the bitmap with the array + bmp.CreateBitmap(rc.Width(), rc.Height(), 1, 32, &(*bitmap)[0]); + + // Render bitmap to the temporary CDC + dcTreeView.SelectObject(&bmp); + + // And lastly, draw the temporary CDC to the real one + pdc->BitBlt(rc.TopLeft().x, rc.TopLeft().y, rc.Width(), rc.Height(), &dcTreeView, 0, 0, SRCCOPY); + if(m_options.grid) { CPen pen(PS_SOLID, 1, m_options.gridColor); @@ -494,10 +549,15 @@ void CTreemap::DrawColorPreview(CDC *pdc, const CRect& rc, COLORREF color, const CSelectStockObject sobrush(pdc, NULL_BRUSH); pdc->Rectangle(rc); } + + // Free memory + bmp.DeleteObject(); + dcTreeView.DeleteDC(); + delete bitmap; } void CTreemap::RecurseDrawGraph( - CDC *pdc, + CArray<COLORREF, COLORREF> *bitmap, Item *item, const CRect& rc, bool asroot, @@ -506,8 +566,8 @@ void CTreemap::RecurseDrawGraph( DWORD flags ) { - ASSERT(rc.Width() >= 0); - ASSERT(rc.Height() >= 0); + WEAK_ASSERT(rc.Width() >= 0); + WEAK_ASSERT(rc.Height() >= 0); WEAK_ASSERT(item->TmiGetSize() > 0); @@ -542,14 +602,14 @@ void CTreemap::RecurseDrawGraph( if(item->TmiIsLeaf()) { - RenderLeaf(pdc, item, surface); + RenderLeaf(bitmap, item, surface); } else { - ASSERT(item->TmiGetChildrenCount() > 0); - ASSERT(item->TmiGetSize() > 0); + WEAK_ASSERT(item->TmiGetChildrenCount() > 0); + WEAK_ASSERT(item->TmiGetSize() > 0); - DrawChildren(pdc, item, surface, h, flags); + DrawChildren(bitmap, item, surface, h, flags); } } @@ -559,7 +619,7 @@ void CTreemap::RecurseDrawGraph( // pointers, factory methods and explicit destruction. It's not worth. void CTreemap::DrawChildren( - CDC *pdc, + CArray<COLORREF, COLORREF> *bitmap, Item *parent, const double *surface, double h, @@ -570,19 +630,19 @@ void CTreemap::DrawChildren( { case KDirStatStyle: { - KDirStat_DrawChildren(pdc, parent, surface, h, flags); + KDirStat_DrawChildren(bitmap, parent, surface, h, flags); } break; case SequoiaViewStyle: { - SequoiaView_DrawChildren(pdc, parent, surface, h, flags); + SequoiaView_DrawChildren(bitmap, parent, surface, h, flags); } break; case SimpleStyle: { - Simple_DrawChildren(pdc, parent, surface, h, flags); + Simple_DrawChildren(bitmap, parent, surface, h, flags); } break; } @@ -592,9 +652,9 @@ void CTreemap::DrawChildren( // I learned this squarification style from the KDirStat executable. // It's the most complex one here but also the clearest, imho. // -void CTreemap::KDirStat_DrawChildren(CDC *pdc, Item *parent, const double *surface, double h, DWORD /*flags*/) +void CTreemap::KDirStat_DrawChildren(CArray<COLORREF, COLORREF> *bitmap, Item *parent, const double *surface, double h, DWORD /*flags*/) { - ASSERT(parent->TmiGetChildrenCount() > 0); + WEAK_ASSERT(parent->TmiGetChildrenCount() > 0); const CRect& rc = parent->TmiGetRectangle(); @@ -608,8 +668,8 @@ void CTreemap::KDirStat_DrawChildren(CDC *pdc, Item *parent, const double *surfa const int width = horizontalRows ? rc.Width() : rc.Height(); const int height = horizontalRows ? rc.Height() : rc.Width(); - ASSERT(width >= 0); - ASSERT(height >= 0); + WEAK_ASSERT(width >= 0); + WEAK_ASSERT(height >= 0); int c = 0; double top = horizontalRows ? rc.top : rc.left; @@ -657,11 +717,11 @@ void CTreemap::KDirStat_DrawChildren(CDC *pdc, Item *parent, const double *surfa { CRect test; test.IntersectRect(parent->TmiGetRectangle(), rcChild); - ASSERT(test == rcChild); + WEAK_ASSERT(test == rcChild); } #endif - RecurseDrawGraph(pdc, child, rcChild, false, surface, h * m_options.scaleFactor, 0); + RecurseDrawGraph(bitmap, child, rcChild, false, surface, h * m_options.scaleFactor, 0); if(lastChild) { @@ -678,10 +738,10 @@ void CTreemap::KDirStat_DrawChildren(CDC *pdc, Item *parent, const double *surfa left = fRight; } - // This asserts due to rounding error: ASSERT(left == (horizontalRows ? rc.right : rc.bottom)); + // This asserts due to rounding error: WEAK_ASSERT(left == (horizontalRows ? rc.right : rc.bottom)); top = fBottom; } - // This asserts due to rounding error: ASSERT(top == (horizontalRows ? rc.bottom : rc.right)); + // This asserts due to rounding error: WEAK_ASSERT(top == (horizontalRows ? rc.bottom : rc.right)); } @@ -694,8 +754,8 @@ bool CTreemap::KDirStat_ArrangeChildren( CArray<int, int>& childrenPerRow ) { - ASSERT(!parent->TmiIsLeaf()); - ASSERT(parent->TmiGetChildrenCount() > 0); + WEAK_ASSERT(!parent->TmiIsLeaf()); + WEAK_ASSERT(parent->TmiGetChildrenCount() > 0); if(parent->TmiGetSize() == 0) { @@ -742,13 +802,13 @@ double CTreemap::KDirStat_CalcutateNextRow(Item *parent, const int nextChild, do { int i = 0; static const double _minProportion = 0.4; - ASSERT(_minProportion < 1); + WEAK_ASSERT(_minProportion < 1); - ASSERT(nextChild < parent->TmiGetChildrenCount()); - ASSERT(width >= 1.0); + WEAK_ASSERT(nextChild < parent->TmiGetChildrenCount()); + WEAK_ASSERT(width >= 1.0); const double mySize = (double)parent->TmiGetSize(); - ASSERT(mySize > 0); + WEAK_ASSERT(mySize > 0); ULONGLONG sizeUsed = 0; double rowHeight = 0; @@ -763,8 +823,8 @@ double CTreemap::KDirStat_CalcutateNextRow(Item *parent, const int nextChild, do sizeUsed += childSize; double virtualRowHeight = sizeUsed / mySize; - ASSERT(virtualRowHeight > 0); - ASSERT(virtualRowHeight <= 1); + WEAK_ASSERT(virtualRowHeight > 0); + WEAK_ASSERT(virtualRowHeight <= 1); // Rectangle(mySize) = width * 1.0 // Rectangle(childSize) = childWidth * virtualRowHeight @@ -774,7 +834,7 @@ double CTreemap::KDirStat_CalcutateNextRow(Item *parent, const int nextChild, do if(childWidth / virtualRowHeight < _minProportion) { - ASSERT(i > nextChild); // because width >= 1 and _minProportion < 1. + WEAK_ASSERT(i > nextChild); // because width >= 1 and _minProportion < 1. // For the first child we have: // childWidth / rowHeight // = childSize / mySize * width / rowHeight / rowHeight @@ -816,17 +876,17 @@ double CTreemap::KDirStat_CalcutateNextRow(Item *parent, const int nextChild, do // The classical squarification method. // -void CTreemap::SequoiaView_DrawChildren(CDC *pdc, Item *parent, const double *surface, double h, DWORD /*flags*/) +void CTreemap::SequoiaView_DrawChildren(CArray<COLORREF, COLORREF> *bitmap, Item *parent, const double *surface, double h, DWORD /*flags*/) { // Rest rectangle to fill CRect remaining(parent->TmiGetRectangle()); - ASSERT(remaining.Width() > 0); - ASSERT(remaining.Height() > 0); + WEAK_ASSERT(remaining.Width() > 0); + WEAK_ASSERT(remaining.Height() > 0); // Size of rest rectangle ULONGLONG remainingSize = parent->TmiGetSize(); - ASSERT(remainingSize > 0); + WEAK_ASSERT(remainingSize > 0); // Scale factor const double sizePerSquarePixel = (double)parent->TmiGetSize() / remaining.Width() / remaining.Height(); @@ -837,8 +897,8 @@ void CTreemap::SequoiaView_DrawChildren(CDC *pdc, Item *parent, const double *su // At least one child left while(head < parent->TmiGetChildrenCount()) { - ASSERT(remaining.Width() > 0); - ASSERT(remaining.Height() > 0); + WEAK_ASSERT(remaining.Width() > 0); + WEAK_ASSERT(remaining.Height() > 0); // How we divide the remaining rectangle bool horizontal = (remaining.Width() >= remaining.Height()); @@ -848,7 +908,7 @@ void CTreemap::SequoiaView_DrawChildren(CDC *pdc, Item *parent, const double *su // Square of height in size scale for ratio formula const double hh = (height * height) * sizePerSquarePixel; - ASSERT(hh > 0); + WEAK_ASSERT(hh > 0); // Row will be made up of child(rowBegin)...child(rowEnd - 1) int rowBegin = head; @@ -909,11 +969,11 @@ void CTreemap::SequoiaView_DrawChildren(CDC *pdc, Item *parent, const double *su // As the size of parent is greater than zero, the size of // the first child must have been greater than zero, too. - ASSERT(sum > 0); + WEAK_ASSERT(sum > 0); // Width of row int width = (horizontal ? remaining.Width() : remaining.Height()); - ASSERT(width > 0); + WEAK_ASSERT(width > 0); if(sum < remainingSize) width = (int)((double)sum / remainingSize * width); @@ -963,15 +1023,15 @@ void CTreemap::SequoiaView_DrawChildren(CDC *pdc, Item *parent, const double *su rc.right = end; } - ASSERT(rc.left <= rc.right); - ASSERT(rc.top <= rc.bottom); + WEAK_ASSERT(rc.left <= rc.right); + WEAK_ASSERT(rc.top <= rc.bottom); - ASSERT(rc.left >= remaining.left); - ASSERT(rc.right <= remaining.right); - ASSERT(rc.top >= remaining.top); - ASSERT(rc.bottom <= remaining.bottom); + WEAK_ASSERT(rc.left >= remaining.left); + WEAK_ASSERT(rc.right <= remaining.right); + WEAK_ASSERT(rc.top >= remaining.top); + WEAK_ASSERT(rc.bottom <= remaining.bottom); - RecurseDrawGraph(pdc, parent->TmiGetChild(i), rc, false, surface, h * m_options.scaleFactor, 0); + RecurseDrawGraph(bitmap, parent->TmiGetChild(i), rc, false, surface, h * m_options.scaleFactor, 0); if(lastChild) break; @@ -991,10 +1051,10 @@ void CTreemap::SequoiaView_DrawChildren(CDC *pdc, Item *parent, const double *su remainingSize -= sum; - ASSERT(remaining.left <= remaining.right); - ASSERT(remaining.top <= remaining.bottom); + WEAK_ASSERT(remaining.left <= remaining.right); + WEAK_ASSERT(remaining.top <= remaining.bottom); - ASSERT(remainingSize >= 0); + WEAK_ASSERT(remainingSize >= 0); head += (rowEnd - rowBegin); @@ -1008,30 +1068,30 @@ void CTreemap::SequoiaView_DrawChildren(CDC *pdc, Item *parent, const double *su break; } } - ASSERT(remainingSize == 0); - ASSERT(remaining.left == remaining.right || remaining.top == remaining.bottom); + WEAK_ASSERT(remainingSize == 0); + WEAK_ASSERT(remaining.left == remaining.right || remaining.top == remaining.bottom); } // No squarification. Children are arranged alternately horizontally and vertically. // -void CTreemap::Simple_DrawChildren(CDC *pdc, Item *parent, const double *surface, double h, DWORD flags) +void CTreemap::Simple_DrawChildren(CArray<COLORREF, COLORREF> *bitmap, Item *parent, const double *surface, double h, DWORD flags) { #if 1 - ASSERT(0); // Not used in WinDirStat. + WEAK_ASSERT(0); // Not used in WinDirStat. - pdc; parent; surface; h; flags; + bitmap; parent; surface; h; flags; #else - ASSERT(parent->TmiGetChildrenCount() > 0); - ASSERT(parent->TmiGetSize() > 0); + WEAK_ASSERT(parent->TmiGetChildrenCount() > 0); + WEAK_ASSERT(parent->TmiGetSize() > 0); const CRect& rc = parent->TmiGetRectangle(); bool horizontal = (flags == 0); int width = horizontal ? rc.Width() : rc.Height(); - ASSERT(width >= 0); + WEAK_ASSERT(width >= 0); double fBegin = horizontal ? rc.left : rc.top; int veryEnd = horizontal ? rc.right : rc.bottom; @@ -1052,8 +1112,8 @@ void CTreemap::Simple_DrawChildren(CDC *pdc, Item *parent, const double *surface int begin = (int)fBegin; int end = (int)fEnd; - ASSERT(begin <= end); - ASSERT(end <= veryEnd); + WEAK_ASSERT(begin <= end); + WEAK_ASSERT(end <= veryEnd); CRect rcChild; if(horizontal) @@ -1072,7 +1132,7 @@ void CTreemap::Simple_DrawChildren(CDC *pdc, Item *parent, const double *surface } RecurseDrawGraph( - pdc, + bitmap, parent->TmiGetChild(i), rcChild, false, @@ -1103,7 +1163,7 @@ bool CTreemap::IsCushionShading() && m_options.scaleFactor > 0.0; } -void CTreemap::RenderLeaf(CDC *pdc, Item *item, const double *surface) +void CTreemap::RenderLeaf(CArray<COLORREF, COLORREF> *bitmap, Item *item, const double *surface) { CRect rc = item->TmiGetRectangle(); @@ -1117,10 +1177,10 @@ void CTreemap::RenderLeaf(CDC *pdc, Item *item, const double *surface) } } - RenderRectangle(pdc, rc, surface, item->TmiGetGraphColor()); + RenderRectangle(bitmap, rc, surface, item->TmiGetGraphColor()); } -void CTreemap::RenderRectangle(CDC *pdc, const CRect& rc, const double *surface, DWORD color) +void CTreemap::RenderRectangle(CArray<COLORREF, COLORREF> *bitmap, const CRect& rc, const double *surface, DWORD color) { double brightness = m_options.brightness; @@ -1145,15 +1205,15 @@ void CTreemap::RenderRectangle(CDC *pdc, const CRect& rc, const double *surface, if(IsCushionShading()) { - DrawCushion(pdc, rc, surface, color, brightness); + DrawCushion(bitmap, rc, surface, color, brightness); } else { - DrawSolidRect(pdc, rc, color, brightness); + DrawSolidRect(bitmap, rc, color, brightness); } } -void CTreemap::DrawSolidRect(CDC *pdc, const CRect& rc, COLORREF col, double brightness) +void CTreemap::DrawSolidRect(CArray<COLORREF, COLORREF> *bitmap, const CRect& rc, COLORREF col, double brightness) { int red = RGB_GET_RVALUE(col); int green = RGB_GET_GVALUE(col); @@ -1167,10 +1227,14 @@ void CTreemap::DrawSolidRect(CDC *pdc, const CRect& rc, COLORREF col, double bri CColorSpace::NormalizeColor(red, green, blue); - pdc->FillSolidRect(rc, RGB(red, green, blue)); + for (int iy = rc.top; iy < rc.bottom; iy++) + for (int ix = rc.left; ix < rc.right; ix++) + { + (*bitmap)[ix + iy * m_renderArea.Width()] = BGR(blue, green, red); + } } -void CTreemap::DrawCushion(CDC *pdc, const CRect& rc, const double *surface, COLORREF col, double brightness) +void CTreemap::DrawCushion(CArray<COLORREF, COLORREF> *bitmap, const CRect& rc, const double *surface, COLORREF col, double brightness) { // Cushion parameters const double Ia = m_options.ambientLight; @@ -1200,7 +1264,7 @@ void CTreemap::DrawCushion(CDC *pdc, const CRect& rc, const double *surface, COL } pixel += Ia; - ASSERT(pixel <= 1.0); + WEAK_ASSERT(pixel <= 1.0); // Now, pixel is the brightness of the pixel, 0...1.0. @@ -1221,7 +1285,7 @@ void CTreemap::DrawCushion(CDC *pdc, const CRect& rc, const double *surface, COL CColorSpace::NormalizeColor(red, green, blue); // ... and set! - pdc->SetPixel(ix, iy, RGB(red, green, blue)); + (*bitmap)[ix + iy * m_renderArea.Width()] = BGR(blue, green, red); } } @@ -1248,7 +1312,7 @@ void CTreemap::AddRidge(const CRect& rc, double *surface, double h) int width = rc.Width(); int height = rc.Height(); - ASSERT(width > 0 && height > 0); + WEAK_ASSERT(width > 0 && height > 0); double h4 = 4 * h; diff --git a/windirstat/Controls/treemap.h b/windirstat/Controls/treemap.h index 046bf61..505289f 100644 --- a/windirstat/Controls/treemap.h +++ b/windirstat/Controls/treemap.h @@ -72,7 +72,7 @@ public: // If you prefer to use the getHead()/getNext() pattern rather // than using an array for the children, you will have to // rewrite CTreemap. - // + // class Item { public: @@ -142,7 +142,7 @@ public: void SetLightSourceYPercent(int n) { lightSourceY = n / 100.0; } void SetLightSourcePoint(CPoint pt) { SetLightSourceXPercent(pt.x); SetLightSourceYPercent(pt.y); } - int RoundDouble(double d) { return signum(d) * (int)(abs(d) + 0.5); } + int RoundDouble(double d) { return signum(d) * (int)(fabs(d) + 0.5); } }; public: @@ -187,7 +187,7 @@ public: protected: // The recursive drawing function void RecurseDrawGraph( - CDC *pdc, + CArray<COLORREF, COLORREF> *bitmap, Item *item, const CRect& rc, bool asroot, @@ -198,7 +198,7 @@ protected: // This function switches to KDirStat-, SequoiaView- or Simple_DrawChildren void DrawChildren( - CDC *pdc, + CArray<COLORREF, COLORREF> *bitmap, Item *parent, const double *surface, double h, @@ -206,15 +206,15 @@ protected: ); // KDirStat-like squarification - void KDirStat_DrawChildren(CDC *pdc, Item *parent, const double *surface, double h, DWORD flags); + void KDirStat_DrawChildren(CArray<COLORREF, COLORREF> *bitmap, Item *parent, const double *surface, double h, DWORD flags); bool KDirStat_ArrangeChildren(Item *parent, CArray<double, double>& childWidth, CArray<double, double>& rows, CArray<int, int>& childrenPerRow); double KDirStat_CalcutateNextRow(Item *parent, const int nextChild, double width, int& childrenUsed, CArray<double, double>& childWidth); // Classical SequoiaView-like squarification - void SequoiaView_DrawChildren(CDC *pdc, Item *parent, const double *surface, double h, DWORD flags); + void SequoiaView_DrawChildren(CArray<COLORREF, COLORREF> *bitmap, Item *parent, const double *surface, double h, DWORD flags); // No squarification (simple style, not used in WinDirStat) - void Simple_DrawChildren(CDC *pdc, Item *parent, const double *surface, double h, DWORD flags); + void Simple_DrawChildren(CArray<COLORREF, COLORREF> *bitmap, Item *parent, const double *surface, double h, DWORD flags); // Sets brightness to a good value, if system has only 256 colors void SetBrightnessFor256(); @@ -223,16 +223,17 @@ protected: bool IsCushionShading(); // Leaves space for grid and then calls RenderRectangle() - void RenderLeaf(CDC *pdc, Item *item, const double *surface); + void RenderLeaf(CArray<COLORREF, COLORREF> *bitmap, Item *item, const double *surface); // Either calls DrawCushion() or DrawSolidRect() - void RenderRectangle(CDC *pdc, const CRect& rc, const double *surface, DWORD color); + void RenderRectangle(CArray<COLORREF, COLORREF> *bitmap, const CRect& rc, const double *surface, DWORD color); + // void RenderRectangle(CDC *pdc, const CRect& rc, const double *surface, DWORD color); // Draws the surface using SetPixel() - void DrawCushion(CDC *pdc, const CRect& rc, const double *surface, COLORREF col, double brightness); + void DrawCushion(CArray<COLORREF, COLORREF> *bitmap, const CRect& rc, const double *surface, COLORREF col, double brightness); // Draws the surface using FillSolidRect() - void DrawSolidRect(CDC *pdc, const CRect& rc, COLORREF col, double brightness); + void DrawSolidRect(CArray<COLORREF, COLORREF> *bitmap, const CRect& rc, COLORREF col, double brightness); // Adds a new ridge to surface static void AddRidge(const CRect& rc, double *surface, double h); @@ -242,6 +243,8 @@ protected: static const COLORREF _defaultCushionColors[]; // Standard palette for WinDirStat static const COLORREF _defaultCushionColors256[]; // Palette for 256-colors mode + CRect m_renderArea; + Options m_options; // Current options double m_Lx; // Derived parameters double m_Ly; diff --git a/windirstat/Controls/typeview.cpp b/windirstat/Controls/typeview.cpp index 756bd7e..9b09372 100644 --- a/windirstat/Controls/typeview.cpp +++ b/windirstat/Controls/typeview.cpp @@ -182,13 +182,13 @@ int CExtensionListControl::CListItem::Compare(const CSortingListItem *baseOther, case COL_COLOR: case COL_BYTES: { - r = signum(m_record.bytes - other->m_record.bytes); + r = usignum(m_record.bytes, other->m_record.bytes); } break; case COL_FILES: { - r = signum(m_record.files - other->m_record.files); + r = usignum(m_record.files, other->m_record.files); } break; diff --git a/windirstat/Dialogs/SelectDrivesDlg.cpp b/windirstat/Dialogs/SelectDrivesDlg.cpp index 7232211..7b23e21 100644 --- a/windirstat/Dialogs/SelectDrivesDlg.cpp +++ b/windirstat/Dialogs/SelectDrivesDlg.cpp @@ -166,12 +166,12 @@ int CDriveItem::Compare(const CSortingListItem *baseOther, int subitem) const break; case COL_TOTAL: { - r = signum(m_totalBytes - other->m_totalBytes); + r = usignum(m_totalBytes, other->m_totalBytes); } break; case COL_FREE: { - r = signum(m_freeBytes - other->m_freeBytes); + r = usignum(m_freeBytes, other->m_freeBytes); } break; case COL_GRAPH: diff --git a/windirstat/dirstatdoc.cpp b/windirstat/dirstatdoc.cpp index 01277ec..dee3ede 100644 --- a/windirstat/dirstatdoc.cpp +++ b/windirstat/dirstatdoc.cpp @@ -749,6 +749,8 @@ void CDirstatDoc::RebuildExtensionData() CWaitCursor wc; m_extensionData.RemoveAll(); + // 2048 is a rough estimate for amount of different extensions + m_extensionData.InitHashTable(2048); m_rootItem->RecurseCollectExtensionData(&m_extensionData); CStringArray sortedExtensions; @@ -808,7 +810,7 @@ int __cdecl CDirstatDoc::_compareExtensions(const void *item1, const void *item2 SExtensionRecord r2; VERIFY(_pqsortExtensionData->Lookup(*ext1, r1)); VERIFY(_pqsortExtensionData->Lookup(*ext2, r2)); - return signum(r2.bytes - r1.bytes); + return usignum(r2.bytes, r1.bytes); } void CDirstatDoc::SetWorkingItemAncestor(CItem *item) diff --git a/windirstat/item.cpp b/windirstat/item.cpp index 50452d9..d788cf8 100644 --- a/windirstat/item.cpp +++ b/windirstat/item.cpp @@ -55,6 +55,7 @@ CItem::CItem(ITEMTYPE type, LPCTSTR name, bool dontFollow) , m_readJobs(0) , m_attributes(0) { + m_etype = (ITEMTYPE)(m_type & ~ITF_FLAGS); // returned by GetType if(GetType() == IT_FILE || dontFollow || GetType() == IT_FREESPACE || GetType() == IT_UNKNOWN || GetType() == IT_MYCOMPUTER) { SetReadJobDone(); @@ -277,7 +278,7 @@ int CItem::CompareSibling(const CTreeListItem *tlib, int subitem) const case COL_SUBTREEPERCENTAGE: if(MustShowReadJobs()) { - r = signum(m_readJobs - other->m_readJobs); + r = usignum(m_readJobs, other->m_readJobs); } else { @@ -293,25 +294,25 @@ int CItem::CompareSibling(const CTreeListItem *tlib, int subitem) const case COL_SUBTREETOTAL: { - r = signum(GetSize() - other->GetSize()); + r = usignum(GetSize(), other->GetSize()); } break; case COL_ITEMS: { - r = signum(GetItemsCount() - other->GetItemsCount()); + r = usignum(GetItemsCount(), other->GetItemsCount()); } break; case COL_FILES: { - r = signum(GetFilesCount() - other->GetFilesCount()); + r = usignum(GetFilesCount(), other->GetFilesCount()); } break; case COL_SUBDIRS: { - r = signum(GetSubdirsCount() - other->GetSubdirsCount()); + r = usignum(GetSubdirsCount(), other->GetSubdirsCount()); } break; @@ -829,7 +830,7 @@ double CItem::GetFraction() const ITEMTYPE CItem::GetType() const { - return (ITEMTYPE)(m_type & ~ITF_FLAGS); + return m_etype; } bool CItem::IsRootItem() const @@ -909,20 +910,27 @@ CString CItem::GetName() const CString CItem::GetExtension() const { + if (m_extension_cached) + return m_extension; + CString ext; + CString name = GetName(); + switch (GetType()) { case IT_FILE: { - int i = GetName().ReverseFind(wds::chrDot); + int i = name.ReverseFind(wds::chrDot); if(i == -1) { - ext = _T("."); + ext = L"."; } else { - ext = GetName().Mid(i); + // Faster than name.Mid(i); + LPCTSTR alpha = static_cast<LPCTSTR>(name); + ext = &alpha[i]; } ext.MakeLower(); break; @@ -930,7 +938,7 @@ CString CItem::GetExtension() const case IT_FREESPACE: case IT_UNKNOWN: { - ext = GetName(); + ext = name; } break; @@ -938,6 +946,9 @@ CString CItem::GetExtension() const ASSERT(0); } + m_extension = ext; + m_extension_cached = true; + return ext; } @@ -1135,6 +1146,11 @@ void CItem::DoSomeWork(DWORD ticks) } if(GetType() == IT_DRIVE || GetType() == IT_DIRECTORY || GetType() == IT_MYCOMPUTER) { + + // <HACK! IsDone() is set after first pass with no decend into dirs + UpwardSetUndone(); + // HACK> + ASSERT(IsReadJobDone()); if(IsDone()) { @@ -1600,9 +1616,10 @@ void CItem::RecurseCollectExtensionData(CExtensionData *ed) { GetWDSApp()->PeriodicalUpdateRamUsage(); - if(IsLeaf(GetType())) + auto type = GetType(); + if(IsLeaf(type)) { - if(GetType() == IT_FILE) + if(type == IT_FILE) { CString ext = GetExtension(); SExtensionRecord r; @@ -1638,7 +1655,7 @@ int __cdecl CItem::_compareBySize(const void *p1, const void *p2) // TODO: Use 2nd sort column (as set in our TreeListView?) - return signum(size2 - size1); // biggest first + return usignum(size2, size1); // biggest first } ULONGLONG CItem::GetProgressRangeMyComputer() const diff --git a/windirstat/item.h b/windirstat/item.h index e6e748f..55f2bba 100644 --- a/windirstat/item.h +++ b/windirstat/item.h @@ -62,7 +62,7 @@ enum ITEMTYPE }; // Whether an item type is a leaf type -inline bool IsLeaf(ITEMTYPE t) { return t == IT_FILE || t == IT_FREESPACE || t == IT_UNKNOWN; } +inline bool IsLeaf(ITEMTYPE t) { return ((t == IT_FILE) | (t == IT_FREESPACE) | (t == IT_UNKNOWN)); } // Compare FILETIMEs inline bool operator< (const FILETIME& t1, const FILETIME& t2) @@ -220,7 +220,10 @@ private: void DrivePacman(); ITEMTYPE m_type; // Indicates our type. See ITEMTYPE. + ITEMTYPE m_etype; CString m_name; // Display name + mutable CString m_extension; // Cache of extension (it's used often) + mutable bool m_extension_cached = false; ULONGLONG m_size; // OwnSize, if IT_FILE or IT_FREESPACE, or IT_UNKNOWN; SubtreeTotal else. ULONGLONG m_files; // # Files in subtree ULONGLONG m_subdirs; // # Folder in subtree diff --git a/windirstat/stdafx.h b/windirstat/stdafx.h index 1514704..8c34010 100644 --- a/windirstat/stdafx.h +++ b/windirstat/stdafx.h @@ -78,6 +78,9 @@ template<class T> int signum(T x) { return (x) < 0 ? -1 : (x) == 0 ? 0 : 1; } +/// signum function for unsigned numbers. +template<class T> int usignum(T x, T y) { return (x) < (y) ? -1 : (x) == (y) ? 0 : 1; } + #define WEAK_ASSERT /##/ ASSERT #endif // __WDS_STDAFX_H__ |