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
23 #include "wine/port.h"
30 /* for read_directory_unix() */
31 #if !defined(_NO_EXTENSIONS) && !defined(_WIN32)
44 #define _MAX_FNAME 256
45 #define _MAX_DIR _MAX_FNAME
46 #define _MAX_EXT _MAX_FNAME
50 WINEFILE_GLOBALS Globals
;
52 extern void WineLicense(HWND hWnd
);
53 extern void WineWarranty(HWND hWnd
);
55 typedef struct _Entry
{
66 #ifndef _NO_EXTENSIONS
67 BY_HANDLE_FILE_INFORMATION bhfi
;
76 TCHAR volname
[_MAX_FNAME
];
86 COL_ATTRIBUTES
= 0x08,
89 COL_ALL
= COL_SIZE
|COL_DATE
|COL_TIME
|COL_ATTRIBUTES
|COL_DOSNAMES
93 COL_ALL
= COL_SIZE
|COL_DATE
|COL_TIME
|COL_ATTRIBUTES
|COL_DOSNAMES
|COL_INDEX
|COL_LINKS
106 #ifndef _NO_EXTENSIONS
110 #ifndef _NO_EXTENSIONS
116 int positions
[COLUMNS
+1];
128 int focus_pane
; /* 0: left 1: right */
131 BOOL header_wdths_ok
;
133 TCHAR path
[MAX_PATH
];
136 SORT_ORDER sortOrder
;
140 static void read_directory(Entry
* parent
, LPCTSTR path
, int sortOrder
);
141 static void set_curdir(ChildWnd
* child
, Entry
* entry
);
143 LRESULT CALLBACK
FrameWndProc(HWND hwnd
, UINT nmsg
, WPARAM wparam
, LPARAM lparam
);
144 LRESULT CALLBACK
ChildWndProc(HWND hwnd
, UINT nmsg
, WPARAM wparam
, LPARAM lparam
);
145 LRESULT CALLBACK
TreeWndProc(HWND hwnd
, UINT nmsg
, WPARAM wparam
, LPARAM lparam
);
148 static void display_error(HWND hwnd
, DWORD error
)
152 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
|FORMAT_MESSAGE_FROM_SYSTEM
,
153 0, error
, MAKELANGID(LANG_NEUTRAL
,SUBLANG_DEFAULT
), (PTSTR
)&msg
, 0, NULL
))
154 MessageBox(hwnd
, msg
, _T("Winefile"), MB_OK
);
156 MessageBox(hwnd
, _T("Error"), _T("Winefile"), MB_OK
);
162 static void read_directory_win(Entry
* parent
, LPCTSTR path
)
164 Entry
* entry
= (Entry
*) malloc(sizeof(Entry
));
165 int level
= parent
->level
+ 1;
168 #ifndef _NO_EXTENSIONS
172 TCHAR buffer
[MAX_PATH
], *p
;
173 for(p
=buffer
; *path
; )
176 lstrcpy(p
, _T("\\*"));
178 hFind
= FindFirstFile(buffer
, &entry
->data
);
180 if (hFind
!= INVALID_HANDLE_VALUE
) {
181 parent
->down
= entry
;
186 entry
->expanded
= FALSE
;
187 entry
->scanned
= FALSE
;
188 entry
->level
= level
;
190 #ifdef _NO_EXTENSIONS
191 /* hide directory entry "." */
192 if (entry
->data
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) {
193 LPCTSTR name
= entry
->data
.cFileName
;
195 if (name
[0]=='.' && name
[1]=='\0')
199 entry
->unix_dir
= FALSE
;
200 entry
->bhfi_valid
= FALSE
;
202 lstrcpy(p
+1, entry
->data
.cFileName
);
204 hFile
= CreateFile(buffer
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
205 0, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0);
207 if (hFile
!= INVALID_HANDLE_VALUE
) {
208 if (GetFileInformationByHandle(hFile
, &entry
->bhfi
))
209 entry
->bhfi_valid
= TRUE
;
217 entry
= (Entry
*) malloc(sizeof(Entry
));
221 } while(FindNextFile(hFind
, &entry
->data
));
231 parent
->scanned
= TRUE
;
235 static Entry
* find_entry_win(Entry
* parent
, LPCTSTR name
)
239 for(entry
=parent
->down
; entry
; entry
=entry
->next
) {
241 LPCTSTR q
= entry
->data
.cFileName
;
244 if (!*p
|| *p
==_T('\\') || *p
==_T('/'))
246 } while(tolower(*p
++) == tolower(*q
++));
249 q
= entry
->data
.cAlternateFileName
;
252 if (!*p
|| *p
==_T('\\') || *p
==_T('/'))
254 } while(tolower(*p
++) == tolower(*q
++));
261 static Entry
* read_tree_win(Root
* root
, LPCTSTR path
, int sortOrder
)
263 TCHAR buffer
[MAX_PATH
];
264 Entry
* entry
= &root
->entry
;
268 #ifndef _NO_EXTENSIONS
269 entry
->unix_dir
= FALSE
;
273 while(*s
&& *s
!=_T('\\') && *s
!=_T('/'))
276 while(*s
==_T('\\') || *s
==_T('/'))
282 read_directory(entry
, buffer
, sortOrder
);
285 entry
->expanded
= TRUE
;
290 entry
= find_entry_win(entry
, s
);
297 #if !defined(_NO_EXTENSIONS) && defined(__linux__)
299 BOOL
to_filetime(const time_t* t
, FILETIME
* ftime
)
301 struct tm
* tm
= gmtime(t
);
307 stime
.wYear
= tm
->tm_year
+1900;
308 stime
.wMonth
= tm
->tm_mon
+1;
309 /* stime.wDayOfWeek */
310 stime
.wDay
= tm
->tm_mday
;
311 stime
.wHour
= tm
->tm_hour
;
312 stime
.wMinute
= tm
->tm_min
;
313 stime
.wSecond
= tm
->tm_sec
;
315 return SystemTimeToFileTime(&stime
, ftime
);
318 static void read_directory_unix(Entry
* parent
, LPCTSTR path
)
320 Entry
* entry
= (Entry
*) malloc(sizeof(Entry
));
321 int level
= parent
->level
+ 1;
324 DIR* dir
= opendir(path
);
329 TCHAR buffer
[MAX_PATH
], *p
;
331 for(p
=buffer
; *path
; )
334 if (p
==buffer
|| p
[-1]!='/')
337 parent
->down
= entry
;
339 while((ent
=readdir(dir
))) {
340 entry
->unix_dir
= TRUE
;
341 lstrcpy(entry
->data
.cFileName
, ent
->d_name
);
342 entry
->data
.dwFileAttributes
= ent
->d_name
[0]=='.'? FILE_ATTRIBUTE_HIDDEN
: 0;
344 strcpy(p
, ent
->d_name
);
346 if (!stat(buffer
, &st
)) {
347 if (S_ISDIR(st
.st_mode
))
348 entry
->data
.dwFileAttributes
|= FILE_ATTRIBUTE_DIRECTORY
;
350 entry
->data
.nFileSizeLow
= st
.st_size
& 0xFFFFFFFF;
351 entry
->data
.nFileSizeHigh
= st
.st_size
>> 32;
353 memset(&entry
->data
.ftCreationTime
, 0, sizeof(FILETIME
));
354 to_filetime(&st
.st_atime
, &entry
->data
.ftLastAccessTime
);
355 to_filetime(&st
.st_mtime
, &entry
->data
.ftLastWriteTime
);
357 entry
->bhfi
.nFileIndexLow
= ent
->d_ino
;
358 entry
->bhfi
.nFileIndexHigh
= 0;
360 entry
->bhfi
.nNumberOfLinks
= st
.st_nlink
;
362 entry
->bhfi_valid
= TRUE
;
364 entry
->data
.nFileSizeLow
= 0;
365 entry
->data
.nFileSizeHigh
= 0;
366 entry
->bhfi_valid
= FALSE
;
371 entry
->expanded
= FALSE
;
372 entry
->scanned
= FALSE
;
373 entry
->level
= level
;
377 entry
= (Entry
*) malloc(sizeof(Entry
));
391 parent
->scanned
= TRUE
;
394 static Entry
* find_entry_unix(Entry
* parent
, LPCTSTR name
)
398 for(entry
=parent
->down
; entry
; entry
=entry
->next
) {
400 LPCTSTR q
= entry
->data
.cFileName
;
403 if (!*p
|| *p
==_T('/'))
405 } while(*p
++ == *q
++);
411 static Entry
* read_tree_unix(Root
* root
, LPCTSTR path
, int sortOrder
)
413 TCHAR buffer
[MAX_PATH
];
414 Entry
* entry
= &root
->entry
;
418 entry
->unix_dir
= TRUE
;
421 while(*s
&& *s
!=_T('/'))
430 read_directory(entry
, buffer
, sortOrder
);
433 entry
->expanded
= TRUE
;
438 entry
= find_entry_unix(entry
, s
);
447 /* directories first... */
448 static int compareType(const WIN32_FIND_DATA
* fd1
, const WIN32_FIND_DATA
* fd2
)
450 int dir1
= fd1
->dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
;
451 int dir2
= fd2
->dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
;
453 return dir2
==dir1
? 0: dir2
<dir1
? -1: 1;
457 static int compareName(const void* arg1
, const void* arg2
)
459 const WIN32_FIND_DATA
* fd1
= &(*(Entry
**)arg1
)->data
;
460 const WIN32_FIND_DATA
* fd2
= &(*(Entry
**)arg2
)->data
;
462 int cmp
= compareType(fd1
, fd2
);
466 return lstrcmpi(fd1
->cFileName
, fd2
->cFileName
);
469 static int compareExt(const void* arg1
, const void* arg2
)
471 const WIN32_FIND_DATA
* fd1
= &(*(Entry
**)arg1
)->data
;
472 const WIN32_FIND_DATA
* fd2
= &(*(Entry
**)arg2
)->data
;
473 const TCHAR
*name1
, *name2
, *ext1
, *ext2
;
475 int cmp
= compareType(fd1
, fd2
);
479 name1
= fd1
->cFileName
;
480 name2
= fd2
->cFileName
;
482 ext1
= _tcsrchr(name1
, _T('.'));
483 ext2
= _tcsrchr(name2
, _T('.'));
495 cmp
= lstrcmpi(ext1
, ext2
);
499 return lstrcmpi(name1
, name2
);
502 static int compareSize(const void* arg1
, const void* arg2
)
504 WIN32_FIND_DATA
* fd1
= &(*(Entry
**)arg1
)->data
;
505 WIN32_FIND_DATA
* fd2
= &(*(Entry
**)arg2
)->data
;
507 int cmp
= compareType(fd1
, fd2
);
511 cmp
= fd2
->nFileSizeHigh
- fd1
->nFileSizeHigh
;
518 cmp
= fd2
->nFileSizeLow
- fd1
->nFileSizeLow
;
520 return cmp
<0? -1: cmp
>0? 1: 0;
523 static int compareDate(const void* arg1
, const void* arg2
)
525 WIN32_FIND_DATA
* fd1
= &(*(Entry
**)arg1
)->data
;
526 WIN32_FIND_DATA
* fd2
= &(*(Entry
**)arg2
)->data
;
528 int cmp
= compareType(fd1
, fd2
);
532 return CompareFileTime(&fd2
->ftLastWriteTime
, &fd1
->ftLastWriteTime
);
536 static int (*sortFunctions
[])(const void* arg1
, const void* arg2
) = {
537 compareName
, /* SORT_NAME */
538 compareExt
, /* SORT_EXT */
539 compareSize
, /* SORT_SIZE */
540 compareDate
/* SORT_DATE */
544 static void SortDirectory(Entry
* parent
, SORT_ORDER sortOrder
)
546 Entry
* entry
= parent
->down
;
551 for(entry
=parent
->down
; entry
; entry
=entry
->next
)
555 array
= (Entry
**) alloca(len
*sizeof(Entry
*));
558 for(entry
=parent
->down
; entry
; entry
=entry
->next
)
561 /* call qsort with the appropriate compare function */
562 qsort(array
, len
, sizeof(array
[0]), sortFunctions
[sortOrder
]);
564 parent
->down
= array
[0];
566 for(p
=array
; --len
; p
++)
574 static void read_directory(Entry
* parent
, LPCTSTR path
, int sortOrder
)
576 TCHAR buffer
[MAX_PATH
];
581 #if !defined(_NO_EXTENSIONS) && defined(__linux__)
582 if (parent
->unix_dir
)
584 read_directory_unix(parent
, path
);
586 if (Globals
.prescan_node
) {
595 for(entry
=parent
->down
; entry
; entry
=entry
->next
)
596 if (entry
->data
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) {
597 lstrcpy(d
, entry
->data
.cFileName
);
598 read_directory_unix(entry
, buffer
);
599 SortDirectory(entry
, sortOrder
);
606 read_directory_win(parent
, path
);
608 if (Globals
.prescan_node
) {
617 for(entry
=parent
->down
; entry
; entry
=entry
->next
)
618 if (entry
->data
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) {
619 lstrcpy(d
, entry
->data
.cFileName
);
620 read_directory_win(entry
, buffer
);
621 SortDirectory(entry
, sortOrder
);
626 SortDirectory(parent
, sortOrder
);
630 static ChildWnd
* alloc_child_window(LPCTSTR path
)
632 TCHAR drv
[_MAX_DRIVE
+1], dir
[_MAX_DIR
], name
[_MAX_FNAME
], ext
[_MAX_EXT
];
633 ChildWnd
* child
= (ChildWnd
*) malloc(sizeof(ChildWnd
));
634 Root
* root
= &child
->root
;
637 memset(child
, 0, sizeof(ChildWnd
));
639 child
->left
.treePane
= TRUE
;
640 child
->left
.visible_cols
= 0;
642 child
->right
.treePane
= FALSE
;
643 #ifndef _NO_EXTENSIONS
644 child
->right
.visible_cols
= COL_SIZE
|COL_DATE
|COL_TIME
|COL_ATTRIBUTES
|COL_INDEX
|COL_LINKS
;
646 child
->right
.visible_cols
= COL_SIZE
|COL_DATE
|COL_TIME
|COL_ATTRIBUTES
;
649 child
->pos
.length
= sizeof(WINDOWPLACEMENT
);
650 child
->pos
.flags
= 0;
651 child
->pos
.showCmd
= SW_SHOWNORMAL
;
652 child
->pos
.rcNormalPosition
.left
= CW_USEDEFAULT
;
653 child
->pos
.rcNormalPosition
.top
= CW_USEDEFAULT
;
654 child
->pos
.rcNormalPosition
.right
= CW_USEDEFAULT
;
655 child
->pos
.rcNormalPosition
.bottom
= CW_USEDEFAULT
;
657 child
->focus_pane
= 0;
658 child
->split_pos
= 200;
659 child
->sortOrder
= SORT_NAME
;
660 child
->header_wdths_ok
= FALSE
;
662 lstrcpy(child
->path
, path
);
664 _tsplitpath(path
, drv
, dir
, name
, ext
);
666 #if !defined(_NO_EXTENSIONS) && defined(__linux__)
669 root
->drive_type
= GetDriveType(path
);
671 lstrcat(drv
, _T("/"));
672 lstrcpy(root
->volname
, _T("root fs"));
674 lstrcpy(root
->fs
, _T("unixfs"));
676 lstrcpy(root
->path
, _T("/"));
677 entry
= read_tree_unix(root
, path
, child
->sortOrder
);
682 root
->drive_type
= GetDriveType(path
);
684 lstrcat(drv
, _T("\\"));
685 GetVolumeInformation(drv
, root
->volname
, _MAX_FNAME
, 0, 0, &root
->fs_flags
, root
->fs
, _MAX_DIR
);
687 lstrcpy(root
->path
, drv
);
688 entry
= read_tree_win(root
, path
, child
->sortOrder
);
691 /*@@lstrcpy(root->entry.data.cFileName, drv); */
692 wsprintf(root
->entry
.data
.cFileName
, _T("%s - %s"), drv
, root
->fs
);
694 root
->entry
.data
.dwFileAttributes
= FILE_ATTRIBUTE_DIRECTORY
;
696 child
->left
.root
= &root
->entry
;
698 set_curdir(child
, entry
);
704 /* recursively free all child entries */
705 static void free_entries(Entry
* parent
)
707 Entry
*entry
, *next
=parent
->down
;
722 /* free all memory associated with a child window */
723 static void free_child_window(ChildWnd
* child
)
725 free_entries(&child
->root
.entry
);
730 /* get full path of specified directory entry */
731 static void get_path(Entry
* dir
, PTSTR path
)
737 for(entry
=dir
; entry
; level
++) {
738 LPCTSTR name
= entry
->data
.cFileName
;
742 for(l
=0; *s
&& *s
!=_T('/') && *s
!=_T('\\'); s
++)
746 memmove(path
+l
+1, path
, len
*sizeof(TCHAR
));
747 memcpy(path
+1, name
, l
*sizeof(TCHAR
));
750 #ifndef _NO_EXTENSIONS
759 memmove(path
+l
, path
, len
*sizeof(TCHAR
));
760 memcpy(path
, name
, l
*sizeof(TCHAR
));
767 #ifndef _NO_EXTENSIONS
769 path
[len
++] = _T('/');
772 path
[len
++] = _T('\\');
775 path
[len
] = _T('\0');
779 static void resize_frame_rect(HWND hwnd
, PRECT prect
)
784 if (IsWindowVisible(Globals
.htoolbar
)) {
785 SendMessage(Globals
.htoolbar
, WM_SIZE
, 0, 0);
786 GetClientRect(Globals
.htoolbar
, &rt
);
787 prect
->top
= rt
.bottom
+3;
788 prect
->bottom
-= rt
.bottom
+3;
791 if (IsWindowVisible(Globals
.hdrivebar
)) {
792 SendMessage(Globals
.hdrivebar
, WM_SIZE
, 0, 0);
793 GetClientRect(Globals
.hdrivebar
, &rt
);
794 new_top
= --prect
->top
+ rt
.bottom
+3;
795 MoveWindow(Globals
.hdrivebar
, 0, prect
->top
, rt
.right
, new_top
, TRUE
);
796 prect
->top
= new_top
;
797 prect
->bottom
-= rt
.bottom
+2;
800 if (IsWindowVisible(Globals
.hstatusbar
)) {
801 int parts
[] = {300, 500};
803 SendMessage(Globals
.hstatusbar
, WM_SIZE
, 0, 0);
804 SendMessage(Globals
.hstatusbar
, SB_SETPARTS
, 2, (LPARAM
)&parts
);
805 GetClientRect(Globals
.hstatusbar
, &rt
);
806 prect
->bottom
-= rt
.bottom
;
809 MoveWindow(Globals
.hmdiclient
, prect
->left
-1,prect
->top
-1,prect
->right
+2,prect
->bottom
+1, TRUE
);
812 static void resize_frame(HWND hwnd
, int cx
, int cy
)
821 resize_frame_rect(hwnd
, &rect
);
824 static void resize_frame_client(HWND hwnd
)
828 GetClientRect(hwnd
, &rect
);
830 resize_frame_rect(hwnd
, &rect
);
834 static HHOOK hcbthook
;
835 static ChildWnd
* newchild
= NULL
;
837 LRESULT CALLBACK
CBTProc(int code
, WPARAM wparam
, LPARAM lparam
)
839 if (code
==HCBT_CREATEWND
&& newchild
) {
840 ChildWnd
* child
= newchild
;
843 child
->hwnd
= (HWND
) wparam
;
844 SetWindowLong(child
->hwnd
, GWL_USERDATA
, (LPARAM
)child
);
847 return CallNextHookEx(hcbthook
, code
, wparam
, lparam
);
850 static HWND
create_child_window(ChildWnd
* child
)
855 mcs
.szClass
= WINEFILETREE
;
856 mcs
.szTitle
= (LPTSTR
)child
->path
;
857 mcs
.hOwner
= Globals
.hInstance
;
858 mcs
.x
= child
->pos
.rcNormalPosition
.left
;
859 mcs
.y
= child
->pos
.rcNormalPosition
.top
;
860 mcs
.cx
= child
->pos
.rcNormalPosition
.right
-child
->pos
.rcNormalPosition
.left
;
861 mcs
.cy
= child
->pos
.rcNormalPosition
.bottom
-child
->pos
.rcNormalPosition
.top
;
865 hcbthook
= SetWindowsHookEx(WH_CBT
, CBTProc
, 0, GetCurrentThreadId());
868 child
->hwnd
= (HWND
) SendMessage(Globals
.hmdiclient
, WM_MDICREATE
, 0, (LPARAM
)&mcs
);
872 UnhookWindowsHookEx(hcbthook
);
874 idx
= ListBox_FindItemData(child
->left
.hwnd
, ListBox_GetCurSel(child
->left
.hwnd
), child
->left
.cur
);
875 ListBox_SetCurSel(child
->left
.hwnd
, idx
);
881 struct ExecuteDialog
{
887 static BOOL CALLBACK
ExecuteDialogWndProg(HWND hwnd
, UINT nmsg
, WPARAM wparam
, LPARAM lparam
)
889 static struct ExecuteDialog
* dlg
;
893 dlg
= (struct ExecuteDialog
*) lparam
;
897 int id
= (int)wparam
;
900 GetWindowText(GetDlgItem(hwnd
, 201), dlg
->cmd
, MAX_PATH
);
901 dlg
->cmdshow
= Button_GetState(GetDlgItem(hwnd
,214))&BST_CHECKED
?
902 SW_SHOWMINIMIZED
: SW_SHOWNORMAL
;
904 } else if (id
== IDCANCEL
)
914 #ifndef _NO_EXTENSIONS
916 static struct FullScreenParameters
{
924 void frame_get_clientspace(HWND hwnd
, PRECT prect
)
929 GetClientRect(hwnd
, prect
);
933 GetWindowPlacement(hwnd
, &wp
);
935 prect
->left
= prect
->top
= 0;
936 prect
->right
= wp
.rcNormalPosition
.right
-wp
.rcNormalPosition
.left
-
937 2*(GetSystemMetrics(SM_CXSIZEFRAME
)+GetSystemMetrics(SM_CXEDGE
));
938 prect
->bottom
= wp
.rcNormalPosition
.bottom
-wp
.rcNormalPosition
.top
-
939 2*(GetSystemMetrics(SM_CYSIZEFRAME
)+GetSystemMetrics(SM_CYEDGE
))-
940 GetSystemMetrics(SM_CYCAPTION
)-GetSystemMetrics(SM_CYMENUSIZE
);
943 if (IsWindowVisible(Globals
.htoolbar
)) {
944 GetClientRect(Globals
.htoolbar
, &rt
);
945 prect
->top
+= rt
.bottom
+2;
948 if (IsWindowVisible(Globals
.hdrivebar
)) {
949 GetClientRect(Globals
.hdrivebar
, &rt
);
950 prect
->top
+= rt
.bottom
+2;
953 if (IsWindowVisible(Globals
.hstatusbar
)) {
954 GetClientRect(Globals
.hstatusbar
, &rt
);
955 prect
->bottom
-= rt
.bottom
;
959 static BOOL
toggle_fullscreen(HWND hwnd
)
963 if ((g_fullscreen
.mode
=!g_fullscreen
.mode
)) {
964 GetWindowRect(hwnd
, &g_fullscreen
.orgPos
);
965 g_fullscreen
.wasZoomed
= IsZoomed(hwnd
);
967 Frame_CalcFrameClient(hwnd
, &rt
);
968 ClientToScreen(hwnd
, (LPPOINT
)&rt
.left
);
969 ClientToScreen(hwnd
, (LPPOINT
)&rt
.right
);
971 rt
.left
= g_fullscreen
.orgPos
.left
-rt
.left
;
972 rt
.top
= g_fullscreen
.orgPos
.top
-rt
.top
;
973 rt
.right
= GetSystemMetrics(SM_CXSCREEN
)+g_fullscreen
.orgPos
.right
-rt
.right
;
974 rt
.bottom
= GetSystemMetrics(SM_CYSCREEN
)+g_fullscreen
.orgPos
.bottom
-rt
.bottom
;
976 MoveWindow(hwnd
, rt
.left
, rt
.top
, rt
.right
-rt
.left
, rt
.bottom
-rt
.top
, TRUE
);
978 MoveWindow(hwnd
, g_fullscreen
.orgPos
.left
, g_fullscreen
.orgPos
.top
,
979 g_fullscreen
.orgPos
.right
-g_fullscreen
.orgPos
.left
,
980 g_fullscreen
.orgPos
.bottom
-g_fullscreen
.orgPos
.top
, TRUE
);
982 if (g_fullscreen
.wasZoomed
)
983 ShowWindow(hwnd
, WS_MAXIMIZE
);
986 return g_fullscreen
.mode
;
989 static void fullscreen_move(HWND hwnd
)
992 GetWindowRect(hwnd
, &pos
);
994 Frame_CalcFrameClient(hwnd
, &rt
);
995 ClientToScreen(hwnd
, (LPPOINT
)&rt
.left
);
996 ClientToScreen(hwnd
, (LPPOINT
)&rt
.right
);
998 rt
.left
= pos
.left
-rt
.left
;
999 rt
.top
= pos
.top
-rt
.top
;
1000 rt
.right
= GetSystemMetrics(SM_CXSCREEN
)+pos
.right
-rt
.right
;
1001 rt
.bottom
= GetSystemMetrics(SM_CYSCREEN
)+pos
.bottom
-rt
.bottom
;
1003 MoveWindow(hwnd
, rt
.left
, rt
.top
, rt
.right
-rt
.left
, rt
.bottom
-rt
.top
, TRUE
);
1009 static void toggle_child(HWND hwnd
, UINT cmd
, HWND hchild
)
1011 BOOL vis
= IsWindowVisible(hchild
);
1013 CheckMenuItem(Globals
.hMenuOptions
, cmd
, vis
?MF_BYCOMMAND
:MF_BYCOMMAND
|MF_CHECKED
);
1015 ShowWindow(hchild
, vis
?SW_HIDE
:SW_SHOW
);
1017 #ifndef _NO_EXTENSIONS
1018 if (g_fullscreen
.mode
)
1019 fullscreen_move(hwnd
);
1022 resize_frame_client(hwnd
);
1025 BOOL
activate_drive_window(LPCTSTR path
)
1027 TCHAR drv1
[_MAX_DRIVE
], drv2
[_MAX_DRIVE
];
1030 _tsplitpath(path
, drv1
, 0, 0, 0);
1032 /* search for a already open window for the same drive */
1033 for(child_wnd
=GetNextWindow(Globals
.hmdiclient
,GW_CHILD
); child_wnd
; child_wnd
=GetNextWindow(child_wnd
, GW_HWNDNEXT
)) {
1034 ChildWnd
* child
= (ChildWnd
*) GetWindowLong(child_wnd
, GWL_USERDATA
);
1037 _tsplitpath(child
->root
.path
, drv2
, 0, 0, 0);
1039 if (!lstrcmpi(drv2
, drv1
)) {
1040 SendMessage(Globals
.hmdiclient
, WM_MDIACTIVATE
, (WPARAM
)child_wnd
, 0);
1042 if (IsMinimized(child_wnd
))
1043 ShowWindow(child_wnd
, SW_SHOWNORMAL
);
1053 LRESULT CALLBACK
FrameWndProc(HWND hwnd
, UINT nmsg
, WPARAM wparam
, LPARAM lparam
)
1057 DestroyWindow(hwnd
);
1065 UINT cmd
= LOWORD(wparam
);
1066 HWND hwndClient
= (HWND
) SendMessage(Globals
.hmdiclient
, WM_MDIGETACTIVE
, 0, 0);
1068 if (SendMessage(hwndClient
, WM_DISPATCH_COMMAND
, wparam
, lparam
))
1071 if (cmd
>=ID_DRIVE_FIRST
&& cmd
<=ID_DRIVE_FIRST
+0xFF) {
1072 TCHAR drv
[_MAX_DRIVE
], path
[MAX_PATH
];
1074 LPCTSTR root
= Globals
.drives
;
1077 for(i
=cmd
-ID_DRIVE_FIRST
; i
--; root
++)
1081 if (activate_drive_window(root
))
1084 _tsplitpath(root
, drv
, 0, 0, 0);
1086 if (!SetCurrentDirectory(drv
)) {
1087 display_error(hwnd
, GetLastError());
1091 GetCurrentDirectory(MAX_PATH
, path
); /*@@ letztes Verzeichnis pro Laufwerk speichern */
1092 child
= alloc_child_window(path
);
1094 if (!create_child_window(child
))
1096 } else switch(cmd
) {
1101 case ID_WINDOW_NEW
: {
1102 TCHAR path
[MAX_PATH
];
1105 GetCurrentDirectory(MAX_PATH
, path
);
1106 child
= alloc_child_window(path
);
1108 if (!create_child_window(child
))
1112 case ID_WINDOW_CASCADE
:
1113 SendMessage(Globals
.hmdiclient
, WM_MDICASCADE
, 0, 0);
1116 case ID_WINDOW_TILE_HORZ
:
1117 SendMessage(Globals
.hmdiclient
, WM_MDITILE
, MDITILE_HORIZONTAL
, 0);
1120 case ID_WINDOW_TILE_VERT
:
1121 SendMessage(Globals
.hmdiclient
, WM_MDITILE
, MDITILE_VERTICAL
, 0);
1124 case ID_WINDOW_ARRANGE
:
1125 SendMessage(Globals
.hmdiclient
, WM_MDIICONARRANGE
, 0, 0);
1128 case ID_VIEW_TOOL_BAR
:
1129 toggle_child(hwnd
, cmd
, Globals
.htoolbar
);
1132 case ID_VIEW_DRIVE_BAR
:
1133 toggle_child(hwnd
, cmd
, Globals
.hdrivebar
);
1136 case ID_VIEW_STATUSBAR
:
1137 toggle_child(hwnd
, cmd
, Globals
.hstatusbar
);
1141 struct ExecuteDialog dlg
= {{0}};
1142 if (DialogBoxParam(Globals
.hInstance
, MAKEINTRESOURCE(IDD_EXECUTE
), hwnd
, ExecuteDialogWndProg
, (LPARAM
)&dlg
) == IDOK
) {
1143 HINSTANCE hinst
= ShellExecute(hwnd
, NULL
/*operation*/, dlg
.cmd
/*file*/, NULL
/*parameters*/, NULL
/*dir*/, dlg
.cmdshow
);
1145 if ((int)hinst
<= 32)
1146 display_error(hwnd
, GetLastError());
1151 WinHelp(hwnd
, _T("winfile"), HELP_INDEX
, 0);
1154 #ifndef _NO_EXTENSIONS
1155 case ID_VIEW_FULLSCREEN
:
1156 CheckMenuItem(Globals
.hMenuOptions
, cmd
, toggle_fullscreen(hwnd
)?MF_CHECKED
:0);
1160 case ID_DRIVE_UNIX_FS
: {
1161 TCHAR path
[MAX_PATH
];
1164 if (activate_drive_window(_T("/")))
1167 getcwd(path
, MAX_PATH
);
1168 child
= alloc_child_window(path
);
1170 if (!create_child_window(child
))
1176 /*TODO: There are even more menu items! */
1178 #ifndef _NO_EXTENSIONS
1180 WineLicense(Globals
.hMainWnd
);
1183 case ID_NO_WARRANTY
:
1184 WineWarranty(Globals
.hMainWnd
);
1188 ShellAbout(hwnd
, _T("WINE"), _T("Winefile"), 0);
1193 /*@@if (wParam >= PM_FIRST_LANGUAGE && wParam <= PM_LAST_LANGUAGE)
1194 STRING_SelectLanguageByNumber(wParam - PM_FIRST_LANGUAGE);
1195 else */if ((cmd
<IDW_FIRST_CHILD
|| cmd
>=IDW_FIRST_CHILD
+0x100) &&
1196 (cmd
<SC_SIZE
|| cmd
>SC_RESTORE
))
1197 MessageBox(hwnd
, _T("Not yet implemented"), _T("Winefile"), MB_OK
);
1199 return DefFrameProc(hwnd
, Globals
.hmdiclient
, nmsg
, wparam
, lparam
);
1204 resize_frame(hwnd
, LOWORD(lparam
), HIWORD(lparam
));
1205 break; /* do not pass message to DefFrameProc */
1207 #ifndef _NO_EXTENSIONS
1208 case WM_GETMINMAXINFO
: {
1209 LPMINMAXINFO lpmmi
= (LPMINMAXINFO
)lparam
;
1211 lpmmi
->ptMaxTrackSize
.x
<<= 1;/*2*GetSystemMetrics(SM_CXSCREEN) / SM_CXVIRTUALSCREEN */
1212 lpmmi
->ptMaxTrackSize
.y
<<= 1;/*2*GetSystemMetrics(SM_CYSCREEN) / SM_CYVIRTUALSCREEN */
1215 case FRM_CALC_CLIENT
:
1216 frame_get_clientspace(hwnd
, (PRECT
)lparam
);
1221 return DefFrameProc(hwnd
, Globals
.hmdiclient
, nmsg
, wparam
, lparam
);
1228 const static LPTSTR g_pos_names
[COLUMNS
] = {
1229 _T(""), /* symbol */
1233 #ifndef _NO_EXTENSIONS
1240 #ifndef _NO_EXTENSIONS
1245 const static int g_pos_align
[] = {
1247 HDF_LEFT
, /* Name */
1248 HDF_RIGHT
, /* Size */
1249 HDF_LEFT
, /* CDate */
1250 #ifndef _NO_EXTENSIONS
1251 HDF_LEFT
, /* ADate */
1252 HDF_LEFT
, /* MDate */
1253 HDF_LEFT
, /* Index */
1254 HDF_CENTER
, /* Links */
1256 HDF_CENTER
, /* Attributes */
1257 #ifndef _NO_EXTENSIONS
1258 HDF_LEFT
/* Security */
1262 static void resize_tree(ChildWnd
* child
, int cx
, int cy
)
1264 HDWP hdwp
= BeginDeferWindowPos(4);
1272 cx
= child
->split_pos
+ SPLIT_WIDTH
/2;
1274 #ifndef _NO_EXTENSIONS
1282 Header_Layout(child
->left
.hwndHeader
, &hdl
);
1284 DeferWindowPos(hdwp
, child
->left
.hwndHeader
, wp
.hwndInsertAfter
,
1285 wp
.x
-1, wp
.y
, child
->split_pos
-SPLIT_WIDTH
/2+1, wp
.cy
, wp
.flags
);
1286 DeferWindowPos(hdwp
, child
->right
.hwndHeader
, wp
.hwndInsertAfter
,
1287 rt
.left
+cx
+1, wp
.y
, wp
.cx
-cx
+2, wp
.cy
, wp
.flags
);
1291 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
);
1292 DeferWindowPos(hdwp
, child
->right
.hwnd
, 0, rt
.left
+cx
+1, rt
.top
, rt
.right
-cx
, rt
.bottom
-rt
.top
, SWP_NOZORDER
|SWP_NOACTIVATE
);
1294 EndDeferWindowPos(hdwp
);
1298 #ifndef _NO_EXTENSIONS
1300 static HWND
create_header(HWND parent
, Pane
* pane
, int id
)
1302 HD_ITEM hdi
= {HDI_TEXT
|HDI_WIDTH
|HDI_FORMAT
};
1305 HWND hwnd
= CreateWindow(WC_HEADER
, 0, WS_CHILD
|WS_VISIBLE
|HDS_HORZ
/*TODO: |HDS_BUTTONS + sort orders*/,
1306 0, 0, 0, 0, parent
, (HMENU
)id
, Globals
.hInstance
, 0);
1310 SendMessage(hwnd
, WM_SETFONT
, (WPARAM
)GetStockObject(DEFAULT_GUI_FONT
), FALSE
);
1312 for(idx
=0; idx
<COLUMNS
; idx
++) {
1313 hdi
.pszText
= g_pos_names
[idx
];
1314 hdi
.fmt
= HDF_STRING
| g_pos_align
[idx
];
1315 hdi
.cxy
= pane
->widths
[idx
];
1316 Header_InsertItem(hwnd
, idx
, &hdi
);
1325 static void init_output(HWND hwnd
)
1329 HDC hdc
= GetDC(hwnd
);
1331 if (GetNumberFormat(LOCALE_USER_DEFAULT
, 0, _T("1000"), 0, b
, 16) > 4)
1332 Globals
.num_sep
= b
[1];
1334 Globals
.num_sep
= _T('.');
1336 old_font
= SelectFont(hdc
, Globals
.hfont
);
1337 GetTextExtentPoint32(hdc
, _T(" "), 1, &Globals
.spaceSize
);
1338 SelectFont(hdc
, old_font
);
1339 ReleaseDC(hwnd
, hdc
);
1342 static void draw_item(Pane
* pane
, LPDRAWITEMSTRUCT dis
, Entry
* entry
, int calcWidthCol
);
1345 /* calculate prefered width for all visible columns */
1347 static BOOL
calc_widths(Pane
* pane
, BOOL anyway
)
1349 int col
, x
, cx
, spc
=3*Globals
.spaceSize
.cx
;
1350 int entries
= ListBox_GetCount(pane
->hwnd
);
1351 int orgWidths
[COLUMNS
];
1352 int orgPositions
[COLUMNS
+1];
1358 memcpy(orgWidths
, pane
->widths
, sizeof(orgWidths
));
1359 memcpy(orgPositions
, pane
->positions
, sizeof(orgPositions
));
1362 for(col
=0; col
<COLUMNS
; col
++)
1363 pane
->widths
[col
] = 0;
1365 hdc
= GetDC(pane
->hwnd
);
1366 hfontOld
= SelectFont(hdc
, Globals
.hfont
);
1368 for(cnt
=0; cnt
<entries
; cnt
++) {
1369 Entry
* entry
= (Entry
*) ListBox_GetItemData(pane
->hwnd
, cnt
);
1378 dis
.hwndItem
= pane
->hwnd
;
1380 dis
.rcItem
.left
= 0;
1382 dis
.rcItem
.right
= 0;
1383 dis
.rcItem
.bottom
= 0;
1384 /*dis.itemData = 0; */
1386 draw_item(pane
, &dis
, entry
, COLUMNS
);
1389 SelectObject(hdc
, hfontOld
);
1390 ReleaseDC(pane
->hwnd
, hdc
);
1393 for(col
=0; col
<COLUMNS
; col
++) {
1394 pane
->positions
[col
] = x
;
1395 cx
= pane
->widths
[col
];
1400 if (cx
< IMAGE_WIDTH
)
1403 pane
->widths
[col
] = cx
;
1409 pane
->positions
[COLUMNS
] = x
;
1411 ListBox_SetHorizontalExtent(pane
->hwnd
, x
);
1414 if (!memcmp(orgWidths
, pane
->widths
, sizeof(orgWidths
)))
1417 /* don't move, if only collapsing an entry */
1418 if (!anyway
&& pane
->widths
[0]<orgWidths
[0] &&
1419 !memcmp(orgWidths
+1, pane
->widths
+1, sizeof(orgWidths
)-sizeof(int))) {
1420 pane
->widths
[0] = orgWidths
[0];
1421 memcpy(pane
->positions
, orgPositions
, sizeof(orgPositions
));
1426 InvalidateRect(pane
->hwnd
, 0, TRUE
);
1432 /* calculate one prefered column width */
1434 static void calc_single_width(Pane
* pane
, int col
)
1438 int entries
= ListBox_GetCount(pane
->hwnd
);
1442 pane
->widths
[col
] = 0;
1444 hdc
= GetDC(pane
->hwnd
);
1445 hfontOld
= SelectFont(hdc
, Globals
.hfont
);
1447 for(cnt
=0; cnt
<entries
; cnt
++) {
1448 Entry
* entry
= (Entry
*) ListBox_GetItemData(pane
->hwnd
, cnt
);
1456 dis
.hwndItem
= pane
->hwnd
;
1458 dis
.rcItem
.left
= 0;
1460 dis
.rcItem
.right
= 0;
1461 dis
.rcItem
.bottom
= 0;
1462 /*dis.itemData = 0; */
1464 draw_item(pane
, &dis
, entry
, col
);
1467 SelectObject(hdc
, hfontOld
);
1468 ReleaseDC(pane
->hwnd
, hdc
);
1470 cx
= pane
->widths
[col
];
1473 cx
+= 3*Globals
.spaceSize
.cx
;
1475 if (cx
< IMAGE_WIDTH
)
1479 pane
->widths
[col
] = cx
;
1481 x
= pane
->positions
[col
] + cx
;
1483 for(; col
<COLUMNS
; ) {
1484 pane
->positions
[++col
] = x
;
1485 x
+= pane
->widths
[col
];
1488 ListBox_SetHorizontalExtent(pane
->hwnd
, x
);
1492 /* insert listbox entries after index idx */
1494 static void insert_entries(Pane
* pane
, Entry
* parent
, int idx
)
1496 Entry
* entry
= parent
;
1501 ShowWindow(pane
->hwnd
, SW_HIDE
);
1503 for(; entry
; entry
=entry
->next
) {
1505 if (pane
->treePane
&& !(entry
->data
.dwFileAttributes
&FILE_ATTRIBUTE_DIRECTORY
))
1509 /* don't display entries "." and ".." in the left pane */
1510 if (pane
->treePane
&& (entry
->data
.dwFileAttributes
&FILE_ATTRIBUTE_DIRECTORY
)
1511 && entry
->data
.cFileName
[0]==_T('.'))
1513 #ifndef _NO_EXTENSIONS
1514 entry
->data
.cFileName
[1]==_T('\0') ||
1516 (entry
->data
.cFileName
[1]==_T('.') && entry
->data
.cFileName
[2]==_T('\0')))
1522 ListBox_InsertItemData(pane
->hwnd
, idx
, entry
);
1524 if (pane
->treePane
&& entry
->expanded
)
1525 insert_entries(pane
, entry
->down
, idx
);
1528 ShowWindow(pane
->hwnd
, SW_SHOW
);
1532 static WNDPROC g_orgTreeWndProc
;
1534 static void create_tree_window(HWND parent
, Pane
* pane
, int id
, int id_header
)
1536 static int s_init
= 0;
1537 Entry
* entry
= pane
->root
;
1539 pane
->hwnd
= CreateWindow(_T("ListBox"), _T(""), WS_CHILD
|WS_VISIBLE
|WS_HSCROLL
|WS_VSCROLL
|
1540 LBS_DISABLENOSCROLL
|LBS_NOINTEGRALHEIGHT
|LBS_OWNERDRAWFIXED
|LBS_NOTIFY
,
1541 0, 0, 0, 0, parent
, (HMENU
)id
, Globals
.hInstance
, 0);
1543 SetWindowLong(pane
->hwnd
, GWL_USERDATA
, (LPARAM
)pane
);
1544 g_orgTreeWndProc
= SubclassWindow(pane
->hwnd
, TreeWndProc
);
1546 SendMessage(pane
->hwnd
, WM_SETFONT
, (WPARAM
)Globals
.hfont
, FALSE
);
1548 /* insert entries into listbox */
1550 insert_entries(pane
, entry
, -1);
1552 /* calculate column widths */
1555 init_output(pane
->hwnd
);
1558 calc_widths(pane
, TRUE
);
1560 #ifndef _NO_EXTENSIONS
1561 pane
->hwndHeader
= create_header(parent
, pane
, id_header
);
1566 static void InitChildWindow(ChildWnd
* child
)
1568 create_tree_window(child
->hwnd
, &child
->left
, IDW_TREE_LEFT
, IDW_HEADER_LEFT
);
1569 create_tree_window(child
->hwnd
, &child
->right
, IDW_TREE_RIGHT
, IDW_HEADER_RIGHT
);
1573 static void format_date(const FILETIME
* ft
, TCHAR
* buffer
, int visible_cols
)
1581 if (!ft
->dwLowDateTime
&& !ft
->dwHighDateTime
)
1584 if (!FileTimeToLocalFileTime(ft
, &lft
))
1585 {err
: _tcscpy(buffer
,_T("???")); return;}
1587 if (!FileTimeToSystemTime(&lft
, &systime
))
1590 if (visible_cols
& COL_DATE
) {
1591 len
= GetDateFormat(LOCALE_USER_DEFAULT
, 0, &systime
, 0, buffer
, BUFFER_LEN
);
1596 if (visible_cols
& COL_TIME
) {
1598 buffer
[len
-1] = ' ';
1600 buffer
[len
++] = ' ';
1602 if (!GetTimeFormat(LOCALE_USER_DEFAULT
, 0, &systime
, 0, buffer
+len
, BUFFER_LEN
-len
))
1603 buffer
[len
] = _T('\0');
1608 static void calc_width(Pane
* pane
, LPDRAWITEMSTRUCT dis
, int col
, LPCTSTR str
)
1612 DrawText(dis
->hDC
, (LPTSTR
)str
, -1, &rt
, DT_CALCRECT
|DT_SINGLELINE
|DT_NOPREFIX
);
1614 if (rt
.right
> pane
->widths
[col
])
1615 pane
->widths
[col
] = rt
.right
;
1618 static void calc_tabbed_width(Pane
* pane
, LPDRAWITEMSTRUCT dis
, int col
, LPCTSTR str
)
1622 /* DRAWTEXTPARAMS dtp = {sizeof(DRAWTEXTPARAMS), 2};
1623 DrawTextEx(dis->hDC, (LPTSTR)str, -1, &rt, DT_CALCRECT|DT_SINGLELINE|DT_NOPREFIX|DT_EXPANDTABS|DT_TABSTOP, &dtp);*/
1625 DrawText(dis
->hDC
, (LPTSTR
)str
, -1, &rt
, DT_CALCRECT
|DT_SINGLELINE
|DT_EXPANDTABS
|DT_TABSTOP
|(2<<8));
1626 /*@@ rt (0,0) ??? */
1628 if (rt
.right
> pane
->widths
[col
])
1629 pane
->widths
[col
] = rt
.right
;
1633 static void output_text(Pane
* pane
, LPDRAWITEMSTRUCT dis
, int col
, LPCTSTR str
, DWORD flags
)
1635 int x
= dis
->rcItem
.left
;
1638 rt
.left
= x
+pane
->positions
[col
]+Globals
.spaceSize
.cx
;
1639 rt
.top
= dis
->rcItem
.top
;
1640 rt
.right
= x
+pane
->positions
[col
+1]-Globals
.spaceSize
.cx
;
1641 rt
.bottom
= dis
->rcItem
.bottom
;
1643 DrawText(dis
->hDC
, (LPTSTR
)str
, -1, &rt
, DT_SINGLELINE
|DT_NOPREFIX
|flags
);
1646 static void output_tabbed_text(Pane
* pane
, LPDRAWITEMSTRUCT dis
, int col
, LPCTSTR str
)
1648 int x
= dis
->rcItem
.left
;
1651 rt
.left
= x
+pane
->positions
[col
]+Globals
.spaceSize
.cx
;
1652 rt
.top
= dis
->rcItem
.top
;
1653 rt
.right
= x
+pane
->positions
[col
+1]-Globals
.spaceSize
.cx
;
1654 rt
.bottom
= dis
->rcItem
.bottom
;
1656 /* DRAWTEXTPARAMS dtp = {sizeof(DRAWTEXTPARAMS), 2};
1657 DrawTextEx(dis->hDC, (LPTSTR)str, -1, &rt, DT_SINGLELINE|DT_NOPREFIX|DT_EXPANDTABS|DT_TABSTOP, &dtp);*/
1659 DrawText(dis
->hDC
, (LPTSTR
)str
, -1, &rt
, DT_SINGLELINE
|DT_EXPANDTABS
|DT_TABSTOP
|(2<<8));
1662 static void output_number(Pane
* pane
, LPDRAWITEMSTRUCT dis
, int col
, LPCTSTR str
)
1664 int x
= dis
->rcItem
.left
;
1671 rt
.left
= x
+pane
->positions
[col
]+Globals
.spaceSize
.cx
;
1672 rt
.top
= dis
->rcItem
.top
;
1673 rt
.right
= x
+pane
->positions
[col
+1]-Globals
.spaceSize
.cx
;
1674 rt
.bottom
= dis
->rcItem
.bottom
;
1679 /* insert number separator characters */
1680 pos
= lstrlen(s
) % 3;
1686 *d
++ = Globals
.num_sep
;
1690 DrawText(dis
->hDC
, b
, d
-b
, &rt
, DT_RIGHT
|DT_SINGLELINE
|DT_NOPREFIX
|DT_END_ELLIPSIS
);
1694 static int is_exe_file(LPCTSTR ext
)
1696 const static LPCTSTR executable_extensions
[] = {
1701 #ifndef _NO_EXTENSIONS
1709 TCHAR ext_buffer
[_MAX_EXT
];
1714 for(s
=ext
+1,d
=ext_buffer
; (*d
=tolower(*s
)); s
++)
1717 for(p
=executable_extensions
; *p
; p
++)
1718 if (!_tcscmp(ext_buffer
, *p
))
1724 static int is_registered_type(LPCTSTR ext
)
1732 static void draw_item(Pane
* pane
, LPDRAWITEMSTRUCT dis
, Entry
* entry
, int calcWidthCol
)
1734 TCHAR buffer
[BUFFER_LEN
];
1736 int visible_cols
= pane
->visible_cols
;
1737 COLORREF bkcolor
, textcolor
;
1738 RECT focusRect
= dis
->rcItem
;
1745 attrs
= entry
->data
.dwFileAttributes
;
1747 if (attrs
& FILE_ATTRIBUTE_DIRECTORY
) {
1748 if (entry
->data
.cFileName
[0]==_T('.') && entry
->data
.cFileName
[1]==_T('.')
1749 && entry
->data
.cFileName
[2]==_T('\0'))
1750 img
= IMG_FOLDER_UP
;
1751 #ifndef _NO_EXTENSIONS
1752 else if (entry
->data
.cFileName
[0]==_T('.') && entry
->data
.cFileName
[1]==_T('\0'))
1753 img
= IMG_FOLDER_CUR
;
1756 #ifdef _NO_EXTENSIONS
1759 (pane
->treePane
&& (dis
->itemState
&ODS_FOCUS
)))
1760 img
= IMG_OPEN_FOLDER
;
1764 LPCTSTR ext
= _tcsrchr(entry
->data
.cFileName
, '.');
1768 if (is_exe_file(ext
))
1769 img
= IMG_EXECUTABLE
;
1770 else if (is_registered_type(ext
))
1780 if (pane
->treePane
) {
1782 img_pos
= dis
->rcItem
.left
+ entry
->level
*(IMAGE_WIDTH
+Globals
.spaceSize
.cx
);
1784 if (calcWidthCol
== -1) {
1786 int y
= dis
->rcItem
.top
+ IMAGE_HEIGHT
/2;
1789 HRGN hrgn_org
= CreateRectRgn(0, 0, 0, 0);
1792 rt_clip
.left
= dis
->rcItem
.left
;
1793 rt_clip
.top
= dis
->rcItem
.top
;
1794 rt_clip
.right
= dis
->rcItem
.left
+pane
->widths
[col
];
1795 rt_clip
.bottom
= dis
->rcItem
.bottom
;
1797 hrgn
= CreateRectRgnIndirect(&rt_clip
);
1799 if (!GetClipRgn(dis
->hDC
, hrgn_org
)) {
1800 DeleteObject(hrgn_org
);
1804 /* HGDIOBJ holdPen = SelectObject(dis->hDC, GetStockObject(BLACK_PEN)); */
1805 ExtSelectClipRgn(dis
->hDC
, hrgn
, RGN_AND
);
1808 if ((up
=entry
->up
) != NULL
) {
1809 MoveToEx(dis
->hDC
, img_pos
-IMAGE_WIDTH
/2, y
, 0);
1810 LineTo(dis
->hDC
, img_pos
-2, y
);
1812 x
= img_pos
- IMAGE_WIDTH
/2;
1815 x
-= IMAGE_WIDTH
+Globals
.spaceSize
.cx
;
1819 && (up
->next
->data
.dwFileAttributes
&FILE_ATTRIBUTE_DIRECTORY
)
1822 MoveToEx(dis
->hDC
, x
, dis
->rcItem
.top
, 0);
1823 LineTo(dis
->hDC
, x
, dis
->rcItem
.bottom
);
1825 } while((up
=up
->up
) != NULL
);
1828 x
= img_pos
- IMAGE_WIDTH
/2;
1830 MoveToEx(dis
->hDC
, x
, dis
->rcItem
.top
, 0);
1831 LineTo(dis
->hDC
, x
, y
);
1835 && (entry
->next
->data
.dwFileAttributes
&FILE_ATTRIBUTE_DIRECTORY
)
1838 LineTo(dis
->hDC
, x
, dis
->rcItem
.bottom
);
1840 if (entry
->down
&& entry
->expanded
) {
1841 x
+= IMAGE_WIDTH
+Globals
.spaceSize
.cx
;
1842 MoveToEx(dis
->hDC
, x
, dis
->rcItem
.top
+IMAGE_HEIGHT
, 0);
1843 LineTo(dis
->hDC
, x
, dis
->rcItem
.bottom
);
1846 SelectClipRgn(dis
->hDC
, hrgn_org
);
1847 if (hrgn_org
) DeleteObject(hrgn_org
);
1848 /* SelectObject(dis->hDC, holdPen); */
1849 } else if (calcWidthCol
==col
|| calcWidthCol
==COLUMNS
) {
1850 int right
= img_pos
+ IMAGE_WIDTH
- Globals
.spaceSize
.cx
;
1852 if (right
> pane
->widths
[col
])
1853 pane
->widths
[col
] = right
;
1856 img_pos
= dis
->rcItem
.left
;
1859 img_pos
= dis
->rcItem
.left
;
1861 if (calcWidthCol
==col
|| calcWidthCol
==COLUMNS
)
1862 pane
->widths
[col
] = IMAGE_WIDTH
;
1865 if (calcWidthCol
== -1) {
1866 focusRect
.left
= img_pos
-2;
1868 #ifdef _NO_EXTENSIONS
1869 if (pane
->treePane
&& entry
) {
1872 DrawText(dis
->hDC
, entry
->data
.cFileName
, -1, &rt
, DT_CALCRECT
|DT_SINGLELINE
|DT_NOPREFIX
);
1874 focusRect
.right
= dis
->rcItem
.left
+pane
->positions
[col
+1]+Globals
.spaceSize
.cx
+ rt
.right
+2;
1878 if (attrs
& FILE_ATTRIBUTE_COMPRESSED
)
1879 textcolor
= COLOR_COMPRESSED
;
1882 textcolor
= RGB(0,0,0);
1884 if (dis
->itemState
& ODS_FOCUS
) {
1885 textcolor
= RGB(255,255,255);
1886 bkcolor
= COLOR_SELECTION
;
1888 bkcolor
= RGB(255,255,255);
1891 hbrush
= CreateSolidBrush(bkcolor
);
1892 FillRect(dis
->hDC
, &focusRect
, hbrush
);
1893 DeleteObject(hbrush
);
1895 SetBkMode(dis
->hDC
, TRANSPARENT
);
1896 SetTextColor(dis
->hDC
, textcolor
);
1898 cx
= pane
->widths
[col
];
1900 if (cx
&& img
!=IMG_NONE
) {
1901 if (cx
> IMAGE_WIDTH
)
1904 ImageList_DrawEx(Globals
.himl
, img
, dis
->hDC
,
1905 img_pos
, dis
->rcItem
.top
, cx
,
1906 IMAGE_HEIGHT
, bkcolor
, CLR_DEFAULT
, ILD_NORMAL
);
1913 #ifdef _NO_EXTENSIONS
1914 if (img
>= IMG_FOLDER_UP
)
1920 /* ouput file name */
1921 if (calcWidthCol
== -1)
1922 output_text(pane
, dis
, col
, entry
->data
.cFileName
, 0);
1923 else if (calcWidthCol
==col
|| calcWidthCol
==COLUMNS
)
1924 calc_width(pane
, dis
, col
, entry
->data
.cFileName
);
1928 #ifdef _NO_EXTENSIONS
1929 if (!pane
->treePane
) {
1932 /* display file size */
1933 if (visible_cols
& COL_SIZE
) {
1934 #ifdef _NO_EXTENSIONS
1935 if (!(attrs
&FILE_ATTRIBUTE_DIRECTORY
))
1940 size
= ((ULONGLONG
)entry
->data
.nFileSizeHigh
<< 32) | entry
->data
.nFileSizeLow
;
1942 _stprintf(buffer
, _T("%") LONGLONGARG
_T("d"), size
);
1944 if (calcWidthCol
== -1)
1945 output_number(pane
, dis
, col
, buffer
);
1946 else if (calcWidthCol
==col
|| calcWidthCol
==COLUMNS
)
1947 calc_width(pane
, dis
, col
, buffer
);/*TODO: not ever time enough */
1953 /* display file date */
1954 if (visible_cols
& (COL_DATE
|COL_TIME
)) {
1955 #ifndef _NO_EXTENSIONS
1956 format_date(&entry
->data
.ftCreationTime
, buffer
, visible_cols
);
1957 if (calcWidthCol
== -1)
1958 output_text(pane
, dis
, col
, buffer
, 0);
1959 else if (calcWidthCol
==col
|| calcWidthCol
==COLUMNS
)
1960 calc_width(pane
, dis
, col
, buffer
);
1963 format_date(&entry
->data
.ftLastAccessTime
, buffer
, visible_cols
);
1964 if (calcWidthCol
== -1)
1965 output_text(pane
, dis
, col
, buffer
, 0);
1966 else if (calcWidthCol
==col
|| calcWidthCol
==COLUMNS
)
1967 calc_width(pane
, dis
, col
, buffer
);
1971 format_date(&entry
->data
.ftLastWriteTime
, buffer
, visible_cols
);
1972 if (calcWidthCol
== -1)
1973 output_text(pane
, dis
, col
, buffer
, 0);
1974 else if (calcWidthCol
==col
|| calcWidthCol
==COLUMNS
)
1975 calc_width(pane
, dis
, col
, buffer
);
1979 #ifndef _NO_EXTENSIONS
1980 if (entry
->bhfi_valid
) {
1981 ULONGLONG index
= ((ULONGLONG
)entry
->bhfi
.nFileIndexHigh
<< 32) | entry
->bhfi
.nFileIndexLow
;
1983 if (visible_cols
& COL_INDEX
) {
1984 _stprintf(buffer
, _T("%") LONGLONGARG
_T("X"), index
);
1985 if (calcWidthCol
== -1)
1986 output_text(pane
, dis
, col
, buffer
, DT_RIGHT
);
1987 else if (calcWidthCol
==col
|| calcWidthCol
==COLUMNS
)
1988 calc_width(pane
, dis
, col
, buffer
);
1992 if (visible_cols
& COL_LINKS
) {
1993 wsprintf(buffer
, _T("%d"), entry
->bhfi
.nNumberOfLinks
);
1994 if (calcWidthCol
== -1)
1995 output_text(pane
, dis
, col
, buffer
, DT_CENTER
);
1996 else if (calcWidthCol
==col
|| calcWidthCol
==COLUMNS
)
1997 calc_width(pane
, dis
, col
, buffer
);
2004 /* show file attributes */
2005 if (visible_cols
& COL_ATTRIBUTES
) {
2006 #ifdef _NO_EXTENSIONS
2007 _tcscpy(buffer
, _T(" \t \t \t \t "));
2009 _tcscpy(buffer
, _T(" \t \t \t \t \t \t \t \t \t \t \t "));
2012 if (attrs
& FILE_ATTRIBUTE_NORMAL
) buffer
[ 0] = 'N';
2014 if (attrs
& FILE_ATTRIBUTE_READONLY
) buffer
[ 2] = 'R';
2015 if (attrs
& FILE_ATTRIBUTE_HIDDEN
) buffer
[ 4] = 'H';
2016 if (attrs
& FILE_ATTRIBUTE_SYSTEM
) buffer
[ 6] = 'S';
2017 if (attrs
& FILE_ATTRIBUTE_ARCHIVE
) buffer
[ 8] = 'A';
2018 if (attrs
& FILE_ATTRIBUTE_COMPRESSED
) buffer
[10] = 'C';
2019 #ifndef _NO_EXTENSIONS
2020 if (attrs
& FILE_ATTRIBUTE_DIRECTORY
) buffer
[12] = 'D';
2021 if (attrs
& FILE_ATTRIBUTE_ENCRYPTED
) buffer
[14] = 'E';
2022 if (attrs
& FILE_ATTRIBUTE_TEMPORARY
) buffer
[16] = 'T';
2023 if (attrs
& FILE_ATTRIBUTE_SPARSE_FILE
) buffer
[18] = 'P';
2024 if (attrs
& FILE_ATTRIBUTE_REPARSE_POINT
) buffer
[20] = 'Q';
2025 if (attrs
& FILE_ATTRIBUTE_OFFLINE
) buffer
[22] = 'O';
2026 if (attrs
& FILE_ATTRIBUTE_NOT_CONTENT_INDEXED
) buffer
[24] = 'X';
2030 if (calcWidthCol
== -1)
2031 output_tabbed_text(pane
, dis
, col
, buffer
);
2032 else if (calcWidthCol
==col
|| calcWidthCol
==COLUMNS
)
2033 calc_tabbed_width(pane
, dis
, col
, buffer
);
2039 if (flags.security) {
2040 DWORD rights = get_access_mask();
2042 tcscpy(buffer, _T(" \t \t \t \t \t \t \t \t \t \t \t "));
2044 if (rights & FILE_READ_DATA) buffer[ 0] = 'R';
2045 if (rights & FILE_WRITE_DATA) buffer[ 2] = 'W';
2046 if (rights & FILE_APPEND_DATA) buffer[ 4] = 'A';
2047 if (rights & FILE_READ_EA) {buffer[6] = 'entry'; buffer[ 7] = 'R';}
2048 if (rights & FILE_WRITE_EA) {buffer[9] = 'entry'; buffer[10] = 'W';}
2049 if (rights & FILE_EXECUTE) buffer[12] = 'X';
2050 if (rights & FILE_DELETE_CHILD) buffer[14] = 'D';
2051 if (rights & FILE_READ_ATTRIBUTES) {buffer[16] = 'a'; buffer[17] = 'R';}
2052 if (rights & FILE_WRITE_ATTRIBUTES) {buffer[19] = 'a'; buffer[20] = 'W';}
2053 if (rights & WRITE_DAC) buffer[22] = 'C';
2054 if (rights & WRITE_OWNER) buffer[24] = 'O';
2055 if (rights & SYNCHRONIZE) buffer[26] = 'S';
2057 output_text(dis, col++, buffer, DT_LEFT, 3, psize);
2060 if (flags.description) {
2061 get_description(buffer);
2062 output_text(dis, col++, buffer, 0, psize);
2066 #ifdef _NO_EXTENSIONS
2069 /* draw focus frame */
2070 if ((dis
->itemState
&ODS_FOCUS
) && calcWidthCol
==-1) {
2071 /* Currently [04/2000] Wine neither behaves exactly the same */
2072 /* way as WIN 95 nor like Windows NT... */
2077 if (!(GetVersion() & 0x80000000)) { /* Windows NT? */
2078 LOGBRUSH lb
= {PS_SOLID
, RGB(255,255,255)};
2079 hpen
= ExtCreatePen(PS_COSMETIC
|PS_ALTERNATE
, 1, &lb
, 0, 0);
2081 hpen
= CreatePen(PS_DOT
, 0, RGB(255,255,255));
2083 lastPen
= SelectPen(dis
->hDC
, hpen
);
2084 lastBrush
= SelectObject(dis
->hDC
, GetStockObject(HOLLOW_BRUSH
));
2085 SetROP2(dis
->hDC
, R2_XORPEN
);
2086 Rectangle(dis
->hDC
, focusRect
.left
, focusRect
.top
, focusRect
.right
, focusRect
.bottom
);
2087 SelectObject(dis
->hDC
, lastBrush
);
2088 SelectObject(dis
->hDC
, lastPen
);
2095 #ifdef _NO_EXTENSIONS
2097 static void draw_splitbar(HWND hwnd
, int x
)
2100 HDC hdc
= GetDC(hwnd
);
2102 GetClientRect(hwnd
, &rt
);
2104 rt
.left
= x
- SPLIT_WIDTH
/2;
2105 rt
.right
= x
+ SPLIT_WIDTH
/2+1;
2107 InvertRect(hdc
, &rt
);
2109 ReleaseDC(hwnd
, hdc
);
2115 #ifndef _NO_EXTENSIONS
2117 static void set_header(Pane
* pane
)
2120 int scroll_pos
= GetScrollPos(pane
->hwnd
, SB_HORZ
);
2123 item
.mask
= HDI_WIDTH
;
2126 for(; x
+pane
->widths
[i
]<scroll_pos
&& i
<COLUMNS
; i
++) {
2127 x
+= pane
->widths
[i
];
2128 Header_SetItem(pane
->hwndHeader
, i
, &item
);
2132 x
+= pane
->widths
[i
];
2133 item
.cxy
= x
- scroll_pos
;
2134 Header_SetItem(pane
->hwndHeader
, i
++, &item
);
2136 for(; i
<COLUMNS
; i
++) {
2137 item
.cxy
= pane
->widths
[i
];
2138 x
+= pane
->widths
[i
];
2139 Header_SetItem(pane
->hwndHeader
, i
, &item
);
2144 static LRESULT
pane_notify(Pane
* pane
, NMHDR
* pnmh
)
2146 switch(pnmh
->code
) {
2148 case HDN_ENDTRACK
: {
2149 HD_NOTIFY
* phdn
= (HD_NOTIFY
*) pnmh
;
2150 int idx
= phdn
->iItem
;
2151 int dx
= phdn
->pitem
->cxy
- pane
->widths
[idx
];
2155 GetClientRect(pane
->hwnd
, &clnt
);
2157 /* move immediate to simulate HDS_FULLDRAG (for now [04/2000] not realy needed with WINELIB) */
2158 Header_SetItem(pane
->hwndHeader
, idx
, phdn
->pitem
);
2160 pane
->widths
[idx
] += dx
;
2162 for(i
=idx
; ++i
<=COLUMNS
; )
2163 pane
->positions
[i
] += dx
;
2166 int scroll_pos
= GetScrollPos(pane
->hwnd
, SB_HORZ
);
2170 rt_scr
.left
= pane
->positions
[idx
+1]-scroll_pos
;
2172 rt_scr
.right
= clnt
.right
;
2173 rt_scr
.bottom
= clnt
.bottom
;
2175 rt_clip
.left
= pane
->positions
[idx
]-scroll_pos
;
2177 rt_clip
.right
= clnt
.right
;
2178 rt_clip
.bottom
= clnt
.bottom
;
2180 if (rt_scr
.left
< 0) rt_scr
.left
= 0;
2181 if (rt_clip
.left
< 0) rt_clip
.left
= 0;
2183 ScrollWindowEx(pane
->hwnd
, dx
, 0, &rt_scr
, &rt_clip
, 0, 0, SW_INVALIDATE
);
2185 rt_clip
.right
= pane
->positions
[idx
+1];
2186 RedrawWindow(pane
->hwnd
, &rt_clip
, 0, RDW_INVALIDATE
|RDW_UPDATENOW
);
2188 if (pnmh
->code
== HDN_ENDTRACK
) {
2189 ListBox_SetHorizontalExtent(pane
->hwnd
, pane
->positions
[COLUMNS
]);
2191 if (GetScrollPos(pane
->hwnd
, SB_HORZ
) != scroll_pos
)
2199 case HDN_DIVIDERDBLCLICK
: {
2200 HD_NOTIFY
* phdn
= (HD_NOTIFY
*) pnmh
;
2203 calc_single_width(pane
, phdn
->iItem
);
2204 item
.mask
= HDI_WIDTH
;
2205 item
.cxy
= pane
->widths
[phdn
->iItem
];
2207 Header_SetItem(pane
->hwndHeader
, phdn
->iItem
, &item
);
2208 InvalidateRect(pane
->hwnd
, 0, TRUE
);
2218 static void scan_entry(ChildWnd
* child
, Entry
* entry
)
2220 TCHAR path
[MAX_PATH
];
2221 int idx
= ListBox_GetCurSel(child
->left
.hwnd
);
2222 HCURSOR crsrOld
= SetCursor(LoadCursor(0, IDC_WAIT
));
2224 /* delete sub entries in left pane */
2226 LRESULT res
= ListBox_GetItemData(child
->left
.hwnd
, idx
+1);
2227 Entry
* sub
= (Entry
*) res
;
2229 if (res
==LB_ERR
|| !sub
|| sub
->level
<=entry
->level
)
2232 ListBox_DeleteString(child
->left
.hwnd
, idx
+1);
2235 /* empty right pane */
2236 ListBox_ResetContent(child
->right
.hwnd
);
2238 /* release memory */
2239 free_entries(entry
);
2241 /* read contents from disk */
2242 get_path(entry
, path
);
2243 read_directory(entry
, path
, child
->sortOrder
);
2245 /* insert found entries in right pane */
2246 insert_entries(&child
->right
, entry
->down
, -1);
2247 calc_widths(&child
->right
, FALSE
);
2248 #ifndef _NO_EXTENSIONS
2249 set_header(&child
->right
);
2252 child
->header_wdths_ok
= FALSE
;
2258 /* expand a directory entry */
2260 static BOOL
expand_entry(ChildWnd
* child
, Entry
* dir
)
2265 if (!dir
|| dir
->expanded
|| !dir
->down
)
2270 if (p
->data
.cFileName
[0]=='.' && p
->data
.cFileName
[1]=='\0' && p
->next
) {
2273 if (p
->data
.cFileName
[0]=='.' && p
->data
.cFileName
[1]=='.' &&
2274 p
->data
.cFileName
[2]=='\0' && p
->next
)
2278 /* no subdirectories ? */
2279 if (!(p
->data
.dwFileAttributes
&FILE_ATTRIBUTE_DIRECTORY
))
2282 idx
= ListBox_FindItemData(child
->left
.hwnd
, 0, dir
);
2284 dir
->expanded
= TRUE
;
2286 /* insert entries in left pane */
2287 insert_entries(&child
->left
, p
, idx
);
2289 if (!child
->header_wdths_ok
) {
2290 if (calc_widths(&child
->left
, FALSE
)) {
2291 #ifndef _NO_EXTENSIONS
2292 set_header(&child
->left
);
2295 child
->header_wdths_ok
= TRUE
;
2303 static void collapse_entry(Pane
* pane
, Entry
* dir
)
2305 int idx
= ListBox_FindItemData(pane
->hwnd
, 0, dir
);
2307 ShowWindow(pane
->hwnd
, SW_HIDE
);
2309 /* hide sub entries */
2311 LRESULT res
= ListBox_GetItemData(pane
->hwnd
, idx
+1);
2312 Entry
* sub
= (Entry
*) res
;
2314 if (res
==LB_ERR
|| !sub
|| sub
->level
<=dir
->level
)
2317 ListBox_DeleteString(pane
->hwnd
, idx
+1);
2320 dir
->expanded
= FALSE
;
2322 ShowWindow(pane
->hwnd
, SW_SHOW
);
2326 static void set_curdir(ChildWnd
* child
, Entry
* entry
)
2328 TCHAR path
[MAX_PATH
];
2330 child
->left
.cur
= entry
;
2331 child
->right
.root
= entry
->down
;
2332 child
->right
.cur
= entry
;
2334 if (!entry
->scanned
)
2335 scan_entry(child
, entry
);
2337 ListBox_ResetContent(child
->right
.hwnd
);
2338 insert_entries(&child
->right
, entry
->down
, -1);
2339 calc_widths(&child
->right
, FALSE
);
2340 #ifndef _NO_EXTENSIONS
2341 set_header(&child
->right
);
2345 get_path(entry
, path
);
2346 lstrcpy(child
->path
, path
);
2348 if (child
->hwnd
) /* only change window title, if the window already exists */
2349 SetWindowText(child
->hwnd
, path
);
2351 SetCurrentDirectory(path
);
2355 static void activate_entry(ChildWnd
* child
, Pane
* pane
)
2357 Entry
* entry
= pane
->cur
;
2362 if (entry
->data
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) {
2363 int scanned_old
= entry
->scanned
;
2366 scan_entry(child
, entry
);
2368 #ifndef _NO_EXTENSIONS
2369 if (entry
->data
.cFileName
[0]=='.' && entry
->data
.cFileName
[1]=='\0')
2373 if (entry
->data
.cFileName
[0]=='.' && entry
->data
.cFileName
[1]=='.' && entry
->data
.cFileName
[2]=='\0') {
2374 entry
= child
->left
.cur
->up
;
2375 collapse_entry(&child
->left
, entry
);
2377 } else if (entry
->expanded
)
2378 collapse_entry(pane
, child
->left
.cur
);
2380 expand_entry(child
, child
->left
.cur
);
2382 if (!pane
->treePane
) focus_entry
: {
2383 int idx
= ListBox_FindItemData(child
->left
.hwnd
, ListBox_GetCurSel(child
->left
.hwnd
), entry
);
2384 ListBox_SetCurSel(child
->left
.hwnd
, idx
);
2385 set_curdir(child
, entry
);
2390 calc_widths(pane
, FALSE
);
2392 #ifndef _NO_EXTENSIONS
2397 TCHAR cmd
[MAX_PATH
];
2400 get_path(entry
, cmd
);
2402 /* start program, open document... */
2403 hinst
= ShellExecute(child
->hwnd
, NULL
/*operation*/, cmd
, NULL
/*parameters*/, NULL
/*dir*/, SW_SHOWNORMAL
);
2405 if ((int)hinst
<= 32)
2406 display_error(child
->hwnd
, GetLastError());
2411 static BOOL
pane_command(Pane
* pane
, UINT cmd
)
2415 if (pane
->visible_cols
) {
2416 pane
->visible_cols
= 0;
2417 calc_widths(pane
, TRUE
);
2418 #ifndef _NO_EXTENSIONS
2421 InvalidateRect(pane
->hwnd
, 0, TRUE
);
2422 CheckMenuItem(Globals
.hMenuView
, ID_VIEW_NAME
, MF_BYCOMMAND
|MF_CHECKED
);
2423 CheckMenuItem(Globals
.hMenuView
, ID_VIEW_ALL_ATTRIBUTES
, MF_BYCOMMAND
);
2424 CheckMenuItem(Globals
.hMenuView
, ID_VIEW_SELECTED_ATTRIBUTES
, MF_BYCOMMAND
);
2428 case ID_VIEW_ALL_ATTRIBUTES
:
2429 if (pane
->visible_cols
!= COL_ALL
) {
2430 pane
->visible_cols
= COL_ALL
;
2431 calc_widths(pane
, TRUE
);
2432 #ifndef _NO_EXTENSIONS
2435 InvalidateRect(pane
->hwnd
, 0, TRUE
);
2436 CheckMenuItem(Globals
.hMenuView
, ID_VIEW_NAME
, MF_BYCOMMAND
);
2437 CheckMenuItem(Globals
.hMenuView
, ID_VIEW_ALL_ATTRIBUTES
, MF_BYCOMMAND
|MF_CHECKED
);
2438 CheckMenuItem(Globals
.hMenuView
, ID_VIEW_SELECTED_ATTRIBUTES
, MF_BYCOMMAND
);
2442 #ifndef _NO_EXTENSIONS
2443 case ID_PREFERED_SIZES
: {
2444 calc_widths(pane
, TRUE
);
2446 InvalidateRect(pane
->hwnd
, 0, TRUE
);
2450 /* TODO: more command ids... */
2460 LRESULT CALLBACK
ChildWndProc(HWND hwnd
, UINT nmsg
, WPARAM wparam
, LPARAM lparam
)
2462 static int last_split
;
2464 ChildWnd
* child
= (ChildWnd
*) GetWindowLong(hwnd
, GWL_USERDATA
);
2469 LPDRAWITEMSTRUCT dis
= (LPDRAWITEMSTRUCT
)lparam
;
2470 Entry
* entry
= (Entry
*) dis
->itemData
;
2472 if (dis
->CtlID
== IDW_TREE_LEFT
)
2473 draw_item(&child
->left
, dis
, entry
, -1);
2475 draw_item(&child
->right
, dis
, entry
, -1);
2480 InitChildWindow(child
);
2484 free_child_window(child
);
2485 SetWindowLong(hwnd
, GWL_USERDATA
, 0);
2492 GetClientRect(hwnd
, &rt
);
2493 BeginPaint(hwnd
, &ps
);
2494 rt
.left
= child
->split_pos
-SPLIT_WIDTH
/2;
2495 rt
.right
= child
->split_pos
+SPLIT_WIDTH
/2+1;
2496 lastBrush
= SelectBrush(ps
.hdc
, (HBRUSH
)GetStockObject(COLOR_SPLITBAR
));
2497 Rectangle(ps
.hdc
, rt
.left
, rt
.top
-1, rt
.right
, rt
.bottom
+1);
2498 SelectObject(ps
.hdc
, lastBrush
);
2499 #ifdef _NO_EXTENSIONS
2500 rt
.top
= rt
.bottom
- GetSystemMetrics(SM_CYHSCROLL
);
2501 FillRect(ps
.hdc
, &rt
, GetStockObject(BLACK_BRUSH
));
2503 EndPaint(hwnd
, &ps
);
2507 if (LOWORD(lparam
) == HTCLIENT
) {
2510 ScreenToClient(hwnd
, &pt
);
2512 if (pt
.x
>=child
->split_pos
-SPLIT_WIDTH
/2 && pt
.x
<child
->split_pos
+SPLIT_WIDTH
/2+1) {
2513 SetCursor(LoadCursor(0, IDC_SIZEWE
));
2519 case WM_LBUTTONDOWN
: {
2521 int x
= LOWORD(lparam
);
2523 GetClientRect(hwnd
, &rt
);
2525 if (x
>=child
->split_pos
-SPLIT_WIDTH
/2 && x
<child
->split_pos
+SPLIT_WIDTH
/2+1) {
2526 last_split
= child
->split_pos
;
2527 #ifdef _NO_EXTENSIONS
2528 draw_splitbar(hwnd
, last_split
);
2536 if (GetCapture() == hwnd
) {
2537 #ifdef _NO_EXTENSIONS
2539 int x
= LOWORD(lparam
);
2540 draw_splitbar(hwnd
, last_split
);
2542 GetClientRect(hwnd
, &rt
);
2543 child
->split_pos
= x
;
2544 resize_tree(child
, rt
.right
, rt
.bottom
);
2550 #ifdef _NO_EXTENSIONS
2551 case WM_CAPTURECHANGED
:
2552 if (GetCapture()==hwnd
&& last_split
>=0)
2553 draw_splitbar(hwnd
, last_split
);
2558 if (wparam
== VK_ESCAPE
)
2559 if (GetCapture() == hwnd
) {
2561 #ifdef _NO_EXTENSIONS
2562 draw_splitbar(hwnd
, last_split
);
2564 child
->split_pos
= last_split
;
2566 GetClientRect(hwnd
, &rt
);
2567 resize_tree(child
, rt
.right
, rt
.bottom
);
2570 SetCursor(LoadCursor(0, IDC_ARROW
));
2575 if (GetCapture() == hwnd
) {
2577 int x
= LOWORD(lparam
);
2579 #ifdef _NO_EXTENSIONS
2580 HDC hdc
= GetDC(hwnd
);
2581 GetClientRect(hwnd
, &rt
);
2583 rt
.left
= last_split
-SPLIT_WIDTH
/2;
2584 rt
.right
= last_split
+SPLIT_WIDTH
/2+1;
2585 InvertRect(hdc
, &rt
);
2588 rt
.left
= x
-SPLIT_WIDTH
/2;
2589 rt
.right
= x
+SPLIT_WIDTH
/2+1;
2590 InvertRect(hdc
, &rt
);
2592 ReleaseDC(hwnd
, hdc
);
2594 GetClientRect(hwnd
, &rt
);
2596 if (x
>=0 && x
<rt
.right
) {
2597 child
->split_pos
= x
;
2598 resize_tree(child
, rt
.right
, rt
.bottom
);
2599 rt
.left
= x
-SPLIT_WIDTH
/2;
2600 rt
.right
= x
+SPLIT_WIDTH
/2+1;
2601 InvalidateRect(hwnd
, &rt
, FALSE
);
2602 UpdateWindow(child
->left
.hwnd
);
2604 UpdateWindow(child
->right
.hwnd
);
2610 #ifndef _NO_EXTENSIONS
2611 case WM_GETMINMAXINFO
:
2612 DefMDIChildProc(hwnd
, nmsg
, wparam
, lparam
);
2614 {LPMINMAXINFO lpmmi
= (LPMINMAXINFO
)lparam
;
2616 lpmmi
->ptMaxTrackSize
.x
<<= 1;/*2*GetSystemMetrics(SM_CXSCREEN) / SM_CXVIRTUALSCREEN */
2617 lpmmi
->ptMaxTrackSize
.y
<<= 1;/*2*GetSystemMetrics(SM_CYSCREEN) / SM_CYVIRTUALSCREEN */
2622 SetCurrentDirectory(child
->path
);
2623 SetFocus(child
->focus_pane
? child
->right
.hwnd
: child
->left
.hwnd
);
2626 case WM_DISPATCH_COMMAND
: {
2627 Pane
* pane
= GetFocus()==child
->left
.hwnd
? &child
->left
: &child
->right
;
2629 switch(LOWORD(wparam
)) {
2630 case ID_WINDOW_NEW
: {
2631 ChildWnd
* new_child
= alloc_child_window(child
->path
);
2633 if (!create_child_window(new_child
))
2639 scan_entry(child
, pane
->cur
);
2643 activate_entry(child
, pane
);
2647 return pane_command(pane
, LOWORD(wparam
));
2653 Pane
* pane
= GetFocus()==child
->left
.hwnd
? &child
->left
: &child
->right
;
2655 switch(HIWORD(wparam
)) {
2656 case LBN_SELCHANGE
: {
2657 int idx
= ListBox_GetCurSel(pane
->hwnd
);
2658 Entry
* entry
= (Entry
*) ListBox_GetItemData(pane
->hwnd
, idx
);
2660 if (pane
== &child
->left
)
2661 set_curdir(child
, entry
);
2667 activate_entry(child
, pane
);
2672 #ifndef _NO_EXTENSIONS
2674 NMHDR
* pnmh
= (NMHDR
*) lparam
;
2675 return pane_notify(pnmh
->idFrom
==IDW_HEADER_LEFT
? &child
->left
: &child
->right
, pnmh
);}
2679 if (wparam
!= SIZE_MINIMIZED
)
2680 resize_tree(child
, LOWORD(lparam
), HIWORD(lparam
));
2684 return DefMDIChildProc(hwnd
, nmsg
, wparam
, lparam
);
2691 LRESULT CALLBACK
TreeWndProc(HWND hwnd
, UINT nmsg
, WPARAM wparam
, LPARAM lparam
)
2693 ChildWnd
* child
= (ChildWnd
*) GetWindowLong(GetParent(hwnd
), GWL_USERDATA
);
2694 Pane
* pane
= (Pane
*) GetWindowLong(hwnd
, GWL_USERDATA
);
2698 #ifndef _NO_EXTENSIONS
2705 child
->focus_pane
= pane
==&child
->right
? 1: 0;
2706 ListBox_SetSel(hwnd
, TRUE
, 1);
2707 /*TODO: check menu items */
2711 if (wparam
== VK_TAB
) {
2712 /*TODO: SetFocus(Globals.hdrivebar) */
2713 SetFocus(child
->focus_pane
? child
->left
.hwnd
: child
->right
.hwnd
);
2717 return CallWindowProc(g_orgTreeWndProc
, hwnd
, nmsg
, wparam
, lparam
);
2721 static void InitInstance(HINSTANCE hinstance
)
2726 WINE_UNUSED ATOM hChildClass
;
2727 HMENU hMenuFrame
= LoadMenu(hinstance
, MAKEINTRESOURCE(IDM_WINEFILE
));
2728 HMENU hMenuWindow
= GetSubMenu(hMenuFrame
, GetMenuItemCount(hMenuFrame
)-2);
2730 CLIENTCREATESTRUCT ccs
;
2732 INITCOMMONCONTROLSEX icc
= {
2733 sizeof(INITCOMMONCONTROLSEX
),
2738 TCHAR path
[MAX_PATH
];
2743 wcFrame
.cbSize
= sizeof(WNDCLASSEX
);
2745 wcFrame
.lpfnWndProc
= FrameWndProc
;
2746 wcFrame
.cbClsExtra
= 0;
2747 wcFrame
.cbWndExtra
= 0;
2748 wcFrame
.hInstance
= hinstance
;
2749 wcFrame
.hIcon
= LoadIcon(hinstance
,
2750 MAKEINTRESOURCE(IDI_WINEFILE
));
2751 wcFrame
.hCursor
= LoadCursor(0, IDC_ARROW
);
2752 wcFrame
.hbrBackground
= 0;
2753 wcFrame
.lpszMenuName
= 0;
2754 wcFrame
.lpszClassName
= WINEFILEFRAME
;
2755 wcFrame
.hIconSm
= (HICON
)LoadImage(hinstance
,
2756 MAKEINTRESOURCE(IDI_WINEFILE
),
2758 GetSystemMetrics(SM_CXSMICON
),
2759 GetSystemMetrics(SM_CYSMICON
),
2762 /* register frame window class */
2763 hframeClass
= RegisterClassEx(&wcFrame
);
2765 wcChild
.style
= CS_CLASSDC
|CS_DBLCLKS
|CS_VREDRAW
;
2766 wcChild
.lpfnWndProc
= ChildWndProc
;
2767 wcChild
.cbClsExtra
= 0;
2768 wcChild
.cbWndExtra
= 0;
2769 wcChild
.hInstance
= hinstance
;
2771 wcChild
.hCursor
= LoadCursor(0, IDC_ARROW
);
2772 wcChild
.hbrBackground
= 0;
2773 wcChild
.lpszMenuName
= 0;
2774 wcChild
.lpszClassName
= WINEFILETREE
;
2776 /* register tree windows class */
2777 hChildClass
= RegisterClass(&wcChild
);
2779 ccs
.hWindowMenu
= hMenuWindow
;
2780 ccs
.idFirstChild
= IDW_FIRST_CHILD
;
2782 Globals
.hMenuFrame
= hMenuFrame
;
2783 Globals
.hMenuView
= GetSubMenu(hMenuFrame
, 3);
2784 Globals
.hMenuOptions
= GetSubMenu(hMenuFrame
, 4);
2786 Globals
.haccel
= LoadAccelerators(hinstance
, MAKEINTRESOURCE(IDA_WINEFILE
));
2788 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"));
2792 Globals
.hInstance
= hinstance
;
2794 /* create main window */
2795 Globals
.hMainWnd
= CreateWindowEx(0, (LPCTSTR
)(int)hframeClass
, _T("Wine File"), WS_OVERLAPPEDWINDOW
,
2796 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
2797 0/*hWndParent*/, Globals
.hMenuFrame
, hinstance
, 0/*lpParam*/);
2800 Globals
.hmdiclient
= CreateWindowEx(0, _T("MDICLIENT"), NULL
,
2801 WS_CHILD
|WS_CLIPCHILDREN
|WS_VSCROLL
|WS_HSCROLL
|WS_VISIBLE
|WS_BORDER
,
2803 Globals
.hMainWnd
, 0, hinstance
, &ccs
);
2806 InitCommonControlsEx(&icc
);
2809 TBBUTTON drivebarBtn
= {0, 0, TBSTATE_ENABLED
, TBSTYLE_SEP
};
2813 Globals
.hdrivebar
= CreateToolbarEx(Globals
.hMainWnd
, WS_CHILD
|WS_VISIBLE
|CCS_NOMOVEY
|TBSTYLE_LIST
,
2814 IDW_DRIVEBAR
, 2, Globals
.hInstance
, IDB_DRIVEBAR
, &drivebarBtn
,
2815 1, 16, 13, 16, 13, sizeof(TBBUTTON
));
2816 CheckMenuItem(Globals
.hMenuOptions
, ID_VIEW_DRIVE_BAR
, MF_BYCOMMAND
|MF_CHECKED
);
2818 GetLogicalDriveStrings(BUFFER_LEN
, Globals
.drives
);
2820 drivebarBtn
.fsStyle
= TBSTYLE_BUTTON
;
2822 #ifndef _NO_EXTENSIONS
2824 /* insert unix file system button */
2825 SendMessage(Globals
.hdrivebar
, TB_ADDSTRING
, 0, (LPARAM
)_T("/\0"));
2827 drivebarBtn
.idCommand
= ID_DRIVE_UNIX_FS
;
2828 SendMessage(Globals
.hdrivebar
, TB_INSERTBUTTON
, btn
++, (LPARAM
)&drivebarBtn
);
2829 drivebarBtn
.iString
++;
2832 /* register windows drive root strings */
2833 SendMessage(Globals
.hdrivebar
, TB_ADDSTRING
, 0, (LPARAM
)Globals
.drives
);
2836 drivebarBtn
.idCommand
= ID_DRIVE_FIRST
;
2838 for(p
=Globals
.drives
; *p
; ) {
2839 #ifdef _NO_EXTENSIONS
2840 /* insert drive letter */
2841 TCHAR b
[3] = {tolower(*p
)};
2842 SendMessage(Globals
.hdrivebar
, TB_ADDSTRING
, 0, (LPARAM
)b
);
2844 switch(GetDriveType(p
)) {
2845 case DRIVE_REMOVABLE
: drivebarBtn
.iBitmap
= 1; break;
2846 case DRIVE_CDROM
: drivebarBtn
.iBitmap
= 3; break;
2847 case DRIVE_REMOTE
: drivebarBtn
.iBitmap
= 4; break;
2848 case DRIVE_RAMDISK
: drivebarBtn
.iBitmap
= 5; break;
2849 default:/*DRIVE_FIXED*/ drivebarBtn
.iBitmap
= 2;
2852 SendMessage(Globals
.hdrivebar
, TB_INSERTBUTTON
, btn
++, (LPARAM
)&drivebarBtn
);
2853 drivebarBtn
.idCommand
++;
2854 drivebarBtn
.iString
++;
2861 TBBUTTON toolbarBtns
[] = {
2862 {0, 0, 0, TBSTYLE_SEP
},
2863 {0, ID_WINDOW_NEW
, TBSTATE_ENABLED
, TBSTYLE_BUTTON
},
2864 {1, ID_WINDOW_CASCADE
, TBSTATE_ENABLED
, TBSTYLE_BUTTON
},
2865 {2, ID_WINDOW_TILE_HORZ
, TBSTATE_ENABLED
, TBSTYLE_BUTTON
},
2866 {3, ID_WINDOW_TILE_VERT
, TBSTATE_ENABLED
, TBSTYLE_BUTTON
},
2867 {4, 2/*TODO: ID_...*/, TBSTATE_ENABLED
, TBSTYLE_BUTTON
},
2868 {5, 2/*TODO: ID_...*/, TBSTATE_ENABLED
, TBSTYLE_BUTTON
},
2871 Globals
.htoolbar
= CreateToolbarEx(Globals
.hMainWnd
, WS_CHILD
|WS_VISIBLE
,
2872 IDW_TOOLBAR
, 2, Globals
.hInstance
, IDB_TOOLBAR
, toolbarBtns
,
2873 sizeof(toolbarBtns
)/sizeof(TBBUTTON
), 16, 15, 16, 15, sizeof(TBBUTTON
));
2874 CheckMenuItem(Globals
.hMenuOptions
, ID_VIEW_TOOL_BAR
, MF_BYCOMMAND
|MF_CHECKED
);
2877 Globals
.hstatusbar
= CreateStatusWindow(WS_CHILD
|WS_VISIBLE
, 0, Globals
.hMainWnd
, IDW_STATUSBAR
);
2878 CheckMenuItem(Globals
.hMenuOptions
, ID_VIEW_STATUSBAR
, MF_BYCOMMAND
|MF_CHECKED
);
2880 /* CreateStatusWindow does not accept WS_BORDER
2881 Globals.hstatusbar = CreateWindowEx(WS_EX_NOPARENTNOTIFY, STATUSCLASSNAME, 0,
2882 WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS|WS_BORDER|CCS_NODIVIDER, 0,0,0,0,
2883 Globals.hMainWnd, (HMENU)IDW_STATUSBAR, hinstance, 0);*/
2885 /*TODO: read paths and window placements from registry */
2886 GetCurrentDirectory(MAX_PATH
, path
);
2887 child
= alloc_child_window(path
);
2889 child
->pos
.showCmd
= SW_SHOWMAXIMIZED
;
2890 child
->pos
.rcNormalPosition
.left
= 0;
2891 child
->pos
.rcNormalPosition
.top
= 0;
2892 child
->pos
.rcNormalPosition
.right
= 320;
2893 child
->pos
.rcNormalPosition
.bottom
= 280;
2895 if (!create_child_window(child
))
2898 SetWindowPlacement(child
->hwnd
, &child
->pos
);
2900 Globals
.himl
= ImageList_LoadBitmap(Globals
.hInstance
, MAKEINTRESOURCE(IDB_IMAGES
), 16, 0, RGB(0,255,0));
2902 Globals
.prescan_node
= FALSE
;
2907 ImageList_Destroy(Globals
.himl
);
2911 #ifdef _NO_EXTENSIONS
2913 /* search for already running win[e]files */
2915 static int g_foundPrevInstance
= 0;
2917 static BOOL CALLBACK
EnumWndProc(HWND hwnd
, LPARAM lparam
)
2921 GetClassName(hwnd
, cls
, 128);
2923 if (!lstrcmp(cls
, (LPCTSTR
)lparam
)) {
2924 g_foundPrevInstance
++;
2934 int APIENTRY
WinMain(HINSTANCE hinstance
,
2935 HINSTANCE previnstance
,
2941 #ifdef _NO_EXTENSIONS
2942 /* allow only one running instance */
2943 EnumWindows(EnumWndProc
, (LPARAM
)WINEFILEFRAME
);
2945 if (g_foundPrevInstance
)
2949 InitInstance(hinstance
);
2951 if (cmdshow
== SW_SHOWNORMAL
) {
2952 /*TODO: read window placement from registry */
2953 cmdshow
= SW_MAXIMIZE
;
2956 ShowWindow(Globals
.hMainWnd
, cmdshow
);
2957 UpdateWindow(Globals
.hMainWnd
);
2959 while(GetMessage(&msg
, 0, 0, 0)) {
2960 if (!TranslateMDISysAccel(Globals
.hmdiclient
, &msg
) &&
2961 !TranslateAccelerator(Globals
.hMainWnd
, Globals
.haccel
, &msg
))
2963 TranslateMessage(&msg
);
2964 DispatchMessage(&msg
);