#include "main.h"
#include "listview.h"
-//#include "entries.h"
+#include "dialogs.h"
#include "utils.h"
-
+#include "run.h"
#include "trace.h"
+
+////////////////////////////////////////////////////////////////////////////////
// Global Variables:
+//
+
extern HINSTANCE hInst;
+static WNDPROC g_orgListWndProc;
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Local module support methods
+//
static void init_output(HWND hWnd)
{
ShowWindow(hWnd, SW_SHOW);
}
+#define MAX_LIST_COLUMNS 5
+static int default_column_widths[MAX_LIST_COLUMNS] = { 175, 100, 100, 100, 70 };
+static int column_alignment[MAX_LIST_COLUMNS] = { LVCFMT_LEFT, LVCFMT_RIGHT, LVCFMT_RIGHT, LVCFMT_RIGHT, LVCFMT_LEFT };
+
static void CreateListColumns(HWND hWndListView)
{
- char szText[50];
+ TCHAR szText[50];
int index;
LV_COLUMN lvC;
// Create columns.
lvC.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
- lvC.fmt = LVCFMT_LEFT;
- lvC.cx = 175;
lvC.pszText = szText;
// Load the column labels from the resource file.
- for (index = 0; index < 4; index++) {
+ for (index = 0; index < MAX_LIST_COLUMNS; index++) {
lvC.iSubItem = index;
+ lvC.cx = default_column_widths[index];
+ lvC.fmt = column_alignment[index];
LoadString(hInst, IDS_LIST_COLUMN_FIRST + index, szText, sizeof(szText));
if (ListView_InsertColumn(hWndListView, index, &lvC) == -1) {
// TODO: handle failure condition...
// Get the dimensions of the parent window's client area, and create the list view control.
GetClientRect(hwndParent, &rcClient);
- hwndLV = CreateWindowEx(0, WC_LISTVIEW, "List View",
+ hwndLV = CreateWindowEx(0, WC_LISTVIEW, _T("List View"),
// WS_VISIBLE | WS_CHILD | WS_BORDER | LVS_REPORT | LVS_NOCOLUMNHEADER,
WS_VISIBLE | WS_CHILD | WS_BORDER | LVS_REPORT,
-// WS_VISIBLE | WS_CHILD | WS_BORDER | LVS_LIST | LVS_NOCOLUMNHEADER,
0, 0, rcClient.right, rcClient.bottom,
hwndParent, (HMENU)id, hInst, NULL);
return hwndLV;
}
+/*
+int GetNumberFormat(
+ LCID Locale, // locale
+ DWORD dwFlags, // options
+ LPCTSTR lpValue, // input number string
+ CONST NUMBERFMT *lpFormat, // formatting information
+ LPTSTR lpNumberStr, // output buffer
+ int cchNumber // size of output buffer
+);
+ */
+/*
+typedef struct _numberfmt {
+ UINT NumDigits;
+ UINT LeadingZero;
+ UINT Grouping;
+ LPTSTR lpDecimalSep;
+ LPTSTR lpThousandSep;
+ UINT NegativeOrder;
+} NUMBERFMT, *LPNUMBERFMT;
+ */
+/*
+typedef struct _BY_HANDLE_FILE_INFORMATION {
+ DWORD dwFileAttributes;
+ FILETIME ftCreationTime;
+ FILETIME ftLastAccessTime;
+ FILETIME ftLastWriteTime;
+ DWORD dwVolumeSerialNumber;
+ DWORD nFileSizeHigh;
+ DWORD nFileSizeLow;
+ DWORD nNumberOfLinks;
+ DWORD nFileIndexHigh;
+ DWORD nFileIndexLow;
+} BY_HANDLE_FILE_INFORMATION, *PBY_HANDLE_FILE_INFORMATION;
+
+GetDriveTypeW
+GetFileType
+GetLocaleInfoW
+GetNumberFormatW
+
+BOOL FileTimeToLocalFileTime(
+ CONST FILETIME *lpFileTime, // UTC file time to convert
+ LPFILETIME lpLocalFileTime // converted file time
+);
+
+BOOL FileTimeToSystemTime(
+ CONST FILETIME *lpFileTime, // file time to convert
+ LPSYSTEMTIME lpSystemTime // receives system time
+);
+ */
+
// OnGetDispInfo - processes the LVN_GETDISPINFO
// notification message.
-void OnGetDispInfo(NMLVDISPINFO* plvdi)
+static void OnGetDispInfo(NMLVDISPINFO* plvdi)
{
- static char buffer[200];
+ SYSTEMTIME SystemTime;
+ FILETIME LocalFileTime;
+ static TCHAR buffer[200];
// LVITEM* pItem = &(plvdi->item);
// Entry* entry = (Entry*)pItem->lParam;
Entry* entry = (Entry*)plvdi->item.lParam;
ASSERT(entry);
+ plvdi->item.pszText = NULL;
+
switch (plvdi->item.iSubItem) {
case 0:
plvdi->item.pszText = entry->data.cFileName;
break;
case 1:
if (entry->bhfi_valid) {
+ NUMBERFMT numFmt;
+ memset(&numFmt, 0, sizeof(numFmt));
+ numFmt.NumDigits = 0;
+ numFmt.LeadingZero = 0;
+ numFmt.Grouping = 3;
+ numFmt.lpDecimalSep = _T(".");
+ numFmt.lpThousandSep = _T(",");
+ numFmt.NegativeOrder = 0;
+
//entry->bhfi.nFileSizeLow;
//entry->bhfi.nFileSizeHigh;
-
//entry->bhfi.ftCreationTime
-
- wsprintf(buffer, "%u", entry->bhfi.nFileSizeLow);
- plvdi->item.pszText = buffer;
+ wsprintf(buffer, _T("%u"), entry->bhfi.nFileSizeLow);
+ if (GetNumberFormat(LOCALE_USER_DEFAULT, 0, buffer, &numFmt,
+ buffer + sizeof(buffer)/2, sizeof(buffer)/2)) {
+ plvdi->item.pszText = buffer + sizeof(buffer)/2;
+ } else {
+ plvdi->item.pszText = buffer;
+ }
} else {
- plvdi->item.pszText = "unknown";
+ plvdi->item.pszText = _T("unknown");
}
break;
case 2:
- plvdi->item.pszText = "TODO:";
+ plvdi->item.pszText = _T("error");
+ if (FileTimeToLocalFileTime(&entry->bhfi.ftLastWriteTime, &LocalFileTime)) {
+ if (FileTimeToSystemTime(&LocalFileTime, &SystemTime)) {
+ if (GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &SystemTime, NULL, buffer, sizeof(buffer))) {
+ plvdi->item.pszText = buffer;
+ }
+ }
+ }
break;
case 3:
- //entry->bhfi.dwFileAttributes
-// plvdi->item.pszText = "rhsa";
- strcpy(buffer, " ");
- if (entry->bhfi.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) strcat(buffer, "a"); else strcat(buffer, " ");
- if (entry->bhfi.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED) strcat(buffer, "c"); else strcat(buffer, " ");
- if (entry->bhfi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) strcat(buffer, "d"); else strcat(buffer, " ");
- if (entry->bhfi.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED) strcat(buffer, "e"); else strcat(buffer, " ");
- if (entry->bhfi.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) strcat(buffer, "h"); else strcat(buffer, " ");
- if (entry->bhfi.dwFileAttributes & FILE_ATTRIBUTE_NORMAL) strcat(buffer, "n"); else strcat(buffer, " ");
- if (entry->bhfi.dwFileAttributes & FILE_ATTRIBUTE_OFFLINE) strcat(buffer, "o"); else strcat(buffer, " ");
- if (entry->bhfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY) strcat(buffer, "r"); else strcat(buffer, " ");
- if (entry->bhfi.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) strcat(buffer, "p"); else strcat(buffer, " ");
- if (entry->bhfi.dwFileAttributes & FILE_ATTRIBUTE_SPARSE_FILE) strcat(buffer, "f"); else strcat(buffer, " ");
- if (entry->bhfi.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) strcat(buffer, "s"); else strcat(buffer, " ");
- if (entry->bhfi.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY) strcat(buffer, "t"); else strcat(buffer, " ");
+ plvdi->item.pszText = _T("error");
+ if (FileTimeToLocalFileTime(&entry->bhfi.ftLastWriteTime, &LocalFileTime)) {
+ if (FileTimeToSystemTime(&LocalFileTime, &SystemTime)) {
+// if (GetTimeFormat(UserDefaultLCID, 0, &SystemTime, NULL, buffer, sizeof(buffer))) {
+ if (GetTimeFormat(LOCALE_USER_DEFAULT, 0, &SystemTime, NULL, buffer, sizeof(buffer))) {
+ plvdi->item.pszText = buffer;
+ }
+ }
+ }
+ break;
+ case 4:
+ plvdi->item.pszText = _T("");
+ _tcscpy(buffer, _T(" "));
+
+ if (entry->bhfi.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) _tcscat(buffer, _T("a")); else _tcscat(buffer, _T(" "));
+ if (entry->bhfi.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED) _tcscat(buffer, _T("c")); else _tcscat(buffer, _T(" "));
+ if (entry->bhfi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) _tcscat(buffer, _T("d")); else _tcscat(buffer, _T(" "));
+ if (entry->bhfi.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED) _tcscat(buffer, _T("e")); else _tcscat(buffer, _T(" "));
+ if (entry->bhfi.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) _tcscat(buffer, _T("h")); else _tcscat(buffer, _T(" "));
+ if (entry->bhfi.dwFileAttributes & FILE_ATTRIBUTE_NORMAL) _tcscat(buffer, _T("n")); else _tcscat(buffer, _T(" "));
+ if (entry->bhfi.dwFileAttributes & FILE_ATTRIBUTE_OFFLINE) _tcscat(buffer, _T("o")); else _tcscat(buffer, _T(" "));
+ if (entry->bhfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY) _tcscat(buffer, _T("r")); else _tcscat(buffer, _T(" "));
+ if (entry->bhfi.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) _tcscat(buffer, _T("p")); else _tcscat(buffer, _T(" "));
+ if (entry->bhfi.dwFileAttributes & FILE_ATTRIBUTE_SPARSE_FILE) _tcscat(buffer, _T("f")); else _tcscat(buffer, _T(" "));
+ if (entry->bhfi.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) _tcscat(buffer, _T("s")); else _tcscat(buffer, _T(" "));
+ if (entry->bhfi.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY) _tcscat(buffer, _T("t")); else _tcscat(buffer, _T(" "));
+ plvdi->item.pszText = buffer;
+ break;
+ default:
+ _tcscpy(buffer, _T(" "));
plvdi->item.pszText = buffer;
+ break;
+ }
+}
/*
FILE_ATTRIBUTE_ARCHIVE The file or directory is an archive file. Applications use this attribute to mark files for backup or removal.
FILE_ATTRIBUTE_COMPRESSED The file or directory is compressed. For a file, this means that all of the data in the file is compressed. For a directory, this means that compression is the default for newly created files and subdirectories.
FILE_ATTRIBUTE_SYSTEM The file or directory is part of the operating system or is used exclusively by the operating system.
FILE_ATTRIBUTE_TEMPORARY The file is being used for temporary storage. File systems attempt to keep all the data in memory for quicker access, rather than flushing the data back to mass storage. A temporary file should be deleted by the application as soon as it is no longer needed.
*/
- break;
- default:
- break;
- }
-}
-/*
-typedef struct _BY_HANDLE_FILE_INFORMATION {
- DWORD dwFileAttributes;
- FILETIME ftCreationTime;
- FILETIME ftLastAccessTime;
- FILETIME ftLastWriteTime;
- DWORD dwVolumeSerialNumber;
- DWORD nFileSizeHigh;
- DWORD nFileSizeLow;
- DWORD nNumberOfLinks;
- DWORD nFileIndexHigh;
- DWORD nFileIndexLow;
-} BY_HANDLE_FILE_INFORMATION, *PBY_HANDLE_FILE_INFORMATION;
- */
// OnEndLabelEdit - processes the LVN_ENDLABELEDIT
// notification message.
// Returns TRUE if the label is changed, or FALSE otherwise.
-BOOL OnEndLabelEdit(NMLVDISPINFO* plvdi)
+static BOOL OnEndLabelEdit(NMLVDISPINFO* plvdi)
{
if (plvdi->item.iItem == -1)
return FALSE;
// many characters in the field.
}
+/*
+typedef struct _BY_HANDLE_FILE_INFORMATION {
+ DWORD dwFileAttributes;
+ FILETIME ftCreationTime;
+ FILETIME ftLastAccessTime;
+ FILETIME ftLastWriteTime;
+ DWORD dwVolumeSerialNumber;
+ DWORD nFileSizeHigh;
+ DWORD nFileSizeLow;
+ DWORD nNumberOfLinks;
+ DWORD nFileIndexHigh;
+ DWORD nFileIndexLow;
+} BY_HANDLE_FILE_INFORMATION, *PBY_HANDLE_FILE_INFORMATION;
+ */
+/*
+typedef struct _WIN32_FIND_DATA {
+ DWORD dwFileAttributes;
+ FILETIME ftCreationTime;
+ FILETIME ftLastAccessTime;
+ FILETIME ftLastWriteTime;
+ DWORD nFileSizeHigh;
+ DWORD nFileSizeLow;
+ DWORD dwReserved0;
+ DWORD dwReserved1;
+ TCHAR cFileName[ MAX_PATH ];
+ TCHAR cAlternateFileName[ 14 ];
+} WIN32_FIND_DATA, *PWIN32_FIND_DATA;
+ */
+
+static int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
+{
+ Entry* pItem1 = (Entry*)lParam1;
+ Entry* pItem2 = (Entry*)lParam2;
+
+ if (pItem1 != NULL && pItem2 != NULL) {
+ switch (lParamSort) {
+ case ID_VIEW_SORT_BY_NAME:
+ return _tcscmp(pItem1->data.cFileName, pItem2->data.cFileName);
+ break;
+ case ID_VIEW_SORT_BY_TYPE:
+// if (pItem1->bhfi.nFileSizeLow != pItem2->bhfi.nFileSizeLow) {
+// return (pItem1->bhfi.nFileSizeLow < pItem2->bhfi.nFileSizeLow) ? -1 : 1;
+// }
+ break;
+ case ID_VIEW_SORT_BY_SIZE:
+ if (pItem1->bhfi.nFileSizeLow != pItem2->bhfi.nFileSizeLow) {
+ return (pItem1->bhfi.nFileSizeLow < pItem2->bhfi.nFileSizeLow) ? -1 : 1;
+ }
+ break;
+ case ID_VIEW_SORT_BY_DATE:
+ return CompareFileTime(&pItem1->bhfi.ftLastWriteTime, &pItem2->bhfi.ftLastWriteTime);
+ break;
+ }
+ }
+ return 0;
+}
+
+static void CmdSortItems(HWND hWnd, UINT cmd)
+{
+ CheckMenuItem(Globals.hMenuView, ID_VIEW_SORT_BY_NAME, MF_BYCOMMAND);
+ CheckMenuItem(Globals.hMenuView, ID_VIEW_SORT_BY_TYPE, MF_BYCOMMAND);
+ CheckMenuItem(Globals.hMenuView, ID_VIEW_SORT_BY_SIZE, MF_BYCOMMAND);
+ CheckMenuItem(Globals.hMenuView, ID_VIEW_SORT_BY_DATE, MF_BYCOMMAND);
+ ListView_SortItems(hWnd, &CompareFunc, cmd);
+ CheckMenuItem(Globals.hMenuView, cmd, MF_BYCOMMAND | MF_CHECKED);
+}
+
+static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ UINT cmd = LOWORD(wParam);
+ //HWND hChildWnd;
+
+ if (1) {
+ switch (cmd) {
+ case ID_FILE_OPEN:
+ {
+ LVITEM item;
+ item.mask = LVIF_PARAM;
+// UINT selected_count = ListView_GetSelectedCount(hWnd);
+
+ item.iItem = ListView_GetNextItem(hWnd, -1, LVNI_SELECTED);
+ if (item.iItem != -1) {
+ if (ListView_GetItem(hWnd, &item)) {
+ Entry* entry = (Entry*)item.lParam;
+ OpenTarget(hWnd, entry->data.cFileName);
+ }
+ }
+ }
+
+ break;
+ case ID_FILE_MOVE:
+ //OnFileMove(hWnd);
+ break;
+ case ID_FILE_COPY:
+ case ID_FILE_COPY_CLIPBOARD:
+ case ID_FILE_DELETE:
+ case ID_FILE_RENAME:
+ case ID_FILE_PROPERTIES:
+ case ID_FILE_COMPRESS:
+ case ID_FILE_UNCOMPRESS:
+ break;
+ case ID_FILE_RUN:
+ OnFileRun();
+ break;
+ case ID_FILE_PRINT:
+ case ID_FILE_ASSOCIATE:
+ case ID_FILE_CREATE_DIRECTORY:
+ break;
+ case ID_VIEW_SORT_BY_NAME:
+ case ID_VIEW_SORT_BY_TYPE:
+ case ID_VIEW_SORT_BY_SIZE:
+ case ID_VIEW_SORT_BY_DATE:
+ CmdSortItems(hWnd, cmd);
+ break;
+ default:
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
////////////////////////////////////////////////////////////////////////////////
-static WNDPROC g_orgListWndProc;
static LRESULT CALLBACK ListWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) {
/*
- case WM_CREATE:
- //CreateListView(hWnd);
- return 0;
+ case WM_CREATE:
+ //CreateListView(hWnd);
+ return 0;
*/
- case WM_NOTIFY:
- switch (((LPNMHDR)lParam)->code) {
- case LVN_GETDISPINFO:
- OnGetDispInfo((NMLVDISPINFO*)lParam);
- break;
- case LVN_ENDLABELEDIT:
- return OnEndLabelEdit((NMLVDISPINFO*)lParam);
+ case WM_COMMAND:
+ if (!_CmdWndProc(hWnd, message, wParam, lParam)) {
+ return CallWindowProc(g_orgListWndProc, hWnd, message, wParam, lParam);
+ }
+ break;
+ case WM_DISPATCH_COMMAND:
+ return _CmdWndProc(hWnd, message, wParam, lParam);
+ break;
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->code) {
+ case LVN_GETDISPINFO:
+ OnGetDispInfo((NMLVDISPINFO*)lParam);
+ break;
+ case NM_DBLCLK:
+ {
+ NMITEMACTIVATE* nmitem = (LPNMITEMACTIVATE)lParam;
+ LVHITTESTINFO info;
+
+ if (nmitem->hdr.hwndFrom != hWnd) break;
+// if (nmitem->hdr.idFrom != IDW_LISTVIEW) break;
+// if (nmitem->hdr.code != ???) break;
+ switch (nmitem->uKeyFlags) {
+ case LVKF_ALT: // The ALT key is pressed.
+ // properties dialog box ?
+ break;
+ case LVKF_CONTROL: // The CTRL key is pressed.
+ // run dialog box for providing parameters...
+ break;
+ case LVKF_SHIFT: // The SHIFT key is pressed.
break;
}
- break;
-// return 0;
+ info.pt.x = nmitem->ptAction.x;
+ info.pt.y = nmitem->ptAction.y;
+ if (ListView_HitTest(hWnd, &info) != -1) {
+ LVITEM item;
+ item.mask = LVIF_PARAM;
+ item.iItem = info.iItem;
+ if (ListView_GetItem(hWnd, &item)) {
+ Entry* entry = (Entry*)item.lParam;
+ OpenTarget(hWnd, entry->data.cFileName);
+ }
+ }
+ }
+ break;
+ case LVN_ENDLABELEDIT:
+ return OnEndLabelEdit((NMLVDISPINFO*)lParam);
+ break;
+ default:
+ return CallWindowProc(g_orgListWndProc, hWnd, message, wParam, lParam);
+ }
+// return 0;
+ break;
+/*
case WM_SETFOCUS:
child->nFocusPanel = pane==&child->right? 1: 0;
ListBox_SetSel(hWnd, TRUE, 1);
//TODO: check menu items
break;
-
case WM_KEYDOWN:
if (wParam == VK_TAB) {
//TODO: SetFocus(Globals.hDriveBar)
SetFocus(child->nFocusPanel? child->left.hWnd: child->right.hWnd);
}
+ break;
+ */
+ default:
+ return CallWindowProc(g_orgListWndProc, hWnd, message, wParam, lParam);
+ break;
}
- return CallWindowProc(g_orgListWndProc, hWnd, message, wParam, lParam);
+ return 0;
}
-void CreateListWnd(HWND parent, Pane* pane, int id, LPSTR lpszPathName)
+void CreateListWnd(HWND parent, Pane* pane, int id, LPTSTR lpszPathName)
{
// static int s_init = 0;
Entry* entry = pane->root;
}
}
}
-/*
-typedef struct _WIN32_FIND_DATA {
- DWORD dwFileAttributes;
- FILETIME ftCreationTime;
- FILETIME ftLastAccessTime;
- FILETIME ftLastWriteTime;
- DWORD nFileSizeHigh;
- DWORD nFileSizeLow;
- DWORD dwReserved0;
- DWORD dwReserved1;
- TCHAR cFileName[ MAX_PATH ];
- TCHAR cAlternateFileName[ 14 ];
-} WIN32_FIND_DATA, *PWIN32_FIND_DATA;
- */
/*
Pane* pane = (Pane*)GetWindowLong(hWnd, GWL_USERDATA);