- Use a separate icon for minimizing windows.
[reactos.git] / reactos / subsys / system / explorer / explorer.cpp
index b6558a3..d2f1df1 100644 (file)
@@ -182,9 +182,7 @@ bool FileTypeManager::is_exe_file(LPCTSTR ext)
 
 const FileTypeInfo& FileTypeManager::operator[](String ext)
 {
-#ifndef __WINE__ ///@todo _tcslwr() for Wine
-       _tcslwr(&ext.at(0));
-#endif
+       ext.toLower();
 
        iterator found = find(ext);
        if (found != end())
@@ -248,10 +246,10 @@ Icon::Icon()
 {
 }
 
-Icon::Icon(ICON_ID id, UINT nid)
+Icon::Icon(ICON_ID id, UINT nid)       //, int cx, int cy
  :     _id(id),
        _itype(IT_STATIC),
-       _hicon(SmallIcon(nid))
+       _hicon(ResIcon(nid))    // ResIconEx(nid, cx, cy)
 {
 }
 
@@ -324,7 +322,24 @@ int Icon::add_to_imagelist(HIMAGELIST himl, HDC hdc_wnd, COLORREF bk_color, HBRU
        return ret;
 }
 
-HBITMAP create_bitmap_from_icon(HICON hIcon, HBRUSH hbrush_bkgnd, HDC hdc_wnd)
+HBITMAP create_bitmap_from_icon(HICON hIcon, HBRUSH hbrush_bkgnd, HDC hdc_wnd/*, bool large_icons*/)
+{
+       int cx = GetSystemMetrics(SM_CXSMICON); //ICON_SIZE_X;
+       int cy = GetSystemMetrics(SM_CYSMICON); //ICON_SIZE_Y;
+       HBITMAP hbmp = CreateCompatibleBitmap(hdc_wnd, cx, cy);
+
+       MemCanvas canvas;
+       BitmapSelection sel(canvas, hbmp);
+
+       RECT rect = {0, 0, cx, cy};
+       FillRect(canvas, &rect, hbrush_bkgnd);
+
+       DrawIconEx(canvas, 0, 0, hIcon, cx, cy, 0, hbrush_bkgnd, DI_NORMAL);
+
+       return hbmp;
+}
+
+HBITMAP create_small_bitmap_from_icon(HICON hIcon, HBRUSH hbrush_bkgnd, HDC hdc_wnd)
 {
        int cx = GetSystemMetrics(SM_CXSMICON);
        int cy = GetSystemMetrics(SM_CYSMICON);
@@ -378,49 +393,94 @@ void IconCache::init()
        _icons[ICID_COMPUTER]   = Icon(ICID_COMPUTER,   IDI_COMPUTER);
        _icons[ICID_LOGOFF]             = Icon(ICID_LOGOFF,             IDI_LOGOFF);
        _icons[ICID_BOOKMARK]   = Icon(ICID_BOOKMARK,   IDI_DOT_TRANS);
+    _icons[ICID_MINIMIZE]      = Icon(ICID_MINIMIZE,   IDI_MINIMIZE);
 }
 
 
-const Icon& IconCache::extract(const String& path)
+const Icon& IconCache::extract(LPCTSTR path, ICONCACHE_FLAGS flags)
 {
-       PathMap::iterator found = _pathMap.find(path);
+        // search for matching icon with unchanged flags in the cache
+       CacheKey mapkey(path, flags);
+       PathCacheMap::iterator found = _pathCache.find(mapkey);
 
-       if (found != _pathMap.end())
+       if (found != _pathCache.end())
                return _icons[found->second];
 
+        // search for matching icon with handle
+       CacheKey mapkey_hicon(path, flags|ICF_HICON);
+       if (flags != mapkey_hicon.second) {
+               found = _pathCache.find(mapkey_hicon);
+
+               if (found != _pathCache.end())
+                       return _icons[found->second];
+       }
+
+        // search for matching icon in the system image list cache
+       CacheKey mapkey_syscache(path, flags|ICF_SYSCACHE);
+       if (flags != mapkey_syscache.second) {
+               found = _pathCache.find(mapkey_syscache);
+
+               if (found != _pathCache.end())
+                       return _icons[found->second];
+       }
+
        SHFILEINFO sfi;
 
-#if 1  // use system image list - the "search program dialog" needs it
-       HIMAGELIST himlSys = (HIMAGELIST) SHGetFileInfo(path, 0, &sfi, sizeof(sfi), SHGFI_SYSICONINDEX|SHGFI_SMALLICON);
+       int shgfi_flags = 0;
 
-       if (himlSys) {
-               _himlSys = himlSys;
+       if (flags & ICF_OPEN)
+               shgfi_flags |= SHGFI_OPENICON;
 
-               const Icon& icon = add(sfi.iIcon/*, IT_SYSCACHE*/);
-#else
-       if (SHGetFileInfo(path, 0, &sfi, sizeof(sfi), SHGFI_ICON|SHGFI_SMALLICON)) {
-               const Icon& icon = add(sfi.hIcon, IT_CACHED);
-#endif
+       if ((flags&(ICF_LARGE|ICF_OVERLAYS|ICF_HICON)) && !(flags&ICF_SYSCACHE)) {
+               shgfi_flags |= SHGFI_ICON;
 
-               ///@todo limit cache size
-               _pathMap[path] = icon;
+               if (!(flags & ICF_LARGE))
+                       shgfi_flags |= SHGFI_SMALLICON;
 
-               return icon;
-       } else
-               return _icons[ICID_NONE];
+               if (flags & ICF_OVERLAYS)
+                       shgfi_flags |= SHGFI_ADDOVERLAYS;
+
+                // get small/big icons with/without overlays
+               if (SHGetFileInfo(path, 0, &sfi, sizeof(sfi), shgfi_flags)) {
+                       const Icon& icon = add(sfi.hIcon, IT_CACHED);
+
+                       ///@todo limit cache size
+                       _pathCache[mapkey_hicon] = icon;
+
+                       return icon;
+               }
+       } else {
+               assert(!(flags&ICF_OVERLAYS));
+
+               shgfi_flags |= SHGFI_SYSICONINDEX|SHGFI_SMALLICON;
+
+                // use system image list - the "search program dialog" needs it
+               HIMAGELIST himlSys_small = (HIMAGELIST) SHGetFileInfo(path, 0, &sfi, sizeof(sfi), shgfi_flags);
+
+               if (himlSys_small) {
+                       _himlSys_small = himlSys_small;
+
+                       const Icon& icon = add(sfi.iIcon/*, IT_SYSCACHE*/);
+
+                       ///@todo limit cache size
+                       _pathCache[mapkey_syscache] = icon;
+
+                       return icon;
+               }
+       }
+
+       return _icons[ICID_NONE];
 }
 
-const Icon& IconCache::extract(LPCTSTR path, int idx)
+const Icon& IconCache::extract(LPCTSTR path, int idx, ICONCACHE_FLAGS flags)
 {
-       CachePair key(path, idx);
+       IdxCacheKey key(path, make_pair(idx, (flags|ICF_HICON)&~ICF_SYSCACHE));
 
-#ifndef __WINE__ ///@todo _tcslwr() for Wine
-       _tcslwr(&key.first.at(0));
-#endif
+       key.first.toLower();
 
-       PathIdxMap::iterator found = _pathIdxMap.find(key);
+       IdxCacheMap::iterator found = _idxCache.find(key);
 
-       if (found != _pathIdxMap.end())
+       if (found != _idxCache.end())
                return _icons[found->second];
 
        HICON hIcon;
@@ -428,7 +488,7 @@ const Icon& IconCache::extract(LPCTSTR path, int idx)
        if ((int)ExtractIconEx(path, idx, NULL, &hIcon, 1) > 0) {
                const Icon& icon = add(hIcon, IT_CACHED);
 
-               _pathIdxMap[key] = icon;
+               _idxCache[key] = icon;
 
                return icon;
        } else {
@@ -439,19 +499,27 @@ const Icon& IconCache::extract(LPCTSTR path, int idx)
        }
 }
 
-const Icon& IconCache::extract(IExtractIcon* pExtract, LPCTSTR path, int idx)
+const Icon& IconCache::extract(IExtractIcon* pExtract, LPCTSTR path, int idx, ICONCACHE_FLAGS flags)
 {
        HICON hIconLarge = 0;
        HICON hIcon;
 
-       HRESULT hr = pExtract->Extract(path, idx, &hIconLarge, &hIcon, MAKELONG(0/*GetSystemMetrics(SM_CXICON)*/,GetSystemMetrics(SM_CXSMICON)));
+       bool large_icons = flags & ICF_LARGE;
+       HRESULT hr = pExtract->Extract(path, idx, &hIconLarge, &hIcon, MAKELONG(GetSystemMetrics(SM_CXICON), ICON_SIZE_X));
 
        if (hr == NOERROR) {    //@@ oder SUCCEEDED(hr) ?
-               if (hIconLarge)
-                       DestroyIcon(hIconLarge);
+               if (large_icons) {      //@@ OK?
+                       if (hIcon)
+                               DestroyIcon(hIcon);
+
+                       hIcon = hIconLarge;
+               } else {
+                       if (hIconLarge)
+                               DestroyIcon(hIconLarge);
+               }
 
                if (hIcon)
-                       return add(hIcon);
+                       return add(hIcon);      //@@ When do we want not to free this icons?
        }
 
        return _icons[ICID_NONE];
@@ -561,7 +629,8 @@ void explorer_show_frame(int cmdShow, LPTSTR lpCmdLine)
        cmd._cmdShow = cmdShow;
 
         // parse command line options, which may overwrite the MDI flag
-       cmd.ParseCmdLine(lpCmdLine);
+       if (lpCmdLine)
+               cmd.ParseCmdLine(lpCmdLine);
 
         // create main window
        MainFrameBase::Create(cmd);
@@ -872,7 +941,7 @@ int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdL
                 // install ROS Explorer into the registry
                TCHAR path[MAX_PATH];
 
-               int l = GetModuleFileName(0, path, MAX_PATH);
+               int l = GetModuleFileName(0, path, COUNTOF(path));
                if (l) {
                        HKEY hkey;
 
@@ -956,7 +1025,7 @@ int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdL
                _dup2(_open_osfhandle((long)GetStdHandle(STD_OUTPUT_HANDLE), 0), 1);
                _dup2(_open_osfhandle((long)GetStdHandle(STD_ERROR_HANDLE), 0), 2);
 
-               g_Globals._log = fdopen(1, "w");
+               g_Globals._log = _fdopen(1, "w");
                setvbuf(g_Globals._log, 0, _IONBF, 0);
 
                LOG(TEXT("starting explorer debug log\n"));