4 * Copyright 2000 Martin Fuchs
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "wine/port.h"
28 /* for read_directory_unix() */
29 #if !defined(_NO_EXTENSIONS)
42 #define _MAX_FNAME 256
43 #define _MAX_DIR _MAX_FNAME
44 #define _MAX_EXT _MAX_FNAME
48 WINEFILE_GLOBALS Globals
;
50 extern void WineLicense(HWND hWnd
);
51 extern void WineWarranty(HWND hWnd
);
53 typedef struct _Entry
{
64 #ifndef _NO_EXTENSIONS
65 BY_HANDLE_FILE_INFORMATION bhfi
;
74 TCHAR volname
[_MAX_FNAME
];
84 COL_ATTRIBUTES
= 0x08,
87 COL_ALL
= COL_SIZE
|COL_DATE
|COL_TIME
|COL_ATTRIBUTES
|COL_DOSNAMES
91 COL_ALL
= COL_SIZE
|COL_DATE
|COL_TIME
|COL_ATTRIBUTES
|COL_DOSNAMES
|COL_INDEX
|COL_LINKS
104 #ifndef _NO_EXTENSIONS
108 #ifndef _NO_EXTENSIONS
114 int positions
[COLUMNS
+1];
126 int focus_pane
; /* 0: left 1: right */
129 BOOL header_wdths_ok
;
131 TCHAR path
[MAX_PATH
];
134 SORT_ORDER sortOrder
;
138 static void read_directory(Entry
* parent
, LPCTSTR path
, int sortOrder
);
139 static void set_curdir(ChildWnd
* child
, Entry
* entry
);
141 LRESULT CALLBACK
FrameWndProc(HWND hwnd
, UINT nmsg
, WPARAM wparam
, LPARAM lparam
);
142 LRESULT CALLBACK
ChildWndProc(HWND hwnd
, UINT nmsg
, WPARAM wparam
, LPARAM lparam
);
143 LRESULT CALLBACK
TreeWndProc(HWND hwnd
, UINT nmsg
, WPARAM wparam
, LPARAM lparam
);
146 static void display_error(HWND hwnd
, DWORD error
)
150 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
|FORMAT_MESSAGE_FROM_SYSTEM
,
151 0, error
, MAKELANGID(LANG_NEUTRAL
,SUBLANG_DEFAULT
), (PTSTR
)&msg
, 0, NULL
))
152 MessageBox(hwnd
, msg
, _T("Winefile"), MB_OK
);
154 MessageBox(hwnd
, _T("Error"), _T("Winefile"), MB_OK
);
160 static void read_directory_win(Entry
* parent
, LPCTSTR path
)
162 Entry
* entry
= (Entry
*) malloc(sizeof(Entry
));
163 int level
= parent
->level
+ 1;
166 #ifndef _NO_EXTENSIONS
170 TCHAR buffer
[MAX_PATH
], *p
;
171 for(p
=buffer
; *path
; )
174 lstrcpy(p
, _T("\\*"));
176 hFind
= FindFirstFile(buffer
, &entry
->data
);
178 if (hFind
!= INVALID_HANDLE_VALUE
) {
179 parent
->down
= entry
;
184 entry
->expanded
= FALSE
;
185 entry
->scanned
= FALSE
;
186 entry
->level
= level
;
188 #ifdef _NO_EXTENSIONS
189 /* hide directory entry "." */
190 if (entry
->data
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) {
191 LPCTSTR name
= entry
->data
.cFileName
;
193 if (name
[0]=='.' && name
[1]=='\0')
197 entry
->unix_dir
= FALSE
;
198 entry
->bhfi_valid
= FALSE
;
200 lstrcpy(p
+1, entry
->data
.cFileName
);
202 hFile
= CreateFile(buffer
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
203 0, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0);
205 if (hFile
!= INVALID_HANDLE_VALUE
) {
206 if (GetFileInformationByHandle(hFile
, &entry
->bhfi
))
207 entry
->bhfi_valid
= TRUE
;
215 entry
= (Entry
*) malloc(sizeof(Entry
));
219 } while(FindNextFile(hFind
, &entry
->data
));
229 parent
->scanned
= TRUE
;
233 static Entry
* find_entry_win(Entry
* parent
, LPCTSTR name
)
237 for(entry
=parent
->down
; entry
; entry
=entry
->next
) {
239 LPCTSTR q
= entry
->data
.cFileName
;
242 if (!*p
|| *p
==_T('\\') || *p
==_T('/'))
244 } while(tolower(*p
++) == tolower(*q
++));
247 q
= entry
->data
.cAlternateFileName
;
250 if (!*p
|| *p
==_T('\\') || *p
==_T('/'))
252 } while(tolower(*p
++) == tolower(*q
++));
259 static Entry
* read_tree_win(Root
* root
, LPCTSTR path
, int sortOrder
)
261 TCHAR buffer
[MAX_PATH
];
262 Entry
* entry
= &root
->entry
;
266 #ifndef _NO_EXTENSIONS
267 entry
->unix_dir
= FALSE
;
271 while(*s
&& *s
!=_T('\\') && *s
!=_T('/'))
274 while(*s
==_T('\\') || *s
==_T('/'))
280 read_directory(entry
, buffer
, sortOrder
);
283 entry
->expanded
= TRUE
;
288 entry
= find_entry_win(entry
, s
);
295 #if !defined(_NO_EXTENSIONS) && defined(__linux__)
297 BOOL
to_filetime(const time_t* t
, FILETIME
* ftime
)
299 struct tm
* tm
= gmtime(t
);
305 stime
.wYear
= tm
->tm_year
+1900;
306 stime
.wMonth
= tm
->tm_mon
+1;
307 /* stime.wDayOfWeek */
308 stime
.wDay
= tm
->tm_mday
;
309 stime
.wHour
= tm
->tm_hour
;
310 stime
.wMinute
= tm
->tm_min
;
311 stime
.wSecond
= tm
->tm_sec
;
313 return SystemTimeToFileTime(&stime
, ftime
);
316 static void read_directory_unix(Entry
* parent
, LPCTSTR path
)
318 Entry
* entry
= (Entry
*) malloc(sizeof(Entry
));
319 int level
= parent
->level
+ 1;
322 DIR* dir
= opendir(path
);
327 TCHAR buffer
[MAX_PATH
], *p
;
329 for(p
=buffer
; *path
; )
332 if (p
==buffer
|| p
[-1]!='/')
335 parent
->down
= entry
;
337 while((ent
=readdir(dir
))) {
338 entry
->unix_dir
= TRUE
;
339 lstrcpy(entry
->data
.cFileName
, ent
->d_name
);
340 entry
->data
.dwFileAttributes
= ent
->d_name
[0]=='.'? FILE_ATTRIBUTE_HIDDEN
: 0;
342 strcpy(p
, ent
->d_name
);
344 if (!stat(buffer
, &st
)) {
345 if (S_ISDIR(st
.st_mode
))
346 entry
->data
.dwFileAttributes
|= FILE_ATTRIBUTE_DIRECTORY
;
348 entry
->data
.nFileSizeLow
= st
.st_size
& 0xFFFFFFFF;
349 entry
->data
.nFileSizeHigh
= st
.st_size
>> 32;
351 memset(&entry
->data
.ftCreationTime
, 0, sizeof(FILETIME
));
352 to_filetime(&st
.st_atime
, &entry
->data
.ftLastAccessTime
);
353 to_filetime(&st
.st_mtime
, &entry
->data
.ftLastWriteTime
);
355 entry
->bhfi
.nFileIndexLow
= ent
->d_ino
;
356 entry
->bhfi
.nFileIndexHigh
= 0;
358 entry
->bhfi
.nNumberOfLinks
= st
.st_nlink
;
360 entry
->bhfi_valid
= TRUE
;
362 entry
->data
.nFileSizeLow
= 0;
363 entry
->data
.nFileSizeHigh
= 0;
364 entry
->bhfi_valid
= FALSE
;
369 entry
->expanded
= FALSE
;
370 entry
->scanned
= FALSE
;
371 entry
->level
= level
;
375 entry
= (Entry
*) malloc(sizeof(Entry
));
389 parent
->scanned
= TRUE
;
392 static Entry
* find_entry_unix(Entry
* parent
, LPCTSTR name
)
396 for(entry
=parent
->down
; entry
; entry
=entry
->next
) {
398 LPCTSTR q
= entry
->data
.cFileName
;
401 if (!*p
|| *p
==_T('/'))
403 } while(*p
++ == *q
++);
409 static Entry
* read_tree_unix(Root
* root
, LPCTSTR path
, int sortOrder
)
411 TCHAR buffer
[MAX_PATH
];
412 Entry
* entry
= &root
->entry
;
416 entry
->unix_dir
= TRUE
;
419 while(*s
&& *s
!=_T('/'))
428 read_directory(entry
, buffer
, sortOrder
);
431 entry
->expanded
= TRUE
;
436 entry
= find_entry_unix(entry
, s
);
445 /* directories first... */
446 static int compareType(const WIN32_FIND_DATA
* fd1
, const WIN32_FIND_DATA
* fd2
)
448 int dir1
= fd1
->dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
;
449 int dir2
= fd2
->dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
;
451 return dir2
==dir1
? 0: dir2
<dir1
? -1: 1;
455 static int compareName(const void* arg1
, const void* arg2
)
457 const WIN32_FIND_DATA
* fd1
= &(*(Entry
**)arg1
)->data
;
458 const WIN32_FIND_DATA
* fd2
= &(*(Entry
**)arg2
)->data
;
460 int cmp
= compareType(fd1
, fd2
);
464 return lstrcmpi(fd1
->cFileName
, fd2
->cFileName
);
467 static int compareExt(const void* arg1
, const void* arg2
)
469 const WIN32_FIND_DATA
* fd1
= &(*(Entry
**)arg1
)->data
;
470 const WIN32_FIND_DATA
* fd2
= &(*(Entry
**)arg2
)->data
;
471 const TCHAR
*name1
, *name2
, *ext1
, *ext2
;
473 int cmp
= compareType(fd1
, fd2
);
477 name1
= fd1
->cFileName
;
478 name2
= fd2
->cFileName
;
480 ext1
= _tcsrchr(name1
, _T('.'));
481 ext2
= _tcsrchr(name2
, _T('.'));
493 cmp
= lstrcmpi(ext1
, ext2
);
497 return lstrcmpi(name1
, name2
);
500 static int compareSize(const void* arg1
, const void* arg2
)
502 WIN32_FIND_DATA
* fd1
= &(*(Entry
**)arg1
)->data
;
503 WIN32_FIND_DATA
* fd2
= &(*(Entry
**)arg2
)->data
;
505 int cmp
= compareType(fd1
, fd2
);
509 cmp
= fd2
->nFileSizeHigh
- fd1
->nFileSizeHigh
;
516 cmp
= fd2
->nFileSizeLow
- fd1
->nFileSizeLow
;
518 return cmp
<0? -1: cmp
>0? 1: 0;
521 static int compareDate(const void* arg1
, const void* arg2
)
523 WIN32_FIND_DATA
* fd1
= &(*(Entry
**)arg1
)->data
;
524 WIN32_FIND_DATA
* fd2
= &(*(Entry
**)arg2
)->data
;
526 int cmp
= compareType(fd1
, fd2
);
530 return CompareFileTime(&fd2
->ftLastWriteTime
, &fd1
->ftLastWriteTime
);
534 static int (*sortFunctions
[])(const void* arg1
, const void* arg2
) = {
535 compareName
, /* SORT_NAME */
536 compareExt
, /* SORT_EXT */
537 compareSize
, /* SORT_SIZE */
538 compareDate
/* SORT_DATE */
542 static void SortDirectory(Entry
* parent
, SORT_ORDER sortOrder
)
544 Entry
* entry
= parent
->down
;
549 for(entry
=parent
->down
; entry
; entry
=entry
->next
)
553 array
= (Entry
**) alloca(len
*sizeof(Entry
*));
556 for(entry
=parent
->down
; entry
; entry
=entry
->next
)
559 /* call qsort with the appropriate compare function */
560 qsort(array
, len
, sizeof(array
[0]), sortFunctions
[sortOrder
]);
562 parent
->down
= array
[0];
564 for(p
=array
; --len
; p
++)
572 static void read_directory(Entry
* parent
, LPCTSTR path
, int sortOrder
)
574 TCHAR buffer
[MAX_PATH
];
579 #if !defined(_NO_EXTENSIONS) && defined(__linux__)
580 if (parent
->unix_dir
)
582 read_directory_unix(parent
, path
);
584 if (Globals
.prescan_node
) {
593 for(entry
=parent
->down
; entry
; entry
=entry
->next
)
594 if (entry
->data
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) {
595 lstrcpy(d
, entry
->data
.cFileName
);
596 read_directory_unix(entry
, buffer
);
597 SortDirectory(entry
, sortOrder
);
604 read_directory_win(parent
, path
);
606 if (Globals
.prescan_node
) {
615 for(entry
=parent
->down
; entry
; entry
=entry
->next
)
616 if (entry
->data
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) {
617 lstrcpy(d
, entry
->data
.cFileName
);
618 read_directory_win(entry
, buffer
);
619 SortDirectory(entry
, sortOrder
);
624 SortDirectory(parent
, sortOrder
);
628 static ChildWnd
* alloc_child_window(LPCTSTR path
)
630 TCHAR drv
[_MAX_DRIVE
+1], dir
[_MAX_DIR
], name
[_MAX_FNAME
], ext
[_MAX_EXT
];
631 ChildWnd
* child
= (ChildWnd
*) malloc(sizeof(ChildWnd
));
632 Root
* root
= &child
->root
;
635 memset(child
, 0, sizeof(ChildWnd
));
637 child
->left
.treePane
= TRUE
;
638 child
->left
.visible_cols
= 0;
640 child
->right
.treePane
= FALSE
;
641 #ifndef _NO_EXTENSIONS
642 child
->right
.visible_cols
= COL_SIZE
|COL_DATE
|COL_TIME
|COL_ATTRIBUTES
|COL_INDEX
|COL_LINKS
;
644 child
->right
.visible_cols
= COL_SIZE
|COL_DATE
|COL_TIME
|COL_ATTRIBUTES
;
647 child
->pos
.length
= sizeof(WINDOWPLACEMENT
);
648 child
->pos
.flags
= 0;
649 child
->pos
.showCmd
= SW_SHOWNORMAL
;
650 child
->pos
.rcNormalPosition
.left
= CW_USEDEFAULT
;
651 child
->pos
.rcNormalPosition
.top
= CW_USEDEFAULT
;
652 child
->pos
.rcNormalPosition
.right
= CW_USEDEFAULT
;
653 child
->pos
.rcNormalPosition
.bottom
= CW_USEDEFAULT
;
655 child
->focus_pane
= 0;
656 child
->split_pos
= 200;
657 child
->sortOrder
= SORT_NAME
;
658 child
->header_wdths_ok
= FALSE
;
660 lstrcpy(child
->path
, path
);
662 _tsplitpath(path
, drv
, dir
, name
, ext
);
664 #if !defined(_NO_EXTENSIONS) && defined(__linux__)
667 root
->drive_type
= GetDriveType(path
);
669 lstrcat(drv
, _T("/"));
670 lstrcpy(root
->volname
, _T("root fs"));
672 lstrcpy(root
->fs
, _T("unixfs"));
674 lstrcpy(root
->path
, _T("/"));
675 entry
= read_tree_unix(root
, path
, child
->sortOrder
);
680 root
->drive_type
= GetDriveType(path
);
682 lstrcat(drv
, _T("\\"));
683 GetVolumeInformation(drv
, root
->volname
, _MAX_FNAME
, 0, 0, &root
->fs_flags
, root
->fs
, _MAX_DIR
);
685 lstrcpy(root
->path
, drv
);
686 entry
= read_tree_win(root
, path
, child
->sortOrder
);
689 /*@@lstrcpy(root->entry.data.cFileName, drv); */
690 wsprintf(root
->entry
.data
.cFileName
, _T("%s - %s"), drv
, root
->fs
);
692 root
->entry
.data
.dwFileAttributes
= FILE_ATTRIBUTE_DIRECTORY
;
694 child
->left
.root
= &root
->entry
;
696 set_curdir(child
, entry
);
702 /* recursively free all child entries */
703 static void free_entries(Entry
* parent
)
705 Entry
*entry
, *next
=parent
->down
;
720 /* free all memory associated with a child window */
721 static void free_child_window(ChildWnd
* child
)
723 free_entries(&child
->root
.entry
);
728 /* get full path of specified directory entry */
729 static void get_path(Entry
* dir
, PTSTR path
)
735 for(entry
=dir
; entry
; level
++) {
736 LPCTSTR name
= entry
->data
.cFileName
;
740 for(l
=0; *s
&& *s
!=_T('/') && *s
!=_T('\\'); s
++)
744 memmove(path
+l
+1, path
, len
*sizeof(TCHAR
));
745 memcpy(path
+1, name
, l
*sizeof(TCHAR
));
748 #ifndef _NO_EXTENSIONS
757 memmove(path
+l
, path
, len
*sizeof(TCHAR
));
758 memcpy(path
, name
, l
*sizeof(TCHAR
));
765 #ifndef _NO_EXTENSIONS
767 path
[len
++] = _T('/');
770 path
[len
++] = _T('\\');
773 path
[len
] = _T('\0');
777 static void resize_frame_rect(HWND hwnd
, PRECT prect
)
782 if (IsWindowVisible(Globals
.htoolbar
)) {
783 SendMessage(Globals
.htoolbar
, WM_SIZE
, 0, 0);
784 GetClientRect(Globals
.htoolbar
, &rt
);
785 prect
->top
= rt
.bottom
+3;
786 prect
->bottom
-= rt
.bottom
+3;
789 if (IsWindowVisible(Globals
.hdrivebar
)) {
790 SendMessage(Globals
.hdrivebar
, WM_SIZE
, 0, 0);
791 GetClientRect(Globals
.hdrivebar
, &rt
);
792 new_top
= --prect
->top
+ rt
.bottom
+3;
793 MoveWindow(Globals
.hdrivebar
, 0, prect
->top
, rt
.right
, new_top
, TRUE
);
794 prect
->top
= new_top
;
795 prect
->bottom
-= rt
.bottom
+2;
798 if (IsWindowVisible(Globals
.hstatusbar
)) {
799 int parts
[] = {300, 500};
801 SendMessage(Globals
.hstatusbar
, WM_SIZE
, 0, 0);
802 SendMessage(Globals
.hstatusbar
, SB_SETPARTS
, 2, (LPARAM
)&parts
);
803 GetClientRect(Globals
.hstatusbar
, &rt
);
804 prect
->bottom
-= rt
.bottom
;
807 MoveWindow(Globals
.hmdiclient
, prect
->left
-1,prect
->top
-1,prect
->right
+2,prect
->bottom
+1, TRUE
);
810 static void resize_frame(HWND hwnd
, int cx
, int cy
)
819 resize_frame_rect(hwnd
, &rect
);
822 static void resize_frame_client(HWND hwnd
)
826 GetClientRect(hwnd
, &rect
);
828 resize_frame_rect(hwnd
, &rect
);
832 static HHOOK hcbthook
;
833 static ChildWnd
* newchild
= NULL
;
835 LRESULT CALLBACK
CBTProc(int code
, WPARAM wparam
, LPARAM lparam
)
837 if (code
==HCBT_CREATEWND
&& newchild
) {
838 ChildWnd
* child
= newchild
;
841 child
->hwnd
= (HWND
) wparam
;
842 SetWindowLong(child
->hwnd
, GWL_USERDATA
, (LPARAM
)child
);
845 return CallNextHookEx(hcbthook
, code
, wparam
, lparam
);
848 static HWND
create_child_window(ChildWnd
* child
)
853 mcs
.szClass
= WINEFILETREE
;
854 mcs
.szTitle
= (LPTSTR
)child
->path
;
855 mcs
.hOwner
= Globals
.hInstance
;
856 mcs
.x
= child
->pos
.rcNormalPosition
.left
;
857 mcs
.y
= child
->pos
.rcNormalPosition
.top
;
858 mcs
.cx
= child
->pos
.rcNormalPosition
.right
-child
->pos
.rcNormalPosition
.left
;
859 mcs
.cy
= child
->pos
.rcNormalPosition
.bottom
-child
->pos
.rcNormalPosition
.top
;
863 hcbthook
= SetWindowsHookEx(WH_CBT
, CBTProc
, 0, GetCurrentThreadId());
866 child
->hwnd
= (HWND
) SendMessage(Globals
.hmdiclient
, WM_MDICREATE
, 0, (LPARAM
)&mcs
);
870 UnhookWindowsHookEx(hcbthook
);
872 idx
= ListBox_FindItemData(child
->left
.hwnd
, ListBox_GetCurSel(child
->left
.hwnd
), child
->left
.cur
);
873 ListBox_SetCurSel(child
->left
.hwnd
, idx
);
879 struct ExecuteDialog
{
885 static BOOL CALLBACK
ExecuteDialogWndProg(HWND hwnd
, UINT nmsg
, WPARAM wparam
, LPARAM lparam
)
887 static struct ExecuteDialog
* dlg
;
891 dlg
= (struct ExecuteDialog
*) lparam
;
895 int id
= (int)wparam
;
898 GetWindowText(GetDlgItem(hwnd
, 201), dlg
->cmd
, MAX_PATH
);
899 dlg
->cmdshow
= Button_GetState(GetDlgItem(hwnd
,214))&BST_CHECKED
?
900 SW_SHOWMINIMIZED
: SW_SHOWNORMAL
;
902 } else if (id
== IDCANCEL
)
912 #ifndef _NO_EXTENSIONS
914 static struct FullScreenParameters
{
922 void frame_get_clientspace(HWND hwnd
, PRECT prect
)
927 GetClientRect(hwnd
, prect
);
931 GetWindowPlacement(hwnd
, &wp
);
933 prect
->left
= prect
->top
= 0;
934 prect
->right
= wp
.rcNormalPosition
.right
-wp
.rcNormalPosition
.left
-
935 2*(GetSystemMetrics(SM_CXSIZEFRAME
)+GetSystemMetrics(SM_CXEDGE
));
936 prect
->bottom
= wp
.rcNormalPosition
.bottom
-wp
.rcNormalPosition
.top
-
937 2*(GetSystemMetrics(SM_CYSIZEFRAME
)+GetSystemMetrics(SM_CYEDGE
))-
938 GetSystemMetrics(SM_CYCAPTION
)-GetSystemMetrics(SM_CYMENUSIZE
);
941 if (IsWindowVisible(Globals
.htoolbar
)) {
942 GetClientRect(Globals
.htoolbar
, &rt
);
943 prect
->top
+= rt
.bottom
+2;
946 if (IsWindowVisible(Globals
.hdrivebar
)) {
947 GetClientRect(Globals
.hdrivebar
, &rt
);
948 prect
->top
+= rt
.bottom
+2;
951 if (IsWindowVisible(Globals
.hstatusbar
)) {
952 GetClientRect(Globals
.hstatusbar
, &rt
);
953 prect
->bottom
-= rt
.bottom
;
957 static BOOL
toggle_fullscreen(HWND hwnd
)
961 if ((g_fullscreen
.mode
=!g_fullscreen
.mode
)) {
962 GetWindowRect(hwnd
, &g_fullscreen
.orgPos
);
963 g_fullscreen
.wasZoomed
= IsZoomed(hwnd
);
965 Frame_CalcFrameClient(hwnd
, &rt
);
966 ClientToScreen(hwnd
, (LPPOINT
)&rt
.left
);
967 ClientToScreen(hwnd
, (LPPOINT
)&rt
.right
);
969 rt
.left
= g_fullscreen
.orgPos
.left
-rt
.left
;
970 rt
.top
= g_fullscreen
.orgPos
.top
-rt
.top
;
971 rt
.right
= GetSystemMetrics(SM_CXSCREEN
)+g_fullscreen
.orgPos
.right
-rt
.right
;
972 rt
.bottom
= GetSystemMetrics(SM_CYSCREEN
)+g_fullscreen
.orgPos
.bottom
-rt
.bottom
;
974 MoveWindow(hwnd
, rt
.left
, rt
.top
, rt
.right
-rt
.left
, rt
.bottom
-rt
.top
, TRUE
);
976 MoveWindow(hwnd
, g_fullscreen
.orgPos
.left
, g_fullscreen
.orgPos
.top
,
977 g_fullscreen
.orgPos
.right
-g_fullscreen
.orgPos
.left
,
978 g_fullscreen
.orgPos
.bottom
-g_fullscreen
.orgPos
.top
, TRUE
);
980 if (g_fullscreen
.wasZoomed
)
981 ShowWindow(hwnd
, WS_MAXIMIZE
);
984 return g_fullscreen
.mode
;
987 static void fullscreen_move(HWND hwnd
)
990 GetWindowRect(hwnd
, &pos
);
992 Frame_CalcFrameClient(hwnd
, &rt
);
993 ClientToScreen(hwnd
, (LPPOINT
)&rt
.left
);
994 ClientToScreen(hwnd
, (LPPOINT
)&rt
.right
);
996 rt
.left
= pos
.left
-rt
.left
;
997 rt
.top
= pos
.top
-rt
.top
;
998 rt
.right
= GetSystemMetrics(SM_CXSCREEN
)+pos
.right
-rt
.right
;
999 rt
.bottom
= GetSystemMetrics(SM_CYSCREEN
)+pos
.bottom
-rt
.bottom
;
1001 MoveWindow(hwnd
, rt
.left
, rt
.top
, rt
.right
-rt
.left
, rt
.bottom
-rt
.top
, TRUE
);
1007 static void toggle_child(HWND hwnd
, UINT cmd
, HWND hchild
)
1009 BOOL vis
= IsWindowVisible(hchild
);
1011 CheckMenuItem(Globals
.hMenuOptions
, cmd
, vis
?MF_BYCOMMAND
:MF_BYCOMMAND
|MF_CHECKED
);
1013 ShowWindow(hchild
, vis
?SW_HIDE
:SW_SHOW
);
1015 #ifndef _NO_EXTENSIONS
1016 if (g_fullscreen
.mode
)
1017 fullscreen_move(hwnd
);
1020 resize_frame_client(hwnd
);
1023 BOOL
activate_drive_window(LPCTSTR path
)
1025 TCHAR drv1
[_MAX_DRIVE
], drv2
[_MAX_DRIVE
];
1028 _tsplitpath(path
, drv1
, 0, 0, 0);
1030 /* search for a already open window for the same drive */
1031 for(child_wnd
=GetNextWindow(Globals
.hmdiclient
,GW_CHILD
); child_wnd
; child_wnd
=GetNextWindow(child_wnd
, GW_HWNDNEXT
)) {
1032 ChildWnd
* child
= (ChildWnd
*) GetWindowLong(child_wnd
, GWL_USERDATA
);
1035 _tsplitpath(child
->root
.path
, drv2
, 0, 0, 0);
1037 if (!lstrcmpi(drv2
, drv1
)) {
1038 SendMessage(Globals
.hmdiclient
, WM_MDIACTIVATE
, (WPARAM
)child_wnd
, 0);
1040 if (IsMinimized(child_wnd
))
1041 ShowWindow(child_wnd
, SW_SHOWNORMAL
);
1051 LRESULT CALLBACK
FrameWndProc(HWND hwnd
, UINT nmsg
, WPARAM wparam
, LPARAM lparam
)
1055 DestroyWindow(hwnd
);
1063 UINT cmd
= LOWORD(wparam
);
1064 HWND hwndClient
= (HWND
) SendMessage(Globals
.hmdiclient
, WM_MDIGETACTIVE
, 0, 0);
1066 if (SendMessage(hwndClient
, WM_DISPATCH_COMMAND
, wparam
, lparam
))
1069 if (cmd
>=ID_DRIVE_FIRST
&& cmd
<=ID_DRIVE_FIRST
+0xFF) {
1070 TCHAR drv
[_MAX_DRIVE
], path
[MAX_PATH
];
1072 LPCTSTR root
= Globals
.drives
;
1075 for(i
=cmd
-ID_DRIVE_FIRST
; i
--; root
++)
1079 if (activate_drive_window(root
))
1082 _tsplitpath(root
, drv
, 0, 0, 0);
1084 if (!SetCurrentDirectory(drv
)) {
1085 display_error(hwnd
, GetLastError());
1089 GetCurrentDirectory(MAX_PATH
, path
); /*@@ letztes Verzeichnis pro Laufwerk speichern */
1090 child
= alloc_child_window(path
);
1092 if (!create_child_window(child
))
1094 } else switch(cmd
) {
1099 case ID_WINDOW_NEW
: {
1100 TCHAR path
[MAX_PATH
];
1103 GetCurrentDirectory(MAX_PATH
, path
);
1104 child
= alloc_child_window(path
);
1106 if (!create_child_window(child
))
1110 case ID_WINDOW_CASCADE
:
1111 SendMessage(Globals
.hmdiclient
, WM_MDICASCADE
, 0, 0);
1114 case ID_WINDOW_TILE_HORZ
:
1115 SendMessage(Globals
.hmdiclient
, WM_MDITILE
, MDITILE_HORIZONTAL
, 0);
1118 case ID_WINDOW_TILE_VERT
:
1119 SendMessage(Globals
.hmdiclient
, WM_MDITILE
, MDITILE_VERTICAL
, 0);
1122 case ID_WINDOW_ARRANGE
:
1123 SendMessage(Globals
.hmdiclient
, WM_MDIICONARRANGE
, 0, 0);
1126 case ID_VIEW_TOOL_BAR
:
1127 toggle_child(hwnd
, cmd
, Globals
.htoolbar
);
1130 case ID_VIEW_DRIVE_BAR
:
1131 toggle_child(hwnd
, cmd
, Globals
.hdrivebar
);
1134 case ID_VIEW_STATUSBAR
:
1135 toggle_child(hwnd
, cmd
, Globals
.hstatusbar
);
1139 struct ExecuteDialog dlg
= {{0}};
1140 if (DialogBoxParam(Globals
.hInstance
, MAKEINTRESOURCE(IDD_EXECUTE
), hwnd
, ExecuteDialogWndProg
, (LPARAM
)&dlg
) == IDOK
)
1141 ShellExecute(hwnd
, _T("open")/*operation*/, dlg
.cmd
/*file*/, NULL
/*parameters*/, NULL
/*dir*/, dlg
.cmdshow
);
1145 WinHelp(hwnd
, _T("winfile"), HELP_INDEX
, 0);
1148 #ifndef _NO_EXTENSIONS
1149 case ID_VIEW_FULLSCREEN
:
1150 CheckMenuItem(Globals
.hMenuOptions
, cmd
, toggle_fullscreen(hwnd
)?MF_CHECKED
:0);
1154 case ID_DRIVE_UNIX_FS
: {
1155 TCHAR path
[MAX_PATH
];
1158 if (activate_drive_window(_T("/")))
1161 getcwd(path
, MAX_PATH
);
1162 child
= alloc_child_window(path
);
1164 if (!create_child_window(child
))
1170 /*TODO: There are even more menu items! */
1172 #ifndef _NO_EXTENSIONS
1174 WineLicense(Globals
.hMainWnd
);
1177 case ID_NO_WARRANTY
:
1178 WineWarranty(Globals
.hMainWnd
);
1182 ShellAbout(hwnd
, _T("WINE"), _T("Winefile"), 0);
1187 /*@@if (wParam >= PM_FIRST_LANGUAGE && wParam <= PM_LAST_LANGUAGE)
1188 STRING_SelectLanguageByNumber(wParam - PM_FIRST_LANGUAGE);
1189 else */if ((cmd
<IDW_FIRST_CHILD
|| cmd
>=IDW_FIRST_CHILD
+0x100) &&
1190 (cmd
<SC_SIZE
|| cmd
>SC_RESTORE
))
1191 MessageBox(hwnd
, _T("Not yet implemented"), _T("Winefile"), MB_OK
);
1193 return DefFrameProc(hwnd
, Globals
.hmdiclient
, nmsg
, wparam
, lparam
);
1198 resize_frame(hwnd
, LOWORD(lparam
), HIWORD(lparam
));
1199 break; /* do not pass message to DefFrameProc */
1201 #ifndef _NO_EXTENSIONS
1202 case WM_GETMINMAXINFO
: {
1203 LPMINMAXINFO lpmmi
= (LPMINMAXINFO
)lparam
;
1205 lpmmi
->ptMaxTrackSize
.x
<<= 1;/*2*GetSystemMetrics(SM_CXSCREEN) / SM_CXVIRTUALSCREEN */
1206 lpmmi
->ptMaxTrackSize
.y
<<= 1;/*2*GetSystemMetrics(SM_CYSCREEN) / SM_CYVIRTUALSCREEN */
1209 case FRM_CALC_CLIENT
:
1210 frame_get_clientspace(hwnd
, (PRECT
)lparam
);
1215 return DefFrameProc(hwnd
, Globals
.hmdiclient
, nmsg
, wparam
, lparam
);
1222 const static LPTSTR g_pos_names
[COLUMNS
] = {
1223 _T(""), /* symbol */
1227 #ifndef _NO_EXTENSIONS
1234 #ifndef _NO_EXTENSIONS
1239 const static int g_pos_align
[] = {
1241 HDF_LEFT
, /* Name */
1242 HDF_RIGHT
, /* Size */
1243 HDF_LEFT
, /* CDate */
1244 #ifndef _NO_EXTENSIONS
1245 HDF_LEFT
, /* ADate */
1246 HDF_LEFT
, /* MDate */
1247 HDF_LEFT
, /* Index */
1248 HDF_CENTER
, /* Links */
1250 HDF_CENTER
, /* Attributes */
1251 #ifndef _NO_EXTENSIONS
1252 HDF_LEFT
/* Security */
1256 static void resize_tree(ChildWnd
* child
, int cx
, int cy
)
1258 HDWP hdwp
= BeginDeferWindowPos(4);
1266 cx
= child
->split_pos
+ SPLIT_WIDTH
/2;
1268 #ifndef _NO_EXTENSIONS
1276 Header_Layout(child
->left
.hwndHeader
, &hdl
);
1278 DeferWindowPos(hdwp
, child
->left
.hwndHeader
, wp
.hwndInsertAfter
,
1279 wp
.x
-1, wp
.y
, child
->split_pos
-SPLIT_WIDTH
/2+1, wp
.cy
, wp
.flags
);
1280 DeferWindowPos(hdwp
, child
->right
.hwndHeader
, wp
.hwndInsertAfter
,
1281 rt
.left
+cx
+1, wp
.y
, wp
.cx
-cx
+2, wp
.cy
, wp
.flags
);
1285 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
);
1286 DeferWindowPos(hdwp
, child
->right
.hwnd
, 0, rt
.left
+cx
+1, rt
.top
, rt
.right
-cx
, rt
.bottom
-rt
.top
, SWP_NOZORDER
|SWP_NOACTIVATE
);
1288 EndDeferWindowPos(hdwp
);
1292 #ifndef _NO_EXTENSIONS
1294 static HWND
create_header(HWND parent
, Pane
* pane
, int id
)
1296 HD_ITEM hdi
= {HDI_TEXT
|HDI_WIDTH
|HDI_FORMAT
};
1299 HWND hwnd
= CreateWindow(WC_HEADER
, 0, WS_CHILD
|WS_VISIBLE
|HDS_HORZ
/*TODO: |HDS_BUTTONS + sort orders*/,
1300 0, 0, 0, 0, parent
, (HMENU
)id
, Globals
.hInstance
, 0);
1304 SendMessage(hwnd
, WM_SETFONT
, (WPARAM
)GetStockObject(DEFAULT_GUI_FONT
), FALSE
);
1306 for(idx
=0; idx
<COLUMNS
; idx
++) {
1307 hdi
.pszText
= g_pos_names
[idx
];
1308 hdi
.fmt
= HDF_STRING
| g_pos_align
[idx
];
1309 hdi
.cxy
= pane
->widths
[idx
];
1310 Header_InsertItem(hwnd
, idx
, &hdi
);
1319 static void init_output(HWND hwnd
)
1323 HDC hdc
= GetDC(hwnd
);
1325 if (GetNumberFormat(LOCALE_USER_DEFAULT
, 0, _T("1000"), 0, b
, 16) > 4)
1326 Globals
.num_sep
= b
[1];
1328 Globals
.num_sep
= _T('.');
1330 old_font
= SelectFont(hdc
, Globals
.hfont
);
1331 GetTextExtentPoint32(hdc
, _T(" "), 1, &Globals
.spaceSize
);
1332 SelectFont(hdc
, old_font
);
1333 ReleaseDC(hwnd
, hdc
);
1336 static void draw_item(Pane
* pane
, LPDRAWITEMSTRUCT dis
, Entry
* entry
, int calcWidthCol
);
1339 /* calculate prefered width for all visible columns */
1341 static BOOL
calc_widths(Pane
* pane
, BOOL anyway
)
1343 int col
, x
, cx
, spc
=3*Globals
.spaceSize
.cx
;
1344 int entries
= ListBox_GetCount(pane
->hwnd
);
1345 int orgWidths
[COLUMNS
];
1346 int orgPositions
[COLUMNS
+1];
1352 memcpy(orgWidths
, pane
->widths
, sizeof(orgWidths
));
1353 memcpy(orgPositions
, pane
->positions
, sizeof(orgPositions
));
1356 for(col
=0; col
<COLUMNS
; col
++)
1357 pane
->widths
[col
] = 0;
1359 hdc
= GetDC(pane
->hwnd
);
1360 hfontOld
= SelectFont(hdc
, Globals
.hfont
);
1362 for(cnt
=0; cnt
<entries
; cnt
++) {
1363 Entry
* entry
= (Entry
*) ListBox_GetItemData(pane
->hwnd
, cnt
);
1372 dis
.hwndItem
= pane
->hwnd
;
1375 draw_item(pane
, &dis
, entry
, COLUMNS
);
1378 SelectObject(hdc
, hfontOld
);
1379 ReleaseDC(pane
->hwnd
, hdc
);
1382 for(col
=0; col
<COLUMNS
; col
++) {
1383 pane
->positions
[col
] = x
;
1384 cx
= pane
->widths
[col
];
1389 if (cx
< IMAGE_WIDTH
)
1392 pane
->widths
[col
] = cx
;
1398 pane
->positions
[COLUMNS
] = x
;
1400 ListBox_SetHorizontalExtent(pane
->hwnd
, x
);
1403 if (!memcmp(orgWidths
, pane
->widths
, sizeof(orgWidths
)))
1406 /* don't move, if only collapsing an entry */
1407 if (!anyway
&& pane
->widths
[0]<orgWidths
[0] &&
1408 !memcmp(orgWidths
+1, pane
->widths
+1, sizeof(orgWidths
)-sizeof(int))) {
1409 pane
->widths
[0] = orgWidths
[0];
1410 memcpy(pane
->positions
, orgPositions
, sizeof(orgPositions
));
1415 InvalidateRect(pane
->hwnd
, 0, TRUE
);
1421 /* calculate one prefered column width */
1423 static void calc_single_width(Pane
* pane
, int col
)
1427 int entries
= ListBox_GetCount(pane
->hwnd
);
1431 pane
->widths
[col
] = 0;
1433 hdc
= GetDC(pane
->hwnd
);
1434 hfontOld
= SelectFont(hdc
, Globals
.hfont
);
1436 for(cnt
=0; cnt
<entries
; cnt
++) {
1437 Entry
* entry
= (Entry
*) ListBox_GetItemData(pane
->hwnd
, cnt
);
1445 dis
.hwndItem
= pane
->hwnd
;
1448 draw_item(pane
, &dis
, entry
, col
);
1451 SelectObject(hdc
, hfontOld
);
1452 ReleaseDC(pane
->hwnd
, hdc
);
1454 cx
= pane
->widths
[col
];
1457 cx
+= 3*Globals
.spaceSize
.cx
;
1459 if (cx
< IMAGE_WIDTH
)
1463 pane
->widths
[col
] = cx
;
1465 x
= pane
->positions
[col
] + cx
;
1467 for(; col
<COLUMNS
; ) {
1468 pane
->positions
[++col
] = x
;
1469 x
+= pane
->widths
[col
];
1472 ListBox_SetHorizontalExtent(pane
->hwnd
, x
);
1476 /* insert listbox entries after index idx */
1478 static void insert_entries(Pane
* pane
, Entry
* parent
, int idx
)
1480 Entry
* entry
= parent
;
1485 ShowWindow(pane
->hwnd
, SW_HIDE
);
1487 for(; entry
; entry
=entry
->next
) {
1489 if (pane
->treePane
&& !(entry
->data
.dwFileAttributes
&FILE_ATTRIBUTE_DIRECTORY
))
1493 /* don't display entries "." and ".." in the left pane */
1494 if (pane
->treePane
&& (entry
->data
.dwFileAttributes
&FILE_ATTRIBUTE_DIRECTORY
)
1495 && entry
->data
.cFileName
[0]==_T('.'))
1497 #ifndef _NO_EXTENSIONS
1498 entry
->data
.cFileName
[1]==_T('\0') ||
1500 (entry
->data
.cFileName
[1]==_T('.') && entry
->data
.cFileName
[2]==_T('\0')))
1506 ListBox_InsertItemData(pane
->hwnd
, idx
, entry
);
1508 if (pane
->treePane
&& entry
->expanded
)
1509 insert_entries(pane
, entry
->down
, idx
);
1512 ShowWindow(pane
->hwnd
, SW_SHOW
);
1516 static WNDPROC g_orgTreeWndProc
;
1518 static void create_tree_window(HWND parent
, Pane
* pane
, int id
, int id_header
)
1520 static int s_init
= 0;
1521 Entry
* entry
= pane
->root
;
1523 pane
->hwnd
= CreateWindow(_T("ListBox"), _T(""), WS_CHILD
|WS_VISIBLE
|WS_HSCROLL
|WS_VSCROLL
|
1524 LBS_DISABLENOSCROLL
|LBS_NOINTEGRALHEIGHT
|LBS_OWNERDRAWFIXED
|LBS_NOTIFY
,
1525 0, 0, 0, 0, parent
, (HMENU
)id
, Globals
.hInstance
, 0);
1527 SetWindowLong(pane
->hwnd
, GWL_USERDATA
, (LPARAM
)pane
);
1528 g_orgTreeWndProc
= SubclassWindow(pane
->hwnd
, TreeWndProc
);
1530 SendMessage(pane
->hwnd
, WM_SETFONT
, (WPARAM
)Globals
.hfont
, FALSE
);
1532 /* insert entries into listbox */
1534 insert_entries(pane
, entry
, -1);
1536 /* calculate column widths */
1539 init_output(pane
->hwnd
);
1542 calc_widths(pane
, TRUE
);
1544 #ifndef _NO_EXTENSIONS
1545 pane
->hwndHeader
= create_header(parent
, pane
, id_header
);
1550 static void InitChildWindow(ChildWnd
* child
)
1552 create_tree_window(child
->hwnd
, &child
->left
, IDW_TREE_LEFT
, IDW_HEADER_LEFT
);
1553 create_tree_window(child
->hwnd
, &child
->right
, IDW_TREE_RIGHT
, IDW_HEADER_RIGHT
);
1557 static void format_date(const FILETIME
* ft
, TCHAR
* buffer
, int visible_cols
)
1565 if (!ft
->dwLowDateTime
&& !ft
->dwHighDateTime
)
1568 if (!FileTimeToLocalFileTime(ft
, &lft
))
1569 {err
: _tcscpy(buffer
,_T("???")); return;}
1571 if (!FileTimeToSystemTime(&lft
, &systime
))
1574 if (visible_cols
& COL_DATE
) {
1575 len
= GetDateFormat(LOCALE_USER_DEFAULT
, 0, &systime
, 0, buffer
, BUFFER_LEN
);
1580 if (visible_cols
& COL_TIME
) {
1582 buffer
[len
-1] = ' ';
1584 buffer
[len
++] = ' ';
1586 if (!GetTimeFormat(LOCALE_USER_DEFAULT
, 0, &systime
, 0, buffer
+len
, BUFFER_LEN
-len
))
1587 buffer
[len
] = _T('\0');
1592 static void calc_width(Pane
* pane
, LPDRAWITEMSTRUCT dis
, int col
, LPCTSTR str
)
1596 DrawText(dis
->hDC
, (LPTSTR
)str
, -1, &rt
, DT_CALCRECT
|DT_SINGLELINE
|DT_NOPREFIX
);
1598 if (rt
.right
> pane
->widths
[col
])
1599 pane
->widths
[col
] = rt
.right
;
1602 static void calc_tabbed_width(Pane
* pane
, LPDRAWITEMSTRUCT dis
, int col
, LPCTSTR str
)
1606 /* DRAWTEXTPARAMS dtp = {sizeof(DRAWTEXTPARAMS), 2};
1607 DrawTextEx(dis->hDC, (LPTSTR)str, -1, &rt, DT_CALCRECT|DT_SINGLELINE|DT_NOPREFIX|DT_EXPANDTABS|DT_TABSTOP, &dtp);*/
1609 DrawText(dis
->hDC
, (LPTSTR
)str
, -1, &rt
, DT_CALCRECT
|DT_SINGLELINE
|DT_EXPANDTABS
|DT_TABSTOP
|(2<<8));
1610 /*@@ rt (0,0) ??? */
1612 if (rt
.right
> pane
->widths
[col
])
1613 pane
->widths
[col
] = rt
.right
;
1617 static void output_text(Pane
* pane
, LPDRAWITEMSTRUCT dis
, int col
, LPCTSTR str
, DWORD flags
)
1619 int x
= dis
->rcItem
.left
;
1622 rt
.left
= x
+pane
->positions
[col
]+Globals
.spaceSize
.cx
;
1623 rt
.top
= dis
->rcItem
.top
;
1624 rt
.right
= x
+pane
->positions
[col
+1]-Globals
.spaceSize
.cx
;
1625 rt
.bottom
= dis
->rcItem
.bottom
;
1627 DrawText(dis
->hDC
, (LPTSTR
)str
, -1, &rt
, DT_SINGLELINE
|DT_NOPREFIX
|flags
);
1630 static void output_tabbed_text(Pane
* pane
, LPDRAWITEMSTRUCT dis
, int col
, LPCTSTR str
)
1632 int x
= dis
->rcItem
.left
;
1635 rt
.left
= x
+pane
->positions
[col
]+Globals
.spaceSize
.cx
;
1636 rt
.top
= dis
->rcItem
.top
;
1637 rt
.right
= x
+pane
->positions
[col
+1]-Globals
.spaceSize
.cx
;
1638 rt
.bottom
= dis
->rcItem
.bottom
;
1640 /* DRAWTEXTPARAMS dtp = {sizeof(DRAWTEXTPARAMS), 2};
1641 DrawTextEx(dis->hDC, (LPTSTR)str, -1, &rt, DT_SINGLELINE|DT_NOPREFIX|DT_EXPANDTABS|DT_TABSTOP, &dtp);*/
1643 DrawText(dis
->hDC
, (LPTSTR
)str
, -1, &rt
, DT_SINGLELINE
|DT_EXPANDTABS
|DT_TABSTOP
|(2<<8));
1646 static void output_number(Pane
* pane
, LPDRAWITEMSTRUCT dis
, int col
, LPCTSTR str
)
1648 int x
= dis
->rcItem
.left
;
1655 rt
.left
= x
+pane
->positions
[col
]+Globals
.spaceSize
.cx
;
1656 rt
.top
= dis
->rcItem
.top
;
1657 rt
.right
= x
+pane
->positions
[col
+1]-Globals
.spaceSize
.cx
;
1658 rt
.bottom
= dis
->rcItem
.bottom
;
1663 /* insert number separator characters */
1664 pos
= lstrlen(s
) % 3;
1670 *d
++ = Globals
.num_sep
;
1674 DrawText(dis
->hDC
, b
, d
-b
, &rt
, DT_RIGHT
|DT_SINGLELINE
|DT_NOPREFIX
|DT_END_ELLIPSIS
);
1678 static int is_exe_file(LPCTSTR ext
)
1680 const static LPCTSTR executable_extensions
[] = {
1685 #ifndef _NO_EXTENSIONS
1693 TCHAR ext_buffer
[_MAX_EXT
];
1698 for(s
=ext
+1,d
=ext_buffer
; (*d
=tolower(*s
)); s
++)
1701 for(p
=executable_extensions
; *p
; p
++)
1702 if (!_tcscmp(ext_buffer
, *p
))
1708 static int is_registered_type(LPCTSTR ext
)
1716 static void draw_item(Pane
* pane
, LPDRAWITEMSTRUCT dis
, Entry
* entry
, int calcWidthCol
)
1718 TCHAR buffer
[BUFFER_LEN
];
1720 int visible_cols
= pane
->visible_cols
;
1721 COLORREF bkcolor
, textcolor
;
1722 RECT focusRect
= dis
->rcItem
;
1725 #ifndef _NO_EXTENSIONS
1732 attrs
= entry
->data
.dwFileAttributes
;
1734 if (attrs
& FILE_ATTRIBUTE_DIRECTORY
) {
1735 if (entry
->data
.cFileName
[0]==_T('.') && entry
->data
.cFileName
[1]==_T('.')
1736 && entry
->data
.cFileName
[2]==_T('\0'))
1737 img
= IMG_FOLDER_UP
;
1738 #ifndef _NO_EXTENSIONS
1739 else if (entry
->data
.cFileName
[0]==_T('.') && entry
->data
.cFileName
[1]==_T('\0'))
1740 img
= IMG_FOLDER_CUR
;
1743 #ifdef _NO_EXTENSIONS
1746 (pane
->treePane
&& (dis
->itemState
&ODS_FOCUS
)))
1747 img
= IMG_OPEN_FOLDER
;
1751 LPCTSTR ext
= _tcsrchr(entry
->data
.cFileName
, '.');
1755 if (is_exe_file(ext
))
1756 img
= IMG_EXECUTABLE
;
1757 else if (is_registered_type(ext
))
1767 if (pane
->treePane
) {
1769 img_pos
= dis
->rcItem
.left
+ entry
->level
*(IMAGE_WIDTH
+Globals
.spaceSize
.cx
);
1771 if (calcWidthCol
== -1) {
1773 int y
= dis
->rcItem
.top
+ IMAGE_HEIGHT
/2;
1776 HRGN hrgn_org
= CreateRectRgn(0, 0, 0, 0);
1779 rt_clip
.left
= dis
->rcItem
.left
;
1780 rt_clip
.top
= dis
->rcItem
.top
;
1781 rt_clip
.right
= dis
->rcItem
.left
+pane
->widths
[col
];
1782 rt_clip
.bottom
= dis
->rcItem
.bottom
;
1784 hrgn
= CreateRectRgnIndirect(&rt_clip
);
1786 if (!GetClipRgn(dis
->hDC
, hrgn_org
)) {
1787 DeleteObject(hrgn_org
);
1791 /* HGDIOBJ holdPen = SelectObject(dis->hDC, GetStockObject(BLACK_PEN)); */
1792 ExtSelectClipRgn(dis
->hDC
, hrgn
, RGN_AND
);
1795 if ((up
=entry
->up
) != NULL
) {
1796 MoveToEx(dis
->hDC
, img_pos
-IMAGE_WIDTH
/2, y
, 0);
1797 LineTo(dis
->hDC
, img_pos
-2, y
);
1799 x
= img_pos
- IMAGE_WIDTH
/2;
1802 x
-= IMAGE_WIDTH
+Globals
.spaceSize
.cx
;
1806 && (up
->next
->data
.dwFileAttributes
&FILE_ATTRIBUTE_DIRECTORY
)
1809 MoveToEx(dis
->hDC
, x
, dis
->rcItem
.top
, 0);
1810 LineTo(dis
->hDC
, x
, dis
->rcItem
.bottom
);
1812 } while((up
=up
->up
) != NULL
);
1815 x
= img_pos
- IMAGE_WIDTH
/2;
1817 MoveToEx(dis
->hDC
, x
, dis
->rcItem
.top
, 0);
1818 LineTo(dis
->hDC
, x
, y
);
1822 && (entry
->next
->data
.dwFileAttributes
&FILE_ATTRIBUTE_DIRECTORY
)
1825 LineTo(dis
->hDC
, x
, dis
->rcItem
.bottom
);
1827 if (entry
->down
&& entry
->expanded
) {
1828 x
+= IMAGE_WIDTH
+Globals
.spaceSize
.cx
;
1829 MoveToEx(dis
->hDC
, x
, dis
->rcItem
.top
+IMAGE_HEIGHT
, 0);
1830 LineTo(dis
->hDC
, x
, dis
->rcItem
.bottom
);
1833 SelectClipRgn(dis
->hDC
, hrgn_org
);
1834 if (hrgn_org
) DeleteObject(hrgn_org
);
1835 /* SelectObject(dis->hDC, holdPen); */
1836 } else if (calcWidthCol
==col
|| calcWidthCol
==COLUMNS
) {
1837 int right
= img_pos
+ IMAGE_WIDTH
- Globals
.spaceSize
.cx
;
1839 if (right
> pane
->widths
[col
])
1840 pane
->widths
[col
] = right
;
1843 img_pos
= dis
->rcItem
.left
;
1846 img_pos
= dis
->rcItem
.left
;
1848 if (calcWidthCol
==col
|| calcWidthCol
==COLUMNS
)
1849 pane
->widths
[col
] = IMAGE_WIDTH
;
1852 if (calcWidthCol
== -1) {
1853 focusRect
.left
= img_pos
-2;
1855 #ifdef _NO_EXTENSIONS
1856 if (pane
->treePane
&& entry
) {
1859 DrawText(dis
->hDC
, entry
->data
.cFileName
, -1, &rt
, DT_CALCRECT
|DT_SINGLELINE
|DT_NOPREFIX
);
1861 focusRect
.right
= dis
->rcItem
.left
+pane
->positions
[col
+1]+Globals
.spaceSize
.cx
+ rt
.right
+2;
1865 if (attrs
& FILE_ATTRIBUTE_COMPRESSED
)
1866 textcolor
= COLOR_COMPRESSED
;
1869 textcolor
= RGB(0,0,0);
1871 if (dis
->itemState
& ODS_FOCUS
) {
1872 textcolor
= RGB(255,255,255);
1873 bkcolor
= COLOR_SELECTION
;
1875 bkcolor
= RGB(255,255,255);
1878 hbrush
= CreateSolidBrush(bkcolor
);
1879 FillRect(dis
->hDC
, &focusRect
, hbrush
);
1880 DeleteObject(hbrush
);
1882 SetBkMode(dis
->hDC
, TRANSPARENT
);
1883 SetTextColor(dis
->hDC
, textcolor
);
1885 cx
= pane
->widths
[col
];
1887 if (cx
&& img
!=IMG_NONE
) {
1888 if (cx
> IMAGE_WIDTH
)
1891 ImageList_DrawEx(Globals
.himl
, img
, dis
->hDC
,
1892 img_pos
, dis
->rcItem
.top
, cx
,
1893 IMAGE_HEIGHT
, bkcolor
, CLR_DEFAULT
, ILD_NORMAL
);
1900 #ifdef _NO_EXTENSIONS
1901 if (img
>= IMG_FOLDER_UP
)
1907 /* ouput file name */
1908 if (calcWidthCol
== -1)
1909 output_text(pane
, dis
, col
, entry
->data
.cFileName
, 0);
1910 else if (calcWidthCol
==col
|| calcWidthCol
==COLUMNS
)
1911 calc_width(pane
, dis
, col
, entry
->data
.cFileName
);
1915 #ifdef _NO_EXTENSIONS
1916 if (!pane
->treePane
) {
1919 /* display file size */
1920 if (visible_cols
& COL_SIZE
) {
1921 #ifdef _NO_EXTENSIONS
1922 if (!(attrs
&FILE_ATTRIBUTE_DIRECTORY
))
1927 *(DWORD
*)(&size
) = entry
->data
.nFileSizeLow
; /*TODO: platform spefific */
1928 *(((DWORD
*)&size
)+1) = entry
->data
.nFileSizeHigh
;
1930 _stprintf(buffer
, _T("%") LONGLONGARG
_T("d"), size
);
1932 if (calcWidthCol
== -1)
1933 output_number(pane
, dis
, col
, buffer
);
1934 else if (calcWidthCol
==col
|| calcWidthCol
==COLUMNS
)
1935 calc_width(pane
, dis
, col
, buffer
);/*TODO: not ever time enough */
1941 /* display file date */
1942 if (visible_cols
& (COL_DATE
|COL_TIME
)) {
1943 #ifndef _NO_EXTENSIONS
1944 format_date(&entry
->data
.ftCreationTime
, buffer
, visible_cols
);
1945 if (calcWidthCol
== -1)
1946 output_text(pane
, dis
, col
, buffer
, 0);
1947 else if (calcWidthCol
==col
|| calcWidthCol
==COLUMNS
)
1948 calc_width(pane
, dis
, col
, buffer
);
1951 format_date(&entry
->data
.ftLastAccessTime
, buffer
, visible_cols
);
1952 if (calcWidthCol
== -1)
1953 output_text(pane
, dis
, col
, buffer
, 0);
1954 else if (calcWidthCol
==col
|| calcWidthCol
==COLUMNS
)
1955 calc_width(pane
, dis
, col
, buffer
);
1959 format_date(&entry
->data
.ftLastWriteTime
, buffer
, visible_cols
);
1960 if (calcWidthCol
== -1)
1961 output_text(pane
, dis
, col
, buffer
, 0);
1962 else if (calcWidthCol
==col
|| calcWidthCol
==COLUMNS
)
1963 calc_width(pane
, dis
, col
, buffer
);
1967 #ifndef _NO_EXTENSIONS
1968 if (entry
->bhfi_valid
) {
1969 ((DWORD
*)&index
)[0] = entry
->bhfi
.nFileIndexLow
; /*TODO: platform spefific */
1970 ((DWORD
*)&index
)[1] = entry
->bhfi
.nFileIndexHigh
;
1972 if (visible_cols
& COL_INDEX
) {
1973 _stprintf(buffer
, _T("%") LONGLONGARG
_T("X"), index
);
1974 if (calcWidthCol
== -1)
1975 output_text(pane
, dis
, col
, buffer
, DT_RIGHT
);
1976 else if (calcWidthCol
==col
|| calcWidthCol
==COLUMNS
)
1977 calc_width(pane
, dis
, col
, buffer
);
1981 if (visible_cols
& COL_LINKS
) {
1982 wsprintf(buffer
, _T("%d"), entry
->bhfi
.nNumberOfLinks
);
1983 if (calcWidthCol
== -1)
1984 output_text(pane
, dis
, col
, buffer
, DT_CENTER
);
1985 else if (calcWidthCol
==col
|| calcWidthCol
==COLUMNS
)
1986 calc_width(pane
, dis
, col
, buffer
);
1993 /* show file attributes */
1994 if (visible_cols
& COL_ATTRIBUTES
) {
1995 #ifdef _NO_EXTENSIONS
1996 _tcscpy(buffer
, _T(" \t \t \t \t "));
1998 _tcscpy(buffer
, _T(" \t \t \t \t \t \t \t \t \t \t \t "));
2001 if (attrs
& FILE_ATTRIBUTE_NORMAL
) buffer
[ 0] = 'N';
2003 if (attrs
& FILE_ATTRIBUTE_READONLY
) buffer
[ 2] = 'R';
2004 if (attrs
& FILE_ATTRIBUTE_HIDDEN
) buffer
[ 4] = 'H';
2005 if (attrs
& FILE_ATTRIBUTE_SYSTEM
) buffer
[ 6] = 'S';
2006 if (attrs
& FILE_ATTRIBUTE_ARCHIVE
) buffer
[ 8] = 'A';
2007 if (attrs
& FILE_ATTRIBUTE_COMPRESSED
) buffer
[10] = 'C';
2008 #ifndef _NO_EXTENSIONS
2009 if (attrs
& FILE_ATTRIBUTE_DIRECTORY
) buffer
[12] = 'D';
2010 if (attrs
& FILE_ATTRIBUTE_ENCRYPTED
) buffer
[14] = 'E';
2011 if (attrs
& FILE_ATTRIBUTE_TEMPORARY
) buffer
[16] = 'T';
2012 if (attrs
& FILE_ATTRIBUTE_SPARSE_FILE
) buffer
[18] = 'P';
2013 if (attrs
& FILE_ATTRIBUTE_REPARSE_POINT
) buffer
[20] = 'Q';
2014 if (attrs
& FILE_ATTRIBUTE_OFFLINE
) buffer
[22] = 'O';
2015 if (attrs
& FILE_ATTRIBUTE_NOT_CONTENT_INDEXED
) buffer
[24] = 'X';
2019 if (calcWidthCol
== -1)
2020 output_tabbed_text(pane
, dis
, col
, buffer
);
2021 else if (calcWidthCol
==col
|| calcWidthCol
==COLUMNS
)
2022 calc_tabbed_width(pane
, dis
, col
, buffer
);
2028 if (flags.security) {
2029 DWORD rights = get_access_mask();
2031 tcscpy(buffer, _T(" \t \t \t \t \t \t \t \t \t \t \t "));
2033 if (rights & FILE_READ_DATA) buffer[ 0] = 'R';
2034 if (rights & FILE_WRITE_DATA) buffer[ 2] = 'W';
2035 if (rights & FILE_APPEND_DATA) buffer[ 4] = 'A';
2036 if (rights & FILE_READ_EA) {buffer[6] = 'entry'; buffer[ 7] = 'R';}
2037 if (rights & FILE_WRITE_EA) {buffer[9] = 'entry'; buffer[10] = 'W';}
2038 if (rights & FILE_EXECUTE) buffer[12] = 'X';
2039 if (rights & FILE_DELETE_CHILD) buffer[14] = 'D';
2040 if (rights & FILE_READ_ATTRIBUTES) {buffer[16] = 'a'; buffer[17] = 'R';}
2041 if (rights & FILE_WRITE_ATTRIBUTES) {buffer[19] = 'a'; buffer[20] = 'W';}
2042 if (rights & WRITE_DAC) buffer[22] = 'C';
2043 if (rights & WRITE_OWNER) buffer[24] = 'O';
2044 if (rights & SYNCHRONIZE) buffer[26] = 'S';
2046 output_text(dis, col++, buffer, DT_LEFT, 3, psize);
2049 if (flags.description) {
2050 get_description(buffer);
2051 output_text(dis, col++, buffer, 0, psize);
2055 #ifdef _NO_EXTENSIONS
2058 /* draw focus frame */
2059 if ((dis
->itemState
&ODS_FOCUS
) && calcWidthCol
==-1) {
2060 /* Currently [04/2000] Wine neither behaves exactly the same */
2061 /* way as WIN 95 nor like Windows NT... */
2066 if (!(GetVersion() & 0x80000000)) { /* Windows NT? */
2067 LOGBRUSH lb
= {PS_SOLID
, RGB(255,255,255)};
2068 hpen
= ExtCreatePen(PS_COSMETIC
|PS_ALTERNATE
, 1, &lb
, 0, 0);
2070 hpen
= CreatePen(PS_DOT
, 0, RGB(255,255,255));
2072 lastPen
= SelectPen(dis
->hDC
, hpen
);
2073 lastBrush
= SelectObject(dis
->hDC
, GetStockObject(HOLLOW_BRUSH
));
2074 SetROP2(dis
->hDC
, R2_XORPEN
);
2075 Rectangle(dis
->hDC
, focusRect
.left
, focusRect
.top
, focusRect
.right
, focusRect
.bottom
);
2076 SelectObject(dis
->hDC
, lastBrush
);
2077 SelectObject(dis
->hDC
, lastPen
);
2084 #ifdef _NO_EXTENSIONS
2086 static void draw_splitbar(HWND hwnd
, int x
)
2089 HDC hdc
= GetDC(hwnd
);
2091 GetClientRect(hwnd
, &rt
);
2093 rt
.left
= x
- SPLIT_WIDTH
/2;
2094 rt
.right
= x
+ SPLIT_WIDTH
/2+1;
2096 InvertRect(hdc
, &rt
);
2098 ReleaseDC(hwnd
, hdc
);
2104 #ifndef _NO_EXTENSIONS
2106 static void set_header(Pane
* pane
)
2109 int scroll_pos
= GetScrollPos(pane
->hwnd
, SB_HORZ
);
2112 item
.mask
= HDI_WIDTH
;
2115 for(; x
+pane
->widths
[i
]<scroll_pos
&& i
<COLUMNS
; i
++) {
2116 x
+= pane
->widths
[i
];
2117 Header_SetItem(pane
->hwndHeader
, i
, &item
);
2121 x
+= pane
->widths
[i
];
2122 item
.cxy
= x
- scroll_pos
;
2123 Header_SetItem(pane
->hwndHeader
, i
++, &item
);
2125 for(; i
<COLUMNS
; i
++) {
2126 item
.cxy
= pane
->widths
[i
];
2127 x
+= pane
->widths
[i
];
2128 Header_SetItem(pane
->hwndHeader
, i
, &item
);
2133 static LRESULT
pane_notify(Pane
* pane
, NMHDR
* pnmh
)
2135 switch(pnmh
->code
) {
2137 case HDN_ENDTRACK
: {
2138 HD_NOTIFY
* phdn
= (HD_NOTIFY
*) pnmh
;
2139 int idx
= phdn
->iItem
;
2140 int dx
= phdn
->pitem
->cxy
- pane
->widths
[idx
];
2144 GetClientRect(pane
->hwnd
, &clnt
);
2146 /* move immediate to simulate HDS_FULLDRAG (for now [04/2000] not realy needed with WINELIB) */
2147 Header_SetItem(pane
->hwndHeader
, idx
, phdn
->pitem
);
2149 pane
->widths
[idx
] += dx
;
2151 for(i
=idx
; ++i
<=COLUMNS
; )
2152 pane
->positions
[i
] += dx
;
2155 int scroll_pos
= GetScrollPos(pane
->hwnd
, SB_HORZ
);
2159 rt_scr
.left
= pane
->positions
[idx
+1]-scroll_pos
;
2161 rt_scr
.right
= clnt
.right
;
2162 rt_scr
.bottom
= clnt
.bottom
;
2164 rt_clip
.left
= pane
->positions
[idx
]-scroll_pos
;
2166 rt_clip
.right
= clnt
.right
;
2167 rt_clip
.bottom
= clnt
.bottom
;
2169 if (rt_scr
.left
< 0) rt_scr
.left
= 0;
2170 if (rt_clip
.left
< 0) rt_clip
.left
= 0;
2172 ScrollWindowEx(pane
->hwnd
, dx
, 0, &rt_scr
, &rt_clip
, 0, 0, SW_INVALIDATE
);
2174 rt_clip
.right
= pane
->positions
[idx
+1];
2175 RedrawWindow(pane
->hwnd
, &rt_clip
, 0, RDW_INVALIDATE
|RDW_UPDATENOW
);
2177 if (pnmh
->code
== HDN_ENDTRACK
) {
2178 ListBox_SetHorizontalExtent(pane
->hwnd
, pane
->positions
[COLUMNS
]);
2180 if (GetScrollPos(pane
->hwnd
, SB_HORZ
) != scroll_pos
)
2188 case HDN_DIVIDERDBLCLICK
: {
2189 HD_NOTIFY
* phdn
= (HD_NOTIFY
*) pnmh
;
2192 calc_single_width(pane
, phdn
->iItem
);
2193 item
.mask
= HDI_WIDTH
;
2194 item
.cxy
= pane
->widths
[phdn
->iItem
];
2196 Header_SetItem(pane
->hwndHeader
, phdn
->iItem
, &item
);
2197 InvalidateRect(pane
->hwnd
, 0, TRUE
);
2207 static void scan_entry(ChildWnd
* child
, Entry
* entry
)
2209 TCHAR path
[MAX_PATH
];
2210 int idx
= ListBox_GetCurSel(child
->left
.hwnd
);
2211 HCURSOR crsrOld
= SetCursor(LoadCursor(0, IDC_WAIT
));
2213 /* delete sub entries in left pane */
2215 LRESULT res
= ListBox_GetItemData(child
->left
.hwnd
, idx
+1);
2216 Entry
* sub
= (Entry
*) res
;
2218 if (res
==LB_ERR
|| !sub
|| sub
->level
<=entry
->level
)
2221 ListBox_DeleteString(child
->left
.hwnd
, idx
+1);
2224 /* empty right pane */
2225 ListBox_ResetContent(child
->right
.hwnd
);
2227 /* release memory */
2228 free_entries(entry
);
2230 /* read contents from disk */
2231 get_path(entry
, path
);
2232 read_directory(entry
, path
, child
->sortOrder
);
2234 /* insert found entries in right pane */
2235 insert_entries(&child
->right
, entry
->down
, -1);
2236 calc_widths(&child
->right
, FALSE
);
2237 #ifndef _NO_EXTENSIONS
2238 set_header(&child
->right
);
2241 child
->header_wdths_ok
= FALSE
;
2247 /* expand a directory entry */
2249 static BOOL
expand_entry(ChildWnd
* child
, Entry
* dir
)
2254 if (!dir
|| dir
->expanded
|| !dir
->down
)
2259 if (p
->data
.cFileName
[0]=='.' && p
->data
.cFileName
[1]=='\0' && p
->next
) {
2262 if (p
->data
.cFileName
[0]=='.' && p
->data
.cFileName
[1]=='.' &&
2263 p
->data
.cFileName
[2]=='\0' && p
->next
)
2267 /* no subdirectories ? */
2268 if (!(p
->data
.dwFileAttributes
&FILE_ATTRIBUTE_DIRECTORY
))
2271 idx
= ListBox_FindItemData(child
->left
.hwnd
, 0, dir
);
2273 dir
->expanded
= TRUE
;
2275 /* insert entries in left pane */
2276 insert_entries(&child
->left
, p
, idx
);
2278 if (!child
->header_wdths_ok
) {
2279 if (calc_widths(&child
->left
, FALSE
)) {
2280 #ifndef _NO_EXTENSIONS
2281 set_header(&child
->left
);
2284 child
->header_wdths_ok
= TRUE
;
2292 static void collapse_entry(Pane
* pane
, Entry
* dir
)
2294 int idx
= ListBox_FindItemData(pane
->hwnd
, 0, dir
);
2296 ShowWindow(pane
->hwnd
, SW_HIDE
);
2298 /* hide sub entries */
2300 LRESULT res
= ListBox_GetItemData(pane
->hwnd
, idx
+1);
2301 Entry
* sub
= (Entry
*) res
;
2303 if (res
==LB_ERR
|| !sub
|| sub
->level
<=dir
->level
)
2306 ListBox_DeleteString(pane
->hwnd
, idx
+1);
2309 dir
->expanded
= FALSE
;
2311 ShowWindow(pane
->hwnd
, SW_SHOW
);
2315 static void set_curdir(ChildWnd
* child
, Entry
* entry
)
2317 TCHAR path
[MAX_PATH
];
2319 child
->left
.cur
= entry
;
2320 child
->right
.root
= entry
;
2321 child
->right
.cur
= entry
;
2323 if (!entry
->scanned
)
2324 scan_entry(child
, entry
);
2326 ListBox_ResetContent(child
->right
.hwnd
);
2327 insert_entries(&child
->right
, entry
->down
, -1);
2328 calc_widths(&child
->right
, FALSE
);
2329 #ifndef _NO_EXTENSIONS
2330 set_header(&child
->right
);
2334 get_path(entry
, path
);
2335 lstrcpy(child
->path
, path
);
2336 SetWindowText(child
->hwnd
, path
);
2337 SetCurrentDirectory(path
);
2341 static void activate_entry(ChildWnd
* child
, Pane
* pane
)
2343 Entry
* entry
= pane
->cur
;
2348 if (entry
->data
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) {
2349 int scanned_old
= entry
->scanned
;
2352 scan_entry(child
, entry
);
2354 #ifndef _NO_EXTENSIONS
2355 if (entry
->data
.cFileName
[0]=='.' && entry
->data
.cFileName
[1]=='\0')
2359 if (entry
->data
.cFileName
[0]=='.' && entry
->data
.cFileName
[1]=='.' && entry
->data
.cFileName
[2]=='\0') {
2360 entry
= child
->left
.cur
->up
;
2361 collapse_entry(&child
->left
, entry
);
2363 } else if (entry
->expanded
)
2364 collapse_entry(pane
, child
->left
.cur
);
2366 expand_entry(child
, child
->left
.cur
);
2368 if (!pane
->treePane
) focus_entry
: {
2369 int idx
= ListBox_FindItemData(child
->left
.hwnd
, ListBox_GetCurSel(child
->left
.hwnd
), entry
);
2370 ListBox_SetCurSel(child
->left
.hwnd
, idx
);
2371 set_curdir(child
, entry
);
2376 calc_widths(pane
, FALSE
);
2378 #ifndef _NO_EXTENSIONS
2384 /*TODO: start program, open document... */
2390 static BOOL
pane_command(Pane
* pane
, UINT cmd
)
2394 if (pane
->visible_cols
) {
2395 pane
->visible_cols
= 0;
2396 calc_widths(pane
, TRUE
);
2397 #ifndef _NO_EXTENSIONS
2400 InvalidateRect(pane
->hwnd
, 0, TRUE
);
2401 CheckMenuItem(Globals
.hMenuView
, ID_VIEW_NAME
, MF_BYCOMMAND
|MF_CHECKED
);
2402 CheckMenuItem(Globals
.hMenuView
, ID_VIEW_ALL_ATTRIBUTES
, MF_BYCOMMAND
);
2403 CheckMenuItem(Globals
.hMenuView
, ID_VIEW_SELECTED_ATTRIBUTES
, MF_BYCOMMAND
);
2407 case ID_VIEW_ALL_ATTRIBUTES
:
2408 if (pane
->visible_cols
!= COL_ALL
) {
2409 pane
->visible_cols
= COL_ALL
;
2410 calc_widths(pane
, TRUE
);
2411 #ifndef _NO_EXTENSIONS
2414 InvalidateRect(pane
->hwnd
, 0, TRUE
);
2415 CheckMenuItem(Globals
.hMenuView
, ID_VIEW_NAME
, MF_BYCOMMAND
);
2416 CheckMenuItem(Globals
.hMenuView
, ID_VIEW_ALL_ATTRIBUTES
, MF_BYCOMMAND
|MF_CHECKED
);
2417 CheckMenuItem(Globals
.hMenuView
, ID_VIEW_SELECTED_ATTRIBUTES
, MF_BYCOMMAND
);
2421 #ifndef _NO_EXTENSIONS
2422 case ID_PREFERED_SIZES
: {
2423 calc_widths(pane
, TRUE
);
2425 InvalidateRect(pane
->hwnd
, 0, TRUE
);
2429 /* TODO: more command ids... */
2439 LRESULT CALLBACK
ChildWndProc(HWND hwnd
, UINT nmsg
, WPARAM wparam
, LPARAM lparam
)
2441 static int last_split
;
2443 ChildWnd
* child
= (ChildWnd
*) GetWindowLong(hwnd
, GWL_USERDATA
);
2448 LPDRAWITEMSTRUCT dis
= (LPDRAWITEMSTRUCT
)lparam
;
2449 Entry
* entry
= (Entry
*) dis
->itemData
;
2451 if (dis
->CtlID
== IDW_TREE_LEFT
)
2452 draw_item(&child
->left
, dis
, entry
, -1);
2454 draw_item(&child
->right
, dis
, entry
, -1);
2459 InitChildWindow(child
);
2463 free_child_window(child
);
2464 SetWindowLong(hwnd
, GWL_USERDATA
, 0);
2471 GetClientRect(hwnd
, &rt
);
2472 BeginPaint(hwnd
, &ps
);
2473 rt
.left
= child
->split_pos
-SPLIT_WIDTH
/2;
2474 rt
.right
= child
->split_pos
+SPLIT_WIDTH
/2+1;
2475 lastBrush
= SelectBrush(ps
.hdc
, (HBRUSH
)GetStockObject(COLOR_SPLITBAR
));
2476 Rectangle(ps
.hdc
, rt
.left
, rt
.top
-1, rt
.right
, rt
.bottom
+1);
2477 SelectObject(ps
.hdc
, lastBrush
);
2478 #ifdef _NO_EXTENSIONS
2479 rt
.top
= rt
.bottom
- GetSystemMetrics(SM_CYHSCROLL
);
2480 FillRect(ps
.hdc
, &rt
, GetStockObject(BLACK_BRUSH
));
2482 EndPaint(hwnd
, &ps
);
2486 if (LOWORD(lparam
) == HTCLIENT
) {
2489 ScreenToClient(hwnd
, &pt
);
2491 if (pt
.x
>=child
->split_pos
-SPLIT_WIDTH
/2 && pt
.x
<child
->split_pos
+SPLIT_WIDTH
/2+1) {
2492 SetCursor(LoadCursor(0, IDC_SIZEWE
));
2498 case WM_LBUTTONDOWN
: {
2500 int x
= LOWORD(lparam
);
2502 GetClientRect(hwnd
, &rt
);
2504 if (x
>=child
->split_pos
-SPLIT_WIDTH
/2 && x
<child
->split_pos
+SPLIT_WIDTH
/2+1) {
2505 last_split
= child
->split_pos
;
2506 #ifdef _NO_EXTENSIONS
2507 draw_splitbar(hwnd
, last_split
);
2515 if (GetCapture() == hwnd
) {
2516 #ifdef _NO_EXTENSIONS
2518 int x
= LOWORD(lparam
);
2519 draw_splitbar(hwnd
, last_split
);
2521 GetClientRect(hwnd
, &rt
);
2522 child
->split_pos
= x
;
2523 resize_tree(child
, rt
.right
, rt
.bottom
);
2529 #ifdef _NO_EXTENSIONS
2530 case WM_CAPTURECHANGED
:
2531 if (GetCapture()==hwnd
&& last_split
>=0)
2532 draw_splitbar(hwnd
, last_split
);
2537 if (wparam
== VK_ESCAPE
)
2538 if (GetCapture() == hwnd
) {
2540 #ifdef _NO_EXTENSIONS
2541 draw_splitbar(hwnd
, last_split
);
2543 child
->split_pos
= last_split
;
2545 GetClientRect(hwnd
, &rt
);
2546 resize_tree(child
, rt
.right
, rt
.bottom
);
2549 SetCursor(LoadCursor(0, IDC_ARROW
));
2554 if (GetCapture() == hwnd
) {
2556 int x
= LOWORD(lparam
);
2558 #ifdef _NO_EXTENSIONS
2559 HDC hdc
= GetDC(hwnd
);
2560 GetClientRect(hwnd
, &rt
);
2562 rt
.left
= last_split
-SPLIT_WIDTH
/2;
2563 rt
.right
= last_split
+SPLIT_WIDTH
/2+1;
2564 InvertRect(hdc
, &rt
);
2567 rt
.left
= x
-SPLIT_WIDTH
/2;
2568 rt
.right
= x
+SPLIT_WIDTH
/2+1;
2569 InvertRect(hdc
, &rt
);
2571 ReleaseDC(hwnd
, hdc
);
2573 GetClientRect(hwnd
, &rt
);
2575 if (x
>=0 && x
<rt
.right
) {
2576 child
->split_pos
= x
;
2577 resize_tree(child
, rt
.right
, rt
.bottom
);
2578 rt
.left
= x
-SPLIT_WIDTH
/2;
2579 rt
.right
= x
+SPLIT_WIDTH
/2+1;
2580 InvalidateRect(hwnd
, &rt
, FALSE
);
2581 UpdateWindow(child
->left
.hwnd
);
2583 UpdateWindow(child
->right
.hwnd
);
2589 #ifndef _NO_EXTENSIONS
2590 case WM_GETMINMAXINFO
:
2591 DefMDIChildProc(hwnd
, nmsg
, wparam
, lparam
);
2593 {LPMINMAXINFO lpmmi
= (LPMINMAXINFO
)lparam
;
2595 lpmmi
->ptMaxTrackSize
.x
<<= 1;/*2*GetSystemMetrics(SM_CXSCREEN) / SM_CXVIRTUALSCREEN */
2596 lpmmi
->ptMaxTrackSize
.y
<<= 1;/*2*GetSystemMetrics(SM_CYSCREEN) / SM_CYVIRTUALSCREEN */
2601 SetCurrentDirectory(child
->path
);
2602 SetFocus(child
->focus_pane
? child
->right
.hwnd
: child
->left
.hwnd
);
2605 case WM_DISPATCH_COMMAND
: {
2606 Pane
* pane
= GetFocus()==child
->left
.hwnd
? &child
->left
: &child
->right
;
2608 switch(LOWORD(wparam
)) {
2609 case ID_WINDOW_NEW
: {
2610 ChildWnd
* new_child
= alloc_child_window(child
->path
);
2612 if (!create_child_window(new_child
))
2618 scan_entry(child
, pane
->cur
);
2622 activate_entry(child
, pane
);
2626 return pane_command(pane
, LOWORD(wparam
));
2632 Pane
* pane
= GetFocus()==child
->left
.hwnd
? &child
->left
: &child
->right
;
2634 switch(HIWORD(wparam
)) {
2635 case LBN_SELCHANGE
: {
2636 int idx
= ListBox_GetCurSel(pane
->hwnd
);
2637 Entry
* entry
= (Entry
*) ListBox_GetItemData(pane
->hwnd
, idx
);
2639 if (pane
== &child
->left
)
2640 set_curdir(child
, entry
);
2646 activate_entry(child
, pane
);
2651 #ifndef _NO_EXTENSIONS
2653 NMHDR
* pnmh
= (NMHDR
*) lparam
;
2654 return pane_notify(pnmh
->idFrom
==IDW_HEADER_LEFT
? &child
->left
: &child
->right
, pnmh
);}
2658 if (wparam
!= SIZE_MINIMIZED
)
2659 resize_tree(child
, LOWORD(lparam
), HIWORD(lparam
));
2663 return DefMDIChildProc(hwnd
, nmsg
, wparam
, lparam
);
2670 LRESULT CALLBACK
TreeWndProc(HWND hwnd
, UINT nmsg
, WPARAM wparam
, LPARAM lparam
)
2672 ChildWnd
* child
= (ChildWnd
*) GetWindowLong(GetParent(hwnd
), GWL_USERDATA
);
2673 Pane
* pane
= (Pane
*) GetWindowLong(hwnd
, GWL_USERDATA
);
2677 #ifndef _NO_EXTENSIONS
2684 child
->focus_pane
= pane
==&child
->right
? 1: 0;
2685 ListBox_SetSel(hwnd
, TRUE
, 1);
2686 /*TODO: check menu items */
2690 if (wparam
== VK_TAB
) {
2691 /*TODO: SetFocus(Globals.hdrivebar) */
2692 SetFocus(child
->focus_pane
? child
->left
.hwnd
: child
->right
.hwnd
);
2696 return CallWindowProc(g_orgTreeWndProc
, hwnd
, nmsg
, wparam
, lparam
);
2700 static void InitInstance(HINSTANCE hinstance
)
2705 WINE_UNUSED ATOM hChildClass
;
2706 HMENU hMenuFrame
= LoadMenu(hinstance
, MAKEINTRESOURCE(IDM_WINEFILE
));
2707 HMENU hMenuWindow
= GetSubMenu(hMenuFrame
, GetMenuItemCount(hMenuFrame
)-2);
2709 CLIENTCREATESTRUCT ccs
;
2711 INITCOMMONCONTROLSEX icc
= {
2712 sizeof(INITCOMMONCONTROLSEX
),
2717 TCHAR path
[MAX_PATH
];
2722 wcFrame
.cbSize
= sizeof(WNDCLASSEX
);
2724 wcFrame
.lpfnWndProc
= FrameWndProc
;
2725 wcFrame
.cbClsExtra
= 0;
2726 wcFrame
.cbWndExtra
= 0;
2727 wcFrame
.hInstance
= hinstance
;
2728 wcFrame
.hIcon
= LoadIcon(hinstance
,
2729 MAKEINTRESOURCE(IDI_WINEFILE
));
2730 wcFrame
.hCursor
= LoadCursor(0, IDC_ARROW
);
2731 wcFrame
.hbrBackground
= 0;
2732 wcFrame
.lpszMenuName
= 0;
2733 wcFrame
.lpszClassName
= WINEFILEFRAME
;
2734 wcFrame
.hIconSm
= (HICON
)LoadImage(hinstance
,
2735 MAKEINTRESOURCE(IDI_WINEFILE
),
2737 GetSystemMetrics(SM_CXSMICON
),
2738 GetSystemMetrics(SM_CYSMICON
),
2741 /* register frame window class */
2742 hframeClass
= RegisterClassEx(&wcFrame
);
2744 wcChild
.style
= CS_CLASSDC
|CS_DBLCLKS
|CS_VREDRAW
;
2745 wcChild
.lpfnWndProc
= ChildWndProc
;
2746 wcChild
.cbClsExtra
= 0;
2747 wcChild
.cbWndExtra
= 0;
2748 wcChild
.hInstance
= hinstance
;
2750 wcChild
.hCursor
= LoadCursor(0, IDC_ARROW
);
2751 wcChild
.hbrBackground
= 0;
2752 wcChild
.lpszMenuName
= 0;
2753 wcChild
.lpszClassName
= WINEFILETREE
;
2755 /* register tree windows class */
2756 hChildClass
= RegisterClass(&wcChild
);
2758 ccs
.hWindowMenu
= hMenuWindow
;
2759 ccs
.idFirstChild
= IDW_FIRST_CHILD
;
2761 Globals
.hMenuFrame
= hMenuFrame
;
2762 Globals
.hMenuView
= GetSubMenu(hMenuFrame
, 3);
2763 Globals
.hMenuOptions
= GetSubMenu(hMenuFrame
, 4);
2765 Globals
.haccel
= LoadAccelerators(hinstance
, MAKEINTRESOURCE(IDA_WINEFILE
));
2767 Globals
.hfont
= CreateFont(-MulDiv(8,GetDeviceCaps(hdc
,LOGPIXELSY
),72), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _T("MS Sans Serif"));
2771 Globals
.hInstance
= hinstance
;
2773 /* create main window */
2774 Globals
.hMainWnd
= CreateWindowEx(0, (LPCTSTR
)(int)hframeClass
, _T("Wine File"), WS_OVERLAPPEDWINDOW
,
2775 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
2776 0/*hWndParent*/, Globals
.hMenuFrame
, hinstance
, 0/*lpParam*/);
2779 Globals
.hmdiclient
= CreateWindowEx(0, _T("MDICLIENT"), NULL
,
2780 WS_CHILD
|WS_CLIPCHILDREN
|WS_VSCROLL
|WS_HSCROLL
|WS_VISIBLE
|WS_BORDER
,
2782 Globals
.hMainWnd
, 0, hinstance
, &ccs
);
2785 InitCommonControlsEx(&icc
);
2788 TBBUTTON drivebarBtn
= {0, 0, TBSTATE_ENABLED
, TBSTYLE_SEP
};
2792 Globals
.hdrivebar
= CreateToolbarEx(Globals
.hMainWnd
, WS_CHILD
|WS_VISIBLE
|CCS_NOMOVEY
|TBSTYLE_LIST
,
2793 IDW_DRIVEBAR
, 2, Globals
.hInstance
, IDB_DRIVEBAR
, &drivebarBtn
,
2794 1, 16, 13, 16, 13, sizeof(TBBUTTON
));
2795 CheckMenuItem(Globals
.hMenuOptions
, ID_VIEW_DRIVE_BAR
, MF_BYCOMMAND
|MF_CHECKED
);
2797 GetLogicalDriveStrings(BUFFER_LEN
, Globals
.drives
);
2799 drivebarBtn
.fsStyle
= TBSTYLE_BUTTON
;
2801 #ifndef _NO_EXTENSIONS
2803 /* insert unix file system button */
2804 SendMessage(Globals
.hdrivebar
, TB_ADDSTRING
, 0, (LPARAM
)_T("/\0"));
2806 drivebarBtn
.idCommand
= ID_DRIVE_UNIX_FS
;
2807 SendMessage(Globals
.hdrivebar
, TB_INSERTBUTTON
, btn
++, (LPARAM
)&drivebarBtn
);
2808 drivebarBtn
.iString
++;
2811 /* register windows drive root strings */
2812 SendMessage(Globals
.hdrivebar
, TB_ADDSTRING
, 0, (LPARAM
)Globals
.drives
);
2815 drivebarBtn
.idCommand
= ID_DRIVE_FIRST
;
2817 for(p
=Globals
.drives
; *p
; ) {
2818 #ifdef _NO_EXTENSIONS
2819 /* insert drive letter */
2820 TCHAR b
[3] = {tolower(*p
)};
2821 SendMessage(Globals
.hdrivebar
, TB_ADDSTRING
, 0, (LPARAM
)b
);
2823 switch(GetDriveType(p
)) {
2824 case DRIVE_REMOVABLE
: drivebarBtn
.iBitmap
= 1; break;
2825 case DRIVE_CDROM
: drivebarBtn
.iBitmap
= 3; break;
2826 case DRIVE_REMOTE
: drivebarBtn
.iBitmap
= 4; break;
2827 case DRIVE_RAMDISK
: drivebarBtn
.iBitmap
= 5; break;
2828 default:/*DRIVE_FIXED*/ drivebarBtn
.iBitmap
= 2;
2831 SendMessage(Globals
.hdrivebar
, TB_INSERTBUTTON
, btn
++, (LPARAM
)&drivebarBtn
);
2832 drivebarBtn
.idCommand
++;
2833 drivebarBtn
.iString
++;
2840 TBBUTTON toolbarBtns
[] = {
2841 {0, 0, 0, TBSTYLE_SEP
},
2842 {0, ID_WINDOW_NEW
, TBSTATE_ENABLED
, TBSTYLE_BUTTON
},
2843 {1, ID_WINDOW_CASCADE
, TBSTATE_ENABLED
, TBSTYLE_BUTTON
},
2844 {2, ID_WINDOW_TILE_HORZ
, TBSTATE_ENABLED
, TBSTYLE_BUTTON
},
2845 {3, ID_WINDOW_TILE_VERT
, TBSTATE_ENABLED
, TBSTYLE_BUTTON
},
2846 {4, 2/*TODO: ID_...*/, TBSTATE_ENABLED
, TBSTYLE_BUTTON
},
2847 {5, 2/*TODO: ID_...*/, TBSTATE_ENABLED
, TBSTYLE_BUTTON
},
2850 Globals
.htoolbar
= CreateToolbarEx(Globals
.hMainWnd
, WS_CHILD
|WS_VISIBLE
,
2851 IDW_TOOLBAR
, 2, Globals
.hInstance
, IDB_TOOLBAR
, toolbarBtns
,
2852 sizeof(toolbarBtns
)/sizeof(TBBUTTON
), 16, 15, 16, 15, sizeof(TBBUTTON
));
2853 CheckMenuItem(Globals
.hMenuOptions
, ID_VIEW_TOOL_BAR
, MF_BYCOMMAND
|MF_CHECKED
);
2856 Globals
.hstatusbar
= CreateStatusWindow(WS_CHILD
|WS_VISIBLE
, 0, Globals
.hMainWnd
, IDW_STATUSBAR
);
2857 CheckMenuItem(Globals
.hMenuOptions
, ID_VIEW_STATUSBAR
, MF_BYCOMMAND
|MF_CHECKED
);
2859 /* CreateStatusWindow does not accept WS_BORDER
2860 Globals.hstatusbar = CreateWindowEx(WS_EX_NOPARENTNOTIFY, STATUSCLASSNAME, 0,
2861 WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS|WS_BORDER|CCS_NODIVIDER, 0,0,0,0,
2862 Globals.hMainWnd, (HMENU)IDW_STATUSBAR, hinstance, 0);*/
2864 /*TODO: read paths and window placements from registry */
2865 GetCurrentDirectory(MAX_PATH
, path
);
2866 child
= alloc_child_window(path
);
2868 child
->pos
.showCmd
= SW_SHOWMAXIMIZED
;
2869 child
->pos
.rcNormalPosition
.left
= 0;
2870 child
->pos
.rcNormalPosition
.top
= 0;
2871 child
->pos
.rcNormalPosition
.right
= 320;
2872 child
->pos
.rcNormalPosition
.bottom
= 280;
2874 if (!create_child_window(child
))
2877 SetWindowPlacement(child
->hwnd
, &child
->pos
);
2879 Globals
.himl
= ImageList_LoadBitmap(Globals
.hInstance
, MAKEINTRESOURCE(IDB_IMAGES
), 16, 0, RGB(0,255,0));
2881 Globals
.prescan_node
= FALSE
;
2886 ImageList_Destroy(Globals
.himl
);
2890 #ifdef _NO_EXTENSIONS
2892 /* search for already running win[e]files */
2894 static int g_foundPrevInstance
= 0;
2896 static BOOL CALLBACK
EnumWndProc(HWND hwnd
, LPARAM lparam
)
2900 GetClassName(hwnd
, cls
, 128);
2902 if (!lstrcmp(cls
, (LPCTSTR
)lparam
)) {
2903 g_foundPrevInstance
++;
2913 int APIENTRY
WinMain(HINSTANCE hinstance
,
2914 HINSTANCE previnstance
,
2920 #ifdef _NO_EXTENSIONS
2921 /* allow only one running instance */
2922 EnumWindows(EnumWndProc
, (LPARAM
)WINEFILEFRAME
);
2924 if (g_foundPrevInstance
)
2928 InitInstance(hinstance
);
2930 if (cmdshow
== SW_SHOWNORMAL
) {
2931 /*TODO: read window placement from registry */
2932 cmdshow
= SW_MAXIMIZE
;
2935 ShowWindow(Globals
.hMainWnd
, cmdshow
);
2936 UpdateWindow(Globals
.hMainWnd
);
2938 while(GetMessage(&msg
, 0, 0, 0)) {
2939 if (!TranslateMDISysAccel(Globals
.hmdiclient
, &msg
) &&
2940 !TranslateAccelerator(Globals
.hMainWnd
, Globals
.haccel
, &msg
))
2942 TranslateMessage(&msg
);
2943 DispatchMessage(&msg
);