2002-06-04 23:29:40 +02:00
/*
* Winefile
*
2005-05-11 20:23:30 +02:00
* Copyright 2000 , 2003 , 2004 , 2005 Martin Fuchs
2006-02-20 18:57:01 +01:00
* Copyright 2006 Jason Green
2002-06-04 23:29:40 +02:00
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
* version 2.1 of the License , or ( at your option ) any later version .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library ; if not , write to the Free Software
2006-05-18 14:49:52 +02:00
* Foundation , Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 , USA
2002-06-04 23:29:40 +02:00
*/
2003-08-13 21:38:22 +02:00
# ifdef __WINE__
2002-06-04 23:29:40 +02:00
# include "config.h"
# include "wine/port.h"
2005-07-07 14:00:17 +02:00
/* for unix filesystem function calls */
# include <sys/stat.h>
# include <sys/types.h>
# include <dirent.h>
2002-10-15 04:21:08 +02:00
# endif
2002-06-04 23:29:40 +02:00
2005-09-07 15:28:25 +02:00
# define COBJMACROS
2002-06-04 23:29:40 +02:00
# include "winefile.h"
# include "resource.h"
# ifdef _NO_EXTENSIONS
# undef _LEFT_FILES
# endif
# ifndef _MAX_PATH
# define _MAX_DRIVE 3
# define _MAX_FNAME 256
# define _MAX_DIR _MAX_FNAME
# define _MAX_EXT _MAX_FNAME
# define _MAX_PATH 260
# endif
2003-08-13 03:18:37 +02:00
# ifdef NONAMELESSUNION
2003-08-13 21:43:19 +02:00
# define UNION_MEMBER(x) DUMMYUNIONNAME.x
2003-08-13 03:18:37 +02:00
# else
# define UNION_MEMBER(x) x
# endif
# ifdef _SHELL_FOLDERS
2004-10-06 20:52:30 +02:00
# define DEFAULT_SPLIT_POS 300
2003-08-13 03:18:37 +02:00
# else
2004-10-06 20:52:30 +02:00
# define DEFAULT_SPLIT_POS 200
2003-08-13 03:18:37 +02:00
# endif
2006-02-20 18:57:01 +01:00
static const WCHAR registry_key [ ] = { ' S ' , ' o ' , ' f ' , ' t ' , ' w ' , ' a ' , ' r ' , ' e ' , ' \\ ' ,
' W ' , ' i ' , ' n ' , ' e ' , ' \\ ' ,
' W ' , ' i ' , ' n ' , ' e ' , ' F ' , ' i ' , ' l ' , ' e ' , ' \0 ' } ;
static const WCHAR reg_start_x [ ] = { ' s ' , ' t ' , ' a ' , ' r ' , ' t ' , ' X ' , ' \0 ' } ;
static const WCHAR reg_start_y [ ] = { ' s ' , ' t ' , ' a ' , ' r ' , ' t ' , ' Y ' , ' \0 ' } ;
static const WCHAR reg_width [ ] = { ' w ' , ' i ' , ' d ' , ' t ' , ' h ' , ' \0 ' } ;
static const WCHAR reg_height [ ] = { ' h ' , ' e ' , ' i ' , ' g ' , ' h ' , ' t ' , ' \0 ' } ;
2003-08-13 03:18:37 +02:00
enum ENTRY_TYPE {
ET_WINDOWS ,
ET_UNIX ,
# ifdef _SHELL_FOLDERS
ET_SHELL
# endif
} ;
2002-06-04 23:29:40 +02:00
typedef struct _Entry {
struct _Entry * next ;
struct _Entry * down ;
struct _Entry * up ;
2003-08-13 03:18:37 +02:00
BOOL expanded ;
BOOL scanned ;
int level ;
2002-06-04 23:29:40 +02:00
WIN32_FIND_DATA data ;
# ifndef _NO_EXTENSIONS
BY_HANDLE_FILE_INFORMATION bhfi ;
2003-08-13 03:18:37 +02:00
BOOL bhfi_valid ;
enum ENTRY_TYPE etype ;
# endif
# ifdef _SHELL_FOLDERS
LPITEMIDLIST pidl ;
IShellFolder * folder ;
HICON hicon ;
2002-06-04 23:29:40 +02:00
# endif
} Entry ;
typedef struct {
Entry entry ;
TCHAR path [ MAX_PATH ] ;
TCHAR volname [ _MAX_FNAME ] ;
TCHAR fs [ _MAX_DIR ] ;
DWORD drive_type ;
DWORD fs_flags ;
} Root ;
enum COLUMN_FLAGS {
COL_SIZE = 0x01 ,
COL_DATE = 0x02 ,
COL_TIME = 0x04 ,
COL_ATTRIBUTES = 0x08 ,
COL_DOSNAMES = 0x10 ,
# ifdef _NO_EXTENSIONS
COL_ALL = COL_SIZE | COL_DATE | COL_TIME | COL_ATTRIBUTES | COL_DOSNAMES
# else
COL_INDEX = 0x20 ,
COL_LINKS = 0x40 ,
COL_ALL = COL_SIZE | COL_DATE | COL_TIME | COL_ATTRIBUTES | COL_DOSNAMES | COL_INDEX | COL_LINKS
# endif
} ;
typedef enum {
SORT_NAME ,
SORT_EXT ,
SORT_SIZE ,
SORT_DATE
} SORT_ORDER ;
typedef struct {
HWND hwnd ;
# ifndef _NO_EXTENSIONS
HWND hwndHeader ;
# endif
# ifndef _NO_EXTENSIONS
# define COLUMNS 10
# else
# define COLUMNS 5
# endif
int widths [ COLUMNS ] ;
int positions [ COLUMNS + 1 ] ;
BOOL treePane ;
int visible_cols ;
Entry * root ;
Entry * cur ;
} Pane ;
typedef struct {
HWND hwnd ;
Pane left ;
Pane right ;
2002-10-16 20:50:38 +02:00
int focus_pane ; /* 0: left 1: right */
2002-06-04 23:29:40 +02:00
WINDOWPLACEMENT pos ;
int split_pos ;
BOOL header_wdths_ok ;
TCHAR path [ MAX_PATH ] ;
2005-05-29 22:05:29 +02:00
TCHAR filter_pattern [ MAX_PATH ] ;
int filter_flags ;
2002-06-04 23:29:40 +02:00
Root root ;
SORT_ORDER sortOrder ;
} ChildWnd ;
2004-11-22 19:24:09 +01:00
2003-08-13 03:18:37 +02:00
static void read_directory ( Entry * dir , LPCTSTR path , SORT_ORDER sortOrder , HWND hwnd ) ;
2005-05-16 10:48:54 +02:00
static void set_curdir ( ChildWnd * child , Entry * entry , int idx , HWND hwnd ) ;
static void refresh_child ( ChildWnd * child ) ;
2005-06-17 12:11:37 +02:00
static void refresh_drives ( void ) ;
2004-02-11 05:18:12 +01:00
static void get_path ( Entry * dir , PTSTR path ) ;
2005-06-06 12:02:43 +02:00
static void format_date ( const FILETIME * ft , TCHAR * buffer , int visible_cols ) ;
2002-06-04 23:29:40 +02:00
2005-06-10 21:32:24 +02:00
static LRESULT CALLBACK FrameWndProc ( HWND hwnd , UINT nmsg , WPARAM wparam , LPARAM lparam ) ;
static LRESULT CALLBACK ChildWndProc ( HWND hwnd , UINT nmsg , WPARAM wparam , LPARAM lparam ) ;
static LRESULT CALLBACK TreeWndProc ( HWND hwnd , UINT nmsg , WPARAM wparam , LPARAM lparam ) ;
2002-06-04 23:29:40 +02:00
2004-11-22 19:24:09 +01:00
/* globals */
WINEFILE_GLOBALS Globals ;
2005-05-23 11:52:51 +02:00
static int last_split ;
2004-11-22 19:24:09 +01:00
/* some common string constants */
2005-10-06 13:38:45 +02:00
static const TCHAR sEmpty [ ] = { ' \0 ' } ;
2007-07-25 23:22:08 +02:00
static const WCHAR sSpace [ ] = { ' ' , ' \0 ' } ;
2005-10-06 13:38:45 +02:00
static const TCHAR sNumFmt [ ] = { ' % ' , ' d ' , ' \0 ' } ;
static const TCHAR sQMarks [ ] = { ' ? ' , ' ? ' , ' ? ' , ' \0 ' } ;
2004-11-22 19:24:09 +01:00
/* window class names */
2005-10-06 13:38:45 +02:00
static const TCHAR sWINEFILEFRAME [ ] = { ' W ' , ' F ' , ' S ' , ' _ ' , ' F ' , ' r ' , ' a ' , ' m ' , ' e ' , ' \0 ' } ;
static const TCHAR sWINEFILETREE [ ] = { ' W ' , ' F ' , ' S ' , ' _ ' , ' T ' , ' r ' , ' e ' , ' e ' , ' \0 ' } ;
2004-11-22 19:24:09 +01:00
# ifdef _MSC_VER
/* #define LONGLONGARG _T("I64") */
2005-10-06 13:38:45 +02:00
static const TCHAR sLongHexFmt [ ] = { ' % ' , ' I ' , ' 6 ' , ' 4 ' , ' X ' , ' \0 ' } ;
static const TCHAR sLongNumFmt [ ] = { ' % ' , ' I ' , ' 6 ' , ' 4 ' , ' d ' , ' \0 ' } ;
2004-11-22 19:24:09 +01:00
# else
/* #define LONGLONGARG _T("L") */
2005-10-06 13:38:45 +02:00
static const TCHAR sLongHexFmt [ ] = { ' % ' , ' L ' , ' X ' , ' \0 ' } ;
static const TCHAR sLongNumFmt [ ] = { ' % ' , ' L ' , ' d ' , ' \0 ' } ;
2004-11-22 19:24:09 +01:00
# endif
2004-10-21 21:51:31 +02:00
/* load resource string */
static LPTSTR load_string ( LPTSTR buffer , UINT id )
{
2004-10-22 21:52:50 +02:00
LoadString ( Globals . hInstance , id , buffer , BUFFER_LEN ) ;
2004-10-21 21:51:31 +02:00
2004-10-22 21:52:50 +02:00
return buffer ;
2004-10-21 21:51:31 +02:00
}
# define RS(b, i) load_string(b, i)
2004-10-06 20:52:30 +02:00
/* display error message for the specified WIN32 error code */
2002-06-04 23:29:40 +02:00
static void display_error ( HWND hwnd , DWORD error )
{
2004-10-22 21:52:50 +02:00
TCHAR b1 [ BUFFER_LEN ] , b2 [ BUFFER_LEN ] ;
2002-06-04 23:29:40 +02:00
PTSTR msg ;
if ( FormatMessage ( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM ,
0 , error , MAKELANGID ( LANG_NEUTRAL , SUBLANG_DEFAULT ) , ( PTSTR ) & msg , 0 , NULL ) )
2004-10-22 21:52:50 +02:00
MessageBox ( hwnd , msg , RS ( b2 , IDS_WINEFILE ) , MB_OK ) ;
2002-06-04 23:29:40 +02:00
else
2004-10-22 21:52:50 +02:00
MessageBox ( hwnd , RS ( b1 , IDS_ERROR ) , RS ( b2 , IDS_WINEFILE ) , MB_OK ) ;
2002-06-04 23:29:40 +02:00
LocalFree ( msg ) ;
}
2005-05-16 23:36:41 +02:00
/* display network error message using WNetGetLastError() */
static void display_network_error ( HWND hwnd )
{
TCHAR msg [ BUFFER_LEN ] , provider [ BUFFER_LEN ] , b2 [ BUFFER_LEN ] ;
DWORD error ;
if ( WNetGetLastError ( & error , msg , BUFFER_LEN , provider , BUFFER_LEN ) = = NO_ERROR )
MessageBox ( hwnd , msg , RS ( b2 , IDS_WINEFILE ) , MB_OK ) ;
}
2006-01-31 18:08:45 +01:00
static VOID WineLicense ( HWND Wnd )
{
2007-07-23 22:38:18 +02:00
WCHAR cap [ 20 ] , text [ 1024 ] ;
LoadStringW ( Globals . hInstance , IDS_LICENSE , text , 1024 ) ;
LoadStringW ( Globals . hInstance , IDS_LICENSE_CAPTION , cap , 20 ) ;
MessageBoxW ( Wnd , text , cap , MB_ICONINFORMATION | MB_OK ) ;
2006-01-31 18:08:45 +01:00
}
static VOID WineWarranty ( HWND Wnd )
{
2007-07-23 22:38:18 +02:00
WCHAR cap [ 20 ] , text [ 1024 ] ;
LoadStringW ( Globals . hInstance , IDS_WARRANTY , text , 1024 ) ;
LoadStringW ( Globals . hInstance , IDS_WARRANTY_CAPTION , cap , 20 ) ;
MessageBoxW ( Wnd , text , cap , MB_ICONEXCLAMATION | MB_OK ) ;
2006-01-31 18:08:45 +01:00
}
2006-03-17 16:57:16 +01:00
static inline BOOL get_check ( HWND hwnd , INT id )
{
2007-07-23 22:38:18 +02:00
return BST_CHECKED & SendMessageW ( GetDlgItem ( hwnd , id ) , BM_GETSTATE , 0 , 0 ) ;
2006-03-17 16:57:16 +01:00
}
static inline INT set_check ( HWND hwnd , INT id , BOOL on )
{
2007-07-23 22:38:18 +02:00
return SendMessageW ( GetDlgItem ( hwnd , id ) , BM_SETCHECK , on ? BST_CHECKED : BST_UNCHECKED , 0 ) ;
2006-03-17 16:57:16 +01:00
}
2005-05-16 23:36:41 +02:00
2007-07-25 23:21:43 +02:00
static inline void choose_font ( HWND hwnd )
{
2007-07-25 23:22:08 +02:00
WCHAR dlg_name [ BUFFER_LEN ] , dlg_info [ BUFFER_LEN ] ;
CHOOSEFONTW chFont ;
LOGFONTW lFont ;
2007-07-25 23:21:43 +02:00
HDC hdc = GetDC ( hwnd ) ;
chFont . lStructSize = sizeof ( CHOOSEFONT ) ;
chFont . hwndOwner = hwnd ;
chFont . hDC = NULL ;
chFont . lpLogFont = & lFont ;
chFont . Flags = CF_SCREENFONTS | CF_FORCEFONTEXIST | CF_LIMITSIZE | CF_NOSCRIPTSEL ;
chFont . rgbColors = RGB ( 0 , 0 , 0 ) ;
chFont . lCustData = 0 ;
chFont . lpfnHook = NULL ;
chFont . lpTemplateName = NULL ;
chFont . hInstance = Globals . hInstance ;
chFont . lpszStyle = NULL ;
chFont . nFontType = SIMULATED_FONTTYPE ;
chFont . nSizeMin = 0 ;
chFont . nSizeMax = 24 ;
2007-07-25 23:22:08 +02:00
if ( ChooseFontW ( & chFont ) ) {
2007-07-25 23:21:43 +02:00
HWND childWnd ;
HFONT hFontOld ;
DeleteObject ( Globals . hfont ) ;
2007-07-25 23:22:08 +02:00
Globals . hfont = CreateFontIndirectW ( & lFont ) ;
2007-07-25 23:21:43 +02:00
hFontOld = SelectObject ( hdc , Globals . hfont ) ;
2007-07-25 23:22:08 +02:00
GetTextExtentPoint32W ( hdc , sSpace , 1 , & Globals . spaceSize ) ;
2007-07-25 23:21:43 +02:00
/* change font in all open child windows */
for ( childWnd = GetWindow ( Globals . hmdiclient , GW_CHILD ) ; childWnd ; childWnd = GetNextWindow ( childWnd , GW_HWNDNEXT ) ) {
2007-07-25 23:22:08 +02:00
ChildWnd * child = ( ChildWnd * ) GetWindowLongPtrW ( childWnd , GWLP_USERDATA ) ;
SendMessageW ( child - > left . hwnd , WM_SETFONT , ( WPARAM ) Globals . hfont , TRUE ) ;
SendMessageW ( child - > right . hwnd , WM_SETFONT , ( WPARAM ) Globals . hfont , TRUE ) ;
SendMessageW ( child - > left . hwnd , LB_SETITEMHEIGHT , 1 , max ( Globals . spaceSize . cy , IMAGE_HEIGHT + 3 ) ) ;
SendMessageW ( child - > right . hwnd , LB_SETITEMHEIGHT , 1 , max ( Globals . spaceSize . cy , IMAGE_HEIGHT + 3 ) ) ;
2007-07-25 23:21:43 +02:00
InvalidateRect ( child - > left . hwnd , NULL , TRUE ) ;
InvalidateRect ( child - > right . hwnd , NULL , TRUE ) ;
}
SelectObject ( hdc , hFontOld ) ;
}
else if ( CommDlgExtendedError ( ) ) {
2007-07-25 23:22:08 +02:00
LoadStringW ( Globals . hInstance , IDS_FONT_SEL_DLG_NAME , dlg_name , BUFFER_LEN ) ;
LoadStringW ( Globals . hInstance , IDS_FONT_SEL_ERROR , dlg_info , BUFFER_LEN ) ;
MessageBoxW ( hwnd , dlg_info , dlg_name , MB_OK ) ;
2007-07-25 23:21:43 +02:00
}
ReleaseDC ( hwnd , hdc ) ;
}
2005-07-07 14:00:17 +02:00
# ifdef __WINE__
# ifdef UNICODE
/* call vswprintf() in msvcrt.dll */
/*TODO: fix swprintf() in non-msvcrt mode, so that this dynamic linking function can be removed */
static int msvcrt_swprintf ( WCHAR * buffer , const WCHAR * fmt , . . . )
{
static int ( __cdecl * pvswprintf ) ( WCHAR * , const WCHAR * , va_list ) = NULL ;
va_list ap ;
int ret ;
if ( ! pvswprintf ) {
HMODULE hModMsvcrt = LoadLibraryA ( " msvcrt " ) ;
pvswprintf = ( int ( __cdecl * ) ( WCHAR * , const WCHAR * , va_list ) ) GetProcAddress ( hModMsvcrt , " vswprintf " ) ;
}
va_start ( ap , fmt ) ;
ret = ( * pvswprintf ) ( buffer , fmt , ap ) ;
va_end ( ap ) ;
return ret ;
}
static LPCWSTR my_wcsrchr ( LPCWSTR str , WCHAR c )
{
LPCWSTR p = str ;
while ( * p )
+ + p ;
do {
if ( - - p < str )
return NULL ;
} while ( * p ! = c ) ;
return p ;
}
# define _tcsrchr my_wcsrchr
# else /* UNICODE */
# define _tcsrchr strrchr
# endif /* UNICODE */
# endif /* __WINE__ */
2004-10-06 20:52:30 +02:00
/* allocate and initialise a directory entry */
2005-06-17 12:11:37 +02:00
static Entry * alloc_entry ( void )
2002-06-04 23:29:40 +02:00
{
2007-07-23 22:25:20 +02:00
Entry * entry = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( Entry ) ) ;
2003-08-13 03:18:37 +02:00
# ifdef _SHELL_FOLDERS
entry - > pidl = NULL ;
entry - > folder = NULL ;
entry - > hicon = 0 ;
# endif
return entry ;
}
/* free a directory entry */
static void free_entry ( Entry * entry )
{
# ifdef _SHELL_FOLDERS
if ( entry - > hicon & & entry - > hicon ! = ( HICON ) - 1 )
DestroyIcon ( entry - > hicon ) ;
if ( entry - > folder & & entry - > folder ! = Globals . iDesktop )
2005-09-07 15:28:25 +02:00
IShellFolder_Release ( entry - > folder ) ;
2003-08-13 03:18:37 +02:00
if ( entry - > pidl )
2005-09-07 15:28:25 +02:00
IMalloc_Free ( Globals . iMalloc , entry - > pidl ) ;
2003-08-13 03:18:37 +02:00
# endif
2007-07-23 22:25:20 +02:00
HeapFree ( GetProcessHeap ( ) , 0 , entry ) ;
2003-08-13 03:18:37 +02:00
}
/* recursively free all child entries */
static void free_entries ( Entry * dir )
{
Entry * entry , * next = dir - > down ;
if ( next ) {
dir - > down = 0 ;
do {
entry = next ;
next = entry - > next ;
free_entries ( entry ) ;
free_entry ( entry ) ;
} while ( next ) ;
}
}
static void read_directory_win ( Entry * dir , LPCTSTR path )
{
Entry * first_entry = NULL ;
Entry * last = NULL ;
Entry * entry ;
int level = dir - > level + 1 ;
WIN32_FIND_DATA w32fd ;
2002-06-04 23:29:40 +02:00
HANDLE hFind ;
# ifndef _NO_EXTENSIONS
HANDLE hFile ;
# endif
TCHAR buffer [ MAX_PATH ] , * p ;
for ( p = buffer ; * path ; )
* p + + = * path + + ;
2004-11-22 19:24:09 +01:00
* p + + = ' \\ ' ;
p [ 0 ] = ' * ' ;
p [ 1 ] = ' \0 ' ;
2002-06-04 23:29:40 +02:00
2003-08-13 03:18:37 +02:00
hFind = FindFirstFile ( buffer , & w32fd ) ;
2002-06-04 23:29:40 +02:00
if ( hFind ! = INVALID_HANDLE_VALUE ) {
do {
2005-05-23 12:26:47 +02:00
# ifdef _NO_EXTENSIONS
/* hide directory entry "." */
if ( w32fd . dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
LPCTSTR name = w32fd . cFileName ;
if ( name [ 0 ] = = ' . ' & & name [ 1 ] = = ' \0 ' )
continue ;
}
# endif
2003-08-13 03:18:37 +02:00
entry = alloc_entry ( ) ;
if ( ! first_entry )
first_entry = entry ;
if ( last )
last - > next = entry ;
memcpy ( & entry - > data , & w32fd , sizeof ( WIN32_FIND_DATA ) ) ;
entry - > down = NULL ;
entry - > up = dir ;
2002-06-04 23:29:40 +02:00
entry - > expanded = FALSE ;
entry - > scanned = FALSE ;
entry - > level = level ;
2005-05-23 12:26:47 +02:00
# ifndef _NO_EXTENSIONS
2003-08-13 03:18:37 +02:00
entry - > etype = ET_WINDOWS ;
2002-06-04 23:29:40 +02:00
entry - > bhfi_valid = FALSE ;
2004-11-22 19:24:09 +01:00
lstrcpy ( p , entry - > data . cFileName ) ;
2002-06-04 23:29:40 +02:00
hFile = CreateFile ( buffer , GENERIC_READ , FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE ,
0 , OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS , 0 ) ;
if ( hFile ! = INVALID_HANDLE_VALUE ) {
if ( GetFileInformationByHandle ( hFile , & entry - > bhfi ) )
entry - > bhfi_valid = TRUE ;
CloseHandle ( hFile ) ;
}
# endif
last = entry ;
2005-05-23 12:26:47 +02:00
} while ( FindNextFile ( hFind , & w32fd ) ) ;
2002-06-04 23:29:40 +02:00
2005-05-23 12:26:47 +02:00
if ( last )
last - > next = NULL ;
2002-06-04 23:29:40 +02:00
FindClose ( hFind ) ;
2003-08-13 03:18:37 +02:00
}
2002-06-04 23:29:40 +02:00
2003-08-13 03:18:37 +02:00
dir - > down = first_entry ;
dir - > scanned = TRUE ;
2002-06-04 23:29:40 +02:00
}
2003-08-13 03:18:37 +02:00
static Entry * find_entry_win ( Entry * dir , LPCTSTR name )
2002-06-04 23:29:40 +02:00
{
Entry * entry ;
2003-08-13 03:18:37 +02:00
for ( entry = dir - > down ; entry ; entry = entry - > next ) {
2002-06-04 23:29:40 +02:00
LPCTSTR p = name ;
LPCTSTR q = entry - > data . cFileName ;
do {
2007-06-27 22:54:56 +02:00
if ( ! * p | | * p = = ' \\ ' | | * p = = ' / ' )
2002-06-04 23:29:40 +02:00
return entry ;
} while ( tolower ( * p + + ) = = tolower ( * q + + ) ) ;
p = name ;
q = entry - > data . cAlternateFileName ;
do {
2007-06-27 22:54:56 +02:00
if ( ! * p | | * p = = ' \\ ' | | * p = = ' / ' )
2002-06-04 23:29:40 +02:00
return entry ;
} while ( tolower ( * p + + ) = = tolower ( * q + + ) ) ;
}
return 0 ;
}
2003-08-13 03:18:37 +02:00
static Entry * read_tree_win ( Root * root , LPCTSTR path , SORT_ORDER sortOrder , HWND hwnd )
2002-06-04 23:29:40 +02:00
{
TCHAR buffer [ MAX_PATH ] ;
Entry * entry = & root - > entry ;
LPCTSTR s = path ;
PTSTR d = buffer ;
2003-08-13 03:18:37 +02:00
HCURSOR old_cursor = SetCursor ( LoadCursor ( 0 , IDC_WAIT ) ) ;
2002-06-04 23:29:40 +02:00
# ifndef _NO_EXTENSIONS
2003-08-13 03:18:37 +02:00
entry - > etype = ET_WINDOWS ;
2002-06-04 23:29:40 +02:00
# endif
while ( entry ) {
2007-06-27 22:54:56 +02:00
while ( * s & & * s ! = ' \\ ' & & * s ! = ' / ' )
2002-06-04 23:29:40 +02:00
* d + + = * s + + ;
2007-06-27 22:54:56 +02:00
while ( * s = = ' \\ ' | | * s = = ' / ' )
2002-06-04 23:29:40 +02:00
s + + ;
2007-06-27 22:54:56 +02:00
* d + + = ' \\ ' ;
* d = ' \0 ' ;
2002-06-04 23:29:40 +02:00
2003-08-13 03:18:37 +02:00
read_directory ( entry , buffer , sortOrder , hwnd ) ;
2002-06-04 23:29:40 +02:00
if ( entry - > down )
entry - > expanded = TRUE ;
if ( ! * s )
break ;
entry = find_entry_win ( entry , s ) ;
}
2003-08-13 03:18:37 +02:00
SetCursor ( old_cursor ) ;
2002-06-04 23:29:40 +02:00
return entry ;
}
2003-08-13 03:18:37 +02:00
# if !defined(_NO_EXTENSIONS) && defined(__WINE__)
2002-06-04 23:29:40 +02:00
2004-10-06 20:52:30 +02:00
static BOOL time_to_filetime ( const time_t * t , FILETIME * ftime )
2002-06-04 23:29:40 +02:00
{
struct tm * tm = gmtime ( t ) ;
SYSTEMTIME stime ;
if ( ! tm )
return FALSE ;
stime . wYear = tm - > tm_year + 1900 ;
stime . wMonth = tm - > tm_mon + 1 ;
2002-06-28 19:37:34 +02:00
/* stime.wDayOfWeek */
2002-06-04 23:29:40 +02:00
stime . wDay = tm - > tm_mday ;
stime . wHour = tm - > tm_hour ;
stime . wMinute = tm - > tm_min ;
stime . wSecond = tm - > tm_sec ;
return SystemTimeToFileTime ( & stime , ftime ) ;
}
2003-08-13 03:18:37 +02:00
static void read_directory_unix ( Entry * dir , LPCTSTR path )
2002-06-04 23:29:40 +02:00
{
2003-08-13 03:18:37 +02:00
Entry * first_entry = NULL ;
Entry * last = NULL ;
Entry * entry ;
2005-07-07 14:00:17 +02:00
DIR * pdir ;
2002-06-04 23:29:40 +02:00
2003-08-13 03:18:37 +02:00
int level = dir - > level + 1 ;
2005-07-07 14:00:17 +02:00
# ifdef UNICODE
char cpath [ MAX_PATH ] ;
2002-06-04 23:29:40 +02:00
2005-07-07 14:00:17 +02:00
WideCharToMultiByte ( CP_UNIXCP , 0 , path , - 1 , cpath , MAX_PATH , NULL , NULL ) ;
# else
const char * cpath = path ;
# endif
pdir = opendir ( cpath ) ;
2003-08-13 03:18:37 +02:00
if ( pdir ) {
2002-06-04 23:29:40 +02:00
struct stat st ;
struct dirent * ent ;
2005-07-07 14:00:17 +02:00
char buffer [ MAX_PATH ] , * p ;
const char * s ;
2002-06-04 23:29:40 +02:00
2005-07-07 14:00:17 +02:00
for ( p = buffer , s = cpath ; * s ; )
* p + + = * s + + ;
2002-06-04 23:29:40 +02:00
if ( p = = buffer | | p [ - 1 ] ! = ' / ' )
* p + + = ' / ' ;
2003-08-13 03:18:37 +02:00
while ( ( ent = readdir ( pdir ) ) ) {
entry = alloc_entry ( ) ;
if ( ! first_entry )
first_entry = entry ;
if ( last )
last - > next = entry ;
entry - > etype = ET_UNIX ;
2002-06-04 23:29:40 +02:00
strcpy ( p , ent - > d_name ) ;
2005-07-07 14:00:17 +02:00
# ifdef UNICODE
MultiByteToWideChar ( CP_UNIXCP , 0 , p , - 1 , entry - > data . cFileName , MAX_PATH ) ;
# else
lstrcpy ( entry - > data . cFileName , p ) ;
# endif
2002-06-04 23:29:40 +02:00
if ( ! stat ( buffer , & st ) ) {
2005-07-07 14:00:17 +02:00
entry - > data . dwFileAttributes = p [ 0 ] = = ' . ' ? FILE_ATTRIBUTE_HIDDEN : 0 ;
2002-06-04 23:29:40 +02:00
if ( S_ISDIR ( st . st_mode ) )
entry - > data . dwFileAttributes | = FILE_ATTRIBUTE_DIRECTORY ;
entry - > data . nFileSizeLow = st . st_size & 0xFFFFFFFF ;
entry - > data . nFileSizeHigh = st . st_size > > 32 ;
memset ( & entry - > data . ftCreationTime , 0 , sizeof ( FILETIME ) ) ;
2003-08-13 03:18:37 +02:00
time_to_filetime ( & st . st_atime , & entry - > data . ftLastAccessTime ) ;
time_to_filetime ( & st . st_mtime , & entry - > data . ftLastWriteTime ) ;
2002-06-04 23:29:40 +02:00
entry - > bhfi . nFileIndexLow = ent - > d_ino ;
entry - > bhfi . nFileIndexHigh = 0 ;
entry - > bhfi . nNumberOfLinks = st . st_nlink ;
entry - > bhfi_valid = TRUE ;
} else {
entry - > data . nFileSizeLow = 0 ;
entry - > data . nFileSizeHigh = 0 ;
entry - > bhfi_valid = FALSE ;
}
2003-08-13 03:18:37 +02:00
entry - > down = NULL ;
entry - > up = dir ;
2002-06-04 23:29:40 +02:00
entry - > expanded = FALSE ;
entry - > scanned = FALSE ;
entry - > level = level ;
last = entry ;
}
2005-05-23 12:26:47 +02:00
if ( last )
last - > next = NULL ;
2002-06-04 23:29:40 +02:00
2003-08-13 03:18:37 +02:00
closedir ( pdir ) ;
}
2002-06-04 23:29:40 +02:00
2003-08-13 03:18:37 +02:00
dir - > down = first_entry ;
dir - > scanned = TRUE ;
2002-06-04 23:29:40 +02:00
}
2003-08-13 03:18:37 +02:00
static Entry * find_entry_unix ( Entry * dir , LPCTSTR name )
2002-06-04 23:29:40 +02:00
{
Entry * entry ;
2003-08-13 03:18:37 +02:00
for ( entry = dir - > down ; entry ; entry = entry - > next ) {
2002-06-04 23:29:40 +02:00
LPCTSTR p = name ;
LPCTSTR q = entry - > data . cFileName ;
do {
2007-06-27 22:54:56 +02:00
if ( ! * p | | * p = = ' / ' )
2002-06-04 23:29:40 +02:00
return entry ;
} while ( * p + + = = * q + + ) ;
}
return 0 ;
}
2003-08-13 03:18:37 +02:00
static Entry * read_tree_unix ( Root * root , LPCTSTR path , SORT_ORDER sortOrder , HWND hwnd )
2002-06-04 23:29:40 +02:00
{
TCHAR buffer [ MAX_PATH ] ;
Entry * entry = & root - > entry ;
LPCTSTR s = path ;
PTSTR d = buffer ;
2003-08-13 03:18:37 +02:00
HCURSOR old_cursor = SetCursor ( LoadCursor ( 0 , IDC_WAIT ) ) ;
entry - > etype = ET_UNIX ;
2002-06-04 23:29:40 +02:00
while ( entry ) {
2007-06-27 22:54:56 +02:00
while ( * s & & * s ! = ' / ' )
2002-06-04 23:29:40 +02:00
* d + + = * s + + ;
2007-06-27 22:54:56 +02:00
while ( * s = = ' / ' )
2002-06-04 23:29:40 +02:00
s + + ;
2007-06-27 22:54:56 +02:00
* d + + = ' / ' ;
* d = ' \0 ' ;
2002-06-04 23:29:40 +02:00
2003-08-13 03:18:37 +02:00
read_directory ( entry , buffer , sortOrder , hwnd ) ;
2002-06-04 23:29:40 +02:00
if ( entry - > down )
entry - > expanded = TRUE ;
if ( ! * s )
break ;
entry = find_entry_unix ( entry , s ) ;
}
2003-08-13 03:18:37 +02:00
SetCursor ( old_cursor ) ;
return entry ;
}
# endif /* !defined(_NO_EXTENSIONS) && defined(__WINE__) */
# ifdef _SHELL_FOLDERS
# ifdef UNICODE
# define get_strret get_strretW
# define path_from_pidl path_from_pidlW
# else
# define get_strret get_strretA
# define path_from_pidl path_from_pidlA
# endif
2005-07-07 14:00:17 +02:00
static void free_strret ( STRRET * str )
2003-08-13 03:18:37 +02:00
{
2005-07-07 14:00:17 +02:00
if ( str - > uType = = STRRET_WSTR )
2005-09-07 15:28:25 +02:00
IMalloc_Free ( Globals . iMalloc , str - > UNION_MEMBER ( pOleStr ) ) ;
2005-07-07 14:00:17 +02:00
}
2003-08-13 03:18:37 +02:00
2005-07-07 14:00:17 +02:00
# ifndef UNICODE
2003-08-13 03:18:37 +02:00
2005-07-07 14:00:17 +02:00
static LPSTR strcpyn ( LPSTR dest , LPCSTR source , size_t count )
2003-08-13 03:18:37 +02:00
{
2005-07-07 14:00:17 +02:00
LPCSTR s ;
LPSTR d = dest ;
2003-08-13 03:18:37 +02:00
for ( s = source ; count & & ( * d + + = * s + + ) ; )
count - - ;
return dest ;
}
static void get_strretA ( STRRET * str , const SHITEMID * shiid , LPSTR buffer , int len )
{
switch ( str - > uType ) {
case STRRET_WSTR :
WideCharToMultiByte ( CP_ACP , 0 , str - > UNION_MEMBER ( pOleStr ) , - 1 , buffer , len , NULL , NULL ) ;
break ;
case STRRET_OFFSET :
strcpyn ( buffer , ( LPCSTR ) shiid + str - > UNION_MEMBER ( uOffset ) , len ) ;
break ;
case STRRET_CSTR :
strcpyn ( buffer , str - > UNION_MEMBER ( cStr ) , len ) ;
}
}
2005-07-07 14:00:17 +02:00
static HRESULT path_from_pidlA ( IShellFolder * folder , LPITEMIDLIST pidl , LPSTR buffer , int len )
{
STRRET str ;
/* SHGDN_FORPARSING: get full path of id list */
2005-09-07 15:28:25 +02:00
HRESULT hr = IShellFolder_GetDisplayNameOf ( folder , pidl , SHGDN_FORPARSING , & str ) ;
2005-07-07 14:00:17 +02:00
if ( SUCCEEDED ( hr ) ) {
get_strretA ( & str , & pidl - > mkid , buffer , len ) ;
free_strret ( & str ) ;
} else
buffer [ 0 ] = ' \0 ' ;
return hr ;
}
# endif
static LPWSTR wcscpyn ( LPWSTR dest , LPCWSTR source , size_t count )
{
LPCWSTR s ;
LPWSTR d = dest ;
for ( s = source ; count & & ( * d + + = * s + + ) ; )
count - - ;
return dest ;
}
2003-08-13 03:18:37 +02:00
static void get_strretW ( STRRET * str , const SHITEMID * shiid , LPWSTR buffer , int len )
{
switch ( str - > uType ) {
case STRRET_WSTR :
wcscpyn ( buffer , str - > UNION_MEMBER ( pOleStr ) , len ) ;
break ;
case STRRET_OFFSET :
MultiByteToWideChar ( CP_ACP , 0 , ( LPCSTR ) shiid + str - > UNION_MEMBER ( uOffset ) , - 1 , buffer , len ) ;
break ;
case STRRET_CSTR :
MultiByteToWideChar ( CP_ACP , 0 , str - > UNION_MEMBER ( cStr ) , - 1 , buffer , len ) ;
}
}
2005-06-10 21:32:24 +02:00
static HRESULT name_from_pidl ( IShellFolder * folder , LPITEMIDLIST pidl , LPTSTR buffer , int len , SHGDNF flags )
2003-08-13 03:18:37 +02:00
{
STRRET str ;
2005-09-07 15:28:25 +02:00
HRESULT hr = IShellFolder_GetDisplayNameOf ( folder , pidl , flags , & str ) ;
2003-08-13 03:18:37 +02:00
if ( SUCCEEDED ( hr ) ) {
get_strret ( & str , & pidl - > mkid , buffer , len ) ;
free_strret ( & str ) ;
} else
buffer [ 0 ] = ' \0 ' ;
return hr ;
}
2005-06-10 21:32:24 +02:00
static HRESULT path_from_pidlW ( IShellFolder * folder , LPITEMIDLIST pidl , LPWSTR buffer , int len )
2003-08-13 03:18:37 +02:00
{
STRRET str ;
/* SHGDN_FORPARSING: get full path of id list */
2005-09-07 15:28:25 +02:00
HRESULT hr = IShellFolder_GetDisplayNameOf ( folder , pidl , SHGDN_FORPARSING , & str ) ;
2003-08-13 03:18:37 +02:00
if ( SUCCEEDED ( hr ) ) {
get_strretW ( & str , & pidl - > mkid , buffer , len ) ;
free_strret ( & str ) ;
} else
buffer [ 0 ] = ' \0 ' ;
return hr ;
}
/* create an item id list from a file system path */
static LPITEMIDLIST get_path_pidl ( LPTSTR path , HWND hwnd )
{
LPITEMIDLIST pidl ;
HRESULT hr ;
ULONG len ;
# ifdef UNICODE
LPWSTR buffer = path ;
# else
WCHAR buffer [ MAX_PATH ] ;
MultiByteToWideChar ( CP_ACP , 0 , path , - 1 , buffer , MAX_PATH ) ;
# endif
2005-09-07 15:28:25 +02:00
hr = IShellFolder_ParseDisplayName ( Globals . iDesktop , hwnd , NULL , buffer , & len , & pidl , NULL ) ;
2003-08-13 03:18:37 +02:00
if ( FAILED ( hr ) )
return NULL ;
return pidl ;
}
/* convert an item id list from relative to absolute (=relative to the desktop) format */
static LPITEMIDLIST get_to_absolute_pidl ( Entry * entry , HWND hwnd )
{
if ( entry - > up & & entry - > up - > etype = = ET_SHELL ) {
IShellFolder * folder = entry - > up - > folder ;
WCHAR buffer [ MAX_PATH ] ;
HRESULT hr = path_from_pidlW ( folder , entry - > pidl , buffer , MAX_PATH ) ;
if ( SUCCEEDED ( hr ) ) {
LPITEMIDLIST pidl ;
ULONG len ;
2005-09-07 15:28:25 +02:00
hr = IShellFolder_ParseDisplayName ( Globals . iDesktop , hwnd , NULL , buffer , & len , & pidl , NULL ) ;
2003-08-13 03:18:37 +02:00
if ( SUCCEEDED ( hr ) )
return pidl ;
}
2004-02-11 05:18:12 +01:00
} else if ( entry - > etype = = ET_WINDOWS ) {
TCHAR path [ MAX_PATH ] ;
get_path ( entry , path ) ;
2003-08-13 03:18:37 +02:00
2004-02-11 05:18:12 +01:00
return get_path_pidl ( path , hwnd ) ;
} else if ( entry - > pidl )
return ILClone ( entry - > pidl ) ;
return NULL ;
2003-08-13 03:18:37 +02:00
}
2005-06-10 21:32:24 +02:00
static HICON extract_icon ( IShellFolder * folder , LPCITEMIDLIST pidl )
2003-08-13 03:18:37 +02:00
{
IExtractIcon * pExtract ;
2005-09-07 15:28:25 +02:00
if ( SUCCEEDED ( IShellFolder_GetUIObjectOf ( folder , 0 , 1 , ( LPCITEMIDLIST * ) & pidl , & IID_IExtractIcon , 0 , ( LPVOID * ) & pExtract ) ) ) {
2003-08-13 03:18:37 +02:00
TCHAR path [ _MAX_PATH ] ;
unsigned flags ;
HICON hicon ;
int idx ;
2005-09-07 15:28:25 +02:00
if ( SUCCEEDED ( IExtractIconW_GetIconLocation ( pExtract , GIL_FORSHELL , path , _MAX_PATH , & idx , & flags ) ) ) {
2003-08-13 03:18:37 +02:00
if ( ! ( flags & GIL_NOTFILENAME ) ) {
if ( idx = = - 1 )
idx = 0 ; /* special case for some control panel applications */
if ( ( int ) ExtractIconEx ( path , idx , 0 , & hicon , 1 ) > 0 )
flags & = ~ GIL_DONTCACHE ;
} else {
HICON hIconLarge = 0 ;
2005-09-07 15:28:25 +02:00
HRESULT hr = IExtractIconW_Extract ( pExtract , path , idx , & hIconLarge , & hicon , MAKELONG ( 0 /*GetSystemMetrics(SM_CXICON)*/ , GetSystemMetrics ( SM_CXSMICON ) ) ) ;
2003-08-13 03:18:37 +02:00
if ( SUCCEEDED ( hr ) )
DestroyIcon ( hIconLarge ) ;
}
return hicon ;
}
}
return 0 ;
}
2005-06-13 12:04:55 +02:00
static Entry * find_entry_shell ( Entry * dir , LPCITEMIDLIST pidl )
2003-08-13 03:18:37 +02:00
{
Entry * entry ;
for ( entry = dir - > down ; entry ; entry = entry - > next ) {
if ( entry - > pidl - > mkid . cb = = pidl - > mkid . cb & &
! memcmp ( entry - > pidl , pidl , entry - > pidl - > mkid . cb ) )
return entry ;
}
return 0 ;
}
static Entry * read_tree_shell ( Root * root , LPITEMIDLIST pidl , SORT_ORDER sortOrder , HWND hwnd )
{
Entry * entry = & root - > entry ;
Entry * next ;
LPITEMIDLIST next_pidl = pidl ;
IShellFolder * folder ;
IShellFolder * child = NULL ;
HRESULT hr ;
HCURSOR old_cursor = SetCursor ( LoadCursor ( 0 , IDC_WAIT ) ) ;
# ifndef _NO_EXTENSIONS
entry - > etype = ET_SHELL ;
# endif
folder = Globals . iDesktop ;
while ( entry ) {
entry - > pidl = next_pidl ;
entry - > folder = folder ;
if ( ! pidl - > mkid . cb )
break ;
/* copy first element of item idlist */
2005-09-07 15:28:25 +02:00
next_pidl = IMalloc_Alloc ( Globals . iMalloc , pidl - > mkid . cb + sizeof ( USHORT ) ) ;
2003-08-13 03:18:37 +02:00
memcpy ( next_pidl , pidl , pidl - > mkid . cb ) ;
( ( LPITEMIDLIST ) ( ( LPBYTE ) next_pidl + pidl - > mkid . cb ) ) - > mkid . cb = 0 ;
2005-09-07 15:28:25 +02:00
hr = IShellFolder_BindToObject ( folder , next_pidl , 0 , & IID_IShellFolder , ( void * * ) & child ) ;
2003-08-13 03:18:37 +02:00
if ( ! SUCCEEDED ( hr ) )
break ;
read_directory ( entry , NULL , sortOrder , hwnd ) ;
if ( entry - > down )
entry - > expanded = TRUE ;
next = find_entry_shell ( entry , next_pidl ) ;
if ( ! next )
break ;
folder = child ;
entry = next ;
/* go to next element */
pidl = ( LPITEMIDLIST ) ( ( LPBYTE ) pidl + pidl - > mkid . cb ) ;
}
SetCursor ( old_cursor ) ;
2002-06-04 23:29:40 +02:00
return entry ;
}
2003-08-13 03:18:37 +02:00
static void fill_w32fdata_shell ( IShellFolder * folder , LPCITEMIDLIST pidl , SFGAOF attribs , WIN32_FIND_DATA * w32fdata )
{
if ( ! ( attribs & SFGAO_FILESYSTEM ) | |
FAILED ( SHGetDataFromIDList ( folder , pidl , SHGDFIL_FINDDATA , w32fdata , sizeof ( WIN32_FIND_DATA ) ) ) ) {
WIN32_FILE_ATTRIBUTE_DATA fad ;
IDataObject * pDataObj ;
STGMEDIUM medium = { 0 , { 0 } , 0 } ;
FORMATETC fmt = { Globals . cfStrFName , 0 , DVASPECT_CONTENT , - 1 , TYMED_HGLOBAL } ;
2005-09-07 15:28:25 +02:00
HRESULT hr = IShellFolder_GetUIObjectOf ( folder , 0 , 1 , & pidl , & IID_IDataObject , 0 , ( LPVOID * ) & pDataObj ) ;
2003-08-13 03:18:37 +02:00
if ( SUCCEEDED ( hr ) ) {
2005-09-07 15:28:25 +02:00
hr = IDataObject_GetData ( pDataObj , & fmt , & medium ) ;
2003-08-13 03:18:37 +02:00
2005-09-07 15:28:25 +02:00
IDataObject_Release ( pDataObj ) ;
2003-08-13 03:18:37 +02:00
if ( SUCCEEDED ( hr ) ) {
LPCTSTR path = ( LPCTSTR ) GlobalLock ( medium . UNION_MEMBER ( hGlobal ) ) ;
UINT sem_org = SetErrorMode ( SEM_FAILCRITICALERRORS ) ;
if ( GetFileAttributesEx ( path , GetFileExInfoStandard , & fad ) ) {
w32fdata - > dwFileAttributes = fad . dwFileAttributes ;
w32fdata - > ftCreationTime = fad . ftCreationTime ;
w32fdata - > ftLastAccessTime = fad . ftLastAccessTime ;
w32fdata - > ftLastWriteTime = fad . ftLastWriteTime ;
if ( ! ( fad . dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) ) {
w32fdata - > nFileSizeLow = fad . nFileSizeLow ;
w32fdata - > nFileSizeHigh = fad . nFileSizeHigh ;
}
}
SetErrorMode ( sem_org ) ;
GlobalUnlock ( medium . UNION_MEMBER ( hGlobal ) ) ;
GlobalFree ( medium . UNION_MEMBER ( hGlobal ) ) ;
}
}
}
if ( attribs & ( SFGAO_FOLDER | SFGAO_HASSUBFOLDER ) )
w32fdata - > dwFileAttributes | = FILE_ATTRIBUTE_DIRECTORY ;
if ( attribs & SFGAO_READONLY )
w32fdata - > dwFileAttributes | = FILE_ATTRIBUTE_READONLY ;
if ( attribs & SFGAO_COMPRESSED )
w32fdata - > dwFileAttributes | = FILE_ATTRIBUTE_COMPRESSED ;
}
static void read_directory_shell ( Entry * dir , HWND hwnd )
{
IShellFolder * folder = dir - > folder ;
int level = dir - > level + 1 ;
HRESULT hr ;
IShellFolder * child ;
IEnumIDList * idlist ;
Entry * first_entry = NULL ;
Entry * last = NULL ;
Entry * entry ;
if ( ! folder )
return ;
2005-09-07 15:28:25 +02:00
hr = IShellFolder_EnumObjects ( folder , hwnd , SHCONTF_FOLDERS | SHCONTF_NONFOLDERS | SHCONTF_INCLUDEHIDDEN | SHCONTF_SHAREABLE | SHCONTF_STORAGE , & idlist ) ;
2003-08-13 03:18:37 +02:00
if ( SUCCEEDED ( hr ) ) {
for ( ; ; ) {
# define FETCH_ITEM_COUNT 32
LPITEMIDLIST pidls [ FETCH_ITEM_COUNT ] ;
SFGAOF attribs ;
ULONG cnt = 0 ;
ULONG n ;
memset ( pidls , 0 , sizeof ( pidls ) ) ;
2005-09-07 15:28:25 +02:00
hr = IEnumIDList_Next ( idlist , FETCH_ITEM_COUNT , pidls , & cnt ) ;
2003-08-13 03:18:37 +02:00
if ( ! SUCCEEDED ( hr ) )
break ;
if ( hr = = S_FALSE )
break ;
for ( n = 0 ; n < cnt ; + + n ) {
entry = alloc_entry ( ) ;
if ( ! first_entry )
first_entry = entry ;
if ( last )
last - > next = entry ;
memset ( & entry - > data , 0 , sizeof ( WIN32_FIND_DATA ) ) ;
entry - > bhfi_valid = FALSE ;
attribs = ~ SFGAO_FILESYSTEM ; /*SFGAO_HASSUBFOLDER|SFGAO_FOLDER; SFGAO_FILESYSTEM sorgt daf<61> r, da<64> "My Documents" anstatt von "Martin's Documents" angezeigt wird */
2005-09-07 15:28:25 +02:00
hr = IShellFolder_GetAttributesOf ( folder , 1 , ( LPCITEMIDLIST * ) & pidls [ n ] , & attribs ) ;
2003-08-13 03:18:37 +02:00
if ( SUCCEEDED ( hr ) ) {
if ( attribs ! = ( SFGAOF ) ~ SFGAO_FILESYSTEM ) {
fill_w32fdata_shell ( folder , pidls [ n ] , attribs , & entry - > data ) ;
entry - > bhfi_valid = TRUE ;
} else
attribs = 0 ;
} else
attribs = 0 ;
entry - > pidl = pidls [ n ] ;
if ( entry - > data . dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
2005-09-07 15:28:25 +02:00
hr = IShellFolder_BindToObject ( folder , pidls [ n ] , 0 , & IID_IShellFolder , ( void * * ) & child ) ;
2003-08-13 03:18:37 +02:00
if ( SUCCEEDED ( hr ) )
entry - > folder = child ;
else
entry - > folder = NULL ;
}
else
entry - > folder = NULL ;
if ( ! entry - > data . cFileName [ 0 ] )
/*hr = */ name_from_pidl ( folder , pidls [ n ] , entry - > data . cFileName , MAX_PATH , /*SHGDN_INFOLDER*/ 0x2000 /*0x2000=SHGDN_INCLUDE_NONFILESYS*/ ) ;
/* get display icons for files and virtual objects */
if ( ! ( entry - > data . dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) | |
! ( attribs & SFGAO_FILESYSTEM ) ) {
entry - > hicon = extract_icon ( folder , pidls [ n ] ) ;
if ( ! entry - > hicon )
entry - > hicon = ( HICON ) - 1 ; /* don't try again later */
}
entry - > down = NULL ;
entry - > up = dir ;
entry - > expanded = FALSE ;
entry - > scanned = FALSE ;
entry - > level = level ;
# ifndef _NO_EXTENSIONS
entry - > etype = ET_SHELL ;
entry - > bhfi_valid = FALSE ;
2002-06-04 23:29:40 +02:00
# endif
2003-08-13 03:18:37 +02:00
last = entry ;
}
}
2005-09-07 15:28:25 +02:00
IEnumIDList_Release ( idlist ) ;
2003-08-13 03:18:37 +02:00
}
if ( last )
last - > next = NULL ;
dir - > down = first_entry ;
dir - > scanned = TRUE ;
}
# endif /* _SHELL_FOLDERS */
2002-06-04 23:29:40 +02:00
2004-09-22 21:11:49 +02:00
/* sort order for different directory/file types */
enum TYPE_ORDER {
TO_DIR = 0 ,
TO_DOT = 1 ,
TO_DOTDOT = 2 ,
TO_OTHER_DIR = 3 ,
TO_FILE = 4
} ;
/* distinguish between ".", ".." and any other directory names */
static int TypeOrderFromDirname ( LPCTSTR name )
{
if ( name [ 0 ] = = ' . ' ) {
if ( name [ 1 ] = = ' \0 ' )
return TO_DOT ; /* "." */
if ( name [ 1 ] = = ' . ' & & name [ 2 ] = = ' \0 ' )
return TO_DOTDOT ; /* ".." */
}
return TO_OTHER_DIR ; /* anything else */
}
2002-06-28 19:37:34 +02:00
/* directories first... */
2002-06-04 23:29:40 +02:00
static int compareType ( const WIN32_FIND_DATA * fd1 , const WIN32_FIND_DATA * fd2 )
{
2004-09-22 21:11:49 +02:00
int order1 = fd1 - > dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ? TO_DIR : TO_FILE ;
int order2 = fd2 - > dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ? TO_DIR : TO_FILE ;
/* Handle "." and ".." as special case and move them at the very first beginning. */
if ( order1 = = TO_DIR & & order2 = = TO_DIR ) {
order1 = TypeOrderFromDirname ( fd1 - > cFileName ) ;
order2 = TypeOrderFromDirname ( fd2 - > cFileName ) ;
}
2002-06-04 23:29:40 +02:00
2004-09-22 21:11:49 +02:00
return order2 = = order1 ? 0 : order1 < order2 ? - 1 : 1 ;
2002-06-04 23:29:40 +02:00
}
static int compareName ( const void * arg1 , const void * arg2 )
{
2004-11-30 22:38:57 +01:00
const WIN32_FIND_DATA * fd1 = & ( * ( const Entry * const * ) arg1 ) - > data ;
const WIN32_FIND_DATA * fd2 = & ( * ( const Entry * const * ) arg2 ) - > data ;
2002-06-04 23:29:40 +02:00
int cmp = compareType ( fd1 , fd2 ) ;
if ( cmp )
return cmp ;
return lstrcmpi ( fd1 - > cFileName , fd2 - > cFileName ) ;
}
static int compareExt ( const void * arg1 , const void * arg2 )
{
2004-11-30 22:38:57 +01:00
const WIN32_FIND_DATA * fd1 = & ( * ( const Entry * const * ) arg1 ) - > data ;
const WIN32_FIND_DATA * fd2 = & ( * ( const Entry * const * ) arg2 ) - > data ;
2002-06-04 23:29:40 +02:00
const TCHAR * name1 , * name2 , * ext1 , * ext2 ;
int cmp = compareType ( fd1 , fd2 ) ;
if ( cmp )
return cmp ;
name1 = fd1 - > cFileName ;
name2 = fd2 - > cFileName ;
2007-06-27 22:54:56 +02:00
ext1 = _tcsrchr ( name1 , ' . ' ) ;
ext2 = _tcsrchr ( name2 , ' . ' ) ;
2002-06-04 23:29:40 +02:00
if ( ext1 )
ext1 + + ;
else
2004-11-22 19:24:09 +01:00
ext1 = sEmpty ;
2002-06-04 23:29:40 +02:00
if ( ext2 )
ext2 + + ;
else
2004-11-22 19:24:09 +01:00
ext2 = sEmpty ;
2002-06-04 23:29:40 +02:00
cmp = lstrcmpi ( ext1 , ext2 ) ;
if ( cmp )
return cmp ;
return lstrcmpi ( name1 , name2 ) ;
}
static int compareSize ( const void * arg1 , const void * arg2 )
{
2004-11-30 22:38:57 +01:00
const WIN32_FIND_DATA * fd1 = & ( * ( const Entry * const * ) arg1 ) - > data ;
const WIN32_FIND_DATA * fd2 = & ( * ( const Entry * const * ) arg2 ) - > data ;
2002-06-04 23:29:40 +02:00
int cmp = compareType ( fd1 , fd2 ) ;
if ( cmp )
return cmp ;
cmp = fd2 - > nFileSizeHigh - fd1 - > nFileSizeHigh ;
if ( cmp < 0 )
return - 1 ;
else if ( cmp > 0 )
return 1 ;
cmp = fd2 - > nFileSizeLow - fd1 - > nFileSizeLow ;
return cmp < 0 ? - 1 : cmp > 0 ? 1 : 0 ;
}
static int compareDate ( const void * arg1 , const void * arg2 )
{
2004-11-30 22:38:57 +01:00
const WIN32_FIND_DATA * fd1 = & ( * ( const Entry * const * ) arg1 ) - > data ;
const WIN32_FIND_DATA * fd2 = & ( * ( const Entry * const * ) arg2 ) - > data ;
2002-06-04 23:29:40 +02:00
int cmp = compareType ( fd1 , fd2 ) ;
if ( cmp )
return cmp ;
return CompareFileTime ( & fd2 - > ftLastWriteTime , & fd1 - > ftLastWriteTime ) ;
}
static int ( * sortFunctions [ ] ) ( const void * arg1 , const void * arg2 ) = {
2003-08-13 03:18:37 +02:00
compareName , /* SORT_NAME */
2002-06-28 19:37:34 +02:00
compareExt , /* SORT_EXT */
compareSize , /* SORT_SIZE */
compareDate /* SORT_DATE */
2002-06-04 23:29:40 +02:00
} ;
2003-08-13 03:18:37 +02:00
static void SortDirectory ( Entry * dir , SORT_ORDER sortOrder )
2002-06-04 23:29:40 +02:00
{
2003-08-13 03:18:37 +02:00
Entry * entry = dir - > down ;
2002-06-04 23:29:40 +02:00
Entry * * array , * * p ;
int len ;
len = 0 ;
2003-08-13 03:18:37 +02:00
for ( entry = dir - > down ; entry ; entry = entry - > next )
2002-06-04 23:29:40 +02:00
len + + ;
if ( len ) {
2003-08-28 21:40:51 +02:00
array = HeapAlloc ( GetProcessHeap ( ) , 0 , len * sizeof ( Entry * ) ) ;
2002-06-04 23:29:40 +02:00
p = array ;
2003-08-13 03:18:37 +02:00
for ( entry = dir - > down ; entry ; entry = entry - > next )
2002-06-04 23:29:40 +02:00
* p + + = entry ;
2002-06-28 19:37:34 +02:00
/* call qsort with the appropriate compare function */
2002-06-04 23:29:40 +02:00
qsort ( array , len , sizeof ( array [ 0 ] ) , sortFunctions [ sortOrder ] ) ;
2003-08-13 03:18:37 +02:00
dir - > down = array [ 0 ] ;
2002-06-04 23:29:40 +02:00
for ( p = array ; - - len ; p + + )
p [ 0 ] - > next = p [ 1 ] ;
( * p ) - > next = 0 ;
2005-06-13 12:04:55 +02:00
HeapFree ( GetProcessHeap ( ) , 0 , array ) ;
2002-06-04 23:29:40 +02:00
}
}
2003-08-13 03:18:37 +02:00
static void read_directory ( Entry * dir , LPCTSTR path , SORT_ORDER sortOrder , HWND hwnd )
2002-06-04 23:29:40 +02:00
{
TCHAR buffer [ MAX_PATH ] ;
Entry * entry ;
LPCTSTR s ;
PTSTR d ;
2003-08-13 03:18:37 +02:00
# ifdef _SHELL_FOLDERS
if ( dir - > etype = = ET_SHELL )
{
read_directory_shell ( dir , hwnd ) ;
if ( Globals . prescan_node ) {
s = path ;
d = buffer ;
while ( * s )
* d + + = * s + + ;
2007-06-27 22:54:56 +02:00
* d + + = ' \\ ' ;
2003-08-13 03:18:37 +02:00
for ( entry = dir - > down ; entry ; entry = entry - > next )
if ( entry - > data . dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
read_directory_shell ( entry , hwnd ) ;
SortDirectory ( entry , sortOrder ) ;
}
}
}
else
# endif
# if !defined(_NO_EXTENSIONS) && defined(__WINE__)
if ( dir - > etype = = ET_UNIX )
2002-06-04 23:29:40 +02:00
{
2003-08-13 03:18:37 +02:00
read_directory_unix ( dir , path ) ;
2002-06-04 23:29:40 +02:00
if ( Globals . prescan_node ) {
s = path ;
d = buffer ;
while ( * s )
* d + + = * s + + ;
2007-06-27 22:54:56 +02:00
* d + + = ' / ' ;
2002-06-04 23:29:40 +02:00
2003-08-13 03:18:37 +02:00
for ( entry = dir - > down ; entry ; entry = entry - > next )
2002-06-04 23:29:40 +02:00
if ( entry - > data . dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
lstrcpy ( d , entry - > data . cFileName ) ;
read_directory_unix ( entry , buffer ) ;
SortDirectory ( entry , sortOrder ) ;
}
}
}
else
# endif
{
2003-08-13 03:18:37 +02:00
read_directory_win ( dir , path ) ;
2002-06-04 23:29:40 +02:00
if ( Globals . prescan_node ) {
s = path ;
d = buffer ;
while ( * s )
* d + + = * s + + ;
2007-06-27 22:54:56 +02:00
* d + + = ' \\ ' ;
2002-06-04 23:29:40 +02:00
2003-08-13 03:18:37 +02:00
for ( entry = dir - > down ; entry ; entry = entry - > next )
2002-06-04 23:29:40 +02:00
if ( entry - > data . dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
lstrcpy ( d , entry - > data . cFileName ) ;
read_directory_win ( entry , buffer ) ;
SortDirectory ( entry , sortOrder ) ;
}
}
}
2003-08-13 03:18:37 +02:00
SortDirectory ( dir , sortOrder ) ;
2002-06-04 23:29:40 +02:00
}
2005-05-16 10:48:54 +02:00
static Entry * read_tree ( Root * root , LPCTSTR path , LPITEMIDLIST pidl , LPTSTR drv , SORT_ORDER sortOrder , HWND hwnd )
2002-06-04 23:29:40 +02:00
{
2004-11-22 19:24:09 +01:00
# if !defined(_NO_EXTENSIONS) && defined(__WINE__)
2005-10-06 13:38:45 +02:00
static const TCHAR sSlash [ ] = { ' / ' , ' \0 ' } ;
2004-11-22 19:24:09 +01:00
# endif
2005-10-06 13:38:45 +02:00
static const TCHAR sBackslash [ ] = { ' \\ ' , ' \0 ' } ;
2005-05-16 10:48:54 +02:00
# ifdef _SHELL_FOLDERS
if ( pidl )
{
/* read shell namespace tree */
root - > drive_type = DRIVE_UNKNOWN ;
drv [ 0 ] = ' \\ ' ;
drv [ 1 ] = ' \0 ' ;
load_string ( root - > volname , IDS_DESKTOP ) ;
root - > fs_flags = 0 ;
load_string ( root - > fs , IDS_SHELL ) ;
return read_tree_shell ( root , pidl , sortOrder , hwnd ) ;
}
else
# endif
# if !defined(_NO_EXTENSIONS) && defined(__WINE__)
if ( * path = = ' / ' )
{
/* read unix file system tree */
root - > drive_type = GetDriveType ( path ) ;
lstrcat ( drv , sSlash ) ;
load_string ( root - > volname , IDS_ROOT_FS ) ;
root - > fs_flags = 0 ;
load_string ( root - > fs , IDS_UNIXFS ) ;
lstrcpy ( root - > path , sSlash ) ;
return read_tree_unix ( root , path , sortOrder , hwnd ) ;
}
# endif
/* read WIN32 file system tree */
root - > drive_type = GetDriveType ( path ) ;
lstrcat ( drv , sBackslash ) ;
GetVolumeInformation ( drv , root - > volname , _MAX_FNAME , 0 , 0 , & root - > fs_flags , root - > fs , _MAX_DIR ) ;
lstrcpy ( root - > path , drv ) ;
2004-11-22 19:24:09 +01:00
2005-05-16 10:48:54 +02:00
return read_tree_win ( root , path , sortOrder , hwnd ) ;
}
2005-05-29 22:05:29 +02:00
/* flags to filter different file types */
enum TYPE_FILTER {
TF_DIRECTORIES = 0x01 ,
TF_PROGRAMS = 0x02 ,
TF_DOCUMENTS = 0x04 ,
TF_OTHERS = 0x08 ,
TF_HIDDEN = 0x10 ,
TF_ALL = 0x1F
} ;
2005-05-16 10:48:54 +02:00
static ChildWnd * alloc_child_window ( LPCTSTR path , LPITEMIDLIST pidl , HWND hwnd )
{
2002-06-04 23:29:40 +02:00
TCHAR drv [ _MAX_DRIVE + 1 ] , dir [ _MAX_DIR ] , name [ _MAX_FNAME ] , ext [ _MAX_EXT ] ;
2006-01-11 12:32:51 +01:00
TCHAR dir_path [ MAX_PATH ] ;
2004-10-22 21:52:50 +02:00
TCHAR b1 [ BUFFER_LEN ] ;
2005-10-06 13:38:45 +02:00
static const TCHAR sAsterics [ ] = { ' * ' , ' \0 ' } ;
2004-10-21 21:51:31 +02:00
2007-07-23 22:25:20 +02:00
ChildWnd * child = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( ChildWnd ) ) ;
2002-06-04 23:29:40 +02:00
Root * root = & child - > root ;
Entry * entry ;
memset ( child , 0 , sizeof ( ChildWnd ) ) ;
child - > left . treePane = TRUE ;
child - > left . visible_cols = 0 ;
child - > right . treePane = FALSE ;
# ifndef _NO_EXTENSIONS
child - > right . visible_cols = COL_SIZE | COL_DATE | COL_TIME | COL_ATTRIBUTES | COL_INDEX | COL_LINKS ;
# else
child - > right . visible_cols = COL_SIZE | COL_DATE | COL_TIME | COL_ATTRIBUTES ;
# endif
child - > pos . length = sizeof ( WINDOWPLACEMENT ) ;
child - > pos . flags = 0 ;
child - > pos . showCmd = SW_SHOWNORMAL ;
child - > pos . rcNormalPosition . left = CW_USEDEFAULT ;
child - > pos . rcNormalPosition . top = CW_USEDEFAULT ;
child - > pos . rcNormalPosition . right = CW_USEDEFAULT ;
child - > pos . rcNormalPosition . bottom = CW_USEDEFAULT ;
child - > focus_pane = 0 ;
2003-08-13 03:18:37 +02:00
child - > split_pos = DEFAULT_SPLIT_POS ;
2002-06-04 23:29:40 +02:00
child - > sortOrder = SORT_NAME ;
child - > header_wdths_ok = FALSE ;
2003-08-13 03:18:37 +02:00
if ( path )
{
lstrcpy ( child - > path , path ) ;
_tsplitpath ( path , drv , dir , name , ext ) ;
}
2002-06-04 23:29:40 +02:00
2005-07-07 14:00:17 +02:00
lstrcpy ( child - > filter_pattern , sAsterics ) ;
2005-05-29 22:05:29 +02:00
child - > filter_flags = TF_ALL ;
2003-08-13 03:18:37 +02:00
root - > entry . level = 0 ;
2006-01-11 12:32:51 +01:00
lstrcpy ( dir_path , drv ) ;
lstrcat ( dir_path , dir ) ;
entry = read_tree ( root , dir_path , pidl , drv , child - > sortOrder , hwnd ) ;
2002-06-04 23:29:40 +02:00
2003-08-13 03:18:37 +02:00
# ifdef _SHELL_FOLDERS
if ( root - > entry . etype = = ET_SHELL )
2004-10-22 21:52:50 +02:00
load_string ( root - > entry . data . cFileName , IDS_DESKTOP ) ;
2003-08-13 03:18:37 +02:00
else
# endif
2004-10-22 21:52:50 +02:00
wsprintf ( root - > entry . data . cFileName , RS ( b1 , IDS_TITLEFMT ) , drv , root - > fs ) ;
2002-06-04 23:29:40 +02:00
root - > entry . data . dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY ;
child - > left . root = & root - > entry ;
2003-08-13 03:18:37 +02:00
child - > right . root = NULL ;
2002-06-04 23:29:40 +02:00
2005-05-16 10:48:54 +02:00
set_curdir ( child , entry , 0 , hwnd ) ;
2002-06-04 23:29:40 +02:00
return child ;
}
2002-06-28 19:37:34 +02:00
/* free all memory associated with a child window */
2002-06-04 23:29:40 +02:00
static void free_child_window ( ChildWnd * child )
{
free_entries ( & child - > root . entry ) ;
2007-07-23 22:25:20 +02:00
HeapFree ( GetProcessHeap ( ) , 0 , child ) ;
2002-06-04 23:29:40 +02:00
}
2002-06-28 19:37:34 +02:00
/* get full path of specified directory entry */
2002-06-04 23:29:40 +02:00
static void get_path ( Entry * dir , PTSTR path )
{
Entry * entry ;
int len = 0 ;
int level = 0 ;
2003-08-13 03:18:37 +02:00
# ifdef _SHELL_FOLDERS
if ( dir - > etype = = ET_SHELL )
{
SFGAOF attribs ;
HRESULT hr = S_OK ;
2007-06-27 22:54:56 +02:00
path [ 0 ] = ' \0 ' ;
2003-08-13 03:18:37 +02:00
attribs = 0 ;
if ( dir - > folder )
2005-09-07 15:28:25 +02:00
hr = IShellFolder_GetAttributesOf ( dir - > folder , 1 , ( LPCITEMIDLIST * ) & dir - > pidl , & attribs ) ;
2003-08-13 03:18:37 +02:00
if ( SUCCEEDED ( hr ) & & ( attribs & SFGAO_FILESYSTEM ) ) {
IShellFolder * parent = dir - > up ? dir - > up - > folder : Globals . iDesktop ;
hr = path_from_pidl ( parent , dir - > pidl , path , MAX_PATH ) ;
}
}
else
# endif
{
for ( entry = dir ; entry ; level + + ) {
LPCTSTR name ;
int l ;
{
LPCTSTR s ;
name = entry - > data . cFileName ;
s = name ;
2002-06-04 23:29:40 +02:00
2007-06-27 22:54:56 +02:00
for ( l = 0 ; * s & & * s ! = ' / ' & & * s ! = ' \\ ' ; s + + )
2003-08-13 03:18:37 +02:00
l + + ;
}
2002-06-04 23:29:40 +02:00
2003-08-13 03:18:37 +02:00
if ( entry - > up ) {
if ( l > 0 ) {
memmove ( path + l + 1 , path , len * sizeof ( TCHAR ) ) ;
memcpy ( path + 1 , name , l * sizeof ( TCHAR ) ) ;
len + = l + 1 ;
2002-06-04 23:29:40 +02:00
# ifndef _NO_EXTENSIONS
2003-08-13 03:18:37 +02:00
if ( entry - > etype = = ET_UNIX )
2007-06-27 22:54:56 +02:00
path [ 0 ] = ' / ' ;
2003-08-13 03:18:37 +02:00
else
2002-06-04 23:29:40 +02:00
# endif
2007-06-27 22:54:56 +02:00
path [ 0 ] = ' \\ ' ;
2003-08-13 03:18:37 +02:00
}
2002-06-04 23:29:40 +02:00
2003-08-13 03:18:37 +02:00
entry = entry - > up ;
} else {
memmove ( path + l , path , len * sizeof ( TCHAR ) ) ;
memcpy ( path , name , l * sizeof ( TCHAR ) ) ;
len + = l ;
break ;
}
2002-06-04 23:29:40 +02:00
}
2003-08-13 03:18:37 +02:00
if ( ! level ) {
2002-06-04 23:29:40 +02:00
# ifndef _NO_EXTENSIONS
2003-08-13 03:18:37 +02:00
if ( entry - > etype = = ET_UNIX )
2007-06-27 22:54:56 +02:00
path [ len + + ] = ' / ' ;
2003-08-13 03:18:37 +02:00
else
2002-06-04 23:29:40 +02:00
# endif
2007-06-27 22:54:56 +02:00
path [ len + + ] = ' \\ ' ;
2003-08-13 03:18:37 +02:00
}
2002-06-04 23:29:40 +02:00
2007-06-27 22:54:56 +02:00
path [ len ] = ' \0 ' ;
2003-08-13 03:18:37 +02:00
}
2002-06-04 23:29:40 +02:00
}
2006-02-20 18:57:01 +01:00
static windowOptions load_registry_settings ( void )
{
DWORD size ;
DWORD type ;
HKEY hKey ;
windowOptions opts ;
2007-07-24 22:28:51 +02:00
RegOpenKeyExW ( HKEY_CURRENT_USER , registry_key ,
0 , KEY_QUERY_VALUE , & hKey ) ;
2006-02-20 18:57:01 +01:00
size = sizeof ( DWORD ) ;
2007-07-24 22:28:51 +02:00
if ( RegQueryValueExW ( hKey , reg_start_x , NULL , & type ,
( LPBYTE ) & opts . start_x , & size ) ! = ERROR_SUCCESS )
2006-02-20 18:57:01 +01:00
opts . start_x = CW_USEDEFAULT ;
2007-07-24 22:28:51 +02:00
if ( RegQueryValueExW ( hKey , reg_start_y , NULL , & type ,
( LPBYTE ) & opts . start_y , & size ) ! = ERROR_SUCCESS )
2006-02-20 18:57:01 +01:00
opts . start_y = CW_USEDEFAULT ;
2007-07-24 22:28:51 +02:00
if ( RegQueryValueExW ( hKey , reg_width , NULL , & type ,
( LPBYTE ) & opts . width , & size ) ! = ERROR_SUCCESS )
2006-02-20 18:57:01 +01:00
opts . width = CW_USEDEFAULT ;
2007-07-24 22:28:51 +02:00
if ( RegQueryValueExW ( hKey , reg_height , NULL , & type ,
( LPBYTE ) & opts . height , & size ) ! = ERROR_SUCCESS )
2006-02-20 18:57:01 +01:00
opts . height = CW_USEDEFAULT ;
RegCloseKey ( hKey ) ;
return opts ;
}
static void save_registry_settings ( void )
{
WINDOWINFO wi ;
HKEY hKey ;
INT width , height ;
wi . cbSize = sizeof ( WINDOWINFO ) ;
GetWindowInfo ( Globals . hMainWnd , & wi ) ;
width = wi . rcWindow . right - wi . rcWindow . left ;
height = wi . rcWindow . bottom - wi . rcWindow . top ;
2007-07-24 22:28:51 +02:00
if ( RegOpenKeyExW ( HKEY_CURRENT_USER , registry_key ,
0 , KEY_SET_VALUE , & hKey ) ! = ERROR_SUCCESS )
2006-02-20 18:57:01 +01:00
{
/* Unable to save registry settings - try to create key */
2007-07-24 22:28:51 +02:00
if ( RegCreateKeyExW ( HKEY_CURRENT_USER , registry_key ,
0 , NULL , REG_OPTION_NON_VOLATILE ,
KEY_SET_VALUE , NULL , & hKey , NULL ) ! = ERROR_SUCCESS )
2006-02-20 18:57:01 +01:00
{
/* FIXME: Cannot create key */
return ;
}
}
/* Save all of the settings */
2007-07-24 22:28:51 +02:00
RegSetValueExW ( hKey , reg_start_x , 0 , REG_DWORD ,
( LPBYTE ) & wi . rcWindow . left , sizeof ( DWORD ) ) ;
RegSetValueExW ( hKey , reg_start_y , 0 , REG_DWORD ,
( LPBYTE ) & wi . rcWindow . top , sizeof ( DWORD ) ) ;
RegSetValueExW ( hKey , reg_width , 0 , REG_DWORD ,
( LPBYTE ) & width , sizeof ( DWORD ) ) ;
RegSetValueExW ( hKey , reg_height , 0 , REG_DWORD ,
( LPBYTE ) & height , sizeof ( DWORD ) ) ;
2006-02-20 18:57:01 +01:00
/* TODO: Save more settings here (List vs. Detailed View, etc.) */
RegCloseKey ( hKey ) ;
}
2002-06-04 23:29:40 +02:00
static void resize_frame_rect ( HWND hwnd , PRECT prect )
{
int new_top ;
RECT rt ;
if ( IsWindowVisible ( Globals . htoolbar ) ) {
SendMessage ( Globals . htoolbar , WM_SIZE , 0 , 0 ) ;
GetClientRect ( Globals . htoolbar , & rt ) ;
prect - > top = rt . bottom + 3 ;
prect - > bottom - = rt . bottom + 3 ;
}
if ( IsWindowVisible ( Globals . hdrivebar ) ) {
SendMessage ( Globals . hdrivebar , WM_SIZE , 0 , 0 ) ;
GetClientRect ( Globals . hdrivebar , & rt ) ;
new_top = - - prect - > top + rt . bottom + 3 ;
MoveWindow ( Globals . hdrivebar , 0 , prect - > top , rt . right , new_top , TRUE ) ;
prect - > top = new_top ;
prect - > bottom - = rt . bottom + 2 ;
}
if ( IsWindowVisible ( Globals . hstatusbar ) ) {
int parts [ ] = { 300 , 500 } ;
SendMessage ( Globals . hstatusbar , WM_SIZE , 0 , 0 ) ;
SendMessage ( Globals . hstatusbar , SB_SETPARTS , 2 , ( LPARAM ) & parts ) ;
GetClientRect ( Globals . hstatusbar , & rt ) ;
prect - > bottom - = rt . bottom ;
}
MoveWindow ( Globals . hmdiclient , prect - > left - 1 , prect - > top - 1 , prect - > right + 2 , prect - > bottom + 1 , TRUE ) ;
}
static void resize_frame ( HWND hwnd , int cx , int cy )
{
2002-07-03 23:06:58 +02:00
RECT rect ;
rect . left = 0 ;
rect . top = 0 ;
rect . right = cx ;
rect . bottom = cy ;
2002-06-04 23:29:40 +02:00
resize_frame_rect ( hwnd , & rect ) ;
}
static void resize_frame_client ( HWND hwnd )
{
RECT rect ;
GetClientRect ( hwnd , & rect ) ;
resize_frame_rect ( hwnd , & rect ) ;
}
static HHOOK hcbthook ;
static ChildWnd * newchild = NULL ;
2005-06-10 21:32:24 +02:00
static LRESULT CALLBACK CBTProc ( int code , WPARAM wparam , LPARAM lparam )
2002-06-04 23:29:40 +02:00
{
if ( code = = HCBT_CREATEWND & & newchild ) {
ChildWnd * child = newchild ;
newchild = NULL ;
child - > hwnd = ( HWND ) wparam ;
2005-09-09 17:20:04 +02:00
SetWindowLongPtr ( child - > hwnd , GWLP_USERDATA , ( LPARAM ) child ) ;
2002-06-04 23:29:40 +02:00
}
return CallNextHookEx ( hcbthook , code , wparam , lparam ) ;
}
static HWND create_child_window ( ChildWnd * child )
{
2002-07-03 23:06:58 +02:00
MDICREATESTRUCT mcs ;
2002-06-04 23:29:40 +02:00
int idx ;
2004-11-22 19:24:09 +01:00
mcs . szClass = sWINEFILETREE ;
2002-07-03 23:06:58 +02:00
mcs . szTitle = ( LPTSTR ) child - > path ;
mcs . hOwner = Globals . hInstance ;
mcs . x = child - > pos . rcNormalPosition . left ;
mcs . y = child - > pos . rcNormalPosition . top ;
mcs . cx = child - > pos . rcNormalPosition . right - child - > pos . rcNormalPosition . left ;
mcs . cy = child - > pos . rcNormalPosition . bottom - child - > pos . rcNormalPosition . top ;
2004-10-07 06:20:04 +02:00
mcs . style = 0 ;
2002-07-03 23:06:58 +02:00
mcs . lParam = 0 ;
2002-06-04 23:29:40 +02:00
hcbthook = SetWindowsHookEx ( WH_CBT , CBTProc , 0 , GetCurrentThreadId ( ) ) ;
newchild = child ;
child - > hwnd = ( HWND ) SendMessage ( Globals . hmdiclient , WM_MDICREATE , 0 , ( LPARAM ) & mcs ) ;
2003-08-13 03:18:37 +02:00
if ( ! child - > hwnd ) {
UnhookWindowsHookEx ( hcbthook ) ;
2002-06-04 23:29:40 +02:00
return 0 ;
2003-08-13 03:18:37 +02:00
}
2002-06-04 23:29:40 +02:00
UnhookWindowsHookEx ( hcbthook ) ;
2006-03-17 16:57:16 +01:00
SendMessage ( child - > left . hwnd , LB_SETITEMHEIGHT , 1 , max ( Globals . spaceSize . cy , IMAGE_HEIGHT + 3 ) ) ;
SendMessage ( child - > right . hwnd , LB_SETITEMHEIGHT , 1 , max ( Globals . spaceSize . cy , IMAGE_HEIGHT + 3 ) ) ;
2005-05-16 10:48:54 +02:00
2006-03-17 16:57:16 +01:00
idx = SendMessage ( child - > left . hwnd , LB_FINDSTRING , 0 , ( LPARAM ) child - > left . cur ) ;
SendMessage ( child - > left . hwnd , LB_SETCURSEL , idx , 0 ) ;
2002-06-04 23:29:40 +02:00
return child - > hwnd ;
}
struct ExecuteDialog {
TCHAR cmd [ MAX_PATH ] ;
int cmdshow ;
} ;
2005-06-13 12:04:55 +02:00
static INT_PTR CALLBACK ExecuteDialogDlgProc ( HWND hwnd , UINT nmsg , WPARAM wparam , LPARAM lparam )
2002-06-04 23:29:40 +02:00
{
static struct ExecuteDialog * dlg ;
switch ( nmsg ) {
case WM_INITDIALOG :
dlg = ( struct ExecuteDialog * ) lparam ;
return 1 ;
case WM_COMMAND : {
int id = ( int ) wparam ;
if ( id = = IDOK ) {
GetWindowText ( GetDlgItem ( hwnd , 201 ) , dlg - > cmd , MAX_PATH ) ;
2006-03-17 16:57:16 +01:00
dlg - > cmdshow = get_check ( hwnd , 214 ) ? SW_SHOWMINIMIZED : SW_SHOWNORMAL ;
2002-06-04 23:29:40 +02:00
EndDialog ( hwnd , id ) ;
} else if ( id = = IDCANCEL )
EndDialog ( hwnd , id ) ;
return 1 ; }
}
return 0 ;
}
2005-05-29 22:05:29 +02:00
2004-11-22 19:24:09 +01:00
static INT_PTR CALLBACK DestinationDlgProc ( HWND hwnd , UINT nmsg , WPARAM wparam , LPARAM lparam )
2004-09-27 22:35:53 +02:00
{
2004-10-22 21:52:50 +02:00
TCHAR b1 [ BUFFER_LEN ] , b2 [ BUFFER_LEN ] ;
2004-10-21 21:51:31 +02:00
2004-09-27 22:35:53 +02:00
switch ( nmsg ) {
case WM_INITDIALOG :
2005-09-09 17:20:04 +02:00
SetWindowLongPtr ( hwnd , GWLP_USERDATA , lparam ) ;
2005-05-13 19:46:11 +02:00
SetWindowText ( GetDlgItem ( hwnd , 201 ) , ( LPCTSTR ) lparam ) ;
2004-09-27 22:35:53 +02:00
return 1 ;
2004-10-07 06:25:29 +02:00
case WM_COMMAND : {
2004-09-27 22:35:53 +02:00
int id = ( int ) wparam ;
2004-10-07 06:25:29 +02:00
switch ( id ) {
case IDOK : {
2005-09-09 17:20:04 +02:00
LPTSTR dest = ( LPTSTR ) GetWindowLongPtr ( hwnd , GWLP_USERDATA ) ;
2004-09-27 22:35:53 +02:00
GetWindowText ( GetDlgItem ( hwnd , 201 ) , dest , MAX_PATH ) ;
2004-10-07 06:25:29 +02:00
EndDialog ( hwnd , id ) ;
break ; }
case IDCANCEL :
EndDialog ( hwnd , id ) ;
break ;
case 254 :
2004-10-22 21:52:50 +02:00
MessageBox ( hwnd , RS ( b1 , IDS_NO_IMPL ) , RS ( b2 , IDS_WINEFILE ) , MB_OK ) ;
2004-10-07 06:25:29 +02:00
break ;
2004-09-27 22:35:53 +02:00
}
2004-10-07 06:25:29 +02:00
2004-09-27 22:35:53 +02:00
return 1 ;
2004-10-07 06:25:29 +02:00
}
2004-09-27 22:35:53 +02:00
}
return 0 ;
}
2002-06-04 23:29:40 +02:00
2005-05-29 22:05:29 +02:00
struct FilterDialog {
TCHAR pattern [ MAX_PATH ] ;
int flags ;
} ;
static INT_PTR CALLBACK FilterDialogDlgProc ( HWND hwnd , UINT nmsg , WPARAM wparam , LPARAM lparam )
{
static struct FilterDialog * dlg ;
switch ( nmsg ) {
case WM_INITDIALOG :
dlg = ( struct FilterDialog * ) lparam ;
SetWindowText ( GetDlgItem ( hwnd , IDC_VIEW_PATTERN ) , dlg - > pattern ) ;
2006-03-17 16:57:16 +01:00
set_check ( hwnd , IDC_VIEW_TYPE_DIRECTORIES , dlg - > flags & TF_DIRECTORIES ) ;
set_check ( hwnd , IDC_VIEW_TYPE_PROGRAMS , dlg - > flags & TF_PROGRAMS ) ;
set_check ( hwnd , IDC_VIEW_TYPE_DOCUMENTS , dlg - > flags & TF_DOCUMENTS ) ;
set_check ( hwnd , IDC_VIEW_TYPE_OTHERS , dlg - > flags & TF_OTHERS ) ;
set_check ( hwnd , IDC_VIEW_TYPE_HIDDEN , dlg - > flags & TF_HIDDEN ) ;
2005-05-29 22:05:29 +02:00
return 1 ;
case WM_COMMAND : {
int id = ( int ) wparam ;
if ( id = = IDOK ) {
int flags = 0 ;
GetWindowText ( GetDlgItem ( hwnd , IDC_VIEW_PATTERN ) , dlg - > pattern , MAX_PATH ) ;
2006-03-17 16:57:16 +01:00
flags | = get_check ( hwnd , IDC_VIEW_TYPE_DIRECTORIES ) ? TF_DIRECTORIES : 0 ;
flags | = get_check ( hwnd , IDC_VIEW_TYPE_PROGRAMS ) ? TF_PROGRAMS : 0 ;
flags | = get_check ( hwnd , IDC_VIEW_TYPE_DOCUMENTS ) ? TF_DOCUMENTS : 0 ;
flags | = get_check ( hwnd , IDC_VIEW_TYPE_OTHERS ) ? TF_OTHERS : 0 ;
flags | = get_check ( hwnd , IDC_VIEW_TYPE_HIDDEN ) ? TF_HIDDEN : 0 ;
2005-05-29 22:05:29 +02:00
dlg - > flags = flags ;
EndDialog ( hwnd , id ) ;
} else if ( id = = IDCANCEL )
EndDialog ( hwnd , id ) ;
return 1 ; }
}
return 0 ;
}
2005-06-06 12:02:43 +02:00
struct PropertiesDialog {
TCHAR path [ MAX_PATH ] ;
Entry entry ;
void * pVersionData ;
} ;
/* Structure used to store enumerated languages and code pages. */
struct LANGANDCODEPAGE {
WORD wLanguage ;
WORD wCodePage ;
} * lpTranslate ;
static LPCSTR InfoStrings [ ] = {
" Comments " ,
" CompanyName " ,
" FileDescription " ,
" FileVersion " ,
" InternalName " ,
" LegalCopyright " ,
" LegalTrademarks " ,
" OriginalFilename " ,
" PrivateBuild " ,
" ProductName " ,
" ProductVersion " ,
" SpecialBuild " ,
NULL
} ;
static void PropDlg_DisplayValue ( HWND hlbox , HWND hedit )
{
2006-03-17 16:57:16 +01:00
int idx = SendMessage ( hlbox , LB_GETCURSEL , 0 , 0 ) ;
2005-06-06 12:02:43 +02:00
if ( idx ! = LB_ERR ) {
2006-03-17 16:57:16 +01:00
LPCTSTR pValue = ( LPCTSTR ) SendMessage ( hlbox , LB_GETITEMDATA , idx , 0 ) ;
2005-06-06 12:02:43 +02:00
if ( pValue )
SetWindowText ( hedit , pValue ) ;
}
}
static void CheckForFileInfo ( struct PropertiesDialog * dlg , HWND hwnd , LPCTSTR strFilename )
{
static TCHAR sBackSlash [ ] = { ' \\ ' , ' \0 ' } ;
static TCHAR sTranslation [ ] = { ' \\ ' , ' V ' , ' a ' , ' r ' , ' F ' , ' i ' , ' l ' , ' e ' , ' I ' , ' n ' , ' f ' , ' o ' , ' \\ ' , ' T ' , ' r ' , ' a ' , ' n ' , ' s ' , ' l ' , ' a ' , ' t ' , ' i ' , ' o ' , ' n ' , ' \0 ' } ;
static TCHAR sStringFileInfo [ ] = { ' \\ ' , ' S ' , ' t ' , ' r ' , ' i ' , ' n ' , ' g ' , ' F ' , ' i ' , ' l ' , ' e ' , ' I ' , ' n ' , ' f ' , ' o ' , ' \\ ' ,
' % ' , ' 0 ' , ' 4 ' , ' x ' , ' % ' , ' 0 ' , ' 4 ' , ' x ' , ' \\ ' , ' % ' , ' s ' , ' \0 ' } ;
DWORD dwVersionDataLen = GetFileVersionInfoSize ( strFilename , NULL ) ;
if ( dwVersionDataLen ) {
2007-07-23 22:25:20 +02:00
dlg - > pVersionData = HeapAlloc ( GetProcessHeap ( ) , 0 , dwVersionDataLen ) ;
2005-06-06 12:02:43 +02:00
if ( GetFileVersionInfo ( strFilename , 0 , dwVersionDataLen , dlg - > pVersionData ) ) {
LPVOID pVal ;
UINT nValLen ;
if ( VerQueryValue ( dlg - > pVersionData , sBackSlash , & pVal , & nValLen ) ) {
if ( nValLen = = sizeof ( VS_FIXEDFILEINFO ) ) {
VS_FIXEDFILEINFO * pFixedFileInfo = ( VS_FIXEDFILEINFO * ) pVal ;
char buffer [ BUFFER_LEN ] ;
sprintf ( buffer , " %d.%d.%d.%d " ,
HIWORD ( pFixedFileInfo - > dwFileVersionMS ) , LOWORD ( pFixedFileInfo - > dwFileVersionMS ) ,
HIWORD ( pFixedFileInfo - > dwFileVersionLS ) , LOWORD ( pFixedFileInfo - > dwFileVersionLS ) ) ;
SetDlgItemTextA ( hwnd , IDC_STATIC_PROP_VERSION , buffer ) ;
}
}
/* Read the list of languages and code pages. */
if ( VerQueryValue ( dlg - > pVersionData , sTranslation , & pVal , & nValLen ) ) {
struct LANGANDCODEPAGE * pTranslate = ( struct LANGANDCODEPAGE * ) pVal ;
struct LANGANDCODEPAGE * pEnd = ( struct LANGANDCODEPAGE * ) ( ( LPBYTE ) pVal + nValLen ) ;
HWND hlbox = GetDlgItem ( hwnd , IDC_LIST_PROP_VERSION_TYPES ) ;
/* Read the file description for each language and code page. */
for ( ; pTranslate < pEnd ; + + pTranslate ) {
LPCSTR * p ;
for ( p = InfoStrings ; * p ; + + p ) {
TCHAR subblock [ 200 ] ;
# ifdef UNICODE
TCHAR infoStr [ 100 ] ;
# endif
LPCTSTR pTxt ;
UINT nValLen ;
LPCSTR pInfoString = * p ;
# ifdef UNICODE
MultiByteToWideChar ( CP_ACP , 0 , pInfoString , - 1 , infoStr , 100 ) ;
# else
# define infoStr pInfoString
# endif
wsprintf ( subblock , sStringFileInfo , pTranslate - > wLanguage , pTranslate - > wCodePage , infoStr ) ;
/* Retrieve file description for language and code page */
if ( VerQueryValue ( dlg - > pVersionData , subblock , ( PVOID ) & pTxt , & nValLen ) ) {
2006-03-17 16:57:16 +01:00
int idx = SendMessage ( hlbox , LB_ADDSTRING , 0L , ( LPARAM ) infoStr ) ;
SendMessage ( hlbox , LB_SETITEMDATA , idx , ( LPARAM ) pTxt ) ;
2005-06-06 12:02:43 +02:00
}
}
}
2006-03-17 16:57:16 +01:00
SendMessage ( hlbox , LB_SETCURSEL , 0 , 0 ) ;
2005-06-06 12:02:43 +02:00
PropDlg_DisplayValue ( hlbox , GetDlgItem ( hwnd , IDC_LIST_PROP_VERSION_VALUES ) ) ;
}
}
}
}
static INT_PTR CALLBACK PropertiesDialogDlgProc ( HWND hwnd , UINT nmsg , WPARAM wparam , LPARAM lparam )
{
static struct PropertiesDialog * dlg ;
switch ( nmsg ) {
case WM_INITDIALOG : {
2005-10-06 13:38:45 +02:00
static const TCHAR sByteFmt [ ] = { ' % ' , ' s ' , ' ' , ' B ' , ' y ' , ' t ' , ' e ' , ' s ' , ' \0 ' } ;
2005-06-06 12:02:43 +02:00
TCHAR b1 [ BUFFER_LEN ] , b2 [ BUFFER_LEN ] ;
LPWIN32_FIND_DATA pWFD ;
ULONGLONG size ;
dlg = ( struct PropertiesDialog * ) lparam ;
pWFD = ( LPWIN32_FIND_DATA ) & dlg - > entry . data ;
GetWindowText ( hwnd , b1 , MAX_PATH ) ;
wsprintf ( b2 , b1 , pWFD - > cFileName ) ;
SetWindowText ( hwnd , b2 ) ;
format_date ( & pWFD - > ftLastWriteTime , b1 , COL_DATE | COL_TIME ) ;
SetWindowText ( GetDlgItem ( hwnd , IDC_STATIC_PROP_LASTCHANGE ) , b1 ) ;
size = ( ( ULONGLONG ) pWFD - > nFileSizeHigh < < 32 ) | pWFD - > nFileSizeLow ;
2005-06-12 12:43:40 +02:00
_stprintf ( b1 , sLongNumFmt , size ) ;
2005-07-07 14:00:17 +02:00
wsprintf ( b2 , sByteFmt , b1 ) ;
2005-06-06 12:02:43 +02:00
SetWindowText ( GetDlgItem ( hwnd , IDC_STATIC_PROP_SIZE ) , b2 ) ;
SetWindowText ( GetDlgItem ( hwnd , IDC_STATIC_PROP_FILENAME ) , pWFD - > cFileName ) ;
SetWindowText ( GetDlgItem ( hwnd , IDC_STATIC_PROP_PATH ) , dlg - > path ) ;
2006-03-17 16:57:16 +01:00
set_check ( hwnd , IDC_CHECK_READONLY , pWFD - > dwFileAttributes & FILE_ATTRIBUTE_READONLY ) ;
set_check ( hwnd , IDC_CHECK_ARCHIVE , pWFD - > dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE ) ;
set_check ( hwnd , IDC_CHECK_COMPRESSED , pWFD - > dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED ) ;
set_check ( hwnd , IDC_CHECK_HIDDEN , pWFD - > dwFileAttributes & FILE_ATTRIBUTE_HIDDEN ) ;
set_check ( hwnd , IDC_CHECK_SYSTEM , pWFD - > dwFileAttributes & FILE_ATTRIBUTE_SYSTEM ) ;
2005-06-06 12:02:43 +02:00
CheckForFileInfo ( dlg , hwnd , dlg - > path ) ;
return 1 ; }
case WM_COMMAND : {
int id = ( int ) wparam ;
switch ( HIWORD ( wparam ) ) {
case LBN_SELCHANGE : {
HWND hlbox = GetDlgItem ( hwnd , IDC_LIST_PROP_VERSION_TYPES ) ;
PropDlg_DisplayValue ( hlbox , GetDlgItem ( hwnd , IDC_LIST_PROP_VERSION_VALUES ) ) ;
break ;
}
case BN_CLICKED :
if ( id = = IDOK | | id = = IDCANCEL )
EndDialog ( hwnd , id ) ;
}
return 1 ; }
case WM_NCDESTROY :
2007-07-23 22:25:20 +02:00
HeapFree ( GetProcessHeap ( ) , 0 , dlg - > pVersionData ) ;
2005-06-06 12:02:43 +02:00
dlg - > pVersionData = NULL ;
break ;
}
return 0 ;
}
static void show_properties_dlg ( Entry * entry , HWND hwnd )
{
struct PropertiesDialog dlg ;
memset ( & dlg , 0 , sizeof ( struct PropertiesDialog ) ) ;
get_path ( entry , dlg . path ) ;
memcpy ( & dlg . entry , entry , sizeof ( Entry ) ) ;
DialogBoxParam ( Globals . hInstance , MAKEINTRESOURCE ( IDD_DIALOG_PROPERTIES ) , hwnd , PropertiesDialogDlgProc , ( LPARAM ) & dlg ) ;
}
2002-06-04 23:29:40 +02:00
# ifndef _NO_EXTENSIONS
static struct FullScreenParameters {
BOOL mode ;
RECT orgPos ;
BOOL wasZoomed ;
} g_fullscreen = {
2003-08-13 03:18:37 +02:00
FALSE , /* mode */
{ 0 , 0 , 0 , 0 } ,
FALSE
2002-06-04 23:29:40 +02:00
} ;
2005-06-10 21:32:24 +02:00
static void frame_get_clientspace ( HWND hwnd , PRECT prect )
2002-06-04 23:29:40 +02:00
{
RECT rt ;
if ( ! IsIconic ( hwnd ) )
GetClientRect ( hwnd , prect ) ;
else {
WINDOWPLACEMENT wp ;
GetWindowPlacement ( hwnd , & wp ) ;
prect - > left = prect - > top = 0 ;
prect - > right = wp . rcNormalPosition . right - wp . rcNormalPosition . left -
2 * ( GetSystemMetrics ( SM_CXSIZEFRAME ) + GetSystemMetrics ( SM_CXEDGE ) ) ;
prect - > bottom = wp . rcNormalPosition . bottom - wp . rcNormalPosition . top -
2 * ( GetSystemMetrics ( SM_CYSIZEFRAME ) + GetSystemMetrics ( SM_CYEDGE ) ) -
GetSystemMetrics ( SM_CYCAPTION ) - GetSystemMetrics ( SM_CYMENUSIZE ) ;
}
if ( IsWindowVisible ( Globals . htoolbar ) ) {
GetClientRect ( Globals . htoolbar , & rt ) ;
prect - > top + = rt . bottom + 2 ;
}
if ( IsWindowVisible ( Globals . hdrivebar ) ) {
GetClientRect ( Globals . hdrivebar , & rt ) ;
prect - > top + = rt . bottom + 2 ;
}
if ( IsWindowVisible ( Globals . hstatusbar ) ) {
GetClientRect ( Globals . hstatusbar , & rt ) ;
prect - > bottom - = rt . bottom ;
}
}
static BOOL toggle_fullscreen ( HWND hwnd )
{
RECT rt ;
if ( ( g_fullscreen . mode = ! g_fullscreen . mode ) ) {
GetWindowRect ( hwnd , & g_fullscreen . orgPos ) ;
g_fullscreen . wasZoomed = IsZoomed ( hwnd ) ;
Frame_CalcFrameClient ( hwnd , & rt ) ;
ClientToScreen ( hwnd , ( LPPOINT ) & rt . left ) ;
ClientToScreen ( hwnd , ( LPPOINT ) & rt . right ) ;
rt . left = g_fullscreen . orgPos . left - rt . left ;
rt . top = g_fullscreen . orgPos . top - rt . top ;
rt . right = GetSystemMetrics ( SM_CXSCREEN ) + g_fullscreen . orgPos . right - rt . right ;
rt . bottom = GetSystemMetrics ( SM_CYSCREEN ) + g_fullscreen . orgPos . bottom - rt . bottom ;
MoveWindow ( hwnd , rt . left , rt . top , rt . right - rt . left , rt . bottom - rt . top , TRUE ) ;
} else {
MoveWindow ( hwnd , g_fullscreen . orgPos . left , g_fullscreen . orgPos . top ,
g_fullscreen . orgPos . right - g_fullscreen . orgPos . left ,
g_fullscreen . orgPos . bottom - g_fullscreen . orgPos . top , TRUE ) ;
if ( g_fullscreen . wasZoomed )
ShowWindow ( hwnd , WS_MAXIMIZE ) ;
}
return g_fullscreen . mode ;
}
static void fullscreen_move ( HWND hwnd )
{
RECT rt , pos ;
GetWindowRect ( hwnd , & pos ) ;
Frame_CalcFrameClient ( hwnd , & rt ) ;
ClientToScreen ( hwnd , ( LPPOINT ) & rt . left ) ;
ClientToScreen ( hwnd , ( LPPOINT ) & rt . right ) ;
rt . left = pos . left - rt . left ;
rt . top = pos . top - rt . top ;
rt . right = GetSystemMetrics ( SM_CXSCREEN ) + pos . right - rt . right ;
rt . bottom = GetSystemMetrics ( SM_CYSCREEN ) + pos . bottom - rt . bottom ;
MoveWindow ( hwnd , rt . left , rt . top , rt . right - rt . left , rt . bottom - rt . top , TRUE ) ;
}
# endif
static void toggle_child ( HWND hwnd , UINT cmd , HWND hchild )
{
BOOL vis = IsWindowVisible ( hchild ) ;
CheckMenuItem ( Globals . hMenuOptions , cmd , vis ? MF_BYCOMMAND : MF_BYCOMMAND | MF_CHECKED ) ;
ShowWindow ( hchild , vis ? SW_HIDE : SW_SHOW ) ;
# ifndef _NO_EXTENSIONS
if ( g_fullscreen . mode )
fullscreen_move ( hwnd ) ;
# endif
resize_frame_client ( hwnd ) ;
}
2005-06-10 21:32:24 +02:00
static BOOL activate_drive_window ( LPCTSTR path )
2002-06-04 23:29:40 +02:00
{
TCHAR drv1 [ _MAX_DRIVE ] , drv2 [ _MAX_DRIVE ] ;
HWND child_wnd ;
_tsplitpath ( path , drv1 , 0 , 0 , 0 ) ;
2002-06-28 19:37:34 +02:00
/* search for a already open window for the same drive */
2002-06-04 23:29:40 +02:00
for ( child_wnd = GetNextWindow ( Globals . hmdiclient , GW_CHILD ) ; child_wnd ; child_wnd = GetNextWindow ( child_wnd , GW_HWNDNEXT ) ) {
2005-09-09 17:20:04 +02:00
ChildWnd * child = ( ChildWnd * ) GetWindowLongPtr ( child_wnd , GWLP_USERDATA ) ;
2002-06-04 23:29:40 +02:00
if ( child ) {
_tsplitpath ( child - > root . path , drv2 , 0 , 0 , 0 ) ;
if ( ! lstrcmpi ( drv2 , drv1 ) ) {
SendMessage ( Globals . hmdiclient , WM_MDIACTIVATE , ( WPARAM ) child_wnd , 0 ) ;
2006-03-17 16:57:16 +01:00
if ( IsIconic ( child_wnd ) )
2002-06-04 23:29:40 +02:00
ShowWindow ( child_wnd , SW_SHOWNORMAL ) ;
return TRUE ;
}
}
}
return FALSE ;
}
2005-06-10 21:32:24 +02:00
static BOOL activate_fs_window ( LPCTSTR filesys )
2003-08-13 03:18:37 +02:00
{
HWND child_wnd ;
/* search for a already open window of the given file system name */
for ( child_wnd = GetNextWindow ( Globals . hmdiclient , GW_CHILD ) ; child_wnd ; child_wnd = GetNextWindow ( child_wnd , GW_HWNDNEXT ) ) {
2005-09-09 17:20:04 +02:00
ChildWnd * child = ( ChildWnd * ) GetWindowLongPtr ( child_wnd , GWLP_USERDATA ) ;
2003-08-13 03:18:37 +02:00
if ( child ) {
if ( ! lstrcmpi ( child - > root . fs , filesys ) ) {
SendMessage ( Globals . hmdiclient , WM_MDIACTIVATE , ( WPARAM ) child_wnd , 0 ) ;
2006-03-17 16:57:16 +01:00
if ( IsIconic ( child_wnd ) )
2003-08-13 03:18:37 +02:00
ShowWindow ( child_wnd , SW_SHOWNORMAL ) ;
return TRUE ;
}
}
}
return FALSE ;
}
2005-06-10 21:32:24 +02:00
static LRESULT CALLBACK FrameWndProc ( HWND hwnd , UINT nmsg , WPARAM wparam , LPARAM lparam )
2002-06-04 23:29:40 +02:00
{
2004-10-22 21:52:50 +02:00
TCHAR b1 [ BUFFER_LEN ] , b2 [ BUFFER_LEN ] ;
2004-10-21 21:51:31 +02:00
2002-06-04 23:29:40 +02:00
switch ( nmsg ) {
case WM_CLOSE :
2006-05-24 12:29:06 +02:00
if ( Globals . saveSettings )
2006-02-20 18:57:01 +01:00
save_registry_settings ( ) ;
2002-06-04 23:29:40 +02:00
DestroyWindow ( hwnd ) ;
2003-08-13 03:18:37 +02:00
/* clear handle variables */
Globals . hMenuFrame = 0 ;
Globals . hMenuView = 0 ;
Globals . hMenuOptions = 0 ;
Globals . hMainWnd = 0 ;
Globals . hmdiclient = 0 ;
Globals . hdrivebar = 0 ;
2002-06-04 23:29:40 +02:00
break ;
case WM_DESTROY :
2005-11-17 12:05:35 +01:00
PostQuitMessage ( 0 ) ;
2002-06-04 23:29:40 +02:00
break ;
2005-05-16 10:48:54 +02:00
case WM_INITMENUPOPUP : {
HWND hwndClient = ( HWND ) SendMessage ( Globals . hmdiclient , WM_MDIGETACTIVE , 0 , 0 ) ;
if ( ! SendMessage ( hwndClient , WM_INITMENUPOPUP , wparam , lparam ) )
return 0 ;
break ; }
2002-06-04 23:29:40 +02:00
case WM_COMMAND : {
UINT cmd = LOWORD ( wparam ) ;
HWND hwndClient = ( HWND ) SendMessage ( Globals . hmdiclient , WM_MDIGETACTIVE , 0 , 0 ) ;
if ( SendMessage ( hwndClient , WM_DISPATCH_COMMAND , wparam , lparam ) )
break ;
if ( cmd > = ID_DRIVE_FIRST & & cmd < = ID_DRIVE_FIRST + 0xFF ) {
TCHAR drv [ _MAX_DRIVE ] , path [ MAX_PATH ] ;
ChildWnd * child ;
LPCTSTR root = Globals . drives ;
int i ;
for ( i = cmd - ID_DRIVE_FIRST ; i - - ; root + + )
while ( * root )
root + + ;
if ( activate_drive_window ( root ) )
return 0 ;
_tsplitpath ( root , drv , 0 , 0 , 0 ) ;
if ( ! SetCurrentDirectory ( drv ) ) {
display_error ( hwnd , GetLastError ( ) ) ;
return 0 ;
}
2003-08-13 03:18:37 +02:00
GetCurrentDirectory ( MAX_PATH , path ) ; /*TODO: store last directory per drive */
child = alloc_child_window ( path , NULL , hwnd ) ;
2002-06-04 23:29:40 +02:00
if ( ! create_child_window ( child ) )
2007-07-23 22:25:20 +02:00
HeapFree ( GetProcessHeap ( ) , 0 , child ) ;
2002-06-04 23:29:40 +02:00
} else switch ( cmd ) {
case ID_FILE_EXIT :
2003-08-13 03:18:37 +02:00
SendMessage ( hwnd , WM_CLOSE , 0 , 0 ) ;
2002-06-04 23:29:40 +02:00
break ;
case ID_WINDOW_NEW : {
TCHAR path [ MAX_PATH ] ;
ChildWnd * child ;
GetCurrentDirectory ( MAX_PATH , path ) ;
2003-08-13 03:18:37 +02:00
child = alloc_child_window ( path , NULL , hwnd ) ;
2002-06-04 23:29:40 +02:00
if ( ! create_child_window ( child ) )
2007-07-23 22:25:20 +02:00
HeapFree ( GetProcessHeap ( ) , 0 , child ) ;
2002-06-04 23:29:40 +02:00
break ; }
2005-05-16 23:36:41 +02:00
case ID_REFRESH :
refresh_drives ( ) ;
break ;
2002-06-04 23:29:40 +02:00
case ID_WINDOW_CASCADE :
SendMessage ( Globals . hmdiclient , WM_MDICASCADE , 0 , 0 ) ;
break ;
case ID_WINDOW_TILE_HORZ :
SendMessage ( Globals . hmdiclient , WM_MDITILE , MDITILE_HORIZONTAL , 0 ) ;
break ;
case ID_WINDOW_TILE_VERT :
SendMessage ( Globals . hmdiclient , WM_MDITILE , MDITILE_VERTICAL , 0 ) ;
break ;
case ID_WINDOW_ARRANGE :
SendMessage ( Globals . hmdiclient , WM_MDIICONARRANGE , 0 , 0 ) ;
break ;
2004-10-07 06:20:04 +02:00
2007-07-25 23:21:43 +02:00
case ID_SELECT_FONT :
choose_font ( hwnd ) ;
break ;
2002-06-04 23:29:40 +02:00
case ID_VIEW_TOOL_BAR :
toggle_child ( hwnd , cmd , Globals . htoolbar ) ;
break ;
case ID_VIEW_DRIVE_BAR :
toggle_child ( hwnd , cmd , Globals . hdrivebar ) ;
break ;
case ID_VIEW_STATUSBAR :
toggle_child ( hwnd , cmd , Globals . hstatusbar ) ;
break ;
2006-02-20 18:57:01 +01:00
case ID_VIEW_SAVESETTINGS :
Globals . saveSettings = ! Globals . saveSettings ;
CheckMenuItem ( Globals . hMenuOptions , ID_VIEW_SAVESETTINGS ,
2006-05-24 12:29:06 +02:00
Globals . saveSettings ? MF_CHECKED : MF_UNCHECKED ) ;
2006-02-20 18:57:01 +01:00
break ;
2002-06-04 23:29:40 +02:00
case ID_EXECUTE : {
2003-08-13 03:18:37 +02:00
struct ExecuteDialog dlg ;
memset ( & dlg , 0 , sizeof ( struct ExecuteDialog ) ) ;
2005-06-13 12:04:55 +02:00
if ( DialogBoxParam ( Globals . hInstance , MAKEINTRESOURCE ( IDD_EXECUTE ) , hwnd , ExecuteDialogDlgProc , ( LPARAM ) & dlg ) = = IDOK ) {
2002-10-16 20:50:38 +02:00
HINSTANCE hinst = ShellExecute ( hwnd , NULL /*operation*/ , dlg . cmd /*file*/ , NULL /*parameters*/ , NULL /*dir*/ , dlg . cmdshow ) ;
if ( ( int ) hinst < = 32 )
display_error ( hwnd , GetLastError ( ) ) ;
}
2002-06-04 23:29:40 +02:00
break ; }
2005-05-16 23:36:41 +02:00
case ID_CONNECT_NETWORK_DRIVE : {
DWORD ret = WNetConnectionDialog ( hwnd , RESOURCETYPE_DISK ) ;
if ( ret = = NO_ERROR )
refresh_drives ( ) ;
else if ( ret ! = ( DWORD ) - 1 ) {
if ( ret = = ERROR_EXTENDED_ERROR )
display_network_error ( hwnd ) ;
else
display_error ( hwnd , ret ) ;
}
break ; }
case ID_DISCONNECT_NETWORK_DRIVE : {
DWORD ret = WNetDisconnectDialog ( hwnd , RESOURCETYPE_DISK ) ;
if ( ret = = NO_ERROR )
refresh_drives ( ) ;
else if ( ret ! = ( DWORD ) - 1 ) {
if ( ret = = ERROR_EXTENDED_ERROR )
display_network_error ( hwnd ) ;
else
display_error ( hwnd , ret ) ;
}
break ; }
2005-05-16 16:08:41 +02:00
case ID_FORMAT_DISK : {
UINT sem_org = SetErrorMode ( 0 ) ; /* Get the current Error Mode settings. */
SetErrorMode ( sem_org & ~ SEM_FAILCRITICALERRORS ) ; /* Force O/S to handle */
SHFormatDrive ( hwnd , 0 /* A: */ , SHFMT_ID_DEFAULT , 0 ) ;
SetErrorMode ( sem_org ) ; /* Put it back the way it was. */
break ; }
2002-06-04 23:29:40 +02:00
case ID_HELP :
2004-10-22 21:52:50 +02:00
WinHelp ( hwnd , RS ( b1 , IDS_WINEFILE ) , HELP_INDEX , 0 ) ;
2002-06-04 23:29:40 +02:00
break ;
# ifndef _NO_EXTENSIONS
case ID_VIEW_FULLSCREEN :
CheckMenuItem ( Globals . hMenuOptions , cmd , toggle_fullscreen ( hwnd ) ? MF_CHECKED : 0 ) ;
break ;
2003-08-13 03:18:37 +02:00
# ifdef __WINE__
2002-06-04 23:29:40 +02:00
case ID_DRIVE_UNIX_FS : {
TCHAR path [ MAX_PATH ] ;
2005-07-07 14:00:17 +02:00
# ifdef UNICODE
char cpath [ MAX_PATH ] ;
# endif
2002-06-04 23:29:40 +02:00
ChildWnd * child ;
2004-10-22 21:52:50 +02:00
if ( activate_fs_window ( RS ( b1 , IDS_UNIXFS ) ) )
2002-06-04 23:29:40 +02:00
break ;
2005-07-07 14:00:17 +02:00
# ifdef UNICODE
getcwd ( cpath , MAX_PATH ) ;
MultiByteToWideChar ( CP_UNIXCP , 0 , cpath , - 1 , path , MAX_PATH ) ;
# else
2002-06-04 23:29:40 +02:00
getcwd ( path , MAX_PATH ) ;
2005-07-07 14:00:17 +02:00
# endif
2003-08-13 03:18:37 +02:00
child = alloc_child_window ( path , NULL , hwnd ) ;
if ( ! create_child_window ( child ) )
2007-07-23 22:25:20 +02:00
HeapFree ( GetProcessHeap ( ) , 0 , child ) ;
2003-08-13 03:18:37 +02:00
break ; }
# endif
# ifdef _SHELL_FOLDERS
case ID_DRIVE_SHELL_NS : {
TCHAR path [ MAX_PATH ] ;
ChildWnd * child ;
2004-10-22 21:52:50 +02:00
if ( activate_fs_window ( RS ( b1 , IDS_SHELL ) ) )
2003-08-13 03:18:37 +02:00
break ;
GetCurrentDirectory ( MAX_PATH , path ) ;
child = alloc_child_window ( path , get_path_pidl ( path , hwnd ) , hwnd ) ;
2002-06-04 23:29:40 +02:00
if ( ! create_child_window ( child ) )
2007-07-23 22:25:20 +02:00
HeapFree ( GetProcessHeap ( ) , 0 , child ) ;
2002-06-04 23:29:40 +02:00
break ; }
# endif
# endif
2002-06-28 19:37:34 +02:00
/*TODO: There are even more menu items! */
2002-06-04 23:29:40 +02:00
# ifndef _NO_EXTENSIONS
2003-08-13 21:38:22 +02:00
# ifdef __WINE__
2002-06-04 23:29:40 +02:00
case ID_LICENSE :
WineLicense ( Globals . hMainWnd ) ;
break ;
case ID_NO_WARRANTY :
WineWarranty ( Globals . hMainWnd ) ;
break ;
case ID_ABOUT_WINE :
2004-10-22 21:52:50 +02:00
ShellAbout ( hwnd , RS ( b2 , IDS_WINE ) , RS ( b1 , IDS_WINEFILE ) , 0 ) ;
2002-06-04 23:29:40 +02:00
break ;
2005-07-07 22:27:24 +02:00
# endif
2003-08-13 03:18:37 +02:00
2005-06-13 12:04:55 +02:00
case ID_ABOUT :
2004-10-22 21:52:50 +02:00
ShellAbout ( hwnd , RS ( b1 , IDS_WINEFILE ) , NULL , 0 ) ;
2003-08-13 03:18:37 +02:00
break ;
# endif /* _NO_EXTENSIONS */
2002-06-04 23:29:40 +02:00
default :
2003-08-13 03:18:37 +02:00
/*TODO: if (wParam >= PM_FIRST_LANGUAGE && wParam <= PM_LAST_LANGUAGE)
2002-06-04 23:29:40 +02:00
STRING_SelectLanguageByNumber ( wParam - PM_FIRST_LANGUAGE ) ;
else */ if ( ( cmd < IDW_FIRST_CHILD | | cmd > = IDW_FIRST_CHILD + 0x100 ) & &
( cmd < SC_SIZE | | cmd > SC_RESTORE ) )
2004-10-22 21:52:50 +02:00
MessageBox ( hwnd , RS ( b2 , IDS_NO_IMPL ) , RS ( b1 , IDS_WINEFILE ) , MB_OK ) ;
2002-06-04 23:29:40 +02:00
return DefFrameProc ( hwnd , Globals . hmdiclient , nmsg , wparam , lparam ) ;
}
break ; }
case WM_SIZE :
resize_frame ( hwnd , LOWORD ( lparam ) , HIWORD ( lparam ) ) ;
2002-06-28 19:37:34 +02:00
break ; /* do not pass message to DefFrameProc */
2002-06-04 23:29:40 +02:00
2006-03-10 21:43:25 +01:00
case WM_DEVICECHANGE :
SendMessage ( hwnd , WM_COMMAND , MAKELONG ( ID_REFRESH , 0 ) , 0 ) ;
break ;
2002-06-04 23:29:40 +02:00
# ifndef _NO_EXTENSIONS
case WM_GETMINMAXINFO : {
LPMINMAXINFO lpmmi = ( LPMINMAXINFO ) lparam ;
2002-06-28 19:37:34 +02:00
lpmmi - > ptMaxTrackSize . x < < = 1 ; /*2*GetSystemMetrics(SM_CXSCREEN) / SM_CXVIRTUALSCREEN */
lpmmi - > ptMaxTrackSize . y < < = 1 ; /*2*GetSystemMetrics(SM_CYSCREEN) / SM_CYVIRTUALSCREEN */
2002-06-04 23:29:40 +02:00
break ; }
case FRM_CALC_CLIENT :
frame_get_clientspace ( hwnd , ( PRECT ) lparam ) ;
return TRUE ;
2003-08-13 03:18:37 +02:00
# endif /* _NO_EXTENSIONS */
2002-06-04 23:29:40 +02:00
default :
return DefFrameProc ( hwnd , Globals . hmdiclient , nmsg , wparam , lparam ) ;
}
return 0 ;
}
2004-11-22 19:24:09 +01:00
static TCHAR g_pos_names [ COLUMNS ] [ 20 ] = {
{ ' \0 ' } /* symbol */
2002-06-04 23:29:40 +02:00
} ;
2003-08-13 03:18:37 +02:00
static const int g_pos_align [ ] = {
2002-06-04 23:29:40 +02:00
0 ,
2002-06-28 19:37:34 +02:00
HDF_LEFT , /* Name */
HDF_RIGHT , /* Size */
HDF_LEFT , /* CDate */
2002-06-04 23:29:40 +02:00
# ifndef _NO_EXTENSIONS
2002-06-28 19:37:34 +02:00
HDF_LEFT , /* ADate */
HDF_LEFT , /* MDate */
HDF_LEFT , /* Index */
HDF_CENTER , /* Links */
2002-06-04 23:29:40 +02:00
# endif
2002-06-28 19:37:34 +02:00
HDF_CENTER , /* Attributes */
2002-06-04 23:29:40 +02:00
# ifndef _NO_EXTENSIONS
2002-06-28 19:37:34 +02:00
HDF_LEFT /* Security */
2002-06-04 23:29:40 +02:00
# endif
} ;
static void resize_tree ( ChildWnd * child , int cx , int cy )
{
HDWP hdwp = BeginDeferWindowPos ( 4 ) ;
2002-07-03 23:06:58 +02:00
RECT rt ;
rt . left = 0 ;
rt . top = 0 ;
rt . right = cx ;
rt . bottom = cy ;
2002-06-04 23:29:40 +02:00
cx = child - > split_pos + SPLIT_WIDTH / 2 ;
# ifndef _NO_EXTENSIONS
{
WINDOWPOS wp ;
2002-07-03 23:06:58 +02:00
HD_LAYOUT hdl ;
hdl . prc = & rt ;
hdl . pwpos = & wp ;
2002-06-04 23:29:40 +02:00
2006-03-21 02:58:23 +01:00
SendMessage ( child - > left . hwndHeader , HDM_LAYOUT , 0 , ( LPARAM ) & hdl ) ;
2002-06-04 23:29:40 +02:00
DeferWindowPos ( hdwp , child - > left . hwndHeader , wp . hwndInsertAfter ,
wp . x - 1 , wp . y , child - > split_pos - SPLIT_WIDTH / 2 + 1 , wp . cy , wp . flags ) ;
DeferWindowPos ( hdwp , child - > right . hwndHeader , wp . hwndInsertAfter ,
rt . left + cx + 1 , wp . y , wp . cx - cx + 2 , wp . cy , wp . flags ) ;
}
2003-08-13 03:18:37 +02:00
# endif /* _NO_EXTENSIONS */
2002-06-04 23:29:40 +02:00
DeferWindowPos ( hdwp , child - > left . hwnd , 0 , rt . left , rt . top , child - > split_pos - SPLIT_WIDTH / 2 - rt . left , rt . bottom - rt . top , SWP_NOZORDER | SWP_NOACTIVATE ) ;
DeferWindowPos ( hdwp , child - > right . hwnd , 0 , rt . left + cx + 1 , rt . top , rt . right - cx , rt . bottom - rt . top , SWP_NOZORDER | SWP_NOACTIVATE ) ;
EndDeferWindowPos ( hdwp ) ;
}
# ifndef _NO_EXTENSIONS
static HWND create_header ( HWND parent , Pane * pane , int id )
{
2003-08-13 03:18:37 +02:00
HD_ITEM hdi ;
2002-06-04 23:29:40 +02:00
int idx ;
2006-04-13 10:38:00 +02:00
HWND hwnd = CreateWindow ( WC_HEADER , 0 , WS_CHILD | WS_VISIBLE | HDS_HORZ | HDS_FULLDRAG /*TODO: |HDS_BUTTONS + sort orders*/ ,
2002-06-04 23:29:40 +02:00
0 , 0 , 0 , 0 , parent , ( HMENU ) id , Globals . hInstance , 0 ) ;
if ( ! hwnd )
return 0 ;
2006-03-17 16:57:16 +01:00
SendMessage ( hwnd , WM_SETFONT , ( WPARAM ) GetStockObject ( DEFAULT_GUI_FONT ) , FALSE ) ;
2002-06-04 23:29:40 +02:00
2003-08-13 03:18:37 +02:00
hdi . mask = HDI_TEXT | HDI_WIDTH | HDI_FORMAT ;
2002-06-04 23:29:40 +02:00
for ( idx = 0 ; idx < COLUMNS ; idx + + ) {
hdi . pszText = g_pos_names [ idx ] ;
hdi . fmt = HDF_STRING | g_pos_align [ idx ] ;
hdi . cxy = pane - > widths [ idx ] ;
2006-03-21 02:58:23 +01:00
SendMessage ( hwnd , HDM_INSERTITEM , idx , ( LPARAM ) & hdi ) ;
2002-06-04 23:29:40 +02:00
}
return hwnd ;
}
2003-08-13 03:18:37 +02:00
# endif /* _NO_EXTENSIONS */
2002-06-04 23:29:40 +02:00
static void init_output ( HWND hwnd )
{
2007-07-25 23:22:08 +02:00
static const WCHAR s1000 [ ] = { ' 1 ' , ' 0 ' , ' 0 ' , ' 0 ' , ' \0 ' } ;
WCHAR b [ 16 ] ;
2002-06-04 23:29:40 +02:00
HFONT old_font ;
HDC hdc = GetDC ( hwnd ) ;
2007-07-25 23:22:08 +02:00
if ( GetNumberFormatW ( LOCALE_USER_DEFAULT , 0 , s1000 , 0 , b , 16 ) > 4 )
2002-06-04 23:29:40 +02:00
Globals . num_sep = b [ 1 ] ;
else
2007-06-27 22:54:56 +02:00
Globals . num_sep = ' . ' ;
2002-06-04 23:29:40 +02:00
2006-03-17 16:57:16 +01:00
old_font = SelectObject ( hdc , Globals . hfont ) ;
2007-07-25 23:22:08 +02:00
GetTextExtentPoint32W ( hdc , sSpace , 1 , & Globals . spaceSize ) ;
2006-03-17 16:57:16 +01:00
SelectObject ( hdc , old_font ) ;
2002-06-04 23:29:40 +02:00
ReleaseDC ( hwnd , hdc ) ;
}
static void draw_item ( Pane * pane , LPDRAWITEMSTRUCT dis , Entry * entry , int calcWidthCol ) ;
2005-02-25 15:07:56 +01:00
/* calculate preferred width for all visible columns */
2002-06-04 23:29:40 +02:00
static BOOL calc_widths ( Pane * pane , BOOL anyway )
{
int col , x , cx , spc = 3 * Globals . spaceSize . cx ;
2006-03-17 16:57:16 +01:00
int entries = SendMessage ( pane - > hwnd , LB_GETCOUNT , 0 , 0 ) ;
2002-06-04 23:29:40 +02:00
int orgWidths [ COLUMNS ] ;
int orgPositions [ COLUMNS + 1 ] ;
HFONT hfontOld ;
HDC hdc ;
int cnt ;
if ( ! anyway ) {
memcpy ( orgWidths , pane - > widths , sizeof ( orgWidths ) ) ;
memcpy ( orgPositions , pane - > positions , sizeof ( orgPositions ) ) ;
}
for ( col = 0 ; col < COLUMNS ; col + + )
pane - > widths [ col ] = 0 ;
hdc = GetDC ( pane - > hwnd ) ;
2006-03-17 16:57:16 +01:00
hfontOld = SelectObject ( hdc , Globals . hfont ) ;
2002-06-04 23:29:40 +02:00
for ( cnt = 0 ; cnt < entries ; cnt + + ) {
2006-03-17 16:57:16 +01:00
Entry * entry = ( Entry * ) SendMessage ( pane - > hwnd , LB_GETITEMDATA , cnt , 0 ) ;
2002-06-04 23:29:40 +02:00
2002-07-03 23:06:58 +02:00
DRAWITEMSTRUCT dis ;
2002-10-15 04:21:08 +02:00
dis . CtlType = 0 ;
dis . CtlID = 0 ;
dis . itemID = 0 ;
dis . itemAction = 0 ;
dis . itemState = 0 ;
dis . hwndItem = pane - > hwnd ;
dis . hDC = hdc ;
dis . rcItem . left = 0 ;
dis . rcItem . top = 0 ;
dis . rcItem . right = 0 ;
dis . rcItem . bottom = 0 ;
/*dis.itemData = 0; */
2002-06-04 23:29:40 +02:00
draw_item ( pane , & dis , entry , COLUMNS ) ;
}
SelectObject ( hdc , hfontOld ) ;
ReleaseDC ( pane - > hwnd , hdc ) ;
x = 0 ;
for ( col = 0 ; col < COLUMNS ; col + + ) {
pane - > positions [ col ] = x ;
cx = pane - > widths [ col ] ;
if ( cx ) {
cx + = spc ;
if ( cx < IMAGE_WIDTH )
cx = IMAGE_WIDTH ;
pane - > widths [ col ] = cx ;
}
x + = cx ;
}
pane - > positions [ COLUMNS ] = x ;
2006-03-17 16:57:16 +01:00
SendMessage ( pane - > hwnd , LB_SETHORIZONTALEXTENT , x , 0 ) ;
2002-06-04 23:29:40 +02:00
2002-06-28 19:37:34 +02:00
/* no change? */
2002-06-04 23:29:40 +02:00
if ( ! memcmp ( orgWidths , pane - > widths , sizeof ( orgWidths ) ) )
return FALSE ;
2002-06-28 19:37:34 +02:00
/* don't move, if only collapsing an entry */
2002-06-04 23:29:40 +02:00
if ( ! anyway & & pane - > widths [ 0 ] < orgWidths [ 0 ] & &
! memcmp ( orgWidths + 1 , pane - > widths + 1 , sizeof ( orgWidths ) - sizeof ( int ) ) ) {
pane - > widths [ 0 ] = orgWidths [ 0 ] ;
memcpy ( pane - > positions , orgPositions , sizeof ( orgPositions ) ) ;
return FALSE ;
}
InvalidateRect ( pane - > hwnd , 0 , TRUE ) ;
return TRUE ;
}
2005-02-25 15:07:56 +01:00
/* calculate one preferred column width */
2002-06-04 23:29:40 +02:00
static void calc_single_width ( Pane * pane , int col )
{
HFONT hfontOld ;
int x , cx ;
2006-03-17 16:57:16 +01:00
int entries = SendMessage ( pane - > hwnd , LB_GETCOUNT , 0 , 0 ) ;
2002-06-04 23:29:40 +02:00
int cnt ;
HDC hdc ;
pane - > widths [ col ] = 0 ;
hdc = GetDC ( pane - > hwnd ) ;
2006-03-17 16:57:16 +01:00
hfontOld = SelectObject ( hdc , Globals . hfont ) ;
2002-06-04 23:29:40 +02:00
for ( cnt = 0 ; cnt < entries ; cnt + + ) {
2006-03-17 16:57:16 +01:00
Entry * entry = ( Entry * ) SendMessage ( pane - > hwnd , LB_GETITEMDATA , cnt , 0 ) ;
2002-07-03 23:06:58 +02:00
DRAWITEMSTRUCT dis ;
2002-10-15 04:21:08 +02:00
dis . CtlType = 0 ;
dis . CtlID = 0 ;
dis . itemID = 0 ;
dis . itemAction = 0 ;
dis . itemState = 0 ;
dis . hwndItem = pane - > hwnd ;
dis . hDC = hdc ;
dis . rcItem . left = 0 ;
dis . rcItem . top = 0 ;
dis . rcItem . right = 0 ;
dis . rcItem . bottom = 0 ;
/*dis.itemData = 0; */
2002-06-04 23:29:40 +02:00
draw_item ( pane , & dis , entry , col ) ;
}
SelectObject ( hdc , hfontOld ) ;
ReleaseDC ( pane - > hwnd , hdc ) ;
cx = pane - > widths [ col ] ;
if ( cx ) {
cx + = 3 * Globals . spaceSize . cx ;
if ( cx < IMAGE_WIDTH )
cx = IMAGE_WIDTH ;
}
pane - > widths [ col ] = cx ;
x = pane - > positions [ col ] + cx ;
for ( ; col < COLUMNS ; ) {
pane - > positions [ + + col ] = x ;
x + = pane - > widths [ col ] ;
}
2006-03-17 16:57:16 +01:00
SendMessage ( pane - > hwnd , LB_SETHORIZONTALEXTENT , x , 0 ) ;
2002-06-04 23:29:40 +02:00
}
2005-05-29 22:05:29 +02:00
static BOOL pattern_match ( LPCTSTR str , LPCTSTR pattern )
{
for ( ; * str & & * pattern ; str + + , pattern + + ) {
if ( * pattern = = ' * ' ) {
do pattern + + ;
while ( * pattern = = ' * ' ) ;
if ( ! * pattern )
return TRUE ;
for ( ; * str ; str + + )
2005-07-07 14:00:17 +02:00
if ( * str = = * pattern & & pattern_match ( str , pattern ) )
2005-05-29 22:05:29 +02:00
return TRUE ;
return FALSE ;
}
2005-07-07 14:00:17 +02:00
else if ( * str ! = * pattern & & * pattern ! = ' ? ' )
2005-05-29 22:05:29 +02:00
return FALSE ;
}
if ( * str | | * pattern )
if ( * pattern ! = ' * ' | | pattern [ 1 ] ! = ' \0 ' )
return FALSE ;
return TRUE ;
}
2005-07-07 14:00:17 +02:00
static BOOL pattern_imatch ( LPCTSTR str , LPCTSTR pattern )
{
TCHAR b1 [ BUFFER_LEN ] , b2 [ BUFFER_LEN ] ;
lstrcpy ( b1 , str ) ;
lstrcpy ( b2 , pattern ) ;
CharUpper ( b1 ) ;
CharUpper ( b2 ) ;
return pattern_match ( b1 , b2 ) ;
}
2005-05-29 22:05:29 +02:00
enum FILE_TYPE {
FT_OTHER = 0 ,
FT_EXECUTABLE = 1 ,
FT_DOCUMENT = 2
} ;
static enum FILE_TYPE get_file_type ( LPCTSTR filename ) ;
2002-06-28 19:37:34 +02:00
/* insert listbox entries after index idx */
2002-06-04 23:29:40 +02:00
2005-05-29 22:05:29 +02:00
static int insert_entries ( Pane * pane , Entry * dir , LPCTSTR pattern , int filter_flags , int idx )
2002-06-04 23:29:40 +02:00
{
2003-08-13 03:18:37 +02:00
Entry * entry = dir ;
2002-06-04 23:29:40 +02:00
if ( ! entry )
2005-05-11 20:23:30 +02:00
return idx ;
2002-06-04 23:29:40 +02:00
ShowWindow ( pane - > hwnd , SW_HIDE ) ;
for ( ; entry ; entry = entry - > next ) {
# ifndef _LEFT_FILES
if ( pane - > treePane & & ! ( entry - > data . dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) )
continue ;
# endif
2005-05-29 22:05:29 +02:00
if ( entry - > data . dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
/* don't display entries "." and ".." in the left pane */
2007-06-27 22:54:56 +02:00
if ( pane - > treePane & & entry - > data . cFileName [ 0 ] = = ' . ' )
2005-05-29 22:05:29 +02:00
if (
2002-06-04 23:29:40 +02:00
# ifndef _NO_EXTENSIONS
2007-06-27 22:54:56 +02:00
entry - > data . cFileName [ 1 ] = = ' \0 ' | |
2002-06-04 23:29:40 +02:00
# endif
2007-06-27 22:54:56 +02:00
( entry - > data . cFileName [ 1 ] = = ' . ' & & entry - > data . cFileName [ 2 ] = = ' \0 ' ) )
2005-05-29 22:05:29 +02:00
continue ;
/* filter directories in right pane */
if ( ! pane - > treePane & & ! ( filter_flags & TF_DIRECTORIES ) )
2002-06-04 23:29:40 +02:00
continue ;
2005-05-29 22:05:29 +02:00
}
/* filter using the file name pattern */
if ( pattern )
2005-07-07 14:00:17 +02:00
if ( ! pattern_imatch ( entry - > data . cFileName , pattern ) )
2005-05-29 22:05:29 +02:00
continue ;
/* filter system and hidden files */
if ( ! ( filter_flags & TF_HIDDEN ) & & ( entry - > data . dwFileAttributes & ( FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM ) ) )
continue ;
/* filter looking at the file type */
if ( ( filter_flags & ( TF_PROGRAMS | TF_DOCUMENTS | TF_OTHERS ) ) ! = ( TF_PROGRAMS | TF_DOCUMENTS | TF_OTHERS ) )
switch ( get_file_type ( entry - > data . cFileName ) ) {
case FT_EXECUTABLE :
if ( ! ( filter_flags & TF_PROGRAMS ) )
continue ;
break ;
case FT_DOCUMENT :
if ( ! ( filter_flags & TF_DOCUMENTS ) )
continue ;
break ;
default : /* TF_OTHERS */
if ( ! ( filter_flags & TF_OTHERS ) )
continue ;
}
2002-06-04 23:29:40 +02:00
if ( idx ! = - 1 )
idx + + ;
2006-03-17 16:57:16 +01:00
SendMessage ( pane - > hwnd , LB_INSERTSTRING , idx , ( LPARAM ) entry ) ;
2002-06-04 23:29:40 +02:00
2005-05-11 20:23:30 +02:00
if ( pane - > treePane & & entry - > expanded )
2005-05-29 22:05:29 +02:00
idx = insert_entries ( pane , entry - > down , pattern , filter_flags , idx ) ;
2002-06-04 23:29:40 +02:00
}
ShowWindow ( pane - > hwnd , SW_SHOW ) ;
2005-05-11 20:23:30 +02:00
return idx ;
2002-06-04 23:29:40 +02:00
}
2005-05-14 13:07:39 +02:00
static void format_bytes ( LPTSTR buffer , LONGLONG bytes )
{
2005-10-06 13:38:45 +02:00
static const TCHAR sFmtGB [ ] = { ' % ' , ' . ' , ' 1 ' , ' f ' , ' ' , ' G ' , ' B ' , ' \0 ' } ;
static const TCHAR sFmtMB [ ] = { ' % ' , ' . ' , ' 1 ' , ' f ' , ' ' , ' M ' , ' B ' , ' \0 ' } ;
static const TCHAR sFmtkB [ ] = { ' % ' , ' . ' , ' 1 ' , ' f ' , ' ' , ' k ' , ' B ' , ' \0 ' } ;
2005-05-14 13:07:39 +02:00
float fBytes = ( float ) bytes ;
if ( bytes > = 1073741824 ) /* 1 GB */
2006-09-06 10:45:02 +02:00
_stprintf ( buffer , sFmtGB , fBytes / 1073741824.f + .5f ) ;
2005-05-14 13:07:39 +02:00
else if ( bytes > = 1048576 ) /* 1 MB */
2006-09-06 10:45:02 +02:00
_stprintf ( buffer , sFmtMB , fBytes / 1048576.f + .5f ) ;
2005-05-14 13:07:39 +02:00
else if ( bytes > = 1024 ) /* 1 kB */
2006-09-06 10:45:02 +02:00
_stprintf ( buffer , sFmtkB , fBytes / 1024.f + .5f ) ;
2005-05-14 13:07:39 +02:00
else
_stprintf ( buffer , sLongNumFmt , bytes ) ;
}
2005-06-10 21:32:24 +02:00
static void set_space_status ( void )
2005-05-14 13:07:39 +02:00
{
ULARGE_INTEGER ulFreeBytesToCaller , ulTotalBytes , ulFreeBytes ;
TCHAR fmt [ 64 ] , b1 [ 64 ] , b2 [ 64 ] , buffer [ BUFFER_LEN ] ;
if ( GetDiskFreeSpaceEx ( NULL , & ulFreeBytesToCaller , & ulTotalBytes , & ulFreeBytes ) ) {
format_bytes ( b1 , ulFreeBytesToCaller . QuadPart ) ;
format_bytes ( b2 , ulTotalBytes . QuadPart ) ;
2005-07-07 14:00:17 +02:00
wsprintf ( buffer , RS ( fmt , IDS_FREE_SPACE_FMT ) , b1 , b2 ) ;
2005-05-14 13:07:39 +02:00
} else
2005-07-07 14:00:17 +02:00
lstrcpy ( buffer , sQMarks ) ;
2005-05-14 13:07:39 +02:00
SendMessage ( Globals . hstatusbar , SB_SETTEXT , 0 , ( LPARAM ) buffer ) ;
}
2002-06-04 23:29:40 +02:00
static WNDPROC g_orgTreeWndProc ;
2005-05-29 22:05:29 +02:00
static void create_tree_window ( HWND parent , Pane * pane , int id , int id_header , LPCTSTR pattern , int filter_flags )
2002-06-04 23:29:40 +02:00
{
2005-10-06 13:38:45 +02:00
static const TCHAR sListBox [ ] = { ' L ' , ' i ' , ' s ' , ' t ' , ' B ' , ' o ' , ' x ' , ' \0 ' } ;
2004-11-22 19:24:09 +01:00
2002-06-04 23:29:40 +02:00
static int s_init = 0 ;
Entry * entry = pane - > root ;
2004-11-22 19:24:09 +01:00
pane - > hwnd = CreateWindow ( sListBox , sEmpty , WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL |
2002-06-04 23:29:40 +02:00
LBS_DISABLENOSCROLL | LBS_NOINTEGRALHEIGHT | LBS_OWNERDRAWFIXED | LBS_NOTIFY ,
0 , 0 , 0 , 0 , parent , ( HMENU ) id , Globals . hInstance , 0 ) ;
2005-09-09 17:20:04 +02:00
SetWindowLongPtr ( pane - > hwnd , GWLP_USERDATA , ( LPARAM ) pane ) ;
2006-03-17 16:57:16 +01:00
g_orgTreeWndProc = ( WNDPROC ) SetWindowLongPtr ( pane - > hwnd , GWLP_WNDPROC , ( LPARAM ) TreeWndProc ) ;
2002-06-04 23:29:40 +02:00
2006-03-17 16:57:16 +01:00
SendMessage ( pane - > hwnd , WM_SETFONT , ( WPARAM ) Globals . hfont , FALSE ) ;
2002-06-04 23:29:40 +02:00
2002-06-28 19:37:34 +02:00
/* insert entries into listbox */
2002-06-04 23:29:40 +02:00
if ( entry )
2005-05-29 22:05:29 +02:00
insert_entries ( pane , entry , pattern , filter_flags , - 1 ) ;
2002-06-04 23:29:40 +02:00
2002-06-28 19:37:34 +02:00
/* calculate column widths */
2002-06-04 23:29:40 +02:00
if ( ! s_init ) {
s_init = 1 ;
init_output ( pane - > hwnd ) ;
}
calc_widths ( pane , TRUE ) ;
# ifndef _NO_EXTENSIONS
pane - > hwndHeader = create_header ( parent , pane , id_header ) ;
# endif
}
static void InitChildWindow ( ChildWnd * child )
{
2005-05-29 22:05:29 +02:00
create_tree_window ( child - > hwnd , & child - > left , IDW_TREE_LEFT , IDW_HEADER_LEFT , NULL , TF_ALL ) ;
create_tree_window ( child - > hwnd , & child - > right , IDW_TREE_RIGHT , IDW_HEADER_RIGHT , child - > filter_pattern , child - > filter_flags ) ;
2002-06-04 23:29:40 +02:00
}
static void format_date ( const FILETIME * ft , TCHAR * buffer , int visible_cols )
{
SYSTEMTIME systime ;
FILETIME lft ;
int len = 0 ;
2007-06-27 22:54:56 +02:00
* buffer = ' \0 ' ;
2002-06-04 23:29:40 +02:00
if ( ! ft - > dwLowDateTime & & ! ft - > dwHighDateTime )
return ;
if ( ! FileTimeToLocalFileTime ( ft , & lft ) )
2005-07-07 14:00:17 +02:00
{ err : lstrcpy ( buffer , sQMarks ) ; return ; }
2002-06-04 23:29:40 +02:00
if ( ! FileTimeToSystemTime ( & lft , & systime ) )
goto err ;
if ( visible_cols & COL_DATE ) {
len = GetDateFormat ( LOCALE_USER_DEFAULT , 0 , & systime , 0 , buffer , BUFFER_LEN ) ;
if ( ! len )
goto err ;
}
if ( visible_cols & COL_TIME ) {
if ( len )
buffer [ len - 1 ] = ' ' ;
buffer [ len + + ] = ' ' ;
if ( ! GetTimeFormat ( LOCALE_USER_DEFAULT , 0 , & systime , 0 , buffer + len , BUFFER_LEN - len ) )
2007-06-27 22:54:56 +02:00
buffer [ len ] = ' \0 ' ;
2002-06-04 23:29:40 +02:00
}
}
static void calc_width ( Pane * pane , LPDRAWITEMSTRUCT dis , int col , LPCTSTR str )
{
2003-08-13 03:18:37 +02:00
RECT rt = { 0 , 0 , 0 , 0 } ;
2002-06-04 23:29:40 +02:00
2006-10-07 16:50:46 +02:00
DrawText ( dis - > hDC , str , - 1 , & rt , DT_CALCRECT | DT_SINGLELINE | DT_NOPREFIX ) ;
2002-06-04 23:29:40 +02:00
if ( rt . right > pane - > widths [ col ] )
pane - > widths [ col ] = rt . right ;
}
static void calc_tabbed_width ( Pane * pane , LPDRAWITEMSTRUCT dis , int col , LPCTSTR str )
{
2003-08-13 03:18:37 +02:00
RECT rt = { 0 , 0 , 0 , 0 } ;
2002-06-04 23:29:40 +02:00
/* DRAWTEXTPARAMS dtp = {sizeof(DRAWTEXTPARAMS), 2};
DrawTextEx ( dis - > hDC , ( LPTSTR ) str , - 1 , & rt , DT_CALCRECT | DT_SINGLELINE | DT_NOPREFIX | DT_EXPANDTABS | DT_TABSTOP , & dtp ) ; */
2006-10-07 16:50:46 +02:00
DrawText ( dis - > hDC , str , - 1 , & rt , DT_CALCRECT | DT_SINGLELINE | DT_EXPANDTABS | DT_TABSTOP | ( 2 < < 8 ) ) ;
2003-08-13 03:18:37 +02:00
/*FIXME rt (0,0) ??? */
2002-06-04 23:29:40 +02:00
if ( rt . right > pane - > widths [ col ] )
pane - > widths [ col ] = rt . right ;
}
static void output_text ( Pane * pane , LPDRAWITEMSTRUCT dis , int col , LPCTSTR str , DWORD flags )
{
int x = dis - > rcItem . left ;
2002-07-03 23:06:58 +02:00
RECT rt ;
rt . left = x + pane - > positions [ col ] + Globals . spaceSize . cx ;
rt . top = dis - > rcItem . top ;
rt . right = x + pane - > positions [ col + 1 ] - Globals . spaceSize . cx ;
rt . bottom = dis - > rcItem . bottom ;
2002-06-04 23:29:40 +02:00
2006-10-07 16:50:46 +02:00
DrawText ( dis - > hDC , str , - 1 , & rt , DT_SINGLELINE | DT_NOPREFIX | flags ) ;
2002-06-04 23:29:40 +02:00
}
static void output_tabbed_text ( Pane * pane , LPDRAWITEMSTRUCT dis , int col , LPCTSTR str )
{
int x = dis - > rcItem . left ;
2002-07-03 23:06:58 +02:00
RECT rt ;
rt . left = x + pane - > positions [ col ] + Globals . spaceSize . cx ;
rt . top = dis - > rcItem . top ;
rt . right = x + pane - > positions [ col + 1 ] - Globals . spaceSize . cx ;
rt . bottom = dis - > rcItem . bottom ;
2002-06-04 23:29:40 +02:00
/* DRAWTEXTPARAMS dtp = {sizeof(DRAWTEXTPARAMS), 2};
DrawTextEx ( dis - > hDC , ( LPTSTR ) str , - 1 , & rt , DT_SINGLELINE | DT_NOPREFIX | DT_EXPANDTABS | DT_TABSTOP , & dtp ) ; */
2006-10-07 16:50:46 +02:00
DrawText ( dis - > hDC , str , - 1 , & rt , DT_SINGLELINE | DT_EXPANDTABS | DT_TABSTOP | ( 2 < < 8 ) ) ;
2002-06-04 23:29:40 +02:00
}
static void output_number ( Pane * pane , LPDRAWITEMSTRUCT dis , int col , LPCTSTR str )
{
int x = dis - > rcItem . left ;
2002-07-03 23:06:58 +02:00
RECT rt ;
2002-06-04 23:29:40 +02:00
LPCTSTR s = str ;
TCHAR b [ 128 ] ;
LPTSTR d = b ;
int pos ;
2002-07-03 23:06:58 +02:00
rt . left = x + pane - > positions [ col ] + Globals . spaceSize . cx ;
rt . top = dis - > rcItem . top ;
rt . right = x + pane - > positions [ col + 1 ] - Globals . spaceSize . cx ;
rt . bottom = dis - > rcItem . bottom ;
2002-06-04 23:29:40 +02:00
if ( * s )
* d + + = * s + + ;
2002-06-28 19:37:34 +02:00
/* insert number separator characters */
2002-06-04 23:29:40 +02:00
pos = lstrlen ( s ) % 3 ;
while ( * s )
if ( pos - - )
* d + + = * s + + ;
else {
* d + + = Globals . num_sep ;
pos = 3 ;
}
DrawText ( dis - > hDC , b , d - b , & rt , DT_RIGHT | DT_SINGLELINE | DT_NOPREFIX | DT_END_ELLIPSIS ) ;
}
2005-05-29 22:05:29 +02:00
static BOOL is_exe_file ( LPCTSTR ext )
2002-06-04 23:29:40 +02:00
{
2004-11-22 19:24:09 +01:00
static const TCHAR executable_extensions [ ] [ 4 ] = {
{ ' C ' , ' O ' , ' M ' , ' \0 ' } ,
{ ' E ' , ' X ' , ' E ' , ' \0 ' } ,
{ ' B ' , ' A ' , ' T ' , ' \0 ' } ,
{ ' C ' , ' M ' , ' D ' , ' \0 ' } ,
2002-06-04 23:29:40 +02:00
# ifndef _NO_EXTENSIONS
2004-11-22 19:24:09 +01:00
{ ' C ' , ' M ' , ' M ' , ' \0 ' } ,
{ ' B ' , ' T ' , ' M ' , ' \0 ' } ,
{ ' A ' , ' W ' , ' K ' , ' \0 ' } ,
2003-08-13 03:18:37 +02:00
# endif /* _NO_EXTENSIONS */
2004-11-22 19:24:09 +01:00
{ ' \0 ' }
2002-06-04 23:29:40 +02:00
} ;
TCHAR ext_buffer [ _MAX_EXT ] ;
2004-11-22 19:24:09 +01:00
const TCHAR ( * p ) [ 4 ] ;
2002-06-04 23:29:40 +02:00
LPCTSTR s ;
LPTSTR d ;
for ( s = ext + 1 , d = ext_buffer ; ( * d = tolower ( * s ) ) ; s + + )
d + + ;
2004-11-22 19:24:09 +01:00
for ( p = executable_extensions ; ( * p ) [ 0 ] ; p + + )
2005-07-07 14:00:17 +02:00
if ( ! lstrcmpi ( ext_buffer , * p ) )
2005-05-29 22:05:29 +02:00
return TRUE ;
2002-06-04 23:29:40 +02:00
2005-05-29 22:05:29 +02:00
return FALSE ;
2002-06-04 23:29:40 +02:00
}
2005-05-29 22:05:29 +02:00
static BOOL is_registered_type ( LPCTSTR ext )
2002-06-04 23:29:40 +02:00
{
2005-05-29 22:05:29 +02:00
/* check if there exists a classname for this file extension in the registry */
if ( ! RegQueryValue ( HKEY_CLASSES_ROOT , ext , NULL , NULL ) )
return TRUE ;
return FALSE ;
}
2002-06-04 23:29:40 +02:00
2005-05-29 22:05:29 +02:00
static enum FILE_TYPE get_file_type ( LPCTSTR filename )
{
LPCTSTR ext = _tcsrchr ( filename , ' . ' ) ;
if ( ! ext )
ext = sEmpty ;
if ( is_exe_file ( ext ) )
return FT_EXECUTABLE ;
else if ( is_registered_type ( ext ) )
return FT_DOCUMENT ;
else
return FT_OTHER ;
2002-06-04 23:29:40 +02:00
}
static void draw_item ( Pane * pane , LPDRAWITEMSTRUCT dis , Entry * entry , int calcWidthCol )
{
TCHAR buffer [ BUFFER_LEN ] ;
DWORD attrs ;
int visible_cols = pane - > visible_cols ;
COLORREF bkcolor , textcolor ;
RECT focusRect = dis - > rcItem ;
HBRUSH hbrush ;
enum IMAGE img ;
int img_pos , cx ;
int col = 0 ;
if ( entry ) {
attrs = entry - > data . dwFileAttributes ;
if ( attrs & FILE_ATTRIBUTE_DIRECTORY ) {
2007-06-27 22:54:56 +02:00
if ( entry - > data . cFileName [ 0 ] = = ' . ' & & entry - > data . cFileName [ 1 ] = = ' . '
& & entry - > data . cFileName [ 2 ] = = ' \0 ' )
2002-06-04 23:29:40 +02:00
img = IMG_FOLDER_UP ;
# ifndef _NO_EXTENSIONS
2007-06-27 22:54:56 +02:00
else if ( entry - > data . cFileName [ 0 ] = = ' . ' & & entry - > data . cFileName [ 1 ] = = ' \0 ' )
2002-06-04 23:29:40 +02:00
img = IMG_FOLDER_CUR ;
# endif
else if (
# ifdef _NO_EXTENSIONS
entry - > expanded | |
# endif
( pane - > treePane & & ( dis - > itemState & ODS_FOCUS ) ) )
img = IMG_OPEN_FOLDER ;
else
img = IMG_FOLDER ;
} else {
2005-05-29 22:05:29 +02:00
switch ( get_file_type ( entry - > data . cFileName ) ) {
case FT_EXECUTABLE : img = IMG_EXECUTABLE ; break ;
case FT_DOCUMENT : img = IMG_DOCUMENT ; break ;
default : img = IMG_FILE ;
}
2002-06-04 23:29:40 +02:00
}
} else {
attrs = 0 ;
img = IMG_NONE ;
}
if ( pane - > treePane ) {
if ( entry ) {
2004-09-27 22:35:53 +02:00
img_pos = dis - > rcItem . left + entry - > level * ( IMAGE_WIDTH + TREE_LINE_DX ) ;
2002-06-04 23:29:40 +02:00
if ( calcWidthCol = = - 1 ) {
int x ;
int y = dis - > rcItem . top + IMAGE_HEIGHT / 2 ;
Entry * up ;
2002-07-03 23:06:58 +02:00
RECT rt_clip ;
2002-06-04 23:29:40 +02:00
HRGN hrgn_org = CreateRectRgn ( 0 , 0 , 0 , 0 ) ;
2002-07-03 23:06:58 +02:00
HRGN hrgn ;
rt_clip . left = dis - > rcItem . left ;
rt_clip . top = dis - > rcItem . top ;
rt_clip . right = dis - > rcItem . left + pane - > widths [ col ] ;
rt_clip . bottom = dis - > rcItem . bottom ;
hrgn = CreateRectRgnIndirect ( & rt_clip ) ;
2002-06-04 23:29:40 +02:00
if ( ! GetClipRgn ( dis - > hDC , hrgn_org ) ) {
DeleteObject ( hrgn_org ) ;
hrgn_org = 0 ;
}
2003-08-13 03:18:37 +02:00
/* HGDIOBJ holdPen = SelectObject(dis->hDC, GetStockObject(BLACK_PEN)); */
2002-06-04 23:29:40 +02:00
ExtSelectClipRgn ( dis - > hDC , hrgn , RGN_AND ) ;
DeleteObject ( hrgn ) ;
if ( ( up = entry - > up ) ! = NULL ) {
MoveToEx ( dis - > hDC , img_pos - IMAGE_WIDTH / 2 , y , 0 ) ;
LineTo ( dis - > hDC , img_pos - 2 , y ) ;
x = img_pos - IMAGE_WIDTH / 2 ;
do {
2004-09-27 22:35:53 +02:00
x - = IMAGE_WIDTH + TREE_LINE_DX ;
2002-06-04 23:29:40 +02:00
if ( up - > next
# ifndef _LEFT_FILES
2003-08-13 03:18:37 +02:00
& & ( up - > next - > data . dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
2002-06-04 23:29:40 +02:00
# endif
) {
MoveToEx ( dis - > hDC , x , dis - > rcItem . top , 0 ) ;
LineTo ( dis - > hDC , x , dis - > rcItem . bottom ) ;
}
} while ( ( up = up - > up ) ! = NULL ) ;
}
x = img_pos - IMAGE_WIDTH / 2 ;
MoveToEx ( dis - > hDC , x , dis - > rcItem . top , 0 ) ;
LineTo ( dis - > hDC , x , y ) ;
if ( entry - > next
# ifndef _LEFT_FILES
& & ( entry - > next - > data . dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
# endif
)
LineTo ( dis - > hDC , x , dis - > rcItem . bottom ) ;
SelectClipRgn ( dis - > hDC , hrgn_org ) ;
if ( hrgn_org ) DeleteObject ( hrgn_org ) ;
2003-08-13 03:18:37 +02:00
/* SelectObject(dis->hDC, holdPen); */
2002-06-04 23:29:40 +02:00
} else if ( calcWidthCol = = col | | calcWidthCol = = COLUMNS ) {
2004-09-27 22:35:53 +02:00
int right = img_pos + IMAGE_WIDTH - TREE_LINE_DX ;
2002-06-04 23:29:40 +02:00
if ( right > pane - > widths [ col ] )
pane - > widths [ col ] = right ;
}
} else {
img_pos = dis - > rcItem . left ;
}
} else {
img_pos = dis - > rcItem . left ;
if ( calcWidthCol = = col | | calcWidthCol = = COLUMNS )
pane - > widths [ col ] = IMAGE_WIDTH ;
}
if ( calcWidthCol = = - 1 ) {
focusRect . left = img_pos - 2 ;
# ifdef _NO_EXTENSIONS
if ( pane - > treePane & & entry ) {
RECT rt = { 0 } ;
DrawText ( dis - > hDC , entry - > data . cFileName , - 1 , & rt , DT_CALCRECT | DT_SINGLELINE | DT_NOPREFIX ) ;
2004-09-27 22:35:53 +02:00
focusRect . right = dis - > rcItem . left + pane - > positions [ col + 1 ] + TREE_LINE_DX + rt . right + 2 ;
2002-06-04 23:29:40 +02:00
}
# else
if ( attrs & FILE_ATTRIBUTE_COMPRESSED )
textcolor = COLOR_COMPRESSED ;
else
2003-08-13 03:18:37 +02:00
# endif /* _NO_EXTENSIONS */
2002-06-04 23:29:40 +02:00
textcolor = RGB ( 0 , 0 , 0 ) ;
if ( dis - > itemState & ODS_FOCUS ) {
textcolor = RGB ( 255 , 255 , 255 ) ;
bkcolor = COLOR_SELECTION ;
} else {
bkcolor = RGB ( 255 , 255 , 255 ) ;
}
hbrush = CreateSolidBrush ( bkcolor ) ;
FillRect ( dis - > hDC , & focusRect , hbrush ) ;
DeleteObject ( hbrush ) ;
SetBkMode ( dis - > hDC , TRANSPARENT ) ;
SetTextColor ( dis - > hDC , textcolor ) ;
cx = pane - > widths [ col ] ;
if ( cx & & img ! = IMG_NONE ) {
if ( cx > IMAGE_WIDTH )
cx = IMAGE_WIDTH ;
2003-08-13 03:18:37 +02:00
# ifdef _SHELL_FOLDERS
if ( entry - > hicon & & entry - > hicon ! = ( HICON ) - 1 )
DrawIconEx ( dis - > hDC , img_pos , dis - > rcItem . top , entry - > hicon , cx , GetSystemMetrics ( SM_CYSMICON ) , 0 , 0 , DI_NORMAL ) ;
else
# endif
ImageList_DrawEx ( Globals . himl , img , dis - > hDC ,
img_pos , dis - > rcItem . top , cx ,
IMAGE_HEIGHT , bkcolor , CLR_DEFAULT , ILD_NORMAL ) ;
2002-06-04 23:29:40 +02:00
}
}
if ( ! entry )
return ;
# ifdef _NO_EXTENSIONS
if ( img > = IMG_FOLDER_UP )
return ;
# endif
col + + ;
2002-06-28 19:37:34 +02:00
/* ouput file name */
2002-06-04 23:29:40 +02:00
if ( calcWidthCol = = - 1 )
output_text ( pane , dis , col , entry - > data . cFileName , 0 ) ;
else if ( calcWidthCol = = col | | calcWidthCol = = COLUMNS )
calc_width ( pane , dis , col , entry - > data . cFileName ) ;
col + + ;
# ifdef _NO_EXTENSIONS
if ( ! pane - > treePane ) {
# endif
2002-06-28 19:37:34 +02:00
/* display file size */
2002-06-04 23:29:40 +02:00
if ( visible_cols & COL_SIZE ) {
# ifdef _NO_EXTENSIONS
if ( ! ( attrs & FILE_ATTRIBUTE_DIRECTORY ) )
# endif
{
2002-09-12 19:29:12 +02:00
ULONGLONG size ;
2002-06-04 23:29:40 +02:00
2002-09-12 19:29:12 +02:00
size = ( ( ULONGLONG ) entry - > data . nFileSizeHigh < < 32 ) | entry - > data . nFileSizeLow ;
2002-06-04 23:29:40 +02:00
2004-11-22 19:24:09 +01:00
_stprintf ( buffer , sLongNumFmt , size ) ;
2002-06-04 23:29:40 +02:00
if ( calcWidthCol = = - 1 )
output_number ( pane , dis , col , buffer ) ;
else if ( calcWidthCol = = col | | calcWidthCol = = COLUMNS )
2002-06-28 19:37:34 +02:00
calc_width ( pane , dis , col , buffer ) ; /*TODO: not ever time enough */
2002-06-04 23:29:40 +02:00
}
col + + ;
}
2002-06-28 19:37:34 +02:00
/* display file date */
2002-06-04 23:29:40 +02:00
if ( visible_cols & ( COL_DATE | COL_TIME ) ) {
# ifndef _NO_EXTENSIONS
format_date ( & entry - > data . ftCreationTime , buffer , visible_cols ) ;
if ( calcWidthCol = = - 1 )
output_text ( pane , dis , col , buffer , 0 ) ;
else if ( calcWidthCol = = col | | calcWidthCol = = COLUMNS )
calc_width ( pane , dis , col , buffer ) ;
col + + ;
format_date ( & entry - > data . ftLastAccessTime , buffer , visible_cols ) ;
if ( calcWidthCol = = - 1 )
output_text ( pane , dis , col , buffer , 0 ) ;
else if ( calcWidthCol = = col | | calcWidthCol = = COLUMNS )
calc_width ( pane , dis , col , buffer ) ;
col + + ;
2003-08-13 03:18:37 +02:00
# endif /* _NO_EXTENSIONS */
2002-06-04 23:29:40 +02:00
format_date ( & entry - > data . ftLastWriteTime , buffer , visible_cols ) ;
if ( calcWidthCol = = - 1 )
output_text ( pane , dis , col , buffer , 0 ) ;
else if ( calcWidthCol = = col | | calcWidthCol = = COLUMNS )
calc_width ( pane , dis , col , buffer ) ;
col + + ;
}
# ifndef _NO_EXTENSIONS
if ( entry - > bhfi_valid ) {
2002-09-12 19:29:12 +02:00
ULONGLONG index = ( ( ULONGLONG ) entry - > bhfi . nFileIndexHigh < < 32 ) | entry - > bhfi . nFileIndexLow ;
2002-06-04 23:29:40 +02:00
if ( visible_cols & COL_INDEX ) {
2004-11-22 19:24:09 +01:00
_stprintf ( buffer , sLongHexFmt , index ) ;
2002-06-04 23:29:40 +02:00
if ( calcWidthCol = = - 1 )
output_text ( pane , dis , col , buffer , DT_RIGHT ) ;
else if ( calcWidthCol = = col | | calcWidthCol = = COLUMNS )
calc_width ( pane , dis , col , buffer ) ;
2004-11-22 19:24:09 +01:00
2002-06-04 23:29:40 +02:00
col + + ;
}
if ( visible_cols & COL_LINKS ) {
2005-07-07 14:00:17 +02:00
wsprintf ( buffer , sNumFmt , entry - > bhfi . nNumberOfLinks ) ;
2004-11-22 19:24:09 +01:00
2002-06-04 23:29:40 +02:00
if ( calcWidthCol = = - 1 )
output_text ( pane , dis , col , buffer , DT_CENTER ) ;
else if ( calcWidthCol = = col | | calcWidthCol = = COLUMNS )
calc_width ( pane , dis , col , buffer ) ;
2004-11-22 19:24:09 +01:00
2002-06-04 23:29:40 +02:00
col + + ;
}
} else
col + = 2 ;
2003-08-13 03:18:37 +02:00
# endif /* _NO_EXTENSIONS */
2002-06-04 23:29:40 +02:00
2002-06-28 19:37:34 +02:00
/* show file attributes */
2002-06-04 23:29:40 +02:00
if ( visible_cols & COL_ATTRIBUTES ) {
# ifdef _NO_EXTENSIONS
2005-10-06 13:38:45 +02:00
static const TCHAR s4Tabs [ ] = { ' ' , ' \t ' , ' ' , ' \t ' , ' ' , ' \t ' , ' ' , ' \t ' , ' ' , ' \0 ' } ;
2005-07-07 14:00:17 +02:00
lstrcpy ( buffer , s4Tabs ) ;
2002-06-04 23:29:40 +02:00
# else
2005-10-06 13:38:45 +02:00
static const TCHAR s11Tabs [ ] = { ' ' , ' \t ' , ' ' , ' \t ' , ' ' , ' \t ' , ' ' , ' \t ' , ' ' , ' \t ' , ' ' , ' \t ' , ' ' , ' \t ' , ' ' , ' \t ' , ' ' , ' \t ' , ' ' , ' \t ' , ' ' , ' \t ' , ' ' , ' \0 ' } ;
2005-07-07 14:00:17 +02:00
lstrcpy ( buffer , s11Tabs ) ;
2002-06-04 23:29:40 +02:00
# endif
if ( attrs & FILE_ATTRIBUTE_NORMAL ) buffer [ 0 ] = ' N ' ;
else {
if ( attrs & FILE_ATTRIBUTE_READONLY ) buffer [ 2 ] = ' R ' ;
if ( attrs & FILE_ATTRIBUTE_HIDDEN ) buffer [ 4 ] = ' H ' ;
if ( attrs & FILE_ATTRIBUTE_SYSTEM ) buffer [ 6 ] = ' S ' ;
if ( attrs & FILE_ATTRIBUTE_ARCHIVE ) buffer [ 8 ] = ' A ' ;
if ( attrs & FILE_ATTRIBUTE_COMPRESSED ) buffer [ 10 ] = ' C ' ;
# ifndef _NO_EXTENSIONS
if ( attrs & FILE_ATTRIBUTE_DIRECTORY ) buffer [ 12 ] = ' D ' ;
if ( attrs & FILE_ATTRIBUTE_ENCRYPTED ) buffer [ 14 ] = ' E ' ;
if ( attrs & FILE_ATTRIBUTE_TEMPORARY ) buffer [ 16 ] = ' T ' ;
if ( attrs & FILE_ATTRIBUTE_SPARSE_FILE ) buffer [ 18 ] = ' P ' ;
if ( attrs & FILE_ATTRIBUTE_REPARSE_POINT ) buffer [ 20 ] = ' Q ' ;
if ( attrs & FILE_ATTRIBUTE_OFFLINE ) buffer [ 22 ] = ' O ' ;
if ( attrs & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED ) buffer [ 24 ] = ' X ' ;
2003-08-13 03:18:37 +02:00
# endif /* _NO_EXTENSIONS */
2002-06-04 23:29:40 +02:00
}
if ( calcWidthCol = = - 1 )
output_tabbed_text ( pane , dis , col , buffer ) ;
else if ( calcWidthCol = = col | | calcWidthCol = = COLUMNS )
calc_tabbed_width ( pane , dis , col , buffer ) ;
col + + ;
}
/*TODO
if ( flags . security ) {
2005-10-06 13:38:45 +02:00
static const TCHAR sSecTabs [ ] = {
2004-11-22 19:24:09 +01:00
' ' , ' \t ' , ' ' , ' \t ' , ' ' , ' \t ' , ' ' ,
' ' , ' \t ' , ' ' ,
' ' , ' \t ' , ' ' , ' \t ' , ' ' , ' \t ' , ' ' ,
' ' , ' \t ' , ' ' ,
' ' , ' \t ' , ' ' , ' \t ' , ' ' , ' \t ' , ' ' ,
' \0 '
} ;
2002-06-04 23:29:40 +02:00
DWORD rights = get_access_mask ( ) ;
2005-07-07 14:00:17 +02:00
lstrcpy ( buffer , sSecTabs ) ;
2002-06-04 23:29:40 +02:00
if ( rights & FILE_READ_DATA ) buffer [ 0 ] = ' R ' ;
if ( rights & FILE_WRITE_DATA ) buffer [ 2 ] = ' W ' ;
if ( rights & FILE_APPEND_DATA ) buffer [ 4 ] = ' A ' ;
if ( rights & FILE_READ_EA ) { buffer [ 6 ] = ' entry ' ; buffer [ 7 ] = ' R ' ; }
if ( rights & FILE_WRITE_EA ) { buffer [ 9 ] = ' entry ' ; buffer [ 10 ] = ' W ' ; }
if ( rights & FILE_EXECUTE ) buffer [ 12 ] = ' X ' ;
if ( rights & FILE_DELETE_CHILD ) buffer [ 14 ] = ' D ' ;
if ( rights & FILE_READ_ATTRIBUTES ) { buffer [ 16 ] = ' a ' ; buffer [ 17 ] = ' R ' ; }
if ( rights & FILE_WRITE_ATTRIBUTES ) { buffer [ 19 ] = ' a ' ; buffer [ 20 ] = ' W ' ; }
if ( rights & WRITE_DAC ) buffer [ 22 ] = ' C ' ;
if ( rights & WRITE_OWNER ) buffer [ 24 ] = ' O ' ;
if ( rights & SYNCHRONIZE ) buffer [ 26 ] = ' S ' ;
output_text ( dis , col + + , buffer , DT_LEFT , 3 , psize ) ;
}
if ( flags . description ) {
get_description ( buffer ) ;
output_text ( dis , col + + , buffer , 0 , psize ) ;
}
*/
# ifdef _NO_EXTENSIONS
}
2002-06-28 19:37:34 +02:00
/* draw focus frame */
2002-06-04 23:29:40 +02:00
if ( ( dis - > itemState & ODS_FOCUS ) & & calcWidthCol = = - 1 ) {
2002-06-28 19:37:34 +02:00
/* Currently [04/2000] Wine neither behaves exactly the same */
/* way as WIN 95 nor like Windows NT... */
2002-06-04 23:29:40 +02:00
HGDIOBJ lastBrush ;
HPEN lastPen ;
HPEN hpen ;
2002-06-28 19:37:34 +02:00
if ( ! ( GetVersion ( ) & 0x80000000 ) ) { /* Windows NT? */
2002-06-04 23:29:40 +02:00
LOGBRUSH lb = { PS_SOLID , RGB ( 255 , 255 , 255 ) } ;
hpen = ExtCreatePen ( PS_COSMETIC | PS_ALTERNATE , 1 , & lb , 0 , 0 ) ;
} else
hpen = CreatePen ( PS_DOT , 0 , RGB ( 255 , 255 , 255 ) ) ;
lastPen = SelectPen ( dis - > hDC , hpen ) ;
lastBrush = SelectObject ( dis - > hDC , GetStockObject ( HOLLOW_BRUSH ) ) ;
SetROP2 ( dis - > hDC , R2_XORPEN ) ;
Rectangle ( dis - > hDC , focusRect . left , focusRect . top , focusRect . right , focusRect . bottom ) ;
SelectObject ( dis - > hDC , lastBrush ) ;
SelectObject ( dis - > hDC , lastPen ) ;
DeleteObject ( hpen ) ;
}
2003-08-13 03:18:37 +02:00
# endif /* _NO_EXTENSIONS */
2002-06-04 23:29:40 +02:00
}
# ifdef _NO_EXTENSIONS
static void draw_splitbar ( HWND hwnd , int x )
{
RECT rt ;
HDC hdc = GetDC ( hwnd ) ;
GetClientRect ( hwnd , & rt ) ;
rt . left = x - SPLIT_WIDTH / 2 ;
rt . right = x + SPLIT_WIDTH / 2 + 1 ;
InvertRect ( hdc , & rt ) ;
ReleaseDC ( hwnd , hdc ) ;
}
2003-08-13 03:18:37 +02:00
# endif /* _NO_EXTENSIONS */
2002-06-04 23:29:40 +02:00
# ifndef _NO_EXTENSIONS
static void set_header ( Pane * pane )
{
HD_ITEM item ;
int scroll_pos = GetScrollPos ( pane - > hwnd , SB_HORZ ) ;
int i = 0 , x = 0 ;
item . mask = HDI_WIDTH ;
item . cxy = 0 ;
for ( ; x + pane - > widths [ i ] < scroll_pos & & i < COLUMNS ; i + + ) {
x + = pane - > widths [ i ] ;
2006-03-21 02:58:23 +01:00
SendMessage ( pane - > hwndHeader , HDM_SETITEM , i , ( LPARAM ) & item ) ;
2002-06-04 23:29:40 +02:00
}
if ( i < COLUMNS ) {
x + = pane - > widths [ i ] ;
item . cxy = x - scroll_pos ;
2006-03-21 02:58:23 +01:00
SendMessage ( pane - > hwndHeader , HDM_SETITEM , i + + , ( LPARAM ) & item ) ;
2002-06-04 23:29:40 +02:00
for ( ; i < COLUMNS ; i + + ) {
item . cxy = pane - > widths [ i ] ;
x + = pane - > widths [ i ] ;
2006-03-21 02:58:23 +01:00
SendMessage ( pane - > hwndHeader , HDM_SETITEM , i , ( LPARAM ) & item ) ;
2002-06-04 23:29:40 +02:00
}
}
}
static LRESULT pane_notify ( Pane * pane , NMHDR * pnmh )
{
switch ( pnmh - > code ) {
2006-04-13 10:38:00 +02:00
case HDN_ITEMCHANGED : {
2002-06-04 23:29:40 +02:00
HD_NOTIFY * phdn = ( HD_NOTIFY * ) pnmh ;
int idx = phdn - > iItem ;
int dx = phdn - > pitem - > cxy - pane - > widths [ idx ] ;
int i ;
RECT clnt ;
GetClientRect ( pane - > hwnd , & clnt ) ;
pane - > widths [ idx ] + = dx ;
for ( i = idx ; + + i < = COLUMNS ; )
pane - > positions [ i ] + = dx ;
{
int scroll_pos = GetScrollPos ( pane - > hwnd , SB_HORZ ) ;
2002-07-03 23:06:58 +02:00
RECT rt_scr ;
RECT rt_clip ;
rt_scr . left = pane - > positions [ idx + 1 ] - scroll_pos ;
rt_scr . top = 0 ;
rt_scr . right = clnt . right ;
rt_scr . bottom = clnt . bottom ;
rt_clip . left = pane - > positions [ idx ] - scroll_pos ;
rt_clip . top = 0 ;
rt_clip . right = clnt . right ;
rt_clip . bottom = clnt . bottom ;
2002-06-04 23:29:40 +02:00
if ( rt_scr . left < 0 ) rt_scr . left = 0 ;
if ( rt_clip . left < 0 ) rt_clip . left = 0 ;
ScrollWindowEx ( pane - > hwnd , dx , 0 , & rt_scr , & rt_clip , 0 , 0 , SW_INVALIDATE ) ;
rt_clip . right = pane - > positions [ idx + 1 ] ;
RedrawWindow ( pane - > hwnd , & rt_clip , 0 , RDW_INVALIDATE | RDW_UPDATENOW ) ;
if ( pnmh - > code = = HDN_ENDTRACK ) {
2006-03-17 16:57:16 +01:00
SendMessage ( pane - > hwnd , LB_SETHORIZONTALEXTENT , pane - > positions [ COLUMNS ] , 0 ) ;
2002-06-04 23:29:40 +02:00
if ( GetScrollPos ( pane - > hwnd , SB_HORZ ) ! = scroll_pos )
set_header ( pane ) ;
}
}
return FALSE ;
}
case HDN_DIVIDERDBLCLICK : {
HD_NOTIFY * phdn = ( HD_NOTIFY * ) pnmh ;
HD_ITEM item ;
calc_single_width ( pane , phdn - > iItem ) ;
item . mask = HDI_WIDTH ;
item . cxy = pane - > widths [ phdn - > iItem ] ;
2006-03-21 02:58:23 +01:00
SendMessage ( pane - > hwndHeader , HDM_SETITEM , phdn - > iItem , ( LPARAM ) & item ) ;
2002-06-04 23:29:40 +02:00
InvalidateRect ( pane - > hwnd , 0 , TRUE ) ;
break ; }
}
return 0 ;
}
2003-08-13 03:18:37 +02:00
# endif /* _NO_EXTENSIONS */
2002-06-04 23:29:40 +02:00
2005-05-16 10:48:54 +02:00
static void scan_entry ( ChildWnd * child , Entry * entry , int idx , HWND hwnd )
2002-06-04 23:29:40 +02:00
{
TCHAR path [ MAX_PATH ] ;
2003-08-13 03:18:37 +02:00
HCURSOR old_cursor = SetCursor ( LoadCursor ( 0 , IDC_WAIT ) ) ;
2002-06-04 23:29:40 +02:00
2002-06-28 19:37:34 +02:00
/* delete sub entries in left pane */
2002-06-04 23:29:40 +02:00
for ( ; ; ) {
2006-03-17 16:57:16 +01:00
LRESULT res = SendMessage ( child - > left . hwnd , LB_GETITEMDATA , idx + 1 , 0 ) ;
2002-06-04 23:29:40 +02:00
Entry * sub = ( Entry * ) res ;
if ( res = = LB_ERR | | ! sub | | sub - > level < = entry - > level )
break ;
2006-03-17 16:57:16 +01:00
SendMessage ( child - > left . hwnd , LB_DELETESTRING , idx + 1 , 0 ) ;
2002-06-04 23:29:40 +02:00
}
2002-06-28 19:37:34 +02:00
/* empty right pane */
2006-03-17 16:57:16 +01:00
SendMessage ( child - > right . hwnd , LB_RESETCONTENT , 0 , 0 ) ;
2002-06-04 23:29:40 +02:00
2002-06-28 19:37:34 +02:00
/* release memory */
2002-06-04 23:29:40 +02:00
free_entries ( entry ) ;
2002-06-28 19:37:34 +02:00
/* read contents from disk */
2003-08-13 03:18:37 +02:00
# ifdef _SHELL_FOLDERS
if ( entry - > etype = = ET_SHELL )
{
read_directory ( entry , NULL , child - > sortOrder , hwnd ) ;
}
else
# endif
{
get_path ( entry , path ) ;
read_directory ( entry , path , child - > sortOrder , hwnd ) ;
}
2002-06-04 23:29:40 +02:00
2002-06-28 19:37:34 +02:00
/* insert found entries in right pane */
2005-05-29 22:05:29 +02:00
insert_entries ( & child - > right , entry - > down , child - > filter_pattern , child - > filter_flags , - 1 ) ;
2002-06-04 23:29:40 +02:00
calc_widths ( & child - > right , FALSE ) ;
# ifndef _NO_EXTENSIONS
set_header ( & child - > right ) ;
# endif
child - > header_wdths_ok = FALSE ;
2003-08-13 03:18:37 +02:00
SetCursor ( old_cursor ) ;
2002-06-04 23:29:40 +02:00
}
2002-06-28 19:37:34 +02:00
/* expand a directory entry */
2002-06-04 23:29:40 +02:00
static BOOL expand_entry ( ChildWnd * child , Entry * dir )
{
int idx ;
Entry * p ;
if ( ! dir | | dir - > expanded | | ! dir - > down )
return FALSE ;
p = dir - > down ;
if ( p - > data . cFileName [ 0 ] = = ' . ' & & p - > data . cFileName [ 1 ] = = ' \0 ' & & p - > next ) {
p = p - > next ;
if ( p - > data . cFileName [ 0 ] = = ' . ' & & p - > data . cFileName [ 1 ] = = ' . ' & &
p - > data . cFileName [ 2 ] = = ' \0 ' & & p - > next )
p = p - > next ;
}
2002-06-28 19:37:34 +02:00
/* no subdirectories ? */
2002-06-04 23:29:40 +02:00
if ( ! ( p - > data . dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) )
return FALSE ;
2006-03-17 16:57:16 +01:00
idx = SendMessage ( child - > left . hwnd , LB_FINDSTRING , 0 , ( LPARAM ) dir ) ;
2002-06-04 23:29:40 +02:00
dir - > expanded = TRUE ;
2002-06-28 19:37:34 +02:00
/* insert entries in left pane */
2005-05-29 22:05:29 +02:00
insert_entries ( & child - > left , p , NULL , TF_ALL , idx ) ;
2002-06-04 23:29:40 +02:00
if ( ! child - > header_wdths_ok ) {
if ( calc_widths ( & child - > left , FALSE ) ) {
# ifndef _NO_EXTENSIONS
set_header ( & child - > left ) ;
# endif
child - > header_wdths_ok = TRUE ;
}
}
return TRUE ;
}
static void collapse_entry ( Pane * pane , Entry * dir )
{
2006-03-17 16:57:16 +01:00
int idx = SendMessage ( pane - > hwnd , LB_FINDSTRING , 0 , ( LPARAM ) dir ) ;
2002-06-04 23:29:40 +02:00
ShowWindow ( pane - > hwnd , SW_HIDE ) ;
2002-06-28 19:37:34 +02:00
/* hide sub entries */
2002-06-04 23:29:40 +02:00
for ( ; ; ) {
2006-03-17 16:57:16 +01:00
LRESULT res = SendMessage ( pane - > hwnd , LB_GETITEMDATA , idx + 1 , 0 ) ;
2002-06-04 23:29:40 +02:00
Entry * sub = ( Entry * ) res ;
if ( res = = LB_ERR | | ! sub | | sub - > level < = dir - > level )
break ;
2006-03-17 16:57:16 +01:00
SendMessage ( pane - > hwnd , LB_DELETESTRING , idx + 1 , 0 ) ;
2002-06-04 23:29:40 +02:00
}
dir - > expanded = FALSE ;
ShowWindow ( pane - > hwnd , SW_SHOW ) ;
}
2005-05-29 22:05:29 +02:00
static void refresh_right_pane ( ChildWnd * child )
{
2006-03-17 16:57:16 +01:00
SendMessage ( child - > right . hwnd , LB_RESETCONTENT , 0 , 0 ) ;
2005-05-29 22:05:29 +02:00
insert_entries ( & child - > right , child - > right . root , child - > filter_pattern , child - > filter_flags , - 1 ) ;
calc_widths ( & child - > right , FALSE ) ;
# ifndef _NO_EXTENSIONS
set_header ( & child - > right ) ;
# endif
}
2005-05-16 10:48:54 +02:00
static void set_curdir ( ChildWnd * child , Entry * entry , int idx , HWND hwnd )
2002-06-04 23:29:40 +02:00
{
TCHAR path [ MAX_PATH ] ;
2005-07-07 14:00:17 +02:00
if ( ! entry )
return ;
2003-08-13 03:18:37 +02:00
path [ 0 ] = ' \0 ' ;
2002-06-04 23:29:40 +02:00
child - > left . cur = entry ;
2005-05-29 22:05:29 +02:00
2003-08-13 03:18:37 +02:00
child - > right . root = entry - > down ? entry - > down : entry ;
2002-06-04 23:29:40 +02:00
child - > right . cur = entry ;
if ( ! entry - > scanned )
2005-05-16 10:48:54 +02:00
scan_entry ( child , entry , idx , hwnd ) ;
2005-05-29 22:05:29 +02:00
else
refresh_right_pane ( child ) ;
2002-06-04 23:29:40 +02:00
get_path ( entry , path ) ;
lstrcpy ( child - > path , path ) ;
2002-10-18 02:20:25 +02:00
if ( child - > hwnd ) /* only change window title, if the window already exists */
SetWindowText ( child - > hwnd , path ) ;
2003-08-13 03:18:37 +02:00
if ( path [ 0 ] )
2005-05-14 13:07:39 +02:00
if ( SetCurrentDirectory ( path ) )
set_space_status ( ) ;
2003-08-13 03:18:37 +02:00
}
2005-05-16 10:48:54 +02:00
static void refresh_child ( ChildWnd * child )
{
TCHAR path [ MAX_PATH ] , drv [ _MAX_DRIVE + 1 ] ;
Entry * entry ;
int idx ;
get_path ( child - > left . cur , path ) ;
_tsplitpath ( path , drv , NULL , NULL , NULL ) ;
child - > right . root = NULL ;
scan_entry ( child , & child - > root . entry , 0 , child - > hwnd ) ;
2005-07-07 22:27:24 +02:00
# ifdef _SHELL_FOLDERS
if ( child - > root . entry . etype = = ET_SHELL )
entry = read_tree ( & child - > root , NULL , get_path_pidl ( path , child - > hwnd ) , drv , child - > sortOrder , child - > hwnd ) ;
else
# endif
entry = read_tree ( & child - > root , path , NULL , drv , child - > sortOrder , child - > hwnd ) ;
if ( ! entry )
entry = & child - > root . entry ;
2005-05-16 10:48:54 +02:00
2005-05-29 22:05:29 +02:00
insert_entries ( & child - > left , child - > root . entry . down , NULL , TF_ALL , 0 ) ;
2005-05-16 10:48:54 +02:00
set_curdir ( child , entry , 0 , child - > hwnd ) ;
2006-03-17 16:57:16 +01:00
idx = SendMessage ( child - > left . hwnd , LB_FINDSTRING , 0 , ( LPARAM ) child - > left . cur ) ;
SendMessage ( child - > left . hwnd , LB_SETCURSEL , idx , 0 ) ;
2005-05-16 10:48:54 +02:00
}
2005-06-10 21:32:24 +02:00
static void create_drive_bar ( void )
2005-05-16 23:36:41 +02:00
{
TBBUTTON drivebarBtn = { 0 , 0 , TBSTATE_ENABLED , BTNS_BUTTON , { 0 , 0 } , 0 , 0 } ;
2005-05-23 12:26:47 +02:00
# ifndef _NO_EXTENSIONS
2005-05-16 23:36:41 +02:00
TCHAR b1 [ BUFFER_LEN ] ;
2005-05-23 12:26:47 +02:00
# endif
2005-05-16 23:36:41 +02:00
int btn = 1 ;
PTSTR p ;
GetLogicalDriveStrings ( BUFFER_LEN , Globals . drives ) ;
Globals . hdrivebar = CreateToolbarEx ( Globals . hMainWnd , WS_CHILD | WS_VISIBLE | CCS_NOMOVEY | TBSTYLE_LIST ,
IDW_DRIVEBAR , 2 , Globals . hInstance , IDB_DRIVEBAR , & drivebarBtn ,
2005-06-13 13:38:27 +02:00
0 , 16 , 13 , 16 , 13 , sizeof ( TBBUTTON ) ) ;
2005-05-16 23:36:41 +02:00
# ifndef _NO_EXTENSIONS
# ifdef __WINE__
/* insert unix file system button */
b1 [ 0 ] = ' / ' ;
b1 [ 1 ] = ' \0 ' ;
b1 [ 2 ] = ' \0 ' ;
SendMessage ( Globals . hdrivebar , TB_ADDSTRING , 0 , ( LPARAM ) b1 ) ;
drivebarBtn . idCommand = ID_DRIVE_UNIX_FS ;
SendMessage ( Globals . hdrivebar , TB_INSERTBUTTON , btn + + , ( LPARAM ) & drivebarBtn ) ;
drivebarBtn . iString + + ;
# endif
# ifdef _SHELL_FOLDERS
/* insert shell namespace button */
load_string ( b1 , IDS_SHELL ) ;
b1 [ lstrlen ( b1 ) + 1 ] = ' \0 ' ;
SendMessage ( Globals . hdrivebar , TB_ADDSTRING , 0 , ( LPARAM ) b1 ) ;
drivebarBtn . idCommand = ID_DRIVE_SHELL_NS ;
SendMessage ( Globals . hdrivebar , TB_INSERTBUTTON , btn + + , ( LPARAM ) & drivebarBtn ) ;
drivebarBtn . iString + + ;
# endif
/* register windows drive root strings */
SendMessage ( Globals . hdrivebar , TB_ADDSTRING , 0 , ( LPARAM ) Globals . drives ) ;
# endif
drivebarBtn . idCommand = ID_DRIVE_FIRST ;
for ( p = Globals . drives ; * p ; ) {
# ifdef _NO_EXTENSIONS
/* insert drive letter */
TCHAR b [ 3 ] = { tolower ( * p ) } ;
SendMessage ( Globals . hdrivebar , TB_ADDSTRING , 0 , ( LPARAM ) b ) ;
# endif
switch ( GetDriveType ( p ) ) {
case DRIVE_REMOVABLE : drivebarBtn . iBitmap = 1 ; break ;
case DRIVE_CDROM : drivebarBtn . iBitmap = 3 ; break ;
case DRIVE_REMOTE : drivebarBtn . iBitmap = 4 ; break ;
case DRIVE_RAMDISK : drivebarBtn . iBitmap = 5 ; break ;
default : /*DRIVE_FIXED*/ drivebarBtn . iBitmap = 2 ;
}
SendMessage ( Globals . hdrivebar , TB_INSERTBUTTON , btn + + , ( LPARAM ) & drivebarBtn ) ;
drivebarBtn . idCommand + + ;
drivebarBtn . iString + + ;
while ( * p + + ) ;
}
}
2005-06-10 21:32:24 +02:00
static void refresh_drives ( void )
2005-05-16 23:36:41 +02:00
{
RECT rect ;
/* destroy drive bar */
DestroyWindow ( Globals . hdrivebar ) ;
Globals . hdrivebar = 0 ;
/* re-create drive bar */
create_drive_bar ( ) ;
/* update window layout */
GetClientRect ( Globals . hMainWnd , & rect ) ;
SendMessage ( Globals . hMainWnd , WM_SIZE , 0 , MAKELONG ( rect . right , rect . bottom ) ) ;
}
2005-06-10 21:32:24 +02:00
static BOOL launch_file ( HWND hwnd , LPCTSTR cmd , UINT nCmdShow )
2003-08-13 03:18:37 +02:00
{
HINSTANCE hinst = ShellExecute ( hwnd , NULL /*operation*/ , cmd , NULL /*parameters*/ , NULL /*dir*/ , nCmdShow ) ;
if ( ( int ) hinst < = 32 ) {
display_error ( hwnd , GetLastError ( ) ) ;
return FALSE ;
}
return TRUE ;
}
2005-06-10 21:32:24 +02:00
static BOOL launch_entry ( Entry * entry , HWND hwnd , UINT nCmdShow )
2003-08-13 03:18:37 +02:00
{
TCHAR cmd [ MAX_PATH ] ;
# ifdef _SHELL_FOLDERS
if ( entry - > etype = = ET_SHELL ) {
BOOL ret = TRUE ;
SHELLEXECUTEINFO shexinfo ;
shexinfo . cbSize = sizeof ( SHELLEXECUTEINFO ) ;
shexinfo . fMask = SEE_MASK_IDLIST ;
shexinfo . hwnd = hwnd ;
2003-12-12 05:11:25 +01:00
shexinfo . lpVerb = NULL ;
shexinfo . lpFile = NULL ;
shexinfo . lpParameters = NULL ;
shexinfo . lpDirectory = NULL ;
2003-08-13 03:18:37 +02:00
shexinfo . nShow = nCmdShow ;
shexinfo . lpIDList = get_to_absolute_pidl ( entry , hwnd ) ;
if ( ! ShellExecuteEx ( & shexinfo ) ) {
display_error ( hwnd , GetLastError ( ) ) ;
ret = FALSE ;
}
if ( shexinfo . lpIDList ! = entry - > pidl )
2005-09-07 15:28:25 +02:00
IMalloc_Free ( Globals . iMalloc , shexinfo . lpIDList ) ;
2003-08-13 03:18:37 +02:00
return ret ;
}
# endif
get_path ( entry , cmd ) ;
/* start program, open document... */
return launch_file ( hwnd , cmd , nCmdShow ) ;
2002-06-04 23:29:40 +02:00
}
2003-08-13 03:18:37 +02:00
static void activate_entry ( ChildWnd * child , Pane * pane , HWND hwnd )
2002-06-04 23:29:40 +02:00
{
Entry * entry = pane - > cur ;
if ( ! entry )
return ;
if ( entry - > data . dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
int scanned_old = entry - > scanned ;
if ( ! scanned_old )
2006-03-17 16:57:16 +01:00
{
int idx = SendMessage ( child - > left . hwnd , LB_GETCURSEL , 0 , 0 ) ;
scan_entry ( child , entry , idx , hwnd ) ;
}
2002-06-04 23:29:40 +02:00
# ifndef _NO_EXTENSIONS
if ( entry - > data . cFileName [ 0 ] = = ' . ' & & entry - > data . cFileName [ 1 ] = = ' \0 ' )
return ;
# endif
if ( entry - > data . cFileName [ 0 ] = = ' . ' & & entry - > data . cFileName [ 1 ] = = ' . ' & & entry - > data . cFileName [ 2 ] = = ' \0 ' ) {
entry = child - > left . cur - > up ;
collapse_entry ( & child - > left , entry ) ;
goto focus_entry ;
} else if ( entry - > expanded )
collapse_entry ( pane , child - > left . cur ) ;
else {
expand_entry ( child , child - > left . cur ) ;
if ( ! pane - > treePane ) focus_entry : {
2006-03-17 16:57:16 +01:00
int idxstart = SendMessage ( child - > left . hwnd , LB_GETCURSEL , 0 , 0 ) ;
int idx = SendMessage ( child - > left . hwnd , LB_FINDSTRING , idxstart , ( LPARAM ) entry ) ;
SendMessage ( child - > left . hwnd , LB_SETCURSEL , idx , 0 ) ;
2005-05-16 10:48:54 +02:00
set_curdir ( child , entry , idx , hwnd ) ;
2002-06-04 23:29:40 +02:00
}
}
if ( ! scanned_old ) {
calc_widths ( pane , FALSE ) ;
# ifndef _NO_EXTENSIONS
set_header ( pane ) ;
# endif
}
} else {
2005-06-06 12:02:43 +02:00
if ( GetKeyState ( VK_MENU ) < 0 )
show_properties_dlg ( entry , child - > hwnd ) ;
else
launch_entry ( entry , child - > hwnd , SW_SHOWNORMAL ) ;
2002-06-04 23:29:40 +02:00
}
}
static BOOL pane_command ( Pane * pane , UINT cmd )
{
switch ( cmd ) {
case ID_VIEW_NAME :
if ( pane - > visible_cols ) {
pane - > visible_cols = 0 ;
calc_widths ( pane , TRUE ) ;
# ifndef _NO_EXTENSIONS
set_header ( pane ) ;
# endif
InvalidateRect ( pane - > hwnd , 0 , TRUE ) ;
CheckMenuItem ( Globals . hMenuView , ID_VIEW_NAME , MF_BYCOMMAND | MF_CHECKED ) ;
CheckMenuItem ( Globals . hMenuView , ID_VIEW_ALL_ATTRIBUTES , MF_BYCOMMAND ) ;
CheckMenuItem ( Globals . hMenuView , ID_VIEW_SELECTED_ATTRIBUTES , MF_BYCOMMAND ) ;
}
break ;
case ID_VIEW_ALL_ATTRIBUTES :
if ( pane - > visible_cols ! = COL_ALL ) {
pane - > visible_cols = COL_ALL ;
calc_widths ( pane , TRUE ) ;
# ifndef _NO_EXTENSIONS
set_header ( pane ) ;
# endif
InvalidateRect ( pane - > hwnd , 0 , TRUE ) ;
CheckMenuItem ( Globals . hMenuView , ID_VIEW_NAME , MF_BYCOMMAND ) ;
CheckMenuItem ( Globals . hMenuView , ID_VIEW_ALL_ATTRIBUTES , MF_BYCOMMAND | MF_CHECKED ) ;
CheckMenuItem ( Globals . hMenuView , ID_VIEW_SELECTED_ATTRIBUTES , MF_BYCOMMAND ) ;
}
break ;
# ifndef _NO_EXTENSIONS
2005-05-14 20:50:30 +02:00
case ID_PREFERRED_SIZES : {
2002-06-04 23:29:40 +02:00
calc_widths ( pane , TRUE ) ;
set_header ( pane ) ;
InvalidateRect ( pane - > hwnd , 0 , TRUE ) ;
break ; }
# endif
2002-06-28 19:37:34 +02:00
/* TODO: more command ids... */
2002-06-04 23:29:40 +02:00
default :
return FALSE ;
}
return TRUE ;
}
2005-05-16 10:48:54 +02:00
static void set_sort_order ( ChildWnd * child , SORT_ORDER sortOrder )
{
if ( child - > sortOrder ! = sortOrder ) {
child - > sortOrder = sortOrder ;
refresh_child ( child ) ;
}
}
static void update_view_menu ( ChildWnd * child )
{
CheckMenuItem ( Globals . hMenuView , ID_VIEW_SORT_NAME , child - > sortOrder = = SORT_NAME ? MF_CHECKED : MF_UNCHECKED ) ;
CheckMenuItem ( Globals . hMenuView , ID_VIEW_SORT_TYPE , child - > sortOrder = = SORT_EXT ? MF_CHECKED : MF_UNCHECKED ) ;
CheckMenuItem ( Globals . hMenuView , ID_VIEW_SORT_SIZE , child - > sortOrder = = SORT_SIZE ? MF_CHECKED : MF_UNCHECKED ) ;
CheckMenuItem ( Globals . hMenuView , ID_VIEW_SORT_DATE , child - > sortOrder = = SORT_DATE ? MF_CHECKED : MF_UNCHECKED ) ;
}
2005-05-30 11:55:19 +02:00
static BOOL is_directory ( LPCTSTR target )
{
/*TODO correctly handle UNIX paths */
DWORD target_attr = GetFileAttributes ( target ) ;
if ( target_attr = = INVALID_FILE_ATTRIBUTES )
return FALSE ;
return target_attr & FILE_ATTRIBUTE_DIRECTORY ? TRUE : FALSE ;
}
static BOOL prompt_target ( Pane * pane , LPTSTR source , LPTSTR target )
{
TCHAR path [ MAX_PATH ] ;
int len ;
get_path ( pane - > cur , path ) ;
if ( DialogBoxParam ( Globals . hInstance , MAKEINTRESOURCE ( IDD_SELECT_DESTINATION ) , pane - > hwnd , DestinationDlgProc , ( LPARAM ) path ) ! = IDOK )
return FALSE ;
get_path ( pane - > cur , source ) ;
/* convert relative targets to absolute paths */
if ( path [ 0 ] ! = ' / ' & & path [ 1 ] ! = ' : ' ) {
get_path ( pane - > cur - > up , target ) ;
len = lstrlen ( target ) ;
if ( target [ len - 1 ] ! = ' \\ ' & & target [ len - 1 ] ! = ' / ' )
target [ len + + ] = ' / ' ;
lstrcpy ( target + len , path ) ;
} else
lstrcpy ( target , path ) ;
/* If the target already exists as directory, create a new target below this. */
if ( is_directory ( path ) ) {
TCHAR fname [ _MAX_FNAME ] , ext [ _MAX_EXT ] ;
2005-10-06 13:38:45 +02:00
static const TCHAR sAppend [ ] = { ' % ' , ' s ' , ' / ' , ' % ' , ' s ' , ' % ' , ' s ' , ' \0 ' } ;
2005-05-30 11:55:19 +02:00
_tsplitpath ( source , NULL , NULL , fname , ext ) ;
wsprintf ( target , sAppend , path , fname , ext ) ;
}
return TRUE ;
}
2005-05-04 11:47:07 +02:00
static IContextMenu2 * s_pctxmenu2 = NULL ;
static IContextMenu3 * s_pctxmenu3 = NULL ;
2005-06-17 12:11:37 +02:00
static void CtxMenu_reset ( void )
2005-05-04 11:47:07 +02:00
{
s_pctxmenu2 = NULL ;
s_pctxmenu3 = NULL ;
}
2005-06-10 21:32:24 +02:00
static IContextMenu * CtxMenu_query_interfaces ( IContextMenu * pcm1 )
2005-05-04 11:47:07 +02:00
{
IContextMenu * pcm = NULL ;
CtxMenu_reset ( ) ;
2005-09-07 15:28:25 +02:00
if ( IContextMenu_QueryInterface ( pcm1 , & IID_IContextMenu3 , ( void * * ) & pcm ) = = NOERROR )
2005-05-04 11:47:07 +02:00
s_pctxmenu3 = ( LPCONTEXTMENU3 ) pcm ;
2005-09-07 15:28:25 +02:00
else if ( IContextMenu_QueryInterface ( pcm1 , & IID_IContextMenu2 , ( void * * ) & pcm ) = = NOERROR )
2005-05-04 11:47:07 +02:00
s_pctxmenu2 = ( LPCONTEXTMENU2 ) pcm ;
if ( pcm ) {
2005-09-07 15:28:25 +02:00
IContextMenu_Release ( pcm1 ) ;
2005-05-04 11:47:07 +02:00
return pcm ;
} else
return pcm1 ;
}
static BOOL CtxMenu_HandleMenuMsg ( UINT nmsg , WPARAM wparam , LPARAM lparam )
{
if ( s_pctxmenu3 ) {
2005-09-07 15:28:25 +02:00
if ( SUCCEEDED ( IContextMenu3_HandleMenuMsg ( s_pctxmenu3 , nmsg , wparam , lparam ) ) )
2005-05-04 11:47:07 +02:00
return TRUE ;
}
if ( s_pctxmenu2 )
2005-09-07 15:28:25 +02:00
if ( SUCCEEDED ( IContextMenu2_HandleMenuMsg ( s_pctxmenu2 , nmsg , wparam , lparam ) ) )
2005-05-04 11:47:07 +02:00
return TRUE ;
return FALSE ;
}
2004-02-11 05:18:12 +01:00
static HRESULT ShellFolderContextMenu ( IShellFolder * shell_folder , HWND hwndParent , int cidl , LPCITEMIDLIST * apidl , int x , int y )
{
IContextMenu * pcm ;
2005-06-05 21:18:11 +02:00
BOOL executed = FALSE ;
2004-02-11 05:18:12 +01:00
2005-09-07 15:28:25 +02:00
HRESULT hr = IShellFolder_GetUIObjectOf ( shell_folder , hwndParent , cidl , apidl , & IID_IContextMenu , NULL , ( LPVOID * ) & pcm ) ;
2004-02-11 05:18:12 +01:00
/* HRESULT hr = CDefFolderMenu_Create2(dir?dir->_pidl:DesktopFolder(), hwndParent, 1, &pidl, shell_folder, NULL, 0, NULL, &pcm); */
if ( SUCCEEDED ( hr ) ) {
HMENU hmenu = CreatePopupMenu ( ) ;
2005-05-04 11:47:07 +02:00
pcm = CtxMenu_query_interfaces ( pcm ) ;
2004-02-11 05:18:12 +01:00
if ( hmenu ) {
2005-09-07 15:28:25 +02:00
hr = IContextMenu_QueryContextMenu ( pcm , hmenu , 0 , FCIDM_SHVIEWFIRST , FCIDM_SHVIEWLAST , CMF_NORMAL ) ;
2004-02-11 05:18:12 +01:00
if ( SUCCEEDED ( hr ) ) {
UINT idCmd = TrackPopupMenu ( hmenu , TPM_LEFTALIGN | TPM_RETURNCMD | TPM_RIGHTBUTTON , x , y , 0 , hwndParent , NULL ) ;
2005-05-04 11:47:07 +02:00
CtxMenu_reset ( ) ;
2004-02-11 05:18:12 +01:00
if ( idCmd ) {
CMINVOKECOMMANDINFO cmi ;
cmi . cbSize = sizeof ( CMINVOKECOMMANDINFO ) ;
cmi . fMask = 0 ;
cmi . hwnd = hwndParent ;
cmi . lpVerb = ( LPCSTR ) ( INT_PTR ) ( idCmd - FCIDM_SHVIEWFIRST ) ;
cmi . lpParameters = NULL ;
cmi . lpDirectory = NULL ;
cmi . nShow = SW_SHOWNORMAL ;
cmi . dwHotKey = 0 ;
cmi . hIcon = 0 ;
2005-09-07 15:28:25 +02:00
hr = IContextMenu_InvokeCommand ( pcm , & cmi ) ;
2005-06-05 21:18:11 +02:00
executed = TRUE ;
2004-02-11 05:18:12 +01:00
}
2005-06-13 12:04:55 +02:00
} else
CtxMenu_reset ( ) ;
2004-02-11 05:18:12 +01:00
}
2005-09-07 15:28:25 +02:00
IContextMenu_Release ( pcm ) ;
2004-02-11 05:18:12 +01:00
}
2005-06-05 21:18:11 +02:00
return FAILED ( hr ) ? hr : executed ? S_OK : S_FALSE ;
2004-02-11 05:18:12 +01:00
}
2005-06-10 21:32:24 +02:00
static LRESULT CALLBACK ChildWndProc ( HWND hwnd , UINT nmsg , WPARAM wparam , LPARAM lparam )
2002-06-04 23:29:40 +02:00
{
2005-09-09 17:20:04 +02:00
ChildWnd * child = ( ChildWnd * ) GetWindowLongPtr ( hwnd , GWLP_USERDATA ) ;
2002-06-04 23:29:40 +02:00
ASSERT ( child ) ;
switch ( nmsg ) {
case WM_DRAWITEM : {
LPDRAWITEMSTRUCT dis = ( LPDRAWITEMSTRUCT ) lparam ;
Entry * entry = ( Entry * ) dis - > itemData ;
if ( dis - > CtlID = = IDW_TREE_LEFT )
draw_item ( & child - > left , dis , entry , - 1 ) ;
2005-05-04 11:47:07 +02:00
else if ( dis - > CtlID = = IDW_TREE_RIGHT )
2002-06-04 23:29:40 +02:00
draw_item ( & child - > right , dis , entry , - 1 ) ;
2005-05-04 11:47:07 +02:00
else
goto draw_menu_item ;
2002-06-04 23:29:40 +02:00
return TRUE ; }
case WM_CREATE :
InitChildWindow ( child ) ;
break ;
case WM_NCDESTROY :
free_child_window ( child ) ;
2005-09-09 17:20:04 +02:00
SetWindowLongPtr ( hwnd , GWLP_USERDATA , 0 ) ;
2002-06-04 23:29:40 +02:00
break ;
case WM_PAINT : {
PAINTSTRUCT ps ;
HBRUSH lastBrush ;
RECT rt ;
GetClientRect ( hwnd , & rt ) ;
BeginPaint ( hwnd , & ps ) ;
rt . left = child - > split_pos - SPLIT_WIDTH / 2 ;
rt . right = child - > split_pos + SPLIT_WIDTH / 2 + 1 ;
2006-03-17 16:57:16 +01:00
lastBrush = SelectObject ( ps . hdc , GetStockObject ( COLOR_SPLITBAR ) ) ;
2002-06-04 23:29:40 +02:00
Rectangle ( ps . hdc , rt . left , rt . top - 1 , rt . right , rt . bottom + 1 ) ;
SelectObject ( ps . hdc , lastBrush ) ;
# ifdef _NO_EXTENSIONS
rt . top = rt . bottom - GetSystemMetrics ( SM_CYHSCROLL ) ;
FillRect ( ps . hdc , & rt , GetStockObject ( BLACK_BRUSH ) ) ;
# endif
EndPaint ( hwnd , & ps ) ;
break ; }
case WM_SETCURSOR :
if ( LOWORD ( lparam ) = = HTCLIENT ) {
POINT pt ;
GetCursorPos ( & pt ) ;
ScreenToClient ( hwnd , & pt ) ;
if ( pt . x > = child - > split_pos - SPLIT_WIDTH / 2 & & pt . x < child - > split_pos + SPLIT_WIDTH / 2 + 1 ) {
SetCursor ( LoadCursor ( 0 , IDC_SIZEWE ) ) ;
return TRUE ;
}
}
goto def ;
case WM_LBUTTONDOWN : {
RECT rt ;
2006-10-25 17:43:09 +02:00
int x = ( short ) LOWORD ( lparam ) ;
2002-06-04 23:29:40 +02:00
GetClientRect ( hwnd , & rt ) ;
if ( x > = child - > split_pos - SPLIT_WIDTH / 2 & & x < child - > split_pos + SPLIT_WIDTH / 2 + 1 ) {
last_split = child - > split_pos ;
# ifdef _NO_EXTENSIONS
draw_splitbar ( hwnd , last_split ) ;
# endif
SetCapture ( hwnd ) ;
}
break ; }
case WM_LBUTTONUP :
if ( GetCapture ( ) = = hwnd ) {
# ifdef _NO_EXTENSIONS
RECT rt ;
2006-10-25 17:43:09 +02:00
int x = ( short ) LOWORD ( lparam ) ;
2002-06-04 23:29:40 +02:00
draw_splitbar ( hwnd , last_split ) ;
last_split = - 1 ;
GetClientRect ( hwnd , & rt ) ;
child - > split_pos = x ;
resize_tree ( child , rt . right , rt . bottom ) ;
# endif
ReleaseCapture ( ) ;
}
break ;
# ifdef _NO_EXTENSIONS
case WM_CAPTURECHANGED :
if ( GetCapture ( ) = = hwnd & & last_split > = 0 )
draw_splitbar ( hwnd , last_split ) ;
break ;
# endif
case WM_KEYDOWN :
if ( wparam = = VK_ESCAPE )
if ( GetCapture ( ) = = hwnd ) {
RECT rt ;
# ifdef _NO_EXTENSIONS
draw_splitbar ( hwnd , last_split ) ;
# else
child - > split_pos = last_split ;
# endif
GetClientRect ( hwnd , & rt ) ;
resize_tree ( child , rt . right , rt . bottom ) ;
last_split = - 1 ;
ReleaseCapture ( ) ;
SetCursor ( LoadCursor ( 0 , IDC_ARROW ) ) ;
}
break ;
case WM_MOUSEMOVE :
if ( GetCapture ( ) = = hwnd ) {
RECT rt ;
2006-10-25 17:43:09 +02:00
int x = ( short ) LOWORD ( lparam ) ;
2002-06-04 23:29:40 +02:00
# ifdef _NO_EXTENSIONS
HDC hdc = GetDC ( hwnd ) ;
GetClientRect ( hwnd , & rt ) ;
rt . left = last_split - SPLIT_WIDTH / 2 ;
rt . right = last_split + SPLIT_WIDTH / 2 + 1 ;
InvertRect ( hdc , & rt ) ;
last_split = x ;
rt . left = x - SPLIT_WIDTH / 2 ;
rt . right = x + SPLIT_WIDTH / 2 + 1 ;
InvertRect ( hdc , & rt ) ;
ReleaseDC ( hwnd , hdc ) ;
# else
GetClientRect ( hwnd , & rt ) ;
if ( x > = 0 & & x < rt . right ) {
child - > split_pos = x ;
resize_tree ( child , rt . right , rt . bottom ) ;
rt . left = x - SPLIT_WIDTH / 2 ;
rt . right = x + SPLIT_WIDTH / 2 + 1 ;
InvalidateRect ( hwnd , & rt , FALSE ) ;
UpdateWindow ( child - > left . hwnd ) ;
UpdateWindow ( hwnd ) ;
UpdateWindow ( child - > right . hwnd ) ;
}
# endif
}
break ;
# ifndef _NO_EXTENSIONS
case WM_GETMINMAXINFO :
DefMDIChildProc ( hwnd , nmsg , wparam , lparam ) ;
{ LPMINMAXINFO lpmmi = ( LPMINMAXINFO ) lparam ;
2002-06-28 19:37:34 +02:00
lpmmi - > ptMaxTrackSize . x < < = 1 ; /*2*GetSystemMetrics(SM_CXSCREEN) / SM_CXVIRTUALSCREEN */
lpmmi - > ptMaxTrackSize . y < < = 1 ; /*2*GetSystemMetrics(SM_CYSCREEN) / SM_CYVIRTUALSCREEN */
2002-06-04 23:29:40 +02:00
break ; }
2003-08-13 03:18:37 +02:00
# endif /* _NO_EXTENSIONS */
2002-06-04 23:29:40 +02:00
case WM_SETFOCUS :
2005-05-14 13:07:39 +02:00
if ( SetCurrentDirectory ( child - > path ) )
set_space_status ( ) ;
2002-06-04 23:29:40 +02:00
SetFocus ( child - > focus_pane ? child - > right . hwnd : child - > left . hwnd ) ;
break ;
case WM_DISPATCH_COMMAND : {
Pane * pane = GetFocus ( ) = = child - > left . hwnd ? & child - > left : & child - > right ;
switch ( LOWORD ( wparam ) ) {
case ID_WINDOW_NEW : {
2003-08-13 03:18:37 +02:00
ChildWnd * new_child = alloc_child_window ( child - > path , NULL , hwnd ) ;
2002-06-04 23:29:40 +02:00
if ( ! create_child_window ( new_child ) )
2007-07-23 22:25:20 +02:00
HeapFree ( GetProcessHeap ( ) , 0 , new_child ) ;
2002-06-04 23:29:40 +02:00
break ; }
case ID_REFRESH :
2005-05-16 23:36:41 +02:00
refresh_drives ( ) ;
2005-05-16 10:48:54 +02:00
refresh_child ( child ) ;
2002-06-04 23:29:40 +02:00
break ;
case ID_ACTIVATE :
2003-08-13 03:18:37 +02:00
activate_entry ( child , pane , hwnd ) ;
2002-06-04 23:29:40 +02:00
break ;
2004-09-27 22:35:53 +02:00
case ID_FILE_MOVE : {
2005-05-30 11:55:19 +02:00
TCHAR source [ BUFFER_LEN ] , target [ BUFFER_LEN ] ;
2004-10-07 06:25:29 +02:00
2005-05-30 11:55:19 +02:00
if ( prompt_target ( pane , source , target ) ) {
SHFILEOPSTRUCT shfo = { hwnd , FO_MOVE , source , target } ;
2005-05-13 19:46:11 +02:00
2005-05-30 11:55:19 +02:00
source [ lstrlen ( source ) + 1 ] = ' \0 ' ;
target [ lstrlen ( target ) + 1 ] = ' \0 ' ;
2004-10-07 06:25:29 +02:00
2005-05-30 11:55:19 +02:00
if ( ! SHFileOperation ( & shfo ) )
refresh_child ( child ) ;
}
break ; }
2004-10-07 06:25:29 +02:00
2005-05-30 11:55:19 +02:00
case ID_FILE_COPY : {
TCHAR source [ BUFFER_LEN ] , target [ BUFFER_LEN ] ;
2004-10-07 06:25:29 +02:00
2005-05-30 11:55:19 +02:00
if ( prompt_target ( pane , source , target ) ) {
SHFILEOPSTRUCT shfo = { hwnd , FO_COPY , source , target } ;
2004-10-07 06:25:29 +02:00
2005-05-30 11:55:19 +02:00
source [ lstrlen ( source ) + 1 ] = ' \0 ' ;
target [ lstrlen ( target ) + 1 ] = ' \0 ' ;
2004-10-07 06:25:29 +02:00
2005-05-30 11:55:19 +02:00
if ( ! SHFileOperation ( & shfo ) )
2005-05-16 10:48:54 +02:00
refresh_child ( child ) ;
2004-09-27 22:35:53 +02:00
}
2005-05-30 11:55:19 +02:00
break ; }
case ID_FILE_DELETE : {
TCHAR path [ BUFFER_LEN ] ;
SHFILEOPSTRUCT shfo = { hwnd , FO_DELETE , path } ;
get_path ( pane - > cur , path ) ;
path [ lstrlen ( path ) + 1 ] = ' \0 ' ;
if ( ! SHFileOperation ( & shfo ) )
refresh_child ( child ) ;
2004-09-27 22:35:53 +02:00
break ; }
2005-05-16 10:48:54 +02:00
case ID_VIEW_SORT_NAME :
set_sort_order ( child , SORT_NAME ) ;
break ;
case ID_VIEW_SORT_TYPE :
set_sort_order ( child , SORT_EXT ) ;
break ;
case ID_VIEW_SORT_SIZE :
set_sort_order ( child , SORT_SIZE ) ;
break ;
case ID_VIEW_SORT_DATE :
set_sort_order ( child , SORT_DATE ) ;
break ;
2005-05-29 22:05:29 +02:00
case ID_VIEW_FILTER : {
struct FilterDialog dlg ;
memset ( & dlg , 0 , sizeof ( struct FilterDialog ) ) ;
2005-07-07 14:00:17 +02:00
lstrcpy ( dlg . pattern , child - > filter_pattern ) ;
2005-05-29 22:05:29 +02:00
dlg . flags = child - > filter_flags ;
if ( DialogBoxParam ( Globals . hInstance , MAKEINTRESOURCE ( IDD_DIALOG_VIEW_TYPE ) , hwnd , FilterDialogDlgProc , ( LPARAM ) & dlg ) = = IDOK ) {
2005-07-07 14:00:17 +02:00
lstrcpy ( child - > filter_pattern , dlg . pattern ) ;
2005-05-29 22:05:29 +02:00
child - > filter_flags = dlg . flags ;
refresh_right_pane ( child ) ;
}
break ; }
2005-05-23 11:52:51 +02:00
case ID_VIEW_SPLIT : {
last_split = child - > split_pos ;
# ifdef _NO_EXTENSIONS
draw_splitbar ( hwnd , last_split ) ;
# endif
SetCapture ( hwnd ) ;
break ; }
2005-06-06 12:02:43 +02:00
case ID_EDIT_PROPERTIES :
show_properties_dlg ( pane - > cur , child - > hwnd ) ;
break ;
2002-06-04 23:29:40 +02:00
default :
return pane_command ( pane , LOWORD ( wparam ) ) ;
}
return TRUE ; }
case WM_COMMAND : {
Pane * pane = GetFocus ( ) = = child - > left . hwnd ? & child - > left : & child - > right ;
switch ( HIWORD ( wparam ) ) {
case LBN_SELCHANGE : {
2006-03-17 16:57:16 +01:00
int idx = SendMessage ( pane - > hwnd , LB_GETCURSEL , 0 , 0 ) ;
Entry * entry = ( Entry * ) SendMessage ( pane - > hwnd , LB_GETITEMDATA , idx , 0 ) ;
2002-06-04 23:29:40 +02:00
if ( pane = = & child - > left )
2005-05-16 10:48:54 +02:00
set_curdir ( child , entry , idx , hwnd ) ;
2002-06-04 23:29:40 +02:00
else
pane - > cur = entry ;
break ; }
case LBN_DBLCLK :
2003-08-13 03:18:37 +02:00
activate_entry ( child , pane , hwnd ) ;
2002-06-04 23:29:40 +02:00
break ;
}
break ; }
# ifndef _NO_EXTENSIONS
case WM_NOTIFY : {
NMHDR * pnmh = ( NMHDR * ) lparam ;
return pane_notify ( pnmh - > idFrom = = IDW_HEADER_LEFT ? & child - > left : & child - > right , pnmh ) ; }
# endif
2004-02-11 05:18:12 +01:00
# ifdef _SHELL_FOLDERS
case WM_CONTEXTMENU : {
2005-05-19 16:22:51 +02:00
POINT pt , pt_clnt ;
2004-02-11 05:18:12 +01:00
Pane * pane ;
int idx ;
/* first select the current item in the listbox */
HWND hpanel = ( HWND ) wparam ;
2005-05-19 16:22:51 +02:00
pt_clnt . x = pt . x = ( short ) LOWORD ( lparam ) ;
pt_clnt . y = pt . y = ( short ) HIWORD ( lparam ) ;
ScreenToClient ( hpanel , & pt_clnt ) ;
SendMessage ( hpanel , WM_LBUTTONDOWN , 0 , MAKELONG ( pt_clnt . x , pt_clnt . y ) ) ;
SendMessage ( hpanel , WM_LBUTTONUP , 0 , MAKELONG ( pt_clnt . x , pt_clnt . y ) ) ;
2004-02-11 05:18:12 +01:00
/* now create the popup menu using shell namespace and IContextMenu */
pane = GetFocus ( ) = = child - > left . hwnd ? & child - > left : & child - > right ;
2006-03-17 16:57:16 +01:00
idx = SendMessage ( pane - > hwnd , LB_GETCURSEL , 0 , 0 ) ;
2004-02-11 05:18:12 +01:00
if ( idx ! = - 1 ) {
2006-03-17 16:57:16 +01:00
Entry * entry = ( Entry * ) SendMessage ( pane - > hwnd , LB_GETITEMDATA , idx , 0 ) ;
2004-02-11 05:18:12 +01:00
LPITEMIDLIST pidl_abs = get_to_absolute_pidl ( entry , hwnd ) ;
if ( pidl_abs ) {
IShellFolder * parentFolder ;
LPCITEMIDLIST pidlLast ;
/* get and use the parent folder to display correct context menu in all cases */
if ( SUCCEEDED ( SHBindToParent ( pidl_abs , & IID_IShellFolder , ( LPVOID * ) & parentFolder , & pidlLast ) ) ) {
2005-06-05 21:18:11 +02:00
if ( ShellFolderContextMenu ( parentFolder , hwnd , 1 , & pidlLast , pt . x , pt . y ) = = S_OK )
2005-05-29 22:17:05 +02:00
refresh_child ( child ) ;
2004-02-11 05:18:12 +01:00
2005-09-07 15:28:25 +02:00
IShellFolder_Release ( parentFolder ) ;
2004-02-11 05:18:12 +01:00
}
2005-09-07 15:28:25 +02:00
IMalloc_Free ( Globals . iMalloc , pidl_abs ) ;
2004-02-11 05:18:12 +01:00
}
}
break ; }
# endif
2005-05-04 11:47:07 +02:00
case WM_MEASUREITEM :
draw_menu_item :
if ( ! wparam ) /* Is the message menu-related? */
if ( CtxMenu_HandleMenuMsg ( nmsg , wparam , lparam ) )
return TRUE ;
break ;
case WM_INITMENUPOPUP :
if ( CtxMenu_HandleMenuMsg ( nmsg , wparam , lparam ) )
return 0 ;
2005-05-16 10:48:54 +02:00
update_view_menu ( child ) ;
2005-05-04 11:47:07 +02:00
break ;
case WM_MENUCHAR : /* only supported by IContextMenu3 */
if ( s_pctxmenu3 ) {
LRESULT lResult = 0 ;
2005-09-07 15:28:25 +02:00
IContextMenu3_HandleMenuMsg2 ( s_pctxmenu3 , nmsg , wparam , lparam , & lResult ) ;
2005-05-04 11:47:07 +02:00
return lResult ;
}
break ;
2002-06-04 23:29:40 +02:00
case WM_SIZE :
if ( wparam ! = SIZE_MINIMIZED )
resize_tree ( child , LOWORD ( lparam ) , HIWORD ( lparam ) ) ;
2002-06-28 19:37:34 +02:00
/* fall through */
2002-06-04 23:29:40 +02:00
default : def :
return DefMDIChildProc ( hwnd , nmsg , wparam , lparam ) ;
}
return 0 ;
}
2005-06-10 21:32:24 +02:00
static LRESULT CALLBACK TreeWndProc ( HWND hwnd , UINT nmsg , WPARAM wparam , LPARAM lparam )
2002-06-04 23:29:40 +02:00
{
2005-09-09 17:20:04 +02:00
ChildWnd * child = ( ChildWnd * ) GetWindowLongPtr ( GetParent ( hwnd ) , GWLP_USERDATA ) ;
Pane * pane = ( Pane * ) GetWindowLongPtr ( hwnd , GWLP_USERDATA ) ;
2002-06-04 23:29:40 +02:00
ASSERT ( child ) ;
switch ( nmsg ) {
# ifndef _NO_EXTENSIONS
case WM_HSCROLL :
set_header ( pane ) ;
break ;
# endif
case WM_SETFOCUS :
child - > focus_pane = pane = = & child - > right ? 1 : 0 ;
2006-03-17 16:57:16 +01:00
SendMessage ( hwnd , LB_SETSEL , TRUE , 1 ) ;
2002-06-28 19:37:34 +02:00
/*TODO: check menu items */
2002-06-04 23:29:40 +02:00
break ;
case WM_KEYDOWN :
if ( wparam = = VK_TAB ) {
2002-06-28 19:37:34 +02:00
/*TODO: SetFocus(Globals.hdrivebar) */
2002-06-04 23:29:40 +02:00
SetFocus ( child - > focus_pane ? child - > left . hwnd : child - > right . hwnd ) ;
}
}
return CallWindowProc ( g_orgTreeWndProc , hwnd , nmsg , wparam , lparam ) ;
}
static void InitInstance ( HINSTANCE hinstance )
{
2005-10-06 13:38:45 +02:00
static const TCHAR sFont [ ] = { ' M ' , ' i ' , ' c ' , ' r ' , ' o ' , ' s ' , ' o ' , ' f ' , ' t ' , ' ' , ' S ' , ' a ' , ' n ' , ' s ' , ' ' , ' S ' , ' e ' , ' r ' , ' i ' , ' f ' , ' \0 ' } ;
2004-11-22 19:24:09 +01:00
2002-07-03 23:06:58 +02:00
WNDCLASSEX wcFrame ;
WNDCLASS wcChild ;
2003-08-13 03:18:37 +02:00
ATOM hChildClass ;
2004-11-22 19:24:09 +01:00
int col ;
2002-06-04 23:29:40 +02:00
INITCOMMONCONTROLSEX icc = {
sizeof ( INITCOMMONCONTROLSEX ) ,
ICC_BAR_CLASSES
} ;
HDC hdc = GetDC ( 0 ) ;
2003-08-13 03:18:37 +02:00
setlocale ( LC_COLLATE , " " ) ; /* set collating rules to local settings for compareName */
InitCommonControlsEx ( & icc ) ;
/* register frame window class */
2002-07-03 23:06:58 +02:00
wcFrame . cbSize = sizeof ( WNDCLASSEX ) ;
wcFrame . style = 0 ;
wcFrame . lpfnWndProc = FrameWndProc ;
wcFrame . cbClsExtra = 0 ;
wcFrame . cbWndExtra = 0 ;
wcFrame . hInstance = hinstance ;
2003-08-13 03:18:37 +02:00
wcFrame . hIcon = LoadIcon ( hinstance , MAKEINTRESOURCE ( IDI_WINEFILE ) ) ;
2002-07-03 23:06:58 +02:00
wcFrame . hCursor = LoadCursor ( 0 , IDC_ARROW ) ;
wcFrame . hbrBackground = 0 ;
wcFrame . lpszMenuName = 0 ;
2004-11-22 19:24:09 +01:00
wcFrame . lpszClassName = sWINEFILEFRAME ;
2002-07-03 23:06:58 +02:00
wcFrame . hIconSm = ( HICON ) LoadImage ( hinstance ,
2003-08-13 03:18:37 +02:00
MAKEINTRESOURCE ( IDI_WINEFILE ) ,
IMAGE_ICON ,
GetSystemMetrics ( SM_CXSMICON ) ,
GetSystemMetrics ( SM_CYSMICON ) ,
LR_SHARED ) ;
2002-07-03 23:06:58 +02:00
2003-08-13 03:18:37 +02:00
Globals . hframeClass = RegisterClassEx ( & wcFrame ) ;
/* register tree windows class */
2002-07-03 23:06:58 +02:00
wcChild . style = CS_CLASSDC | CS_DBLCLKS | CS_VREDRAW ;
wcChild . lpfnWndProc = ChildWndProc ;
wcChild . cbClsExtra = 0 ;
wcChild . cbWndExtra = 0 ;
wcChild . hInstance = hinstance ;
wcChild . hIcon = 0 ;
wcChild . hCursor = LoadCursor ( 0 , IDC_ARROW ) ;
wcChild . hbrBackground = 0 ;
wcChild . lpszMenuName = 0 ;
2004-11-22 19:24:09 +01:00
wcChild . lpszClassName = sWINEFILETREE ;
2002-07-03 23:06:58 +02:00
hChildClass = RegisterClass ( & wcChild ) ;
2002-06-04 23:29:40 +02:00
Globals . haccel = LoadAccelerators ( hinstance , MAKEINTRESOURCE ( IDA_WINEFILE ) ) ;
2004-11-22 19:24:09 +01:00
Globals . hfont = CreateFont ( - MulDiv ( 8 , GetDeviceCaps ( hdc , LOGPIXELSY ) , 72 ) , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , sFont ) ;
2002-06-04 23:29:40 +02:00
ReleaseDC ( 0 , hdc ) ;
Globals . hInstance = hinstance ;
2003-08-13 03:18:37 +02:00
# ifdef _SHELL_FOLDERS
CoInitialize ( NULL ) ;
CoGetMalloc ( MEMCTX_TASK , & Globals . iMalloc ) ;
SHGetDesktopFolder ( & Globals . iDesktop ) ;
2004-11-22 19:24:09 +01:00
# ifdef __WINE__
Globals . cfStrFName = RegisterClipboardFormatA ( CFSTR_FILENAME ) ;
# else
2003-08-13 03:18:37 +02:00
Globals . cfStrFName = RegisterClipboardFormat ( CFSTR_FILENAME ) ;
# endif
2004-11-22 19:24:09 +01:00
# endif
/* load column strings */
2005-06-03 13:25:17 +02:00
col = 1 ;
2004-11-22 19:24:09 +01:00
load_string ( g_pos_names [ col + + ] , IDS_COL_NAME ) ;
load_string ( g_pos_names [ col + + ] , IDS_COL_SIZE ) ;
load_string ( g_pos_names [ col + + ] , IDS_COL_CDATE ) ;
# ifndef _NO_EXTENSIONS
load_string ( g_pos_names [ col + + ] , IDS_COL_ADATE ) ;
load_string ( g_pos_names [ col + + ] , IDS_COL_MDATE ) ;
load_string ( g_pos_names [ col + + ] , IDS_COL_IDX ) ;
load_string ( g_pos_names [ col + + ] , IDS_COL_LINKS ) ;
# endif
load_string ( g_pos_names [ col + + ] , IDS_COL_ATTR ) ;
# ifndef _NO_EXTENSIONS
load_string ( g_pos_names [ col + + ] , IDS_COL_SEC ) ;
# endif
2003-08-13 03:18:37 +02:00
}
2005-11-17 12:05:35 +01:00
static void show_frame ( HWND hwndParent , int cmdshow , LPCTSTR path )
2003-08-13 03:18:37 +02:00
{
2005-10-06 13:38:45 +02:00
static const TCHAR sMDICLIENT [ ] = { ' M ' , ' D ' , ' I ' , ' C ' , ' L ' , ' I ' , ' E ' , ' N ' , ' T ' , ' \0 ' } ;
2004-11-22 19:24:09 +01:00
2005-11-17 12:05:35 +01:00
TCHAR buffer [ MAX_PATH ] , b1 [ BUFFER_LEN ] ;
2003-08-13 03:18:37 +02:00
ChildWnd * child ;
HMENU hMenuFrame , hMenuWindow ;
2006-02-20 18:57:01 +01:00
windowOptions opts ;
2003-08-13 03:18:37 +02:00
CLIENTCREATESTRUCT ccs ;
if ( Globals . hMainWnd )
return ;
2006-02-20 18:57:01 +01:00
opts = load_registry_settings ( ) ;
2003-08-13 03:18:37 +02:00
hMenuFrame = LoadMenu ( Globals . hInstance , MAKEINTRESOURCE ( IDM_WINEFILE ) ) ;
hMenuWindow = GetSubMenu ( hMenuFrame , GetMenuItemCount ( hMenuFrame ) - 2 ) ;
Globals . hMenuFrame = hMenuFrame ;
Globals . hMenuView = GetSubMenu ( hMenuFrame , 3 ) ;
Globals . hMenuOptions = GetSubMenu ( hMenuFrame , 4 ) ;
ccs . hWindowMenu = hMenuWindow ;
ccs . idFirstChild = IDW_FIRST_CHILD ;
2002-06-28 19:37:34 +02:00
/* create main window */
2004-10-22 21:52:50 +02:00
Globals . hMainWnd = CreateWindowEx ( 0 , ( LPCTSTR ) ( int ) Globals . hframeClass , RS ( b1 , IDS_WINE_FILE ) , WS_OVERLAPPEDWINDOW ,
2006-02-20 18:57:01 +01:00
opts . start_x , opts . start_y , opts . width , opts . height ,
2003-08-13 03:18:37 +02:00
hwndParent , Globals . hMenuFrame , Globals . hInstance , 0 /*lpParam*/ ) ;
2002-06-04 23:29:40 +02:00
2004-11-22 19:24:09 +01:00
Globals . hmdiclient = CreateWindowEx ( 0 , sMDICLIENT , NULL ,
2002-06-04 23:29:40 +02:00
WS_CHILD | WS_CLIPCHILDREN | WS_VSCROLL | WS_HSCROLL | WS_VISIBLE | WS_BORDER ,
0 , 0 , 0 , 0 ,
2003-08-13 03:18:37 +02:00
Globals . hMainWnd , 0 , Globals . hInstance , & ccs ) ;
2006-02-20 18:57:01 +01:00
2005-05-16 23:36:41 +02:00
CheckMenuItem ( Globals . hMenuOptions , ID_VIEW_DRIVE_BAR , MF_BYCOMMAND | MF_CHECKED ) ;
2006-02-20 18:57:01 +01:00
CheckMenuItem ( Globals . hMenuOptions , ID_VIEW_SAVESETTINGS , MF_BYCOMMAND ) ;
2002-06-04 23:29:40 +02:00
2005-05-16 23:36:41 +02:00
create_drive_bar ( ) ;
2002-06-04 23:29:40 +02:00
{
TBBUTTON toolbarBtns [ ] = {
2004-02-09 22:01:10 +01:00
{ 0 , 0 , 0 , BTNS_SEP , { 0 , 0 } , 0 , 0 } ,
{ 0 , ID_WINDOW_NEW , TBSTATE_ENABLED , BTNS_BUTTON , { 0 , 0 } , 0 , 0 } ,
{ 1 , ID_WINDOW_CASCADE , TBSTATE_ENABLED , BTNS_BUTTON , { 0 , 0 } , 0 , 0 } ,
{ 2 , ID_WINDOW_TILE_HORZ , TBSTATE_ENABLED , BTNS_BUTTON , { 0 , 0 } , 0 , 0 } ,
{ 3 , ID_WINDOW_TILE_VERT , TBSTATE_ENABLED , BTNS_BUTTON , { 0 , 0 } , 0 , 0 } ,
2003-08-13 03:18:37 +02:00
/*TODO
2005-05-14 20:50:30 +02:00
{ 4 , ID_ . . . , TBSTATE_ENABLED , BTNS_BUTTON , { 0 , 0 } , 0 , 0 } ,
{ 5 , ID_ . . . , TBSTATE_ENABLED , BTNS_BUTTON , { 0 , 0 } , 0 , 0 } ,
2003-08-13 03:18:37 +02:00
*/ } ;
2002-06-04 23:29:40 +02:00
Globals . htoolbar = CreateToolbarEx ( Globals . hMainWnd , WS_CHILD | WS_VISIBLE ,
IDW_TOOLBAR , 2 , Globals . hInstance , IDB_TOOLBAR , toolbarBtns ,
sizeof ( toolbarBtns ) / sizeof ( TBBUTTON ) , 16 , 15 , 16 , 15 , sizeof ( TBBUTTON ) ) ;
CheckMenuItem ( Globals . hMenuOptions , ID_VIEW_TOOL_BAR , MF_BYCOMMAND | MF_CHECKED ) ;
}
Globals . hstatusbar = CreateStatusWindow ( WS_CHILD | WS_VISIBLE , 0 , Globals . hMainWnd , IDW_STATUSBAR ) ;
CheckMenuItem ( Globals . hMenuOptions , ID_VIEW_STATUSBAR , MF_BYCOMMAND | MF_CHECKED ) ;
/* CreateStatusWindow does not accept WS_BORDER
Globals . hstatusbar = CreateWindowEx ( WS_EX_NOPARENTNOTIFY , STATUSCLASSNAME , 0 ,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_BORDER | CCS_NODIVIDER , 0 , 0 , 0 , 0 ,
Globals . hMainWnd , ( HMENU ) IDW_STATUSBAR , hinstance , 0 ) ; */
2006-02-20 18:57:01 +01:00
/*TODO: read paths from registry */
2005-11-17 12:05:35 +01:00
if ( ! path | | ! * path ) {
GetCurrentDirectory ( MAX_PATH , buffer ) ;
path = buffer ;
}
2003-08-13 03:18:37 +02:00
ShowWindow ( Globals . hMainWnd , cmdshow ) ;
2003-08-13 21:38:22 +02:00
# if defined(_SHELL_FOLDERS) && !defined(__WINE__)
2003-08-13 03:18:37 +02:00
/* Shell Namespace as default: */
child = alloc_child_window ( path , get_path_pidl ( path , Globals . hMainWnd ) , Globals . hMainWnd ) ;
# else
child = alloc_child_window ( path , NULL , Globals . hMainWnd ) ;
# endif
2002-06-04 23:29:40 +02:00
child - > pos . showCmd = SW_SHOWMAXIMIZED ;
child - > pos . rcNormalPosition . left = 0 ;
child - > pos . rcNormalPosition . top = 0 ;
child - > pos . rcNormalPosition . right = 320 ;
child - > pos . rcNormalPosition . bottom = 280 ;
if ( ! create_child_window ( child ) )
2007-07-23 22:25:20 +02:00
HeapFree ( GetProcessHeap ( ) , 0 , child ) ;
2002-06-04 23:29:40 +02:00
SetWindowPlacement ( child - > hwnd , & child - > pos ) ;
Globals . himl = ImageList_LoadBitmap ( Globals . hInstance , MAKEINTRESOURCE ( IDB_IMAGES ) , 16 , 0 , RGB ( 0 , 255 , 0 ) ) ;
Globals . prescan_node = FALSE ;
2003-08-13 03:18:37 +02:00
UpdateWindow ( Globals . hMainWnd ) ;
2006-01-11 12:32:51 +01:00
if ( path & & path [ 0 ] )
{
int index , count ;
TCHAR drv [ _MAX_DRIVE + 1 ] , dir [ _MAX_DIR ] , name [ _MAX_FNAME ] , ext [ _MAX_EXT ] ;
TCHAR fullname [ _MAX_FNAME + _MAX_EXT + 1 ] ;
memset ( name , 0 , sizeof ( name ) ) ;
memset ( name , 0 , sizeof ( ext ) ) ;
_tsplitpath ( path , drv , dir , name , ext ) ;
if ( name [ 0 ] )
{
2006-03-17 16:57:16 +01:00
count = SendMessage ( child - > right . hwnd , LB_GETCOUNT , 0 , 0 ) ;
2006-01-11 12:32:51 +01:00
lstrcpy ( fullname , name ) ;
lstrcat ( fullname , ext ) ;
for ( index = 0 ; index < count ; index + + )
{
2006-03-17 16:57:16 +01:00
Entry * entry = ( Entry * ) SendMessage ( child - > right . hwnd , LB_GETITEMDATA , index , 0 ) ;
2006-01-11 12:32:51 +01:00
if ( lstrcmp ( entry - > data . cFileName , fullname ) = = 0 | |
lstrcmp ( entry - > data . cAlternateFileName , fullname ) = = 0 )
{
2006-03-17 16:57:16 +01:00
SendMessage ( child - > right . hwnd , LB_SETCURSEL , index , 0 ) ;
2006-01-11 12:32:51 +01:00
SetFocus ( child - > right . hwnd ) ;
break ;
}
}
}
}
2002-06-04 23:29:40 +02:00
}
2005-06-10 21:32:24 +02:00
static void ExitInstance ( void )
2002-06-04 23:29:40 +02:00
{
2003-08-13 03:18:37 +02:00
# ifdef _SHELL_FOLDERS
2005-09-07 15:28:25 +02:00
IShellFolder_Release ( Globals . iDesktop ) ;
IMalloc_Release ( Globals . iMalloc ) ;
2003-08-13 03:18:37 +02:00
CoUninitialize ( ) ;
# endif
2005-10-03 13:03:04 +02:00
DeleteObject ( Globals . hfont ) ;
2002-06-04 23:29:40 +02:00
ImageList_Destroy ( Globals . himl ) ;
}
2005-06-10 21:32:24 +02:00
# ifdef _NO_EXTENSIONS
2002-06-04 23:29:40 +02:00
2002-06-28 19:37:34 +02:00
/* search for already running win[e]files */
2002-06-04 23:29:40 +02:00
static int g_foundPrevInstance = 0 ;
static BOOL CALLBACK EnumWndProc ( HWND hwnd , LPARAM lparam )
{
TCHAR cls [ 128 ] ;
GetClassName ( hwnd , cls , 128 ) ;
if ( ! lstrcmp ( cls , ( LPCTSTR ) lparam ) ) {
g_foundPrevInstance + + ;
return FALSE ;
}
return TRUE ;
}
2003-08-13 03:18:37 +02:00
/* search for window of given class name to allow only one running instance */
2005-06-10 21:32:24 +02:00
static int find_window_class ( LPCTSTR classname )
2002-06-04 23:29:40 +02:00
{
2003-08-13 03:18:37 +02:00
EnumWindows ( EnumWndProc , ( LPARAM ) classname ) ;
2002-06-04 23:29:40 +02:00
if ( g_foundPrevInstance )
return 1 ;
2003-08-13 03:18:37 +02:00
return 0 ;
}
2005-06-10 21:32:24 +02:00
# endif
2003-08-13 03:18:37 +02:00
2005-11-17 12:05:35 +01:00
static int winefile_main ( HINSTANCE hinstance , int cmdshow , LPCTSTR path )
2003-08-13 03:18:37 +02:00
{
MSG msg ;
2006-02-20 18:57:01 +01:00
2002-06-04 23:29:40 +02:00
InitInstance ( hinstance ) ;
2005-11-17 12:05:35 +01:00
show_frame ( 0 , cmdshow , path ) ;
2002-06-04 23:29:40 +02:00
while ( GetMessage ( & msg , 0 , 0 , 0 ) ) {
2003-08-13 03:18:37 +02:00
if ( Globals . hmdiclient & & TranslateMDISysAccel ( Globals . hmdiclient , & msg ) )
continue ;
if ( Globals . hMainWnd & & TranslateAccelerator ( Globals . hMainWnd , Globals . haccel , & msg ) )
continue ;
TranslateMessage ( & msg ) ;
DispatchMessage ( & msg ) ;
2002-06-04 23:29:40 +02:00
}
ExitInstance ( ) ;
2003-08-13 03:18:37 +02:00
return msg . wParam ;
}
2005-11-17 12:05:35 +01:00
# if defined(UNICODE) && defined(_MSC_VER)
int APIENTRY wWinMain ( HINSTANCE hinstance , HINSTANCE previnstance , LPWSTR cmdline , int cmdshow )
# else
int APIENTRY WinMain ( HINSTANCE hinstance , HINSTANCE previnstance , LPSTR cmdline , int cmdshow )
# endif
2003-08-13 03:18:37 +02:00
{
# ifdef _NO_EXTENSIONS
2004-11-22 19:24:09 +01:00
if ( find_window_class ( sWINEFILEFRAME ) )
2003-08-13 03:18:37 +02:00
return 1 ;
# endif
2005-11-17 12:05:35 +01:00
# if defined(UNICODE) && !defined(_MSC_VER)
{ /* convert ANSI cmdline into WCS path string */
TCHAR buffer [ MAX_PATH ] ;
MultiByteToWideChar ( CP_ACP , 0 , cmdline , - 1 , buffer , MAX_PATH ) ;
winefile_main ( hinstance , cmdshow , buffer ) ;
}
# else
winefile_main ( hinstance , cmdshow , cmdline ) ;
# endif
2003-08-13 03:18:37 +02:00
2002-06-04 23:29:40 +02:00
return 0 ;
}