Index: dll/win32/shimgvw/CMakeLists.txt =================================================================== --- dll/win32/shimgvw/CMakeLists.txt (revision 61535) +++ dll/win32/shimgvw/CMakeLists.txt (working copy) @@ -18,6 +18,7 @@ gdi32 gdiplus comdlg32 + shlwapi msvcrt kernel32 ntdll) Index: dll/win32/shimgvw/shimgvw.c =================================================================== --- dll/win32/shimgvw/shimgvw.c (revision 61535) +++ dll/win32/shimgvw/shimgvw.c (working copy) @@ -26,6 +26,7 @@ #include #include #include +#include #define NDEBUG #include @@ -35,6 +36,7 @@ HINSTANCE hInstance; SHIMGVW_SETTINGS shiSettings; +SHIMGVW_FILENODE *currentFile; GpImage *image; WNDPROC PrevProc = NULL; @@ -141,6 +143,166 @@ } static VOID +pLoadImageFromNode(SHIMGVW_FILENODE *node, HWND hwnd) +{ + WCHAR szTitleBuf[800]; + WCHAR szResStr[512]; + WCHAR *c; + + if (node) + { + c = wcsrchr(node->FileName, '\\'); + if (c) + { + c++; + } + + LoadStringW(hInstance, IDS_APPTITLE, szResStr, 512); + StringCbPrintfExW(szTitleBuf, 800, NULL, NULL, 0, L"%ls%ls%ls", szResStr, L" - ", c); + SetWindowTextW(hwnd, szTitleBuf); + + if (image) + { + GdipDisposeImage(image); + } + + pLoadImage(node->FileName); + InvalidateRect(hDispWnd, NULL, TRUE); + UpdateWindow(hDispWnd); + } +} + +static SHIMGVW_FILENODE* +pBuildFileList(LPWSTR szFirstFile) +{ + HANDLE hFindHandle; + WCHAR *extension; + WCHAR szSearchPath[MAX_PATH]; + WCHAR szSearchMask[MAX_PATH]; + WCHAR szFileTypes[MAX_PATH]; + WIN32_FIND_DATAW findData; + SHIMGVW_FILENODE *currentNode; + SHIMGVW_FILENODE *root; + SHIMGVW_FILENODE *conductor; + ImageCodecInfo *codecInfo; + UINT num; + UINT size; + UINT j; + + + wcscpy(szSearchPath, szFirstFile); + PathRemoveFileSpecW(szSearchPath); + + GdipGetImageDecodersSize(&num, &size); + codecInfo = malloc(size); + if (!codecInfo) + { + DPRINT1("malloc() failed in pLoadFileList()\n"); + return NULL; + } + + GdipGetImageDecoders(num, size, codecInfo); + + root = malloc(sizeof(SHIMGVW_FILENODE)); + if (!root) + { + DPRINT1("malloc() failed in pLoadFileList()\n"); + free(codecInfo); + return NULL; + } + + conductor = root; + + for (j = 0; j < num; ++j) + { + StringCbPrintfExW(szFileTypes, MAX_PATH, NULL, NULL, 0, L"%ls", codecInfo[j].FilenameExtension); + + extension = wcstok(szFileTypes, L";"); + while (extension != NULL) + { + StringCbPrintfExW(szSearchMask, MAX_PATH, NULL, NULL, 0, L"%ls%ls%ls", szSearchPath, L"\\", extension); + + hFindHandle = FindFirstFileW(szSearchMask, &findData); + if (hFindHandle != INVALID_HANDLE_VALUE) + { + do + { + StringCbPrintfExW(conductor->FileName, MAX_PATH, NULL, NULL, 0, L"%ls%ls%ls", szSearchPath, L"\\", findData.cFileName); + + // compare the name of the requested file with the one currently found. + // if the name matches, the current node is returned by the function. + if (wcscmp(szFirstFile, conductor->FileName) == 0) + { + currentNode = conductor; + } + + conductor->Next = malloc(sizeof(SHIMGVW_FILENODE)); + + // if malloc fails, make circular what we have and return it + if (!conductor->Next) + { + DPRINT1("malloc() failed in pLoadFileList()\n"); + + conductor->Next = root; + root->Prev = conductor; + + FindClose(hFindHandle); + free(codecInfo); + return conductor; + } + + conductor->Next->Prev = conductor; + conductor = conductor->Next; + } + while (FindNextFileW(hFindHandle, &findData) != 0); + + FindClose(hFindHandle); + } + + extension = wcstok(NULL, L";"); + } + } + + // we now have a node too much in the list. In case the requested file was not found, + // we use this node to store the name of it, otherwise we free it. + if (currentNode == NULL) + { + StringCbPrintfExW(conductor->FileName, MAX_PATH, NULL, NULL, 0, L"%ls", szFirstFile); + currentNode = conductor; + } + else + { + conductor = conductor->Prev; + free(conductor->Next); + } + + // link the last node with the first one to make the list circular + conductor->Next = root; + root->Prev = conductor; + conductor = currentNode; + + free(codecInfo); + + return conductor; +} + +static VOID +pFreeFileList(SHIMGVW_FILENODE *root) +{ + SHIMGVW_FILENODE *conductor; + + root->Prev->Next = NULL; + root->Prev = NULL; + + while (root) + { + conductor = root; + root = conductor->Next; + free(conductor); + } +} + +static VOID ImageView_DrawImage(HWND hwnd) { GpGraphics *graphics; @@ -391,9 +553,17 @@ switch (wParam) { case IDC_PREV: + { + currentFile = currentFile->Prev; + pLoadImageFromNode(currentFile, hwnd); + } break; case IDC_NEXT: + { + currentFile = currentFile->Next; + pLoadImageFromNode(currentFile, hwnd); + } break; case IDC_ZOOMP: @@ -502,6 +672,7 @@ ULONG_PTR gdiplusToken; WNDCLASS WndClass = {0}; TCHAR szBuf[512]; + WCHAR szInitialFile[MAX_PATH]; HWND hMainWnd; MSG msg; @@ -540,6 +711,16 @@ CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, NULL, NULL, hInstance, NULL); + // make sure the path has no quotes on it + wcscpy(szInitialFile, szFileName); + PathUnquoteSpacesW(szInitialFile); + + currentFile = pBuildFileList(szInitialFile); + if (currentFile) + { + pLoadImageFromNode(currentFile, hMainWnd); + } + // Show it ShowWindow(hMainWnd, SW_SHOW); UpdateWindow(hMainWnd); @@ -551,6 +732,8 @@ DispatchMessageW(&msg); } + pFreeFileList(currentFile); + if (image) GdipDisposeImage(image); GdiplusShutdown(gdiplusToken); Index: dll/win32/shimgvw/shimgvw.h =================================================================== --- dll/win32/shimgvw/shimgvw.h (revision 61535) +++ dll/win32/shimgvw/shimgvw.h (working copy) @@ -13,3 +13,10 @@ INT Right; INT Bottom; } SHIMGVW_SETTINGS; + +typedef struct SHIMGVW_FILENODE_INTERNAL +{ + WCHAR FileName[MAX_PATH]; + struct SHIMGVW_FILENODE_INTERNAL *Prev; + struct SHIMGVW_FILENODE_INTERNAL *Next; +} SHIMGVW_FILENODE;