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"
2009-01-06 20:52:55 +01:00
# include "wine/unicode.h"
2002-06-04 23:29:40 +02:00
# 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
2004-10-06 20:52:30 +02:00
# define DEFAULT_SPLIT_POS 300
2003-08-13 03:18:37 +02:00
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 ' } ;
2007-12-20 14:15:16 +01:00
static const WCHAR reg_logfont [ ] = { ' l ' , ' o ' , ' g ' , ' f ' , ' o ' , ' n ' , ' t ' , ' \0 ' } ;
2003-08-13 03:18:37 +02:00
enum ENTRY_TYPE {
ET_WINDOWS ,
ET_UNIX ,
ET_SHELL
} ;
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
2009-08-25 00:24:52 +02:00
WIN32_FIND_DATAW data ;
2002-06-04 23:29:40 +02:00
BY_HANDLE_FILE_INFORMATION bhfi ;
2003-08-13 03:18:37 +02:00
BOOL bhfi_valid ;
enum ENTRY_TYPE etype ;
LPITEMIDLIST pidl ;
IShellFolder * folder ;
HICON hicon ;
2002-06-04 23:29:40 +02:00
} Entry ;
typedef struct {
Entry entry ;
2009-08-25 00:24:41 +02:00
WCHAR path [ MAX_PATH ] ;
WCHAR volname [ _MAX_FNAME ] ;
WCHAR fs [ _MAX_DIR ] ;
2002-06-04 23:29:40 +02:00
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 ,
COL_INDEX = 0x20 ,
COL_LINKS = 0x40 ,
COL_ALL = COL_SIZE | COL_DATE | COL_TIME | COL_ATTRIBUTES | COL_DOSNAMES | COL_INDEX | COL_LINKS
} ;
typedef enum {
SORT_NAME ,
SORT_EXT ,
SORT_SIZE ,
SORT_DATE
} SORT_ORDER ;
typedef struct {
HWND hwnd ;
HWND hwndHeader ;
# define COLUMNS 10
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 ;
2009-08-25 00:24:41 +02:00
WCHAR path [ MAX_PATH ] ;
WCHAR filter_pattern [ MAX_PATH ] ;
2005-05-29 22:05:29 +02:00
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
2009-08-25 00:24:46 +02:00
static void read_directory ( Entry * dir , LPCWSTR 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 ) ;
2009-08-25 00:24:46 +02:00
static void get_path ( Entry * dir , PWSTR path ) ;
2009-08-25 00:24:41 +02:00
static void format_date ( const FILETIME * ft , WCHAR * 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 */
2009-08-25 00:24:41 +02:00
static const WCHAR sEmpty [ ] = { ' \0 ' } ;
2007-07-25 23:22:08 +02:00
static const WCHAR sSpace [ ] = { ' ' , ' \0 ' } ;
2009-08-25 00:24:41 +02:00
static const WCHAR sNumFmt [ ] = { ' % ' , ' d ' , ' \0 ' } ;
static const WCHAR sQMarks [ ] = { ' ? ' , ' ? ' , ' ? ' , ' \0 ' } ;
2004-11-22 19:24:09 +01:00
/* window class names */
2009-08-25 00:24:41 +02:00
static const WCHAR sWINEFILEFRAME [ ] = { ' W ' , ' F ' , ' S ' , ' _ ' , ' F ' , ' r ' , ' a ' , ' m ' , ' e ' , ' \0 ' } ;
static const WCHAR sWINEFILETREE [ ] = { ' W ' , ' F ' , ' S ' , ' _ ' , ' T ' , ' r ' , ' e ' , ' e ' , ' \0 ' } ;
2004-11-22 19:24:09 +01:00
2009-01-06 20:52:55 +01:00
static void format_longlong ( LPWSTR ret , ULONGLONG val )
{
WCHAR buffer [ 65 ] , * p = & buffer [ 64 ] ;
* p = 0 ;
do {
* ( - - p ) = ' 0 ' + val % 10 ;
val / = 10 ;
} while ( val ) ;
lstrcpyW ( ret , p ) ;
}
2004-11-22 19:24:09 +01:00
2004-10-21 21:51:31 +02:00
/* load resource string */
2009-08-25 00:24:46 +02:00
static LPWSTR load_string ( LPWSTR buffer , DWORD size , UINT id )
2004-10-21 21:51:31 +02:00
{
2009-08-25 00:24:25 +02:00
LoadStringW ( Globals . hInstance , id , buffer , size ) ;
2004-10-22 21:52:50 +02:00
return buffer ;
2004-10-21 21:51:31 +02:00
}
2008-09-13 22:43:34 +02:00
# define RS(b, i) load_string(b, sizeof(b) / sizeof(b[0]), i)
2004-10-21 21:51:31 +02:00
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 )
{
2009-08-25 00:24:41 +02:00
WCHAR b1 [ BUFFER_LEN ] , b2 [ BUFFER_LEN ] ;
2009-08-25 00:24:46 +02:00
PWSTR msg ;
2002-06-04 23:29:40 +02:00
2009-08-25 00:24:36 +02:00
if ( FormatMessageW ( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM ,
2009-08-25 00:24:46 +02:00
0 , error , MAKELANGID ( LANG_NEUTRAL , SUBLANG_DEFAULT ) , ( PWSTR ) & msg , 0 , NULL ) )
2009-08-25 00:24:36 +02:00
MessageBoxW ( hwnd , msg , RS ( b2 , IDS_WINEFILE ) , MB_OK ) ;
2002-06-04 23:29:40 +02:00
else
2009-08-25 00:24:36 +02:00
MessageBoxW ( 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
2009-08-25 00:24:36 +02:00
/* display network error message using WNetGetLastErrorW() */
2005-05-16 23:36:41 +02:00
static void display_network_error ( HWND hwnd )
{
2009-08-25 00:24:41 +02:00
WCHAR msg [ BUFFER_LEN ] , provider [ BUFFER_LEN ] , b2 [ BUFFER_LEN ] ;
2005-05-16 23:36:41 +02:00
DWORD error ;
2009-08-25 00:24:36 +02:00
if ( WNetGetLastErrorW ( & error , msg , BUFFER_LEN , provider , BUFFER_LEN ) = = NO_ERROR )
MessageBoxW ( hwnd , msg , RS ( b2 , IDS_WINEFILE ) , MB_OK ) ;
2005-05-16 23:36:41 +02: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 ) ;
2011-02-08 20:03:25 +01:00
GetObjectW ( Globals . hfont , sizeof ( LOGFONTW ) , & lFont ) ;
2009-08-25 00:24:52 +02:00
chFont . lStructSize = sizeof ( CHOOSEFONTW ) ;
2007-07-25 23:21:43 +02:00
chFont . hwndOwner = hwnd ;
chFont . hDC = NULL ;
chFont . lpLogFont = & lFont ;
2013-06-25 12:39:37 +02:00
chFont . Flags = CF_SCREENFONTS | CF_FORCEFONTEXIST | CF_LIMITSIZE | CF_NOSCRIPTSEL | CF_INITTOLOGFONTSTRUCT | CF_NOVERTFONTS ;
2007-07-25 23:21:43 +02:00
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
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
entry - > pidl = NULL ;
entry - > folder = NULL ;
entry - > hicon = 0 ;
return entry ;
}
/* free a directory entry */
static void free_entry ( Entry * entry )
{
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
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 ) ;
}
}
2009-08-25 00:24:46 +02:00
static void read_directory_win ( Entry * dir , LPCWSTR path )
2003-08-13 03:18:37 +02:00
{
Entry * first_entry = NULL ;
Entry * last = NULL ;
Entry * entry ;
int level = dir - > level + 1 ;
2009-08-25 00:24:52 +02:00
WIN32_FIND_DATAW w32fd ;
2002-06-04 23:29:40 +02:00
HANDLE hFind ;
HANDLE hFile ;
2009-08-25 00:24:41 +02:00
WCHAR buffer [ MAX_PATH ] , * p ;
2002-06-04 23:29:40 +02:00
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
2009-08-25 00:24:30 +02:00
hFind = FindFirstFileW ( buffer , & w32fd ) ;
2002-06-04 23:29:40 +02:00
if ( hFind ! = INVALID_HANDLE_VALUE ) {
do {
2003-08-13 03:18:37 +02:00
entry = alloc_entry ( ) ;
if ( ! first_entry )
first_entry = entry ;
if ( last )
last - > next = entry ;
2009-08-25 00:24:52 +02:00
memcpy ( & entry - > data , & w32fd , sizeof ( WIN32_FIND_DATAW ) ) ;
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 ;
2003-08-13 03:18:37 +02:00
entry - > etype = ET_WINDOWS ;
2002-06-04 23:29:40 +02:00
entry - > bhfi_valid = FALSE ;
2009-08-25 00:24:11 +02:00
lstrcpyW ( p , entry - > data . cFileName ) ;
2002-06-04 23:29:40 +02:00
2009-08-25 00:24:30 +02:00
hFile = CreateFileW ( buffer , GENERIC_READ , FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE ,
2002-06-04 23:29:40 +02:00
0 , OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS , 0 ) ;
if ( hFile ! = INVALID_HANDLE_VALUE ) {
if ( GetFileInformationByHandle ( hFile , & entry - > bhfi ) )
entry - > bhfi_valid = TRUE ;
CloseHandle ( hFile ) ;
}
last = entry ;
2009-08-25 00:24:30 +02:00
} while ( FindNextFileW ( 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
}
2009-08-25 00:24:46 +02:00
static Entry * find_entry_win ( Entry * dir , LPCWSTR 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 ) {
2009-08-25 00:24:46 +02:00
LPCWSTR p = name ;
LPCWSTR q = entry - > data . cFileName ;
2002-06-04 23:29:40 +02:00
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 ;
}
2009-08-25 00:24:46 +02:00
static Entry * read_tree_win ( Root * root , LPCWSTR path , SORT_ORDER sortOrder , HWND hwnd )
2002-06-04 23:29:40 +02:00
{
2009-08-25 00:24:41 +02:00
WCHAR buffer [ MAX_PATH ] ;
2002-06-04 23:29:40 +02:00
Entry * entry = & root - > entry ;
2009-08-25 00:24:46 +02:00
LPCWSTR s = path ;
PWSTR d = buffer ;
2002-06-04 23:29:40 +02:00
2009-08-25 00:24:25 +02:00
HCURSOR old_cursor = SetCursor ( LoadCursorW ( 0 , ( LPCWSTR ) IDC_WAIT ) ) ;
2003-08-13 03:18:37 +02:00
entry - > etype = ET_WINDOWS ;
2002-06-04 23:29:40 +02:00
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 ;
}
2012-03-18 19:22:11 +01:00
# ifdef __WINE__
2002-06-04 23:29:40 +02:00
2013-03-13 12:47:07 +01:00
static BOOL time_to_filetime ( time_t t , FILETIME * ftime )
2002-06-04 23:29:40 +02:00
{
2013-03-13 12:47:07 +01:00
struct tm * tm = gmtime ( & t ) ;
2002-06-04 23:29:40 +02:00
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 ;
2011-11-25 14:55:40 +01:00
stime . wMilliseconds = 0 ;
2002-06-04 23:29:40 +02:00
return SystemTimeToFileTime ( & stime , ftime ) ;
}
2009-08-25 00:24:46 +02:00
static void read_directory_unix ( Entry * dir , LPCWSTR 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
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 ) ;
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
MultiByteToWideChar ( CP_UNIXCP , 0 , p , - 1 , entry - > data . cFileName , MAX_PATH ) ;
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 ) ) ;
2013-03-13 12:47:07 +01: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
}
2009-08-25 00:24:46 +02:00
static Entry * find_entry_unix ( Entry * dir , LPCWSTR 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 ) {
2009-08-25 00:24:46 +02:00
LPCWSTR p = name ;
LPCWSTR q = entry - > data . cFileName ;
2002-06-04 23:29:40 +02:00
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 ;
}
2009-08-25 00:24:46 +02:00
static Entry * read_tree_unix ( Root * root , LPCWSTR path , SORT_ORDER sortOrder , HWND hwnd )
2002-06-04 23:29:40 +02:00
{
2009-08-25 00:24:41 +02:00
WCHAR buffer [ MAX_PATH ] ;
2002-06-04 23:29:40 +02:00
Entry * entry = & root - > entry ;
2009-08-25 00:24:46 +02:00
LPCWSTR s = path ;
PWSTR d = buffer ;
2002-06-04 23:29:40 +02:00
2009-08-25 00:24:25 +02:00
HCURSOR old_cursor = SetCursor ( LoadCursorW ( 0 , ( LPCWSTR ) IDC_WAIT ) ) ;
2003-08-13 03:18:37 +02:00
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 ;
}
2012-03-18 19:22:11 +01:00
# endif /* __WINE__ */
2003-08-13 03:18:37 +02:00
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
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 ) ;
}
}
2009-08-25 00:24:46 +02:00
static HRESULT name_from_pidl ( IShellFolder * folder , LPITEMIDLIST pidl , LPWSTR 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 ) ) {
2009-08-25 00:23:46 +02:00
get_strretW ( & str , & pidl - > mkid , buffer , len ) ;
2003-08-13 03:18:37 +02:00
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 */
2009-08-25 00:24:46 +02:00
static LPITEMIDLIST get_path_pidl ( LPWSTR path , HWND hwnd )
2003-08-13 03:18:37 +02:00
{
LPITEMIDLIST pidl ;
HRESULT hr ;
ULONG len ;
LPWSTR buffer = path ;
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 ) {
2008-07-26 01:34:15 +02:00
LPITEMIDLIST idl = NULL ;
2003-08-13 03:18:37 +02:00
2008-07-26 01:34:15 +02:00
while ( entry - > up ) {
idl = ILCombine ( ILClone ( entry - > pidl ) , idl ) ;
entry = entry - > up ;
2003-08-13 03:18:37 +02:00
}
2008-07-26 01:34:15 +02:00
return idl ;
2004-02-11 05:18:12 +01:00
} else if ( entry - > etype = = ET_WINDOWS ) {
2009-08-25 00:24:41 +02:00
WCHAR path [ MAX_PATH ] ;
2004-02-11 05:18:12 +01:00
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
{
2009-08-25 00:24:52 +02:00
IExtractIconW * pExtract ;
2003-08-13 03:18:37 +02:00
2009-08-25 00:24:52 +02:00
if ( SUCCEEDED ( IShellFolder_GetUIObjectOf ( folder , 0 , 1 , ( LPCITEMIDLIST * ) & pidl , & IID_IExtractIconW , 0 , ( LPVOID * ) & pExtract ) ) ) {
2009-08-25 00:24:41 +02:00
WCHAR path [ _MAX_PATH ] ;
2003-08-13 03:18:37 +02:00
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 */
2009-08-25 00:24:36 +02:00
if ( ( int ) ExtractIconExW ( path , idx , 0 , & hicon , 1 ) > 0 )
2003-08-13 03:18:37 +02:00
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 ;
2009-08-25 00:24:25 +02:00
HCURSOR old_cursor = SetCursor ( LoadCursorW ( 0 , ( LPCWSTR ) IDC_WAIT ) ) ;
2003-08-13 03:18:37 +02:00
entry - > etype = ET_SHELL ;
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 ) ;
2008-10-08 01:34:27 +02:00
if ( FAILED ( hr ) )
2003-08-13 03:18:37 +02:00
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
2009-08-25 00:24:52 +02:00
static void fill_w32fdata_shell ( IShellFolder * folder , LPCITEMIDLIST pidl , SFGAOF attribs , WIN32_FIND_DATAW * w32fdata )
2003-08-13 03:18:37 +02:00
{
if ( ! ( attribs & SFGAO_FILESYSTEM ) | |
2009-08-25 00:24:30 +02:00
FAILED ( SHGetDataFromIDListW ( folder , pidl , SHGDFIL_FINDDATA , w32fdata , sizeof ( WIN32_FIND_DATAW ) ) ) ) {
2003-08-13 03:18:37 +02:00
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 ) ) {
2009-08-25 00:24:46 +02:00
LPCWSTR path = GlobalLock ( medium . UNION_MEMBER ( hGlobal ) ) ;
2003-08-13 03:18:37 +02:00
UINT sem_org = SetErrorMode ( SEM_FAILCRITICALERRORS ) ;
2009-08-25 00:24:30 +02:00
if ( GetFileAttributesExW ( path , GetFileExInfoStandard , & fad ) ) {
2003-08-13 03:18:37 +02:00
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 ) ;
2008-10-08 01:34:27 +02:00
if ( FAILED ( hr ) )
2003-08-13 03:18:37 +02:00
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 ;
2009-08-25 00:24:52 +02:00
memset ( & entry - > data , 0 , sizeof ( WIN32_FIND_DATAW ) ) ;
2003-08-13 03:18:37 +02:00
entry - > bhfi_valid = FALSE ;
2008-10-18 19:22:19 +02:00
attribs = ~ SFGAO_FILESYSTEM ; /*SFGAO_HASSUBFOLDER|SFGAO_FOLDER; SFGAO_FILESYSTEM sorgt dafür, daß "My Documents" anstatt von "Martin's Documents" angezeigt wird */
2003-08-13 03:18:37 +02:00
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 ;
entry - > etype = ET_SHELL ;
entry - > bhfi_valid = FALSE ;
2002-06-04 23:29:40 +02:00
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 ;
}
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 */
2009-08-25 00:24:46 +02:00
static int TypeOrderFromDirname ( LPCWSTR name )
2004-09-22 21:11:49 +02:00
{
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... */
2009-08-25 00:24:52 +02:00
static int compareType ( const WIN32_FIND_DATAW * fd1 , const WIN32_FIND_DATAW * fd2 )
2002-06-04 23:29:40 +02:00
{
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 )
{
2009-08-25 00:24:52 +02:00
const WIN32_FIND_DATAW * fd1 = & ( * ( const Entry * const * ) arg1 ) - > data ;
const WIN32_FIND_DATAW * fd2 = & ( * ( const Entry * const * ) arg2 ) - > data ;
2002-06-04 23:29:40 +02:00
int cmp = compareType ( fd1 , fd2 ) ;
if ( cmp )
return cmp ;
2009-08-25 00:24:11 +02:00
return lstrcmpiW ( fd1 - > cFileName , fd2 - > cFileName ) ;
2002-06-04 23:29:40 +02:00
}
static int compareExt ( const void * arg1 , const void * arg2 )
{
2009-08-25 00:24:52 +02:00
const WIN32_FIND_DATAW * fd1 = & ( * ( const Entry * const * ) arg1 ) - > data ;
const WIN32_FIND_DATAW * fd2 = & ( * ( const Entry * const * ) arg2 ) - > data ;
2009-08-25 00:24:41 +02:00
const WCHAR * name1 , * name2 , * ext1 , * ext2 ;
2002-06-04 23:29:40 +02:00
int cmp = compareType ( fd1 , fd2 ) ;
if ( cmp )
return cmp ;
name1 = fd1 - > cFileName ;
name2 = fd2 - > cFileName ;
2009-01-06 20:52:55 +01:00
ext1 = strrchrW ( name1 , ' . ' ) ;
ext2 = strrchrW ( 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
2009-08-25 00:24:11 +02:00
cmp = lstrcmpiW ( ext1 , ext2 ) ;
2002-06-04 23:29:40 +02:00
if ( cmp )
return cmp ;
2009-08-25 00:24:11 +02:00
return lstrcmpiW ( name1 , name2 ) ;
2002-06-04 23:29:40 +02:00
}
static int compareSize ( const void * arg1 , const void * arg2 )
{
2009-08-25 00:24:52 +02:00
const WIN32_FIND_DATAW * fd1 = & ( * ( const Entry * const * ) arg1 ) - > data ;
const WIN32_FIND_DATAW * 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 )
{
2009-08-25 00:24:52 +02:00
const WIN32_FIND_DATAW * fd1 = & ( * ( const Entry * const * ) arg1 ) - > data ;
const WIN32_FIND_DATAW * 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
{
2011-07-05 21:37:27 +02:00
Entry * entry ;
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
}
}
2009-08-25 00:24:46 +02:00
static void read_directory ( Entry * dir , LPCWSTR path , SORT_ORDER sortOrder , HWND hwnd )
2002-06-04 23:29:40 +02:00
{
2009-08-25 00:24:41 +02:00
WCHAR buffer [ MAX_PATH ] ;
2002-06-04 23:29:40 +02:00
Entry * entry ;
2009-08-25 00:24:46 +02:00
LPCWSTR s ;
PWSTR d ;
2002-06-04 23:29:40 +02:00
2003-08-13 03:18:37 +02:00
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
2012-03-18 19:22:11 +01:00
# ifdef __WINE__
2003-08-13 03:18:37 +02:00
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 ) {
2009-08-25 00:24:11 +02:00
lstrcpyW ( d , entry - > data . cFileName ) ;
2002-06-04 23:29:40 +02:00
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 ) {
2009-08-25 00:24:11 +02:00
lstrcpyW ( d , entry - > data . cFileName ) ;
2002-06-04 23:29:40 +02:00
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
}
2009-08-25 00:24:46 +02:00
static Entry * read_tree ( Root * root , LPCWSTR path , LPITEMIDLIST pidl , LPWSTR drv , SORT_ORDER sortOrder , HWND hwnd )
2002-06-04 23:29:40 +02:00
{
2012-03-18 19:22:11 +01:00
# ifdef __WINE__
2009-08-25 00:24:41 +02:00
static const WCHAR sSlash [ ] = { ' / ' , ' \0 ' } ;
2004-11-22 19:24:09 +01:00
# endif
2009-08-25 00:24:41 +02:00
static const WCHAR sBackslash [ ] = { ' \\ ' , ' \0 ' } ;
2005-05-16 10:48:54 +02:00
if ( pidl )
{
/* read shell namespace tree */
root - > drive_type = DRIVE_UNKNOWN ;
drv [ 0 ] = ' \\ ' ;
drv [ 1 ] = ' \0 ' ;
2008-09-13 22:43:34 +02:00
load_string ( root - > volname , sizeof ( root - > volname ) / sizeof ( root - > volname [ 0 ] ) , IDS_DESKTOP ) ;
2005-05-16 10:48:54 +02:00
root - > fs_flags = 0 ;
2008-09-13 22:43:34 +02:00
load_string ( root - > fs , sizeof ( root - > fs ) / sizeof ( root - > fs [ 0 ] ) , IDS_SHELL ) ;
2005-05-16 10:48:54 +02:00
return read_tree_shell ( root , pidl , sortOrder , hwnd ) ;
}
else
2012-03-18 19:22:11 +01:00
# ifdef __WINE__
2005-05-16 10:48:54 +02:00
if ( * path = = ' / ' )
{
2009-08-25 00:24:30 +02:00
/* read unix file system tree */
root - > drive_type = GetDriveTypeW ( path ) ;
2005-05-16 10:48:54 +02:00
2009-08-25 00:24:11 +02:00
lstrcatW ( drv , sSlash ) ;
2008-09-13 22:43:34 +02:00
load_string ( root - > volname , sizeof ( root - > volname ) / sizeof ( root - > volname [ 0 ] ) , IDS_ROOT_FS ) ;
2005-05-16 10:48:54 +02:00
root - > fs_flags = 0 ;
2008-09-13 22:43:34 +02:00
load_string ( root - > fs , sizeof ( root - > fs ) / sizeof ( root - > fs [ 0 ] ) , IDS_UNIXFS ) ;
2005-05-16 10:48:54 +02:00
2009-08-25 00:24:11 +02:00
lstrcpyW ( root - > path , sSlash ) ;
2005-05-16 10:48:54 +02:00
return read_tree_unix ( root , path , sortOrder , hwnd ) ;
}
# endif
/* read WIN32 file system tree */
2009-08-25 00:24:30 +02:00
root - > drive_type = GetDriveTypeW ( path ) ;
2005-05-16 10:48:54 +02:00
2009-08-25 00:24:11 +02:00
lstrcatW ( drv , sBackslash ) ;
2009-08-25 00:24:30 +02:00
GetVolumeInformationW ( drv , root - > volname , _MAX_FNAME , 0 , 0 , & root - > fs_flags , root - > fs , _MAX_DIR ) ;
2005-05-16 10:48:54 +02:00
2009-08-25 00:24:11 +02:00
lstrcpyW ( 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
} ;
2009-08-25 00:24:46 +02:00
static ChildWnd * alloc_child_window ( LPCWSTR path , LPITEMIDLIST pidl , HWND hwnd )
2005-05-16 10:48:54 +02:00
{
2009-08-25 00:24:41 +02:00
WCHAR drv [ _MAX_DRIVE + 1 ] , dir [ _MAX_DIR ] , name [ _MAX_FNAME ] , ext [ _MAX_EXT ] ;
WCHAR dir_path [ MAX_PATH ] ;
static const WCHAR sAsterics [ ] = { ' * ' , ' \0 ' } ;
2011-08-26 15:32:46 +02:00
static const WCHAR sTitleFmt [ ] = { ' % ' , ' s ' , ' ' , ' - ' , ' ' , ' % ' , ' s ' , ' \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 ;
child - > right . visible_cols = COL_SIZE | COL_DATE | COL_TIME | COL_ATTRIBUTES | COL_INDEX | COL_LINKS ;
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 )
{
2014-12-13 16:59:42 +01:00
int pathlen = strlenW ( path ) ;
const WCHAR * npath = path ;
2003-08-13 03:18:37 +02:00
2014-12-13 16:59:42 +01:00
if ( path [ 0 ] = = ' " ' & & path [ pathlen - 1 ] = = ' " ' )
{
npath + + ;
pathlen - - ;
}
lstrcpynW ( child - > path , npath , pathlen + 1 ) ;
_wsplitpath ( child - > path , drv , dir , name , ext ) ;
2003-08-13 03:18:37 +02:00
}
2002-06-04 23:29:40 +02:00
2009-08-25 00:24:11 +02:00
lstrcpyW ( 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 ;
2009-08-25 00:24:11 +02:00
lstrcpyW ( dir_path , drv ) ;
lstrcatW ( dir_path , dir ) ;
2006-01-11 12:32:51 +01:00
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
if ( root - > entry . etype = = ET_SHELL )
2008-09-13 22:43:34 +02:00
load_string ( root - > entry . data . cFileName , sizeof ( root - > entry . data . cFileName ) / sizeof ( root - > entry . data . cFileName [ 0 ] ) , IDS_DESKTOP ) ;
2003-08-13 03:18:37 +02:00
else
2011-08-26 15:32:46 +02:00
wsprintfW ( root - > entry . data . cFileName , sTitleFmt , 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 */
2009-08-25 00:24:46 +02:00
static void get_path ( Entry * dir , PWSTR path )
2002-06-04 23:29:40 +02:00
{
Entry * entry ;
int len = 0 ;
int level = 0 ;
2003-08-13 03:18:37 +02:00
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 ;
2009-08-25 00:23:46 +02:00
hr = path_from_pidlW ( parent , dir - > pidl , path , MAX_PATH ) ;
2003-08-13 03:18:37 +02:00
}
}
else
{
for ( entry = dir ; entry ; level + + ) {
2009-08-25 00:24:46 +02:00
LPCWSTR name ;
2003-08-13 03:18:37 +02:00
int l ;
{
2009-08-25 00:24:46 +02:00
LPCWSTR s ;
2003-08-13 03:18:37 +02:00
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 ) {
2009-08-25 00:24:41 +02:00
memmove ( path + l + 1 , path , len * sizeof ( WCHAR ) ) ;
memcpy ( path + 1 , name , l * sizeof ( WCHAR ) ) ;
2003-08-13 03:18:37 +02:00
len + = l + 1 ;
2002-06-04 23:29:40 +02:00
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
2012-03-18 19:22:11 +01: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 {
2009-08-25 00:24:41 +02:00
memmove ( path + l , path , len * sizeof ( WCHAR ) ) ;
memcpy ( path , name , l * sizeof ( WCHAR ) ) ;
2003-08-13 03:18:37 +02:00
len + = l ;
break ;
}
2002-06-04 23:29:40 +02:00
}
2003-08-13 03:18:37 +02:00
if ( ! level ) {
if ( entry - > etype = = ET_UNIX )
2007-06-27 22:54:56 +02:00
path [ len + + ] = ' / ' ;
2003-08-13 03:18:37 +02:00
else
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 ;
2009-08-25 00:24:52 +02:00
LOGFONTW logfont ;
2006-02-20 18:57:01 +01:00
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 ;
2007-12-20 14:15:16 +01:00
size = sizeof ( logfont ) ;
if ( RegQueryValueExW ( hKey , reg_logfont , NULL , & type ,
( LPBYTE ) & logfont , & size ) ! = ERROR_SUCCESS )
2009-08-25 00:24:36 +02:00
GetObjectW ( GetStockObject ( DEFAULT_GUI_FONT ) , sizeof ( logfont ) , & logfont ) ;
2006-02-20 18:57:01 +01:00
RegCloseKey ( hKey ) ;
2009-08-25 00:24:36 +02:00
Globals . hfont = CreateFontIndirectW ( & logfont ) ;
2006-02-20 18:57:01 +01:00
return opts ;
}
static void save_registry_settings ( void )
{
WINDOWINFO wi ;
HKEY hKey ;
INT width , height ;
2009-08-25 00:24:52 +02:00
LOGFONTW logfont ;
2006-02-20 18:57:01 +01:00
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 ) ) ;
2009-08-25 00:24:36 +02:00
GetObjectW ( Globals . hfont , sizeof ( logfont ) , & logfont ) ;
2007-12-20 14:15:16 +01:00
RegSetValueExW ( hKey , reg_logfont , 0 , REG_BINARY ,
2009-08-25 00:24:52 +02:00
( LPBYTE ) & logfont , sizeof ( LOGFONTW ) ) ;
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 ) ) {
2009-08-25 00:24:06 +02:00
SendMessageW ( Globals . htoolbar , WM_SIZE , 0 , 0 ) ;
2002-06-04 23:29:40 +02:00
GetClientRect ( Globals . htoolbar , & rt ) ;
prect - > top = rt . bottom + 3 ;
prect - > bottom - = rt . bottom + 3 ;
}
if ( IsWindowVisible ( Globals . hdrivebar ) ) {
2009-08-25 00:24:06 +02:00
SendMessageW ( Globals . hdrivebar , WM_SIZE , 0 , 0 ) ;
2002-06-04 23:29:40 +02:00
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 } ;
2009-08-25 00:24:06 +02:00
SendMessageW ( Globals . hstatusbar , WM_SIZE , 0 , 0 ) ;
SendMessageW ( Globals . hstatusbar , SB_SETPARTS , 2 , ( LPARAM ) & parts ) ;
2002-06-04 23:29:40 +02:00
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 ;
2009-08-25 00:24:19 +02:00
SetWindowLongPtrW ( 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 )
{
2009-08-25 00:24:52 +02:00
MDICREATESTRUCTW mcs ;
2002-06-04 23:29:40 +02:00
int idx ;
2004-11-22 19:24:09 +01:00
mcs . szClass = sWINEFILETREE ;
2009-08-25 00:24:46 +02:00
mcs . szTitle = child - > path ;
2002-07-03 23:06:58 +02:00
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 ;
2009-08-25 00:24:19 +02:00
hcbthook = SetWindowsHookExW ( WH_CBT , CBTProc , 0 , GetCurrentThreadId ( ) ) ;
2002-06-04 23:29:40 +02:00
newchild = child ;
2009-08-25 00:24:06 +02:00
child - > hwnd = ( HWND ) SendMessageW ( 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 ) ;
2009-08-25 00:24:06 +02:00
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 ) ) ;
2005-05-16 10:48:54 +02:00
2009-08-25 00:24:06 +02:00
idx = SendMessageW ( child - > left . hwnd , LB_FINDSTRING , 0 , ( LPARAM ) child - > left . cur ) ;
SendMessageW ( child - > left . hwnd , LB_SETCURSEL , idx , 0 ) ;
2002-06-04 23:29:40 +02:00
return child - > hwnd ;
}
2009-12-28 17:44:20 +01:00
# define RFF_NODEFAULT 0x02 /* No default item selected. */
2002-06-04 23:29:40 +02:00
2009-12-28 17:44:20 +01:00
static void WineFile_OnRun ( HWND hwnd )
2002-06-04 23:29:40 +02:00
{
2009-12-28 17:44:20 +01:00
static const WCHAR shell32_dll [ ] = { ' S ' , ' H ' , ' E ' , ' L ' , ' L ' , ' 3 ' , ' 2 ' , ' . ' , ' D ' , ' L ' , ' L ' , 0 } ;
void ( WINAPI * pRunFileDlgAW ) ( HWND , HICON , LPWSTR , LPWSTR , LPWSTR , DWORD ) ;
HMODULE hshell = GetModuleHandleW ( shell32_dll ) ;
2002-06-04 23:29:40 +02:00
2009-12-28 17:44:20 +01:00
pRunFileDlgAW = ( void * ) GetProcAddress ( hshell , ( LPCSTR ) 61 ) ;
if ( pRunFileDlgAW ) pRunFileDlgAW ( hwnd , 0 , NULL , NULL , NULL , RFF_NODEFAULT ) ;
2002-06-04 23:29:40 +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
{
2009-08-25 00:24:41 +02:00
WCHAR 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 :
2009-08-25 00:24:19 +02:00
SetWindowLongPtrW ( hwnd , GWLP_USERDATA , lparam ) ;
SetWindowTextW ( GetDlgItem ( hwnd , 201 ) , ( LPCWSTR ) 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 : {
2009-08-25 00:24:19 +02:00
LPWSTR dest = ( LPWSTR ) GetWindowLongPtrW ( hwnd , GWLP_USERDATA ) ;
GetWindowTextW ( 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 :
2009-08-25 00:24:36 +02:00
MessageBoxW ( 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 {
2009-08-25 00:24:41 +02:00
WCHAR pattern [ MAX_PATH ] ;
2005-05-29 22:05:29 +02:00
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 ;
2009-08-25 00:24:19 +02:00
SetWindowTextW ( 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 ;
2009-08-25 00:24:19 +02:00
GetWindowTextW ( GetDlgItem ( hwnd , IDC_VIEW_PATTERN ) , dlg - > pattern , MAX_PATH ) ;
2005-05-29 22:05:29 +02:00
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 {
2009-08-25 00:24:41 +02:00
WCHAR path [ MAX_PATH ] ;
2005-06-06 12:02:43 +02:00
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 )
{
2009-08-25 00:24:06 +02:00
int idx = SendMessageW ( hlbox , LB_GETCURSEL , 0 , 0 ) ;
2005-06-06 12:02:43 +02:00
if ( idx ! = LB_ERR ) {
2009-08-25 00:24:06 +02:00
LPCWSTR pValue = ( LPCWSTR ) SendMessageW ( hlbox , LB_GETITEMDATA , idx , 0 ) ;
2005-06-06 12:02:43 +02:00
if ( pValue )
2009-08-25 00:24:19 +02:00
SetWindowTextW ( hedit , pValue ) ;
2005-06-06 12:02:43 +02:00
}
}
2009-08-25 00:24:46 +02:00
static void CheckForFileInfo ( struct PropertiesDialog * dlg , HWND hwnd , LPCWSTR strFilename )
2005-06-06 12:02:43 +02:00
{
2013-12-19 22:25:12 +01:00
static const WCHAR sBackSlash [ ] = { ' \\ ' , ' \0 ' } ;
static const WCHAR 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 const WCHAR sStringFileInfo [ ] = { ' \\ ' , ' S ' , ' t ' , ' r ' , ' i ' , ' n ' , ' g ' , ' F ' , ' i ' , ' l ' , ' e ' , ' I ' , ' n ' , ' f ' , ' o ' , ' \\ ' ,
2005-06-06 12:02:43 +02:00
' % ' , ' 0 ' , ' 4 ' , ' x ' , ' % ' , ' 0 ' , ' 4 ' , ' x ' , ' \\ ' , ' % ' , ' s ' , ' \0 ' } ;
2013-12-19 22:25:12 +01:00
static const WCHAR sFmt [ ] = { ' % ' , ' d ' , ' . ' , ' % ' , ' d ' , ' . ' , ' % ' , ' d ' , ' . ' , ' % ' , ' d ' , ' \0 ' } ;
2009-08-25 00:24:30 +02:00
DWORD dwVersionDataLen = GetFileVersionInfoSizeW ( strFilename , NULL ) ;
2005-06-06 12:02:43 +02:00
if ( dwVersionDataLen ) {
2007-07-23 22:25:20 +02:00
dlg - > pVersionData = HeapAlloc ( GetProcessHeap ( ) , 0 , dwVersionDataLen ) ;
2005-06-06 12:02:43 +02:00
2009-08-25 00:24:30 +02:00
if ( GetFileVersionInfoW ( strFilename , 0 , dwVersionDataLen , dlg - > pVersionData ) ) {
2005-06-06 12:02:43 +02:00
LPVOID pVal ;
UINT nValLen ;
2009-08-25 00:24:36 +02:00
if ( VerQueryValueW ( dlg - > pVersionData , sBackSlash , & pVal , & nValLen ) ) {
2005-06-06 12:02:43 +02:00
if ( nValLen = = sizeof ( VS_FIXEDFILEINFO ) ) {
VS_FIXEDFILEINFO * pFixedFileInfo = ( VS_FIXEDFILEINFO * ) pVal ;
2012-03-18 19:24:28 +01:00
WCHAR buffer [ BUFFER_LEN ] ;
2005-06-06 12:02:43 +02:00
2012-03-18 19:24:28 +01:00
sprintfW ( buffer , sFmt ,
HIWORD ( pFixedFileInfo - > dwFileVersionMS ) , LOWORD ( pFixedFileInfo - > dwFileVersionMS ) ,
HIWORD ( pFixedFileInfo - > dwFileVersionLS ) , LOWORD ( pFixedFileInfo - > dwFileVersionLS ) ) ;
2005-06-06 12:02:43 +02:00
2012-03-18 19:24:28 +01:00
SetDlgItemTextW ( hwnd , IDC_STATIC_PROP_VERSION , buffer ) ;
2005-06-06 12:02:43 +02:00
}
}
/* Read the list of languages and code pages. */
2009-08-25 00:24:36 +02:00
if ( VerQueryValueW ( dlg - > pVersionData , sTranslation , & pVal , & nValLen ) ) {
2005-06-06 12:02:43 +02:00
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 ) {
2009-08-25 00:24:41 +02:00
WCHAR subblock [ 200 ] ;
WCHAR infoStr [ 100 ] ;
2009-08-25 00:24:46 +02:00
LPCWSTR pTxt ;
2005-06-06 12:02:43 +02:00
UINT nValLen ;
LPCSTR pInfoString = * p ;
MultiByteToWideChar ( CP_ACP , 0 , pInfoString , - 1 , infoStr , 100 ) ;
2009-08-25 00:24:11 +02:00
wsprintfW ( subblock , sStringFileInfo , pTranslate - > wLanguage , pTranslate - > wCodePage , infoStr ) ;
2005-06-06 12:02:43 +02:00
/* Retrieve file description for language and code page */
2009-08-25 00:24:36 +02:00
if ( VerQueryValueW ( dlg - > pVersionData , subblock , ( PVOID ) & pTxt , & nValLen ) ) {
2009-08-25 00:24:06 +02:00
int idx = SendMessageW ( hlbox , LB_ADDSTRING , 0L , ( LPARAM ) infoStr ) ;
SendMessageW ( hlbox , LB_SETITEMDATA , idx , ( LPARAM ) pTxt ) ;
2005-06-06 12:02:43 +02:00
}
}
}
2009-08-25 00:24:06 +02:00
SendMessageW ( 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 : {
2009-08-25 00:24:41 +02:00
static const WCHAR sByteFmt [ ] = { ' % ' , ' s ' , ' ' , ' B ' , ' y ' , ' t ' , ' e ' , ' s ' , ' \0 ' } ;
WCHAR b1 [ BUFFER_LEN ] , b2 [ BUFFER_LEN ] ;
2009-08-25 00:24:52 +02:00
LPWIN32_FIND_DATAW pWFD ;
2005-06-06 12:02:43 +02:00
dlg = ( struct PropertiesDialog * ) lparam ;
2009-08-25 00:24:52 +02:00
pWFD = ( LPWIN32_FIND_DATAW ) & dlg - > entry . data ;
2005-06-06 12:02:43 +02:00
2009-08-25 00:24:19 +02:00
GetWindowTextW ( hwnd , b1 , MAX_PATH ) ;
2009-08-25 00:24:11 +02:00
wsprintfW ( b2 , b1 , pWFD - > cFileName ) ;
2009-08-25 00:24:19 +02:00
SetWindowTextW ( hwnd , b2 ) ;
2005-06-06 12:02:43 +02:00
format_date ( & pWFD - > ftLastWriteTime , b1 , COL_DATE | COL_TIME ) ;
2009-08-25 00:24:19 +02:00
SetWindowTextW ( GetDlgItem ( hwnd , IDC_STATIC_PROP_LASTCHANGE ) , b1 ) ;
2005-06-06 12:02:43 +02:00
2009-01-06 20:52:55 +01:00
format_longlong ( b1 , ( ( ULONGLONG ) pWFD - > nFileSizeHigh < < 32 ) | pWFD - > nFileSizeLow ) ;
2009-08-25 00:24:11 +02:00
wsprintfW ( b2 , sByteFmt , b1 ) ;
2009-08-25 00:24:19 +02:00
SetWindowTextW ( GetDlgItem ( hwnd , IDC_STATIC_PROP_SIZE ) , b2 ) ;
2005-06-06 12:02:43 +02:00
2009-08-25 00:24:19 +02:00
SetWindowTextW ( GetDlgItem ( hwnd , IDC_STATIC_PROP_FILENAME ) , pWFD - > cFileName ) ;
SetWindowTextW ( GetDlgItem ( hwnd , IDC_STATIC_PROP_PATH ) , dlg - > path ) ;
2005-06-06 12:02:43 +02:00
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 ) ) ;
2009-08-25 00:24:36 +02:00
DialogBoxParamW ( Globals . hInstance , MAKEINTRESOURCEW ( IDD_DIALOG_PROPERTIES ) , hwnd , PropertiesDialogDlgProc , ( LPARAM ) & dlg ) ;
2005-06-06 12:02:43 +02:00
}
2002-06-04 23:29:40 +02:00
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 ) ;
2010-10-05 14:02:41 +02:00
MapWindowPoints ( hwnd , 0 , ( POINT * ) & rt , 2 ) ;
2002-06-04 23:29:40 +02:00
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 ) ;
2010-10-05 14:02:41 +02:00
MapWindowPoints ( hwnd , 0 , ( POINT * ) & rt , 2 ) ;
2002-06-04 23:29:40 +02:00
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 ) ;
}
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 ) ;
if ( g_fullscreen . mode )
fullscreen_move ( hwnd ) ;
resize_frame_client ( hwnd ) ;
}
2009-08-25 00:24:46 +02:00
static BOOL activate_drive_window ( LPCWSTR path )
2002-06-04 23:29:40 +02:00
{
2009-08-25 00:24:41 +02:00
WCHAR drv1 [ _MAX_DRIVE ] , drv2 [ _MAX_DRIVE ] ;
2002-06-04 23:29:40 +02:00
HWND child_wnd ;
2009-08-25 00:23:55 +02:00
_wsplitpath ( path , drv1 , 0 , 0 , 0 ) ;
2002-06-04 23:29:40 +02:00
2013-12-03 14:25:04 +01:00
/* search for an 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 ) ) {
2009-08-25 00:24:19 +02:00
ChildWnd * child = ( ChildWnd * ) GetWindowLongPtrW ( child_wnd , GWLP_USERDATA ) ;
2002-06-04 23:29:40 +02:00
if ( child ) {
2009-08-25 00:23:55 +02:00
_wsplitpath ( child - > root . path , drv2 , 0 , 0 , 0 ) ;
2002-06-04 23:29:40 +02:00
2009-08-25 00:24:11 +02:00
if ( ! lstrcmpiW ( drv2 , drv1 ) ) {
2009-08-25 00:24:06 +02:00
SendMessageW ( Globals . hmdiclient , WM_MDIACTIVATE , ( WPARAM ) child_wnd , 0 ) ;
2002-06-04 23:29:40 +02:00
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 ;
}
2009-08-25 00:24:46 +02:00
static BOOL activate_fs_window ( LPCWSTR filesys )
2003-08-13 03:18:37 +02:00
{
HWND child_wnd ;
2013-12-03 14:25:04 +01:00
/* search for an already open window of the given file system name */
2003-08-13 03:18:37 +02:00
for ( child_wnd = GetNextWindow ( Globals . hmdiclient , GW_CHILD ) ; child_wnd ; child_wnd = GetNextWindow ( child_wnd , GW_HWNDNEXT ) ) {
2009-08-25 00:24:19 +02:00
ChildWnd * child = ( ChildWnd * ) GetWindowLongPtrW ( child_wnd , GWLP_USERDATA ) ;
2003-08-13 03:18:37 +02:00
if ( child ) {
2009-08-25 00:24:11 +02:00
if ( ! lstrcmpiW ( child - > root . fs , filesys ) ) {
2009-08-25 00:24:06 +02:00
SendMessageW ( Globals . hmdiclient , WM_MDIACTIVATE , ( WPARAM ) child_wnd , 0 ) ;
2003-08-13 03:18:37 +02:00
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
{
2009-08-25 00:24:41 +02:00
WCHAR 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 : {
2009-08-25 00:24:06 +02:00
HWND hwndClient = ( HWND ) SendMessageW ( Globals . hmdiclient , WM_MDIGETACTIVE , 0 , 0 ) ;
2005-05-16 10:48:54 +02:00
2009-08-25 00:24:06 +02:00
if ( ! SendMessageW ( hwndClient , WM_INITMENUPOPUP , wparam , lparam ) )
2005-05-16 10:48:54 +02:00
return 0 ;
break ; }
2002-06-04 23:29:40 +02:00
case WM_COMMAND : {
UINT cmd = LOWORD ( wparam ) ;
2009-08-25 00:24:06 +02:00
HWND hwndClient = ( HWND ) SendMessageW ( Globals . hmdiclient , WM_MDIGETACTIVE , 0 , 0 ) ;
2002-06-04 23:29:40 +02:00
2009-08-25 00:24:06 +02:00
if ( SendMessageW ( hwndClient , WM_DISPATCH_COMMAND , wparam , lparam ) )
2002-06-04 23:29:40 +02:00
break ;
if ( cmd > = ID_DRIVE_FIRST & & cmd < = ID_DRIVE_FIRST + 0xFF ) {
2009-08-25 00:24:41 +02:00
WCHAR drv [ _MAX_DRIVE ] , path [ MAX_PATH ] ;
2002-06-04 23:29:40 +02:00
ChildWnd * child ;
2009-08-25 00:24:46 +02:00
LPCWSTR root = Globals . drives ;
2002-06-04 23:29:40 +02:00
int i ;
for ( i = cmd - ID_DRIVE_FIRST ; i - - ; root + + )
while ( * root )
root + + ;
if ( activate_drive_window ( root ) )
return 0 ;
2009-08-25 00:23:55 +02:00
_wsplitpath ( root , drv , 0 , 0 , 0 ) ;
2002-06-04 23:29:40 +02:00
2009-08-25 00:24:30 +02:00
if ( ! SetCurrentDirectoryW ( drv ) ) {
2002-06-04 23:29:40 +02:00
display_error ( hwnd , GetLastError ( ) ) ;
return 0 ;
}
2009-08-25 00:24:30 +02:00
GetCurrentDirectoryW ( MAX_PATH , path ) ; /*TODO: store last directory per drive */
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
} else switch ( cmd ) {
case ID_FILE_EXIT :
2009-08-25 00:24:06 +02:00
SendMessageW ( hwnd , WM_CLOSE , 0 , 0 ) ;
2002-06-04 23:29:40 +02:00
break ;
case ID_WINDOW_NEW : {
2009-08-25 00:24:41 +02:00
WCHAR path [ MAX_PATH ] ;
2002-06-04 23:29:40 +02:00
ChildWnd * child ;
2009-08-25 00:24:30 +02:00
GetCurrentDirectoryW ( 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 :
2009-08-25 00:24:06 +02:00
SendMessageW ( Globals . hmdiclient , WM_MDICASCADE , 0 , 0 ) ;
2002-06-04 23:29:40 +02:00
break ;
case ID_WINDOW_TILE_HORZ :
2009-08-25 00:24:06 +02:00
SendMessageW ( Globals . hmdiclient , WM_MDITILE , MDITILE_HORIZONTAL , 0 ) ;
2002-06-04 23:29:40 +02:00
break ;
case ID_WINDOW_TILE_VERT :
2009-08-25 00:24:06 +02:00
SendMessageW ( Globals . hmdiclient , WM_MDITILE , MDITILE_VERTICAL , 0 ) ;
2002-06-04 23:29:40 +02:00
break ;
case ID_WINDOW_ARRANGE :
2009-08-25 00:24:06 +02:00
SendMessageW ( Globals . hmdiclient , WM_MDIICONARRANGE , 0 , 0 ) ;
2002-06-04 23:29:40 +02:00
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 ;
2009-12-28 17:44:20 +01:00
case ID_RUN :
WineFile_OnRun ( hwnd ) ;
break ;
2002-06-04 23:29:40 +02:00
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 ; }
2002-06-04 23:29:40 +02:00
case ID_HELP :
2009-08-25 00:24:36 +02:00
WinHelpW ( hwnd , RS ( b1 , IDS_WINEFILE ) , HELP_INDEX , 0 ) ;
2002-06-04 23:29:40 +02:00
break ;
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 : {
2009-08-25 00:24:41 +02:00
WCHAR path [ MAX_PATH ] ;
2005-07-07 14:00:17 +02:00
char cpath [ MAX_PATH ] ;
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
getcwd ( cpath , MAX_PATH ) ;
MultiByteToWideChar ( CP_UNIXCP , 0 , cpath , - 1 , path , MAX_PATH ) ;
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
case ID_DRIVE_SHELL_NS : {
2009-08-25 00:24:41 +02:00
WCHAR path [ MAX_PATH ] ;
2003-08-13 03:18:37 +02:00
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 ;
2009-08-25 00:24:30 +02:00
GetCurrentDirectoryW ( MAX_PATH , path ) ;
2003-08-13 03:18:37 +02:00
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 ; }
2002-06-28 19:37:34 +02:00
/*TODO: There are even more menu items! */
2002-06-04 23:29:40 +02:00
2005-06-13 12:04:55 +02:00
case ID_ABOUT :
2009-08-25 00:24:36 +02:00
ShellAboutW ( hwnd , RS ( b1 , IDS_WINEFILE ) , NULL ,
2009-08-25 00:24:25 +02:00
LoadImageW ( Globals . hInstance , MAKEINTRESOURCEW ( IDI_WINEFILE ) ,
2008-03-27 13:44:04 +01:00
IMAGE_ICON , 48 , 48 , LR_SHARED ) ) ;
2003-08-13 03:18:37 +02:00
break ;
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 ) )
2009-08-25 00:24:36 +02:00
MessageBoxW ( hwnd , RS ( b2 , IDS_NO_IMPL ) , RS ( b1 , IDS_WINEFILE ) , MB_OK ) ;
2002-06-04 23:29:40 +02:00
2009-08-25 00:24:36 +02:00
return DefFrameProcW ( hwnd , Globals . hmdiclient , nmsg , wparam , lparam ) ;
2002-06-04 23:29:40 +02:00
}
break ; }
case WM_SIZE :
resize_frame ( hwnd , LOWORD ( lparam ) , HIWORD ( lparam ) ) ;
2009-08-25 00:24:36 +02:00
break ; /* do not pass message to DefFrameProcW */
2002-06-04 23:29:40 +02:00
2006-03-10 21:43:25 +01:00
case WM_DEVICECHANGE :
2009-08-25 00:24:06 +02:00
SendMessageW ( hwnd , WM_COMMAND , MAKELONG ( ID_REFRESH , 0 ) , 0 ) ;
2006-03-10 21:43:25 +01:00
break ;
2002-06-04 23:29:40 +02:00
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 ;
default :
2009-08-25 00:24:36 +02:00
return DefFrameProcW ( hwnd , Globals . hmdiclient , nmsg , wparam , lparam ) ;
2002-06-04 23:29:40 +02:00
}
return 0 ;
}
2013-06-18 11:32:45 +02:00
static WCHAR g_pos_names [ COLUMNS ] [ 40 ] = {
2004-11-22 19:24:09 +01:00
{ ' \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 */
HDF_LEFT , /* ADate */
HDF_LEFT , /* MDate */
HDF_LEFT , /* Index */
HDF_CENTER , /* Links */
HDF_CENTER , /* Attributes */
HDF_LEFT /* Security */
2002-06-04 23:29:40 +02:00
} ;
static void resize_tree ( ChildWnd * child , int cx , int cy )
{
HDWP hdwp = BeginDeferWindowPos ( 4 ) ;
2002-07-03 23:06:58 +02:00
RECT rt ;
2012-03-18 19:22:11 +01:00
WINDOWPOS wp ;
HD_LAYOUT hdl ;
2002-07-03 23:06:58 +02:00
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 ;
2012-03-18 19:22:11 +01:00
hdl . prc = & rt ;
hdl . pwpos = & wp ;
2002-06-04 23:29:40 +02:00
2012-03-18 19:22:11 +01:00
SendMessageW ( child - > left . hwndHeader , HDM_LAYOUT , 0 , ( LPARAM ) & hdl ) ;
2002-06-04 23:29:40 +02:00
2012-03-18 19:22:11 +01: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 ) ;
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 ) ;
}
2008-04-09 14:23:47 +02:00
static HWND create_header ( HWND parent , Pane * pane , UINT id )
2002-06-04 23:29:40 +02:00
{
2009-08-25 00:24:52 +02:00
HDITEMW hdi ;
2002-06-04 23:29:40 +02:00
int idx ;
2009-08-25 00:24:19 +02:00
HWND hwnd = CreateWindowW ( WC_HEADERW , 0 , WS_CHILD | WS_VISIBLE | HDS_HORZ | HDS_FULLDRAG /*TODO: |HDS_BUTTONS + sort orders*/ ,
2008-04-09 14:23:47 +02:00
0 , 0 , 0 , 0 , parent , ( HMENU ) ULongToHandle ( id ) , Globals . hInstance , 0 ) ;
2002-06-04 23:29:40 +02:00
if ( ! hwnd )
return 0 ;
2009-08-25 00:24:06 +02:00
SendMessageW ( 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 ] ;
2009-08-25 00:24:06 +02:00
SendMessageW ( hwnd , HDM_INSERTITEMW , idx , ( LPARAM ) & hdi ) ;
2002-06-04 23:29:40 +02:00
}
return hwnd ;
}
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 ;
2009-08-25 00:24:06 +02:00
int entries = SendMessageW ( 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 + + ) {
2009-08-25 00:24:06 +02:00
Entry * entry = ( Entry * ) SendMessageW ( 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 ;
2009-08-25 00:24:06 +02:00
SendMessageW ( pane - > hwnd , LB_SETHORIZONTALEXTENT , x , 0 ) ;
2002-06-04 23:29:40 +02:00
2002-06-28 19:37:34 +02:00
/* no change? */
2008-07-17 19:53:16 +02:00
if ( ! anyway & & ! memcmp ( orgWidths , pane - > widths , sizeof ( orgWidths ) ) )
2002-06-04 23:29:40 +02:00
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 ;
2009-08-25 00:24:06 +02:00
int entries = SendMessageW ( 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 + + ) {
2009-08-25 00:24:06 +02:00
Entry * entry = ( Entry * ) SendMessageW ( 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 ;
2009-01-24 09:52:36 +01:00
for ( ; col < COLUMNS - 1 ; ) {
2002-06-04 23:29:40 +02:00
pane - > positions [ + + col ] = x ;
x + = pane - > widths [ col ] ;
}
2009-08-25 00:24:06 +02:00
SendMessageW ( pane - > hwnd , LB_SETHORIZONTALEXTENT , x , 0 ) ;
2002-06-04 23:29:40 +02:00
}
2009-08-25 00:24:46 +02:00
static BOOL pattern_match ( LPCWSTR str , LPCWSTR pattern )
2005-05-29 22:05:29 +02:00
{
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 ;
}
2009-08-25 00:24:46 +02:00
static BOOL pattern_imatch ( LPCWSTR str , LPCWSTR pattern )
2005-07-07 14:00:17 +02:00
{
2009-08-25 00:24:41 +02:00
WCHAR b1 [ BUFFER_LEN ] , b2 [ BUFFER_LEN ] ;
2005-07-07 14:00:17 +02:00
2009-08-25 00:24:11 +02:00
lstrcpyW ( b1 , str ) ;
lstrcpyW ( b2 , pattern ) ;
2009-08-25 00:24:36 +02:00
CharUpperW ( b1 ) ;
CharUpperW ( b2 ) ;
2005-07-07 14:00:17 +02:00
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
} ;
2009-08-25 00:24:46 +02:00
static enum FILE_TYPE get_file_type ( LPCWSTR filename ) ;
2005-05-29 22:05:29 +02:00
2002-06-28 19:37:34 +02:00
/* insert listbox entries after index idx */
2002-06-04 23:29:40 +02:00
2009-08-25 00:24:46 +02:00
static int insert_entries ( Pane * pane , Entry * dir , LPCWSTR 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 ) {
if ( pane - > treePane & & ! ( entry - > data . dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) )
continue ;
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 ] = = ' . ' )
2012-03-18 19:22:11 +01:00
if ( entry - > data . cFileName [ 1 ] = = ' \0 ' | |
( 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 + + ;
2009-08-25 00:24:06 +02:00
SendMessageW ( 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
}
2009-08-25 00:24:46 +02:00
static void format_bytes ( LPWSTR buffer , LONGLONG bytes )
2005-05-14 13:07:39 +02:00
{
2011-11-19 15:09:53 +01:00
static const WCHAR sFmtSmall [ ] = { ' % ' , ' u ' , 0 } ;
static const WCHAR sFmtBig [ ] = { ' % ' , ' . ' , ' 1 ' , ' f ' , ' ' , ' % ' , ' s ' , ' \0 ' } ;
if ( bytes < 1024 )
sprintfW ( buffer , sFmtSmall , ( DWORD ) bytes ) ;
2005-05-14 13:07:39 +02:00
else
2011-11-19 15:09:53 +01:00
{
WCHAR unit [ 64 ] ;
UINT resid ;
float fBytes ;
if ( bytes > = 1073741824 ) /* 1 GB */
{
fBytes = ( ( float ) bytes ) / 1073741824.f + .5f ;
resid = IDS_UNIT_GB ;
}
else if ( bytes > = 1048576 ) /* 1 MB */
{
fBytes = ( ( float ) bytes ) / 1048576.f + .5f ;
resid = IDS_UNIT_MB ;
}
2013-10-15 22:34:59 +02:00
else /* bytes >= 1024 */ /* 1 kB */
2011-11-19 15:09:53 +01:00
{
fBytes = ( ( float ) bytes ) / 1024.f + .5f ;
resid = IDS_UNIT_KB ;
}
LoadStringW ( Globals . hInstance , resid , unit , sizeof ( unit ) / sizeof ( * unit ) ) ;
sprintfW ( buffer , sFmtBig , fBytes , unit ) ;
}
2005-05-14 13:07:39 +02:00
}
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 ;
2009-08-25 00:24:41 +02:00
WCHAR fmt [ 64 ] , b1 [ 64 ] , b2 [ 64 ] , buffer [ BUFFER_LEN ] ;
2005-05-14 13:07:39 +02:00
2009-08-25 00:24:30 +02:00
if ( GetDiskFreeSpaceExW ( NULL , & ulFreeBytesToCaller , & ulTotalBytes , & ulFreeBytes ) ) {
2011-10-20 14:48:10 +02:00
DWORD_PTR args [ 2 ] ;
2005-05-14 13:07:39 +02:00
format_bytes ( b1 , ulFreeBytesToCaller . QuadPart ) ;
format_bytes ( b2 , ulTotalBytes . QuadPart ) ;
2011-10-20 14:48:10 +02:00
args [ 0 ] = ( DWORD_PTR ) b1 ;
args [ 1 ] = ( DWORD_PTR ) b2 ;
FormatMessageW ( FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY ,
RS ( fmt , IDS_FREE_SPACE_FMT ) , 0 , 0 , buffer ,
sizeof ( buffer ) / sizeof ( * buffer ) , ( __ms_va_list * ) args ) ;
2005-05-14 13:07:39 +02:00
} else
2009-08-25 00:24:11 +02:00
lstrcpyW ( buffer , sQMarks ) ;
2005-05-14 13:07:39 +02:00
2009-08-25 00:24:06 +02:00
SendMessageW ( Globals . hstatusbar , SB_SETTEXTW , 0 , ( LPARAM ) buffer ) ;
2005-05-14 13:07:39 +02:00
}
2002-06-04 23:29:40 +02:00
static WNDPROC g_orgTreeWndProc ;
2009-08-25 00:24:46 +02:00
static void create_tree_window ( HWND parent , Pane * pane , UINT id , UINT id_header , LPCWSTR pattern , int filter_flags )
2002-06-04 23:29:40 +02:00
{
2009-08-25 00:24:41 +02:00
static const WCHAR sListBox [ ] = { ' L ' , ' i ' , ' s ' , ' t ' , ' B ' , ' o ' , ' x ' , ' \0 ' } ;
2004-11-22 19:24:09 +01:00
2013-10-16 23:38:34 +02:00
static BOOL s_init = FALSE ;
2002-06-04 23:29:40 +02:00
Entry * entry = pane - > root ;
2009-08-25 00:24:19 +02:00
pane - > hwnd = CreateWindowW ( sListBox , sEmpty , WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL |
2008-04-09 14:23:47 +02:00
LBS_DISABLENOSCROLL | LBS_NOINTEGRALHEIGHT | LBS_OWNERDRAWFIXED | LBS_NOTIFY ,
0 , 0 , 0 , 0 , parent , ( HMENU ) ULongToHandle ( id ) , Globals . hInstance , 0 ) ;
2002-06-04 23:29:40 +02:00
2009-08-25 00:24:19 +02:00
SetWindowLongPtrW ( pane - > hwnd , GWLP_USERDATA , ( LPARAM ) pane ) ;
g_orgTreeWndProc = ( WNDPROC ) SetWindowLongPtrW ( pane - > hwnd , GWLP_WNDPROC , ( LPARAM ) TreeWndProc ) ;
2002-06-04 23:29:40 +02:00
2009-08-25 00:24:06 +02:00
SendMessageW ( 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 ) {
2013-10-16 23:38:34 +02:00
s_init = TRUE ;
2002-06-04 23:29:40 +02:00
init_output ( pane - > hwnd ) ;
}
calc_widths ( pane , TRUE ) ;
pane - > hwndHeader = create_header ( parent , pane , id_header ) ;
}
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
}
2009-08-25 00:24:41 +02:00
static void format_date ( const FILETIME * ft , WCHAR * buffer , int visible_cols )
2002-06-04 23:29:40 +02:00
{
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 ) )
2009-08-25 00:24:11 +02:00
{ err : lstrcpyW ( buffer , sQMarks ) ; return ; }
2002-06-04 23:29:40 +02:00
if ( ! FileTimeToSystemTime ( & lft , & systime ) )
goto err ;
if ( visible_cols & COL_DATE ) {
2009-08-25 00:24:36 +02:00
len = GetDateFormatW ( LOCALE_USER_DEFAULT , 0 , & systime , 0 , buffer , BUFFER_LEN ) ;
2002-06-04 23:29:40 +02:00
if ( ! len )
goto err ;
}
if ( visible_cols & COL_TIME ) {
if ( len )
buffer [ len - 1 ] = ' ' ;
buffer [ len + + ] = ' ' ;
2009-08-25 00:24:36 +02:00
if ( ! GetTimeFormatW ( 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
}
}
2009-08-25 00:24:46 +02:00
static void calc_width ( Pane * pane , LPDRAWITEMSTRUCT dis , int col , LPCWSTR str )
2002-06-04 23:29:40 +02:00
{
2003-08-13 03:18:37 +02:00
RECT rt = { 0 , 0 , 0 , 0 } ;
2002-06-04 23:29:40 +02:00
2009-08-25 00:24:36 +02:00
DrawTextW ( 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 ;
}
2009-08-25 00:24:46 +02:00
static void calc_tabbed_width ( Pane * pane , LPDRAWITEMSTRUCT dis , int col , LPCWSTR str )
2002-06-04 23:29:40 +02:00
{
2003-08-13 03:18:37 +02:00
RECT rt = { 0 , 0 , 0 , 0 } ;
2002-06-04 23:29:40 +02:00
2009-08-25 00:24:36 +02:00
DrawTextW ( 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 ;
}
2009-08-25 00:24:46 +02:00
static void output_text ( Pane * pane , LPDRAWITEMSTRUCT dis , int col , LPCWSTR str , DWORD flags )
2002-06-04 23:29:40 +02:00
{
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
2009-08-25 00:24:36 +02:00
DrawTextW ( dis - > hDC , str , - 1 , & rt , DT_SINGLELINE | DT_NOPREFIX | flags ) ;
2002-06-04 23:29:40 +02:00
}
2009-08-25 00:24:46 +02:00
static void output_tabbed_text ( Pane * pane , LPDRAWITEMSTRUCT dis , int col , LPCWSTR str )
2002-06-04 23:29:40 +02:00
{
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
2009-08-25 00:24:36 +02:00
DrawTextW ( dis - > hDC , str , - 1 , & rt , DT_SINGLELINE | DT_EXPANDTABS | DT_TABSTOP | ( 2 < < 8 ) ) ;
2002-06-04 23:29:40 +02:00
}
2009-08-25 00:24:46 +02:00
static void output_number ( Pane * pane , LPDRAWITEMSTRUCT dis , int col , LPCWSTR str )
2002-06-04 23:29:40 +02:00
{
int x = dis - > rcItem . left ;
2002-07-03 23:06:58 +02:00
RECT rt ;
2009-08-25 00:24:46 +02:00
LPCWSTR s = str ;
2009-08-25 00:24:41 +02:00
WCHAR b [ 128 ] ;
2009-08-25 00:24:46 +02:00
LPWSTR d = b ;
2002-06-04 23:29:40 +02:00
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 */
2009-08-25 00:24:11 +02:00
pos = lstrlenW ( s ) % 3 ;
2002-06-04 23:29:40 +02:00
while ( * s )
if ( pos - - )
* d + + = * s + + ;
else {
* d + + = Globals . num_sep ;
pos = 3 ;
}
2009-08-25 00:24:36 +02:00
DrawTextW ( dis - > hDC , b , d - b , & rt , DT_RIGHT | DT_SINGLELINE | DT_NOPREFIX | DT_END_ELLIPSIS ) ;
2002-06-04 23:29:40 +02:00
}
2009-08-25 00:24:46 +02:00
static BOOL is_exe_file ( LPCWSTR ext )
2002-06-04 23:29:40 +02:00
{
2009-08-25 00:24:41 +02:00
static const WCHAR executable_extensions [ ] [ 4 ] = {
2004-11-22 19:24:09 +01:00
{ ' C ' , ' O ' , ' M ' , ' \0 ' } ,
{ ' E ' , ' X ' , ' E ' , ' \0 ' } ,
{ ' B ' , ' A ' , ' T ' , ' \0 ' } ,
{ ' C ' , ' M ' , ' D ' , ' \0 ' } ,
{ ' C ' , ' M ' , ' M ' , ' \0 ' } ,
{ ' B ' , ' T ' , ' M ' , ' \0 ' } ,
{ ' A ' , ' W ' , ' K ' , ' \0 ' } ,
{ ' \0 ' }
2002-06-04 23:29:40 +02:00
} ;
2009-08-25 00:24:41 +02:00
WCHAR ext_buffer [ _MAX_EXT ] ;
const WCHAR ( * p ) [ 4 ] ;
2009-08-25 00:24:46 +02:00
LPCWSTR s ;
LPWSTR d ;
2002-06-04 23:29:40 +02:00
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 + + )
2009-08-25 00:24:11 +02:00
if ( ! lstrcmpiW ( 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
}
2009-08-25 00:24:46 +02:00
static BOOL is_registered_type ( LPCWSTR 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 */
2009-08-25 00:24:36 +02:00
if ( ! RegQueryValueW ( HKEY_CLASSES_ROOT , ext , NULL , NULL ) )
2005-05-29 22:05:29 +02:00
return TRUE ;
return FALSE ;
}
2002-06-04 23:29:40 +02:00
2009-08-25 00:24:46 +02:00
static enum FILE_TYPE get_file_type ( LPCWSTR filename )
2005-05-29 22:05:29 +02:00
{
2009-08-25 00:24:46 +02:00
LPCWSTR ext = strrchrW ( filename , ' . ' ) ;
2005-05-29 22:05:29 +02:00
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 )
{
2009-08-25 00:24:41 +02:00
WCHAR buffer [ BUFFER_LEN ] ;
2002-06-04 23:29:40 +02:00
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 ;
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 ;
2012-03-18 19:22:11 +01:00
else if ( pane - > treePane & & ( dis - > itemState & ODS_FOCUS ) )
2002-06-04 23:29:40 +02:00
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 ;
}
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
2003-08-13 03:18:37 +02:00
& & ( up - > next - > data . dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
2002-06-04 23:29:40 +02:00
) {
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
2012-03-18 19:22:11 +01:00
& & ( entry - > next - > data . dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) )
2002-06-04 23:29:40 +02:00
LineTo ( dis - > hDC , x , dis - > rcItem . bottom ) ;
SelectClipRgn ( dis - > hDC , hrgn_org ) ;
if ( hrgn_org ) DeleteObject ( hrgn_org ) ;
} 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 ;
if ( attrs & FILE_ATTRIBUTE_COMPRESSED )
textcolor = COLOR_COMPRESSED ;
else
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
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
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 ;
col + + ;
2011-08-24 15:28:14 +02:00
/* output 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 + + ;
2002-06-28 19:37:34 +02:00
/* display file size */
2002-06-04 23:29:40 +02:00
if ( visible_cols & COL_SIZE ) {
2012-03-18 19:22:11 +01:00
format_longlong ( buffer , ( ( ULONGLONG ) entry - > data . nFileSizeHigh < < 32 ) | entry - > data . nFileSizeLow ) ;
2002-06-04 23:29:40 +02:00
2012-03-18 19:22:11 +01:00
if ( calcWidthCol = = - 1 )
output_number ( pane , dis , col , buffer ) ;
else if ( calcWidthCol = = col | | calcWidthCol = = COLUMNS )
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 ) ) {
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 + + ;
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 + + ;
}
if ( entry - > bhfi_valid ) {
if ( visible_cols & COL_INDEX ) {
2009-08-25 00:24:41 +02:00
static const WCHAR fmtlow [ ] = { ' % ' , ' X ' , 0 } ;
static const WCHAR fmthigh [ ] = { ' % ' , ' X ' , ' % ' , ' 0 ' , ' 8 ' , ' X ' , 0 } ;
2009-01-06 20:52:55 +01:00
if ( entry - > bhfi . nFileIndexHigh )
2009-08-25 00:24:11 +02:00
wsprintfW ( buffer , fmthigh ,
2009-01-06 20:52:55 +01:00
entry - > bhfi . nFileIndexHigh , entry - > bhfi . nFileIndexLow ) ;
else
2009-08-25 00:24:11 +02:00
wsprintfW ( buffer , fmtlow , entry - > bhfi . nFileIndexLow ) ;
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_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 ) {
2009-08-25 00:24:11 +02:00
wsprintfW ( 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 ;
2002-06-28 19:37:34 +02:00
/* show file attributes */
2002-06-04 23:29:40 +02:00
if ( visible_cols & COL_ATTRIBUTES ) {
2009-08-25 00:24:41 +02:00
static const WCHAR s11Tabs [ ] = { ' ' , ' \t ' , ' ' , ' \t ' , ' ' , ' \t ' , ' ' , ' \t ' , ' ' , ' \t ' , ' ' , ' \t ' , ' ' , ' \t ' , ' ' , ' \t ' , ' ' , ' \t ' , ' ' , ' \t ' , ' ' , ' \t ' , ' ' , ' \0 ' } ;
2009-08-25 00:24:11 +02:00
lstrcpyW ( buffer , s11Tabs ) ;
2002-06-04 23:29:40 +02:00
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 ' ;
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 ' ;
}
if ( calcWidthCol = = - 1 )
output_tabbed_text ( pane , dis , col , buffer ) ;
else if ( calcWidthCol = = col | | calcWidthCol = = COLUMNS )
calc_tabbed_width ( pane , dis , col , buffer ) ;
col + + ;
}
}
static void set_header ( Pane * pane )
{
2009-08-25 00:24:52 +02:00
HDITEMW item ;
2002-06-04 23:29:40 +02:00
int scroll_pos = GetScrollPos ( pane - > hwnd , SB_HORZ ) ;
int i = 0 , x = 0 ;
item . mask = HDI_WIDTH ;
item . cxy = 0 ;
2012-10-13 16:58:05 +02:00
for ( ; ( i < COLUMNS ) & & ( x + pane - > widths [ i ] < scroll_pos ) ; i + + ) {
2002-06-04 23:29:40 +02:00
x + = pane - > widths [ i ] ;
2009-08-25 00:24:06 +02:00
SendMessageW ( pane - > hwndHeader , HDM_SETITEMW , i , ( LPARAM ) & item ) ;
2002-06-04 23:29:40 +02:00
}
if ( i < COLUMNS ) {
x + = pane - > widths [ i ] ;
item . cxy = x - scroll_pos ;
2009-08-25 00:24:06 +02:00
SendMessageW ( pane - > hwndHeader , HDM_SETITEMW , i + + , ( LPARAM ) & item ) ;
2002-06-04 23:29:40 +02:00
2012-10-13 16:58:05 +02:00
for ( ; i < COLUMNS ; i + + ) {
2002-06-04 23:29:40 +02:00
item . cxy = pane - > widths [ i ] ;
x + = pane - > widths [ i ] ;
2009-08-25 00:24:06 +02:00
SendMessageW ( pane - > hwndHeader , HDM_SETITEMW , i , ( LPARAM ) & item ) ;
2002-06-04 23:29:40 +02:00
}
}
}
static LRESULT pane_notify ( Pane * pane , NMHDR * pnmh )
{
switch ( pnmh - > code ) {
2009-08-25 00:24:52 +02:00
case HDN_ITEMCHANGEDW : {
LPNMHEADERW phdn = ( LPNMHEADERW ) pnmh ;
2002-06-04 23:29:40 +02:00
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 ) ;
2009-08-25 00:24:52 +02:00
if ( pnmh - > code = = HDN_ENDTRACKW ) {
2009-08-25 00:24:06 +02:00
SendMessageW ( 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 ;
}
2009-08-25 00:24:52 +02:00
case HDN_DIVIDERDBLCLICKW : {
LPNMHEADERW phdn = ( LPNMHEADERW ) pnmh ;
HDITEMW item ;
2002-06-04 23:29:40 +02:00
calc_single_width ( pane , phdn - > iItem ) ;
item . mask = HDI_WIDTH ;
item . cxy = pane - > widths [ phdn - > iItem ] ;
2009-08-25 00:24:06 +02:00
SendMessageW ( pane - > hwndHeader , HDM_SETITEMW , phdn - > iItem , ( LPARAM ) & item ) ;
2002-06-04 23:29:40 +02:00
InvalidateRect ( pane - > hwnd , 0 , TRUE ) ;
break ; }
}
return 0 ;
}
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
{
2009-08-25 00:24:41 +02:00
WCHAR path [ MAX_PATH ] ;
2009-08-25 00:24:25 +02:00
HCURSOR old_cursor = SetCursor ( LoadCursorW ( 0 , ( LPCWSTR ) 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 ( ; ; ) {
2009-08-25 00:24:06 +02:00
LRESULT res = SendMessageW ( 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 ;
2009-08-25 00:24:06 +02:00
SendMessageW ( 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 */
2009-08-25 00:24:06 +02:00
SendMessageW ( 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
if ( entry - > etype = = ET_SHELL )
{
read_directory ( entry , NULL , child - > sortOrder , hwnd ) ;
}
else
{
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 ) ;
set_header ( & child - > right ) ;
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 ;
2009-08-25 00:24:06 +02:00
idx = SendMessageW ( 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 ) ) {
set_header ( & child - > left ) ;
child - > header_wdths_ok = TRUE ;
}
}
return TRUE ;
}
static void collapse_entry ( Pane * pane , Entry * dir )
{
2012-02-14 19:33:54 +01:00
int idx ;
if ( ! dir ) return ;
idx = SendMessageW ( 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 ( ; ; ) {
2009-08-25 00:24:06 +02:00
LRESULT res = SendMessageW ( 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 ;
2009-08-25 00:24:06 +02:00
SendMessageW ( 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 )
{
2009-08-25 00:24:06 +02:00
SendMessageW ( 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 ) ;
set_header ( & child - > right ) ;
}
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
{
2009-08-25 00:24:41 +02:00
WCHAR path [ MAX_PATH ] ;
2002-06-04 23:29:40 +02:00
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 ) ;
2009-08-25 00:24:11 +02:00
lstrcpyW ( child - > path , path ) ;
2002-10-18 02:20:25 +02:00
if ( child - > hwnd ) /* only change window title, if the window already exists */
2009-08-25 00:24:19 +02:00
SetWindowTextW ( child - > hwnd , path ) ;
2002-10-18 02:20:25 +02:00
2003-08-13 03:18:37 +02:00
if ( path [ 0 ] )
2009-08-25 00:24:30 +02:00
if ( SetCurrentDirectoryW ( path ) )
2005-05-14 13:07:39 +02:00
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 )
{
2009-08-25 00:24:41 +02:00
WCHAR path [ MAX_PATH ] , drv [ _MAX_DRIVE + 1 ] ;
2005-05-16 10:48:54 +02:00
Entry * entry ;
int idx ;
get_path ( child - > left . cur , path ) ;
2009-08-25 00:23:55 +02:00
_wsplitpath ( path , drv , NULL , NULL , NULL ) ;
2005-05-16 10:48:54 +02:00
child - > right . root = NULL ;
scan_entry ( child , & child - > root . entry , 0 , child - > hwnd ) ;
2005-07-07 22:27:24 +02:00
if ( child - > root . entry . etype = = ET_SHELL )
2009-01-10 10:48:54 +01:00
{
LPITEMIDLIST local_pidl = get_path_pidl ( path , child - > hwnd ) ;
if ( local_pidl )
entry = read_tree ( & child - > root , NULL , local_pidl , drv , child - > sortOrder , child - > hwnd ) ;
else
entry = NULL ;
}
2005-07-07 22:27:24 +02:00
else
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 ) ;
2009-08-25 00:24:06 +02:00
idx = SendMessageW ( child - > left . hwnd , LB_FINDSTRING , 0 , ( LPARAM ) child - > left . cur ) ;
SendMessageW ( 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 } ;
2009-08-25 00:24:41 +02:00
WCHAR b1 [ BUFFER_LEN ] ;
2005-05-16 23:36:41 +02:00
int btn = 1 ;
2009-08-25 00:24:46 +02:00
PWSTR p ;
2005-05-16 23:36:41 +02:00
2009-08-25 00:24:30 +02:00
GetLogicalDriveStringsW ( BUFFER_LEN , Globals . drives ) ;
2005-05-16 23:36:41 +02:00
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
# ifdef __WINE__
/* insert unix file system button */
b1 [ 0 ] = ' / ' ;
b1 [ 1 ] = ' \0 ' ;
b1 [ 2 ] = ' \0 ' ;
2009-08-25 00:24:06 +02:00
SendMessageW ( Globals . hdrivebar , TB_ADDSTRINGW , 0 , ( LPARAM ) b1 ) ;
2005-05-16 23:36:41 +02:00
drivebarBtn . idCommand = ID_DRIVE_UNIX_FS ;
2009-08-25 00:24:06 +02:00
SendMessageW ( Globals . hdrivebar , TB_INSERTBUTTONW , btn + + , ( LPARAM ) & drivebarBtn ) ;
2005-05-16 23:36:41 +02:00
drivebarBtn . iString + + ;
# endif
/* insert shell namespace button */
2008-09-13 22:43:34 +02:00
load_string ( b1 , sizeof ( b1 ) / sizeof ( b1 [ 0 ] ) , IDS_SHELL ) ;
2009-08-25 00:24:11 +02:00
b1 [ lstrlenW ( b1 ) + 1 ] = ' \0 ' ;
2009-08-25 00:24:06 +02:00
SendMessageW ( Globals . hdrivebar , TB_ADDSTRINGW , 0 , ( LPARAM ) b1 ) ;
2005-05-16 23:36:41 +02:00
drivebarBtn . idCommand = ID_DRIVE_SHELL_NS ;
2009-08-25 00:24:06 +02:00
SendMessageW ( Globals . hdrivebar , TB_INSERTBUTTONW , btn + + , ( LPARAM ) & drivebarBtn ) ;
2005-05-16 23:36:41 +02:00
drivebarBtn . iString + + ;
/* register windows drive root strings */
2009-08-25 00:24:06 +02:00
SendMessageW ( Globals . hdrivebar , TB_ADDSTRINGW , 0 , ( LPARAM ) Globals . drives ) ;
2005-05-16 23:36:41 +02:00
drivebarBtn . idCommand = ID_DRIVE_FIRST ;
for ( p = Globals . drives ; * p ; ) {
2009-08-25 00:24:30 +02:00
switch ( GetDriveTypeW ( p ) ) {
2005-05-16 23:36:41 +02:00
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 ;
}
2009-08-25 00:24:06 +02:00
SendMessageW ( Globals . hdrivebar , TB_INSERTBUTTONW , btn + + , ( LPARAM ) & drivebarBtn ) ;
2005-05-16 23:36:41 +02:00
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 ) ;
2009-08-25 00:24:06 +02:00
SendMessageW ( Globals . hMainWnd , WM_SIZE , 0 , MAKELONG ( rect . right , rect . bottom ) ) ;
2005-05-16 23:36:41 +02:00
}
2009-08-25 00:24:46 +02:00
static BOOL launch_file ( HWND hwnd , LPCWSTR cmd , UINT nCmdShow )
2003-08-13 03:18:37 +02:00
{
2009-08-25 00:24:36 +02:00
HINSTANCE hinst = ShellExecuteW ( hwnd , NULL /*operation*/ , cmd , NULL /*parameters*/ , NULL /*dir*/ , nCmdShow ) ;
2003-08-13 03:18:37 +02:00
2008-04-09 14:23:47 +02:00
if ( PtrToUlong ( hinst ) < = 32 ) {
2003-08-13 03:18:37 +02:00
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
{
2009-08-25 00:24:41 +02:00
WCHAR cmd [ MAX_PATH ] ;
2003-08-13 03:18:37 +02:00
if ( entry - > etype = = ET_SHELL ) {
BOOL ret = TRUE ;
2009-08-25 00:24:52 +02:00
SHELLEXECUTEINFOW shexinfo ;
2003-08-13 03:18:37 +02:00
2009-08-25 00:24:52 +02:00
shexinfo . cbSize = sizeof ( SHELLEXECUTEINFOW ) ;
2003-08-13 03:18:37 +02:00
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 ) ;
2009-08-25 00:24:36 +02:00
if ( ! ShellExecuteExW ( & shexinfo ) ) {
2003-08-13 03:18:37 +02:00
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 ;
}
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
{
2009-08-25 00:24:06 +02:00
int idx = SendMessageW ( child - > left . hwnd , LB_GETCURSEL , 0 , 0 ) ;
2006-03-17 16:57:16 +01:00
scan_entry ( child , entry , idx , hwnd ) ;
}
2002-06-04 23:29:40 +02:00
if ( entry - > data . cFileName [ 0 ] = = ' . ' & & entry - > data . cFileName [ 1 ] = = ' \0 ' )
return ;
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 : {
2009-08-25 00:24:06 +02:00
int idxstart = SendMessageW ( child - > left . hwnd , LB_GETCURSEL , 0 , 0 ) ;
int idx = SendMessageW ( child - > left . hwnd , LB_FINDSTRING , idxstart , ( LPARAM ) entry ) ;
SendMessageW ( 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 ) ;
set_header ( pane ) ;
}
} 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 ) ;
set_header ( pane ) ;
InvalidateRect ( pane - > hwnd , 0 , TRUE ) ;
CheckMenuItem ( Globals . hMenuView , ID_VIEW_NAME , MF_BYCOMMAND | MF_CHECKED ) ;
CheckMenuItem ( Globals . hMenuView , ID_VIEW_ALL_ATTRIBUTES , MF_BYCOMMAND ) ;
}
break ;
case ID_VIEW_ALL_ATTRIBUTES :
if ( pane - > visible_cols ! = COL_ALL ) {
pane - > visible_cols = COL_ALL ;
calc_widths ( pane , TRUE ) ;
set_header ( pane ) ;
InvalidateRect ( pane - > hwnd , 0 , TRUE ) ;
CheckMenuItem ( Globals . hMenuView , ID_VIEW_NAME , MF_BYCOMMAND ) ;
CheckMenuItem ( Globals . hMenuView , ID_VIEW_ALL_ATTRIBUTES , MF_BYCOMMAND | MF_CHECKED ) ;
}
break ;
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 ; }
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 ) ;
}
2009-08-25 00:24:46 +02:00
static BOOL is_directory ( LPCWSTR target )
2005-05-30 11:55:19 +02:00
{
/*TODO correctly handle UNIX paths */
2009-08-25 00:24:30 +02:00
DWORD target_attr = GetFileAttributesW ( target ) ;
2005-05-30 11:55:19 +02:00
if ( target_attr = = INVALID_FILE_ATTRIBUTES )
return FALSE ;
2012-08-14 23:43:24 +02:00
return ( target_attr & FILE_ATTRIBUTE_DIRECTORY ) ! = 0 ;
2005-05-30 11:55:19 +02:00
}
2009-08-25 00:24:46 +02:00
static BOOL prompt_target ( Pane * pane , LPWSTR source , LPWSTR target )
2005-05-30 11:55:19 +02:00
{
2009-08-25 00:24:41 +02:00
WCHAR path [ MAX_PATH ] ;
2005-05-30 11:55:19 +02:00
int len ;
get_path ( pane - > cur , path ) ;
2009-08-25 00:24:36 +02:00
if ( DialogBoxParamW ( Globals . hInstance , MAKEINTRESOURCEW ( IDD_SELECT_DESTINATION ) , pane - > hwnd , DestinationDlgProc , ( LPARAM ) path ) ! = IDOK )
2005-05-30 11:55:19 +02:00
return FALSE ;
get_path ( pane - > cur , source ) ;
/* convert relative targets to absolute paths */
if ( path [ 0 ] ! = ' / ' & & path [ 1 ] ! = ' : ' ) {
get_path ( pane - > cur - > up , target ) ;
2009-08-25 00:24:11 +02:00
len = lstrlenW ( target ) ;
2005-05-30 11:55:19 +02:00
if ( target [ len - 1 ] ! = ' \\ ' & & target [ len - 1 ] ! = ' / ' )
target [ len + + ] = ' / ' ;
2009-08-25 00:24:11 +02:00
lstrcpyW ( target + len , path ) ;
2005-05-30 11:55:19 +02:00
} else
2009-08-25 00:24:11 +02:00
lstrcpyW ( target , path ) ;
2005-05-30 11:55:19 +02:00
/* If the target already exists as directory, create a new target below this. */
if ( is_directory ( path ) ) {
2009-08-25 00:24:41 +02:00
WCHAR fname [ _MAX_FNAME ] , ext [ _MAX_EXT ] ;
static const WCHAR sAppend [ ] = { ' % ' , ' s ' , ' / ' , ' % ' , ' s ' , ' % ' , ' s ' , ' \0 ' } ;
2005-05-30 11:55:19 +02:00
2009-08-25 00:23:55 +02:00
_wsplitpath ( source , NULL , NULL , fname , ext ) ;
2005-05-30 11:55:19 +02:00
2009-08-25 00:24:11 +02:00
wsprintfW ( target , sAppend , path , fname , ext ) ;
2005-05-30 11:55:19 +02:00
}
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
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
{
2009-08-25 00:24:19 +02:00
ChildWnd * child = ( ChildWnd * ) GetWindowLongPtrW ( 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 ) ;
2009-08-25 00:24:19 +02:00
SetWindowLongPtrW ( 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 ) ;
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 ) {
2009-08-25 00:24:25 +02:00
SetCursor ( LoadCursorW ( 0 , ( LPCWSTR ) IDC_SIZEWE ) ) ;
2002-06-04 23:29:40 +02:00
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 ;
SetCapture ( hwnd ) ;
}
break ; }
case WM_LBUTTONUP :
2012-03-18 19:22:11 +01:00
if ( GetCapture ( ) = = hwnd )
ReleaseCapture ( ) ;
2002-06-04 23:29:40 +02:00
break ;
case WM_KEYDOWN :
if ( wparam = = VK_ESCAPE )
if ( GetCapture ( ) = = hwnd ) {
RECT rt ;
child - > split_pos = last_split ;
GetClientRect ( hwnd , & rt ) ;
resize_tree ( child , rt . right , rt . bottom ) ;
last_split = - 1 ;
ReleaseCapture ( ) ;
2009-08-25 00:24:25 +02:00
SetCursor ( LoadCursorW ( 0 , ( LPCWSTR ) IDC_ARROW ) ) ;
2002-06-04 23:29:40 +02:00
}
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
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 ) ;
}
}
break ;
case WM_GETMINMAXINFO :
2009-08-25 00:24:36 +02:00
DefMDIChildProcW ( hwnd , nmsg , wparam , lparam ) ;
2002-06-04 23:29:40 +02:00
{ 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 WM_SETFOCUS :
2009-08-25 00:24:30 +02:00
if ( SetCurrentDirectoryW ( child - > path ) )
2005-05-14 13:07:39 +02:00
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 : {
2009-08-25 00:24:41 +02:00
WCHAR 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 ) ) {
2009-08-25 00:24:52 +02:00
SHFILEOPSTRUCTW shfo = { hwnd , FO_MOVE , source , target } ;
2005-05-13 19:46:11 +02:00
2009-08-25 00:24:11 +02:00
source [ lstrlenW ( source ) + 1 ] = ' \0 ' ;
target [ lstrlenW ( target ) + 1 ] = ' \0 ' ;
2004-10-07 06:25:29 +02:00
2009-08-25 00:24:30 +02:00
if ( ! SHFileOperationW ( & shfo ) )
2005-05-30 11:55:19 +02:00
refresh_child ( child ) ;
}
break ; }
2004-10-07 06:25:29 +02:00
2005-05-30 11:55:19 +02:00
case ID_FILE_COPY : {
2009-08-25 00:24:41 +02:00
WCHAR 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 ) ) {
2009-08-25 00:24:52 +02:00
SHFILEOPSTRUCTW shfo = { hwnd , FO_COPY , source , target } ;
2004-10-07 06:25:29 +02:00
2009-08-25 00:24:11 +02:00
source [ lstrlenW ( source ) + 1 ] = ' \0 ' ;
target [ lstrlenW ( target ) + 1 ] = ' \0 ' ;
2004-10-07 06:25:29 +02:00
2009-08-25 00:24:30 +02:00
if ( ! SHFileOperationW ( & 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 : {
2009-08-25 00:24:41 +02:00
WCHAR path [ BUFFER_LEN ] ;
2009-08-25 00:24:52 +02:00
SHFILEOPSTRUCTW shfo = { hwnd , FO_DELETE , path , NULL , FOF_ALLOWUNDO } ;
2005-05-30 11:55:19 +02:00
get_path ( pane - > cur , path ) ;
2009-08-25 00:24:11 +02:00
path [ lstrlenW ( path ) + 1 ] = ' \0 ' ;
2005-05-30 11:55:19 +02:00
2009-08-25 00:24:30 +02:00
if ( ! SHFileOperationW ( & shfo ) )
2005-05-30 11:55:19 +02:00
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 ) ) ;
2009-08-25 00:24:11 +02:00
lstrcpyW ( dlg . pattern , child - > filter_pattern ) ;
2005-05-29 22:05:29 +02:00
dlg . flags = child - > filter_flags ;
2009-08-25 00:24:36 +02:00
if ( DialogBoxParamW ( Globals . hInstance , MAKEINTRESOURCEW ( IDD_DIALOG_VIEW_TYPE ) , hwnd , FilterDialogDlgProc , ( LPARAM ) & dlg ) = = IDOK ) {
2009-08-25 00:24:11 +02:00
lstrcpyW ( 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 ;
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 : {
2009-08-25 00:24:06 +02:00
int idx = SendMessageW ( pane - > hwnd , LB_GETCURSEL , 0 , 0 ) ;
Entry * entry = ( Entry * ) SendMessageW ( 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 ; }
case WM_NOTIFY : {
NMHDR * pnmh = ( NMHDR * ) lparam ;
return pane_notify ( pnmh - > idFrom = = IDW_HEADER_LEFT ? & child - > left : & child - > right , pnmh ) ; }
2004-02-11 05:18:12 +01:00
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 ) ;
2009-08-25 00:24:06 +02:00
SendMessageW ( hpanel , WM_LBUTTONDOWN , 0 , MAKELONG ( pt_clnt . x , pt_clnt . y ) ) ;
SendMessageW ( 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 ;
2009-08-25 00:24:06 +02:00
idx = SendMessageW ( pane - > hwnd , LB_GETCURSEL , 0 , 0 ) ;
2004-02-11 05:18:12 +01:00
if ( idx ! = - 1 ) {
2009-08-25 00:24:06 +02:00
Entry * entry = ( Entry * ) SendMessageW ( 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 ; }
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 :
2009-08-25 00:24:36 +02:00
return DefMDIChildProcW ( hwnd , nmsg , wparam , lparam ) ;
2002-06-04 23:29:40 +02:00
}
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
{
2009-08-25 00:24:19 +02:00
ChildWnd * child = ( ChildWnd * ) GetWindowLongPtrW ( GetParent ( hwnd ) , GWLP_USERDATA ) ;
Pane * pane = ( Pane * ) GetWindowLongPtrW ( hwnd , GWLP_USERDATA ) ;
2002-06-04 23:29:40 +02:00
ASSERT ( child ) ;
switch ( nmsg ) {
case WM_HSCROLL :
set_header ( pane ) ;
break ;
case WM_SETFOCUS :
child - > focus_pane = pane = = & child - > right ? 1 : 0 ;
2009-08-25 00:24:06 +02:00
SendMessageW ( 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 ) ;
}
}
2009-08-25 00:24:36 +02:00
return CallWindowProcW ( g_orgTreeWndProc , hwnd , nmsg , wparam , lparam ) ;
2002-06-04 23:29:40 +02:00
}
static void InitInstance ( HINSTANCE hinstance )
{
2009-08-25 00:24:41 +02:00
static const WCHAR 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
2009-08-25 00:24:52 +02:00
WNDCLASSEXW wcFrame ;
WNDCLASSW wcChild ;
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
2009-08-25 00:24:52 +02:00
wcFrame . cbSize = sizeof ( WNDCLASSEXW ) ;
2002-07-03 23:06:58 +02:00
wcFrame . style = 0 ;
wcFrame . lpfnWndProc = FrameWndProc ;
wcFrame . cbClsExtra = 0 ;
wcFrame . cbWndExtra = 0 ;
wcFrame . hInstance = hinstance ;
2009-08-25 00:24:25 +02:00
wcFrame . hIcon = LoadIconW ( hinstance , MAKEINTRESOURCEW ( IDI_WINEFILE ) ) ;
wcFrame . hCursor = LoadCursorW ( 0 , ( LPCWSTR ) IDC_ARROW ) ;
2002-07-03 23:06:58 +02:00
wcFrame . hbrBackground = 0 ;
wcFrame . lpszMenuName = 0 ;
2004-11-22 19:24:09 +01:00
wcFrame . lpszClassName = sWINEFILEFRAME ;
2009-08-25 00:24:25 +02:00
wcFrame . hIconSm = LoadImageW ( hinstance , MAKEINTRESOURCEW ( IDI_WINEFILE ) , IMAGE_ICON , GetSystemMetrics ( SM_CXSMICON ) , GetSystemMetrics ( SM_CYSMICON ) , LR_SHARED ) ;
2002-07-03 23:06:58 +02:00
2009-08-25 00:24:36 +02:00
Globals . hframeClass = RegisterClassExW ( & wcFrame ) ;
2003-08-13 03:18:37 +02:00
/* 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 ;
2009-08-25 00:24:25 +02:00
wcChild . hCursor = LoadCursorW ( 0 , ( LPCWSTR ) IDC_ARROW ) ;
2002-07-03 23:06:58 +02:00
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
2010-05-07 22:30:39 +02:00
RegisterClassW ( & wcChild ) ;
2002-07-03 23:06:58 +02:00
2002-06-04 23:29:40 +02:00
2009-08-25 00:24:25 +02:00
Globals . haccel = LoadAcceleratorsW ( hinstance , MAKEINTRESOURCEW ( IDA_WINEFILE ) ) ;
2002-06-04 23:29:40 +02:00
2009-08-25 00:24:36 +02:00
Globals . hfont = CreateFontW ( - 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
CoInitialize ( NULL ) ;
CoGetMalloc ( MEMCTX_TASK , & Globals . iMalloc ) ;
SHGetDesktopFolder ( & Globals . iDesktop ) ;
2009-08-25 00:24:36 +02:00
Globals . cfStrFName = RegisterClipboardFormatW ( CFSTR_FILENAMEW ) ;
2004-11-22 19:24:09 +01:00
/* load column strings */
2005-06-03 13:25:17 +02:00
col = 1 ;
2004-11-22 19:24:09 +01:00
2008-09-13 22:43:34 +02:00
load_string ( g_pos_names [ col + + ] , sizeof ( g_pos_names [ col ] ) / sizeof ( g_pos_names [ col ] [ 0 ] ) , IDS_COL_NAME ) ;
load_string ( g_pos_names [ col + + ] , sizeof ( g_pos_names [ col ] ) / sizeof ( g_pos_names [ col ] [ 0 ] ) , IDS_COL_SIZE ) ;
load_string ( g_pos_names [ col + + ] , sizeof ( g_pos_names [ col ] ) / sizeof ( g_pos_names [ col ] [ 0 ] ) , IDS_COL_CDATE ) ;
load_string ( g_pos_names [ col + + ] , sizeof ( g_pos_names [ col ] ) / sizeof ( g_pos_names [ col ] [ 0 ] ) , IDS_COL_ADATE ) ;
load_string ( g_pos_names [ col + + ] , sizeof ( g_pos_names [ col ] ) / sizeof ( g_pos_names [ col ] [ 0 ] ) , IDS_COL_MDATE ) ;
load_string ( g_pos_names [ col + + ] , sizeof ( g_pos_names [ col ] ) / sizeof ( g_pos_names [ col ] [ 0 ] ) , IDS_COL_IDX ) ;
load_string ( g_pos_names [ col + + ] , sizeof ( g_pos_names [ col ] ) / sizeof ( g_pos_names [ col ] [ 0 ] ) , IDS_COL_LINKS ) ;
load_string ( g_pos_names [ col + + ] , sizeof ( g_pos_names [ col ] ) / sizeof ( g_pos_names [ col ] [ 0 ] ) , IDS_COL_ATTR ) ;
load_string ( g_pos_names [ col + + ] , sizeof ( g_pos_names [ col ] ) / sizeof ( g_pos_names [ col ] [ 0 ] ) , IDS_COL_SEC ) ;
2003-08-13 03:18:37 +02:00
}
2009-08-25 00:24:46 +02:00
static BOOL show_frame ( HWND hwndParent , int cmdshow , LPCWSTR path )
2003-08-13 03:18:37 +02:00
{
2009-08-25 00:24:41 +02:00
static const WCHAR sMDICLIENT [ ] = { ' M ' , ' D ' , ' I ' , ' C ' , ' L ' , ' I ' , ' E ' , ' N ' , ' T ' , ' \0 ' } ;
2004-11-22 19:24:09 +01:00
2009-08-25 00:24:41 +02:00
WCHAR 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 )
2009-02-02 23:39:32 +01:00
return TRUE ;
2003-08-13 03:18:37 +02:00
2006-02-20 18:57:01 +01:00
opts = load_registry_settings ( ) ;
2009-08-25 00:24:25 +02:00
hMenuFrame = LoadMenuW ( Globals . hInstance , MAKEINTRESOURCEW ( IDM_WINEFILE ) ) ;
2003-08-13 03:18:37 +02:00
hMenuWindow = GetSubMenu ( hMenuFrame , GetMenuItemCount ( hMenuFrame ) - 2 ) ;
Globals . hMenuFrame = hMenuFrame ;
2011-05-03 00:38:44 +02:00
Globals . hMenuView = GetSubMenu ( hMenuFrame , 2 ) ;
Globals . hMenuOptions = GetSubMenu ( hMenuFrame , 3 ) ;
2003-08-13 03:18:37 +02:00
ccs . hWindowMenu = hMenuWindow ;
ccs . idFirstChild = IDW_FIRST_CHILD ;
2002-06-28 19:37:34 +02:00
/* create main window */
2011-09-11 23:17:10 +02:00
Globals . hMainWnd = CreateWindowExW ( 0 , MAKEINTRESOURCEW ( Globals . hframeClass ) , RS ( b1 , IDS_WINEFILE ) , 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
2009-08-25 00:24:19 +02:00
Globals . hmdiclient = CreateWindowExW ( 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 } ,
2011-03-30 16:50:55 +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 ) ;
}
2009-08-25 00:24:19 +02:00
Globals . hstatusbar = CreateStatusWindowW ( WS_CHILD | WS_VISIBLE , 0 , Globals . hMainWnd , IDW_STATUSBAR ) ;
2002-06-04 23:29:40 +02:00
CheckMenuItem ( Globals . hMenuOptions , ID_VIEW_STATUSBAR , MF_BYCOMMAND | MF_CHECKED ) ;
2006-02-20 18:57:01 +01:00
/*TODO: read paths from registry */
2005-11-17 12:05:35 +01:00
if ( ! path | | ! * path ) {
2009-08-25 00:24:30 +02:00
GetCurrentDirectoryW ( MAX_PATH , buffer ) ;
2005-11-17 12:05:35 +01:00
path = buffer ;
}
2003-08-13 03:18:37 +02:00
ShowWindow ( Globals . hMainWnd , cmdshow ) ;
2012-03-18 19:22:11 +01:00
# ifndef __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 ;
2009-02-02 23:39:32 +01:00
if ( ! create_child_window ( child ) ) {
2007-07-23 22:25:20 +02:00
HeapFree ( GetProcessHeap ( ) , 0 , child ) ;
2009-02-02 23:39:32 +01:00
return FALSE ;
}
2002-06-04 23:29:40 +02:00
SetWindowPlacement ( child - > hwnd , & child - > pos ) ;
2009-08-25 00:24:25 +02:00
Globals . himl = ImageList_LoadImageW ( Globals . hInstance , MAKEINTRESOURCEW ( IDB_IMAGES ) , 16 , 0 , RGB ( 0 , 255 , 0 ) , IMAGE_BITMAP , 0 ) ;
2002-06-04 23:29:40 +02:00
Globals . prescan_node = FALSE ;
2003-08-13 03:18:37 +02:00
UpdateWindow ( Globals . hMainWnd ) ;
2006-01-11 12:32:51 +01:00
2009-02-02 23:39:32 +01:00
if ( child - > hwnd & & path & & path [ 0 ] )
2006-01-11 12:32:51 +01:00
{
int index , count ;
2009-08-25 00:24:41 +02:00
WCHAR drv [ _MAX_DRIVE + 1 ] , dir [ _MAX_DIR ] , name [ _MAX_FNAME ] , ext [ _MAX_EXT ] ;
WCHAR fullname [ _MAX_FNAME + _MAX_EXT + 1 ] ;
2006-01-11 12:32:51 +01:00
memset ( name , 0 , sizeof ( name ) ) ;
memset ( name , 0 , sizeof ( ext ) ) ;
2009-08-25 00:23:55 +02:00
_wsplitpath ( path , drv , dir , name , ext ) ;
2006-01-11 12:32:51 +01:00
if ( name [ 0 ] )
{
2009-08-25 00:24:06 +02:00
count = SendMessageW ( child - > right . hwnd , LB_GETCOUNT , 0 , 0 ) ;
2009-08-25 00:24:11 +02:00
lstrcpyW ( fullname , name ) ;
lstrcatW ( fullname , ext ) ;
2006-01-11 12:32:51 +01:00
for ( index = 0 ; index < count ; index + + )
{
2009-08-25 00:24:06 +02:00
Entry * entry = ( Entry * ) SendMessageW ( child - > right . hwnd , LB_GETITEMDATA , index , 0 ) ;
2009-08-25 00:24:11 +02:00
if ( lstrcmpW ( entry - > data . cFileName , fullname ) = = 0 | |
lstrcmpW ( entry - > data . cAlternateFileName , fullname ) = = 0 )
2006-01-11 12:32:51 +01:00
{
2009-08-25 00:24:06 +02:00
SendMessageW ( child - > right . hwnd , LB_SETCURSEL , index , 0 ) ;
2006-01-11 12:32:51 +01:00
SetFocus ( child - > right . hwnd ) ;
break ;
}
}
}
}
2009-02-02 23:39:32 +01:00
return TRUE ;
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
{
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 ( ) ;
2005-10-03 13:03:04 +02:00
DeleteObject ( Globals . hfont ) ;
2002-06-04 23:29:40 +02:00
ImageList_Destroy ( Globals . himl ) ;
}
2012-03-18 19:24:28 +01:00
int APIENTRY wWinMain ( HINSTANCE hinstance , HINSTANCE previnstance , LPWSTR cmdline , int cmdshow )
2003-08-13 03:18:37 +02:00
{
MSG msg ;
2009-08-25 00:24:46 +02:00
2002-06-04 23:29:40 +02:00
InitInstance ( hinstance ) ;
2012-03-18 19:24:28 +01:00
if ( ! show_frame ( 0 , cmdshow , cmdline ) )
2009-02-02 23:39:32 +01:00
{
ExitInstance ( ) ;
return 1 ;
}
2002-06-04 23:29:40 +02:00
2009-08-25 00:24:36 +02:00
while ( GetMessageW ( & msg , 0 , 0 , 0 ) ) {
2003-08-13 03:18:37 +02:00
if ( Globals . hmdiclient & & TranslateMDISysAccel ( Globals . hmdiclient , & msg ) )
continue ;
2009-08-25 00:24:36 +02:00
if ( Globals . hMainWnd & & TranslateAcceleratorW ( Globals . hMainWnd , Globals . haccel , & msg ) )
2003-08-13 03:18:37 +02:00
continue ;
TranslateMessage ( & msg ) ;
2009-08-25 00:24:36 +02:00
DispatchMessageW ( & msg ) ;
2002-06-04 23:29:40 +02:00
}
ExitInstance ( ) ;
2003-08-13 03:18:37 +02:00
return msg . wParam ;
}