00001 /* 00002 * Winefile 00003 * 00004 * Copyright 2000, 2003, 2004, 2005, 2008 Martin Fuchs 00005 * Copyright 2006 Jason Green 00006 * 00007 * This library is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * This library is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with this library; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00020 */ 00021 00022 #include "winefile.h" 00023 00024 00025 static void set_curdir(ChildWnd* child, Entry* entry, int idx, HWND hwnd); 00026 static void refresh_child(ChildWnd* child); 00027 static void refresh_drives(void); 00028 00029 00030 /* some common string constants */ 00031 const TCHAR sEmpty[] = {'\0'}; 00032 const TCHAR sSpace[] = {' ', '\0'}; 00033 const TCHAR sNumFmt[] = {'%','d','\0'}; 00034 const TCHAR sQMarks[] = {'?','?','?','\0'}; 00035 00036 #ifdef _MSC_VER 00037 const TCHAR sLongHexFmt[] = {'%','I','6','4','X','\0'}; 00038 const TCHAR sLongNumFmt[] = {'%','I','6','4','d','\0'}; 00039 #else 00040 const TCHAR sLongHexFmt[] = {'%','L','X','\0'}; 00041 const TCHAR sLongNumFmt[] = {'%','L','d','\0'}; 00042 #endif 00043 00044 /* window class names */ 00045 const TCHAR sWINEFILEFRAME[] = {'W','F','S','_','F','r','a','m','e','\0'}; 00046 const TCHAR sWINEFILETREE[] = {'W','F','S','_','T','r','e','e','\0'}; 00047 00048 00049 /* globals */ 00050 struct WINEFILE_GLOBALS Globals; 00051 00052 static int last_split; 00053 00054 00055 /* load resource string */ 00056 LPTSTR load_string(LPTSTR buffer, UINT id) 00057 { 00058 LoadString(Globals.hInstance, id, buffer, BUFFER_LEN); 00059 00060 return buffer; 00061 } 00062 00063 00064 /* display error message for the specified WIN32 error code */ 00065 void display_error(HWND hwnd, DWORD error) 00066 { 00067 TCHAR b1[BUFFER_LEN], b2[BUFFER_LEN]; 00068 PTSTR msg; 00069 00070 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, 00071 0, error, MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), (PTSTR)&msg, 0, NULL)) 00072 MessageBox(hwnd, msg, RS(b2,IDS_WINEFILE), MB_OK); 00073 else 00074 MessageBox(hwnd, RS(b1,IDS_ERROR), RS(b2,IDS_WINEFILE), MB_OK); 00075 00076 LocalFree(msg); 00077 } 00078 00079 00080 /* display network error message using WNetGetLastError() */ 00081 void display_network_error(HWND hwnd) 00082 { 00083 TCHAR msg[BUFFER_LEN], provider[BUFFER_LEN], b2[BUFFER_LEN]; 00084 DWORD error; 00085 00086 if (WNetGetLastError(&error, msg, BUFFER_LEN, provider, BUFFER_LEN) == NO_ERROR) 00087 MessageBox(hwnd, msg, RS(b2,IDS_WINEFILE), MB_OK); 00088 } 00089 00090 00091 #ifdef __WINE__ 00092 00093 #ifdef UNICODE 00094 00095 /* call vswprintf() in msvcrt.dll */ 00096 /*TODO: fix swprintf() in non-msvcrt mode, so that this dynamic linking function can be removed */ 00097 static int msvcrt_swprintf(WCHAR* buffer, const WCHAR* fmt, ...) 00098 { 00099 static int (__cdecl *pvswprintf)(WCHAR*, const WCHAR*, va_list) = NULL; 00100 va_list ap; 00101 int ret; 00102 00103 if (!pvswprintf) { 00104 HMODULE hModMsvcrt = LoadLibraryA("msvcrt"); 00105 pvswprintf = (int(__cdecl*)(WCHAR*,const WCHAR*,va_list)) GetProcAddress(hModMsvcrt, "vswprintf"); 00106 } 00107 00108 va_start(ap, fmt); 00109 ret = (*pvswprintf)(buffer, fmt, ap); 00110 va_end(ap); 00111 00112 return ret; 00113 } 00114 00115 /* UNICODE version of strrchr() for WINE */ 00116 static LPCWSTR my_wcsrchr(LPCWSTR str, WCHAR c) 00117 { 00118 LPCWSTR p = str; 00119 00120 while(*p) 00121 ++p; 00122 00123 do { 00124 if (--p < str) 00125 return NULL; 00126 } while(*p != c); 00127 00128 return p; 00129 } 00130 00131 #define _tcsrchr my_wcsrchr 00132 #else /* UNICODE */ 00133 #define _tcsrchr strrchr 00134 #endif /* UNICODE */ 00135 00136 #endif /* __WINE__ */ 00137 00138 00139 /* allocate and initialize memeory for a new child window for the given path */ 00140 00141 static ChildWnd* alloc_child_window(LPCTSTR path, LPITEMIDLIST pidl, HWND hwnd) 00142 { 00143 TCHAR drv[_MAX_DRIVE+1], dir[_MAX_DIR], name[_MAX_FNAME], ext[_MAX_EXT]; 00144 TCHAR dir_path[MAX_PATH]; 00145 TCHAR b1[BUFFER_LEN]; 00146 static const TCHAR sAsterics[] = {'*', '\0'}; 00147 00148 ChildWnd* child = (ChildWnd*) heap_alloc(sizeof(ChildWnd)); 00149 Root* root = &child->root; 00150 Entry* entry; 00151 00152 memset(child, 0, sizeof(ChildWnd)); 00153 00154 child->left.treePane = TRUE; 00155 child->left.visible_cols = 0; 00156 00157 child->right.treePane = FALSE; 00158 #ifndef _NO_EXTENSIONS 00159 child->right.visible_cols = COL_SIZE|COL_DATE|COL_TIME|COL_ATTRIBUTES|COL_INDEX|COL_LINKS; 00160 #else 00161 child->right.visible_cols = COL_SIZE|COL_DATE|COL_TIME|COL_ATTRIBUTES; 00162 #endif 00163 00164 child->pos.length = sizeof(WINDOWPLACEMENT); 00165 child->pos.flags = 0; 00166 child->pos.showCmd = SW_SHOWNORMAL; 00167 child->pos.rcNormalPosition.left = CW_USEDEFAULT; 00168 child->pos.rcNormalPosition.top = CW_USEDEFAULT; 00169 child->pos.rcNormalPosition.right = CW_USEDEFAULT; 00170 child->pos.rcNormalPosition.bottom = CW_USEDEFAULT; 00171 00172 child->focus_pane = 0; 00173 child->split_pos = DEFAULT_SPLIT_POS; 00174 child->sortOrder = SORT_NAME; 00175 child->header_wdths_ok = FALSE; 00176 00177 if (path) { 00178 lstrcpy(child->path, path); 00179 00180 _tsplitpath(path, drv, dir, name, ext); 00181 } 00182 00183 lstrcpy(child->filter_pattern, sAsterics); 00184 child->filter_flags = TF_ALL; 00185 00186 root->entry.level = 0; 00187 00188 lstrcpy(dir_path, drv); 00189 lstrcat(dir_path, dir); 00190 entry = read_tree(root, dir_path, pidl, drv, child->sortOrder, hwnd); 00191 00192 #ifdef _SHELL_FOLDERS 00193 if (root->entry.etype == ET_SHELL) 00194 load_string(root->entry.data.cFileName, IDS_DESKTOP); 00195 else 00196 #endif 00197 wsprintf(root->entry.data.cFileName, RS(b1,IDS_TITLEFMT), drv, root->fs); 00198 00199 root->entry.data.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY; 00200 00201 child->left.root = &root->entry; 00202 child->right.root = NULL; 00203 00204 set_curdir(child, entry, 0, hwnd); 00205 00206 return child; 00207 } 00208 00209 00210 /* free all memory associated with a child window */ 00211 00212 static void free_child_window(ChildWnd* child) 00213 { 00214 free_entries(&child->root.entry); 00215 heap_free(child); 00216 } 00217 00218 00219 /* adjust child windows to the new frame window size */ 00220 00221 static void resize_frame_rect(HWND hwnd, PRECT prect) 00222 { 00223 int new_top; 00224 RECT rt; 00225 00226 if (IsWindowVisible(Globals.htoolbar)) { 00227 SendMessage(Globals.htoolbar, WM_SIZE, 0, 0); 00228 GetClientRect(Globals.htoolbar, &rt); 00229 prect->top = rt.bottom+3; 00230 prect->bottom -= rt.bottom+3; 00231 } 00232 00233 if (IsWindowVisible(Globals.hdrivebar)) { 00234 SendMessage(Globals.hdrivebar, WM_SIZE, 0, 0); 00235 GetClientRect(Globals.hdrivebar, &rt); 00236 new_top = --prect->top + rt.bottom+3; 00237 MoveWindow(Globals.hdrivebar, 0, prect->top, rt.right, new_top, TRUE); 00238 prect->top = new_top; 00239 prect->bottom -= rt.bottom+2; 00240 } 00241 00242 if (IsWindowVisible(Globals.hstatusbar)) { 00243 int parts[] = {300, 500}; 00244 00245 SendMessage(Globals.hstatusbar, WM_SIZE, 0, 0); 00246 SendMessage(Globals.hstatusbar, SB_SETPARTS, 2, (LPARAM)&parts); 00247 GetClientRect(Globals.hstatusbar, &rt); 00248 prect->bottom -= rt.bottom; 00249 } 00250 00251 MoveWindow(Globals.hmdiclient, prect->left-1,prect->top-1,prect->right+2,prect->bottom+1, TRUE); 00252 } 00253 00254 00255 /* set the frame window size */ 00256 00257 static void resize_frame(HWND hwnd, int cx, int cy) 00258 { 00259 RECT rect; 00260 00261 rect.left = 0; 00262 rect.top = 0; 00263 rect.right = cx; 00264 rect.bottom = cy; 00265 00266 resize_frame_rect(hwnd, &rect); 00267 } 00268 00269 00270 /* update window layouts to the current frame window size */ 00271 00272 static void resize_frame_client(HWND hwnd) 00273 { 00274 RECT rect; 00275 00276 GetClientRect(hwnd, &rect); 00277 00278 resize_frame_rect(hwnd, &rect); 00279 } 00280 00281 00282 static HHOOK hcbthook; 00283 static ChildWnd* newchild = NULL; 00284 00285 /* window creation callback function used in create_child_window() */ 00286 static LRESULT CALLBACK CBTProc(int code, WPARAM wparam, LPARAM lparam) 00287 { 00288 if (code==HCBT_CREATEWND && newchild) { 00289 ChildWnd* child = newchild; 00290 newchild = NULL; 00291 00292 child->hwnd = (HWND) wparam; 00293 SetWindowLongPtr(child->hwnd, GWLP_USERDATA, (LPARAM)child); 00294 } 00295 00296 return CallNextHookEx(hcbthook, code, wparam, lparam); 00297 } 00298 00299 /* create a new MDI child window */ 00300 static HWND create_child_window(ChildWnd* child) 00301 { 00302 MDICREATESTRUCT mcs; 00303 int idx; 00304 00305 mcs.szClass = sWINEFILETREE; 00306 mcs.szTitle = (LPTSTR)child->path; 00307 mcs.hOwner = Globals.hInstance; 00308 mcs.x = child->pos.rcNormalPosition.left; 00309 mcs.y = child->pos.rcNormalPosition.top; 00310 mcs.cx = child->pos.rcNormalPosition.right-child->pos.rcNormalPosition.left; 00311 mcs.cy = child->pos.rcNormalPosition.bottom-child->pos.rcNormalPosition.top; 00312 mcs.style = 0; 00313 mcs.lParam = 0; 00314 00315 hcbthook = SetWindowsHookEx(WH_CBT, CBTProc, 0, GetCurrentThreadId()); 00316 00317 newchild = child; 00318 child->hwnd = (HWND) SendMessage(Globals.hmdiclient, WM_MDICREATE, 0, (LPARAM)&mcs); 00319 if (!child->hwnd) { 00320 UnhookWindowsHookEx(hcbthook); 00321 return 0; 00322 } 00323 00324 UnhookWindowsHookEx(hcbthook); 00325 00326 (void)ListBox_SetItemHeight(child->left.hwnd, 1, max(Globals.spaceSize.cy,IMAGE_HEIGHT+3)); 00327 (void)ListBox_SetItemHeight(child->right.hwnd, 1, max(Globals.spaceSize.cy,IMAGE_HEIGHT+3)); 00328 00329 idx = ListBox_FindItemData(child->left.hwnd, 0, child->left.cur); 00330 (void)ListBox_SetCurSel(child->left.hwnd, idx); 00331 00332 return child->hwnd; 00333 } 00334 00335 00336 #ifndef _NO_EXTENSIONS 00337 00338 /* calculate client space for the frame window */ 00339 static void frame_get_clientspace(HWND hwnd, PRECT prect) 00340 { 00341 RECT rt; 00342 00343 if (!IsIconic(hwnd)) 00344 GetClientRect(hwnd, prect); 00345 else { 00346 WINDOWPLACEMENT wp; 00347 00348 GetWindowPlacement(hwnd, &wp); 00349 00350 prect->left = prect->top = 0; 00351 prect->right = wp.rcNormalPosition.right-wp.rcNormalPosition.left- 00352 2*(GetSystemMetrics(SM_CXSIZEFRAME)+GetSystemMetrics(SM_CXEDGE)); 00353 prect->bottom = wp.rcNormalPosition.bottom-wp.rcNormalPosition.top- 00354 2*(GetSystemMetrics(SM_CYSIZEFRAME)+GetSystemMetrics(SM_CYEDGE))- 00355 GetSystemMetrics(SM_CYCAPTION)-GetSystemMetrics(SM_CYMENUSIZE); 00356 } 00357 00358 if (IsWindowVisible(Globals.htoolbar)) { 00359 GetClientRect(Globals.htoolbar, &rt); 00360 prect->top += rt.bottom+2; 00361 } 00362 00363 if (IsWindowVisible(Globals.hdrivebar)) { 00364 GetClientRect(Globals.hdrivebar, &rt); 00365 prect->top += rt.bottom+2; 00366 } 00367 00368 if (IsWindowVisible(Globals.hstatusbar)) { 00369 GetClientRect(Globals.hstatusbar, &rt); 00370 prect->bottom -= rt.bottom; 00371 } 00372 } 00373 00374 00375 /* full screen mode state */ 00376 static struct FullScreenParameters { 00377 BOOL mode; 00378 RECT orgPos; 00379 BOOL wasZoomed; 00380 } g_fullscreen = { 00381 FALSE, /* mode */ 00382 {0, 0, 0, 0}, 00383 FALSE 00384 }; 00385 00386 /* toggle full screen mode */ 00387 static BOOL toggle_fullscreen(HWND hwnd) 00388 { 00389 RECT rt; 00390 00391 if ((g_fullscreen.mode=!g_fullscreen.mode)) { 00392 GetWindowRect(hwnd, &g_fullscreen.orgPos); 00393 g_fullscreen.wasZoomed = IsZoomed(hwnd); 00394 00395 (void)Frame_CalcFrameClient(hwnd, &rt); 00396 ClientToScreen(hwnd, (LPPOINT)&rt.left); 00397 ClientToScreen(hwnd, (LPPOINT)&rt.right); 00398 00399 rt.left = g_fullscreen.orgPos.left-rt.left; 00400 rt.top = g_fullscreen.orgPos.top-rt.top; 00401 rt.right = GetSystemMetrics(SM_CXSCREEN)+g_fullscreen.orgPos.right-rt.right; 00402 rt.bottom = GetSystemMetrics(SM_CYSCREEN)+g_fullscreen.orgPos.bottom-rt.bottom; 00403 00404 MoveWindow(hwnd, rt.left, rt.top, rt.right-rt.left, rt.bottom-rt.top, TRUE); 00405 } else { 00406 MoveWindow(hwnd, g_fullscreen.orgPos.left, g_fullscreen.orgPos.top, 00407 g_fullscreen.orgPos.right-g_fullscreen.orgPos.left, 00408 g_fullscreen.orgPos.bottom-g_fullscreen.orgPos.top, TRUE); 00409 00410 if (g_fullscreen.wasZoomed) 00411 ShowWindow(hwnd, WS_MAXIMIZE); 00412 } 00413 00414 return g_fullscreen.mode; 00415 } 00416 00417 /* adjust window coordinates in full screen mode */ 00418 static void fullscreen_move(HWND hwnd) 00419 { 00420 RECT rt, pos; 00421 GetWindowRect(hwnd, &pos); 00422 00423 (void)Frame_CalcFrameClient(hwnd, &rt); 00424 ClientToScreen(hwnd, (LPPOINT)&rt.left); 00425 ClientToScreen(hwnd, (LPPOINT)&rt.right); 00426 00427 rt.left = pos.left-rt.left; 00428 rt.top = pos.top-rt.top; 00429 rt.right = GetSystemMetrics(SM_CXSCREEN)+pos.right-rt.right; 00430 rt.bottom = GetSystemMetrics(SM_CYSCREEN)+pos.bottom-rt.bottom; 00431 00432 MoveWindow(hwnd, rt.left, rt.top, rt.right-rt.left, rt.bottom-rt.top, TRUE); 00433 } 00434 00435 #endif 00436 00437 00438 /* toggle the visibility of a child window */ 00439 00440 static void toggle_child(HWND hwnd, UINT cmd, HWND hchild) 00441 { 00442 BOOL vis = IsWindowVisible(hchild); 00443 00444 CheckMenuItem(Globals.hMenuOptions, cmd, vis?MF_BYCOMMAND:MF_BYCOMMAND|MF_CHECKED); 00445 00446 ShowWindow(hchild, vis?SW_HIDE:SW_SHOW); 00447 00448 #ifndef _NO_EXTENSIONS 00449 if (g_fullscreen.mode) 00450 fullscreen_move(hwnd); 00451 #endif 00452 00453 resize_frame_client(hwnd); 00454 } 00455 00456 00457 /* activate a drive child window */ 00458 static BOOL activate_drive_window(LPCTSTR path) 00459 { 00460 TCHAR drv1[_MAX_DRIVE], drv2[_MAX_DRIVE]; 00461 HWND child_wnd; 00462 00463 _tsplitpath(path, drv1, 0, 0, 0); 00464 00465 /* search for a already open window for the same drive */ 00466 for(child_wnd=GetNextWindow(Globals.hmdiclient,GW_CHILD); child_wnd; child_wnd=GetNextWindow(child_wnd, GW_HWNDNEXT)) { 00467 ChildWnd* child = (ChildWnd*) GetWindowLongPtr(child_wnd, GWLP_USERDATA); 00468 00469 if (child) { 00470 _tsplitpath(child->root.path, drv2, 0, 0, 0); 00471 00472 if (!lstrcmpi(drv2, drv1)) { 00473 SendMessage(Globals.hmdiclient, WM_MDIACTIVATE, (WPARAM)child_wnd, 0); 00474 00475 if (IsMinimized(child_wnd)) 00476 ShowWindow(child_wnd, SW_SHOWNORMAL); 00477 00478 return TRUE; 00479 } 00480 } 00481 } 00482 00483 return FALSE; 00484 } 00485 00486 /* activate window containing a file system tree */ 00487 static BOOL activate_fs_window(LPCTSTR filesys) 00488 { 00489 HWND child_wnd; 00490 00491 /* search for a already open window of the given file system name */ 00492 for(child_wnd=GetNextWindow(Globals.hmdiclient,GW_CHILD); child_wnd; child_wnd=GetNextWindow(child_wnd, GW_HWNDNEXT)) { 00493 ChildWnd* child = (ChildWnd*) GetWindowLongPtr(child_wnd, GWLP_USERDATA); 00494 00495 if (child) { 00496 if (!lstrcmpi(child->root.fs, filesys)) { 00497 SendMessage(Globals.hmdiclient, WM_MDIACTIVATE, (WPARAM)child_wnd, 0); 00498 00499 if (IsMinimized(child_wnd)) 00500 ShowWindow(child_wnd, SW_SHOWNORMAL); 00501 00502 return TRUE; 00503 } 00504 } 00505 } 00506 00507 return FALSE; 00508 } 00509 00510 00511 /* frame window message handler */ 00512 00513 static LRESULT CALLBACK FrameWndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam) 00514 { 00515 TCHAR b1[BUFFER_LEN], b2[BUFFER_LEN]; 00516 00517 switch(nmsg) { 00518 case WM_CLOSE: 00519 if (Globals.saveSettings) 00520 save_registry_settings(); 00521 00522 DestroyWindow(hwnd); 00523 00524 /* clear handle variables */ 00525 Globals.hMenuFrame = 0; 00526 Globals.hMenuView = 0; 00527 Globals.hMenuOptions = 0; 00528 Globals.hMainWnd = 0; 00529 Globals.hmdiclient = 0; 00530 Globals.hdrivebar = 0; 00531 break; 00532 00533 case WM_DESTROY: 00534 PostQuitMessage(0); 00535 break; 00536 00537 case WM_INITMENUPOPUP: { 00538 HWND hwndClient = (HWND) SendMessage(Globals.hmdiclient, WM_MDIGETACTIVE, 0, 0); 00539 00540 if (!SendMessage(hwndClient, WM_INITMENUPOPUP, wparam, lparam)) 00541 return 0; 00542 break;} 00543 00544 case WM_COMMAND: { 00545 UINT cmd = LOWORD(wparam); 00546 HWND hwndClient = (HWND) SendMessage(Globals.hmdiclient, WM_MDIGETACTIVE, 0, 0); 00547 00548 if (SendMessage(hwndClient, WM_DISPATCH_COMMAND, wparam, lparam)) 00549 break; 00550 00551 if (cmd>=ID_DRIVE_FIRST && cmd<=ID_DRIVE_FIRST+0xFF) { 00552 TCHAR drv[_MAX_DRIVE], path[MAX_PATH]; 00553 ChildWnd* child; 00554 LPCTSTR root = Globals.drives; 00555 int i; 00556 00557 for(i=cmd-ID_DRIVE_FIRST; i--; root++) 00558 while(*root) 00559 root++; 00560 00561 if (activate_drive_window(root)) 00562 return 0; 00563 00564 _tsplitpath(root, drv, 0, 0, 0); 00565 00566 if (!SetCurrentDirectory(drv)) { 00567 display_error(hwnd, GetLastError()); 00568 return 0; 00569 } 00570 00571 GetCurrentDirectory(MAX_PATH, path); /*TODO: store last directory per drive */ 00572 child = alloc_child_window(path, NULL, hwnd); 00573 00574 if (!create_child_window(child)) 00575 heap_free(child); 00576 } else switch(cmd) { 00577 case ID_FILE_EXIT: 00578 SendMessage(hwnd, WM_CLOSE, 0, 0); 00579 break; 00580 00581 case ID_WINDOW_NEW: { 00582 TCHAR path[MAX_PATH]; 00583 ChildWnd* child; 00584 00585 GetCurrentDirectory(MAX_PATH, path); 00586 child = alloc_child_window(path, NULL, hwnd); 00587 00588 if (!create_child_window(child)) 00589 heap_free(child); 00590 break;} 00591 00592 case ID_REFRESH: 00593 refresh_drives(); 00594 break; 00595 00596 case ID_WINDOW_CASCADE: 00597 SendMessage(Globals.hmdiclient, WM_MDICASCADE, 0, 0); 00598 break; 00599 00600 case ID_WINDOW_TILE_HORZ: 00601 SendMessage(Globals.hmdiclient, WM_MDITILE, MDITILE_HORIZONTAL, 0); 00602 break; 00603 00604 case ID_WINDOW_TILE_VERT: 00605 SendMessage(Globals.hmdiclient, WM_MDITILE, MDITILE_VERTICAL, 0); 00606 break; 00607 00608 case ID_WINDOW_ARRANGE: 00609 SendMessage(Globals.hmdiclient, WM_MDIICONARRANGE, 0, 0); 00610 break; 00611 00612 case ID_SELECT_FONT: 00613 choose_font(hwnd); 00614 break; 00615 00616 case ID_VIEW_TOOL_BAR: 00617 toggle_child(hwnd, cmd, Globals.htoolbar); 00618 break; 00619 00620 case ID_VIEW_DRIVE_BAR: 00621 toggle_child(hwnd, cmd, Globals.hdrivebar); 00622 break; 00623 00624 case ID_VIEW_STATUSBAR: 00625 toggle_child(hwnd, cmd, Globals.hstatusbar); 00626 break; 00627 00628 case ID_VIEW_SAVESETTINGS: 00629 Globals.saveSettings = !Globals.saveSettings; 00630 CheckMenuItem(Globals.hMenuOptions, ID_VIEW_SAVESETTINGS, 00631 Globals.saveSettings ? MF_CHECKED : MF_UNCHECKED); 00632 break; 00633 00634 case ID_EXECUTE: { 00635 struct ExecuteDialog dlg; 00636 00637 memset(&dlg, 0, sizeof(struct ExecuteDialog)); 00638 00639 if (DialogBoxParam(Globals.hInstance, MAKEINTRESOURCE(IDD_EXECUTE), hwnd, ExecuteDialogDlgProc, (LPARAM)&dlg) == IDOK) { 00640 HINSTANCE hinst = ShellExecute(hwnd, NULL/*operation*/, dlg.cmd/*file*/, NULL/*parameters*/, NULL/*dir*/, dlg.cmdshow); 00641 00642 if (PtrToUlong(hinst) <= 32) 00643 display_error(hwnd, GetLastError()); 00644 } 00645 break;} 00646 00647 case ID_CONNECT_NETWORK_DRIVE: { 00648 DWORD ret = WNetConnectionDialog(hwnd, RESOURCETYPE_DISK); 00649 if (ret == NO_ERROR) 00650 refresh_drives(); 00651 else if (ret != (DWORD)-1) { 00652 if (ret == ERROR_EXTENDED_ERROR) 00653 display_network_error(hwnd); 00654 else 00655 display_error(hwnd, ret); 00656 } 00657 break;} 00658 00659 case ID_DISCONNECT_NETWORK_DRIVE: { 00660 DWORD ret = WNetDisconnectDialog(hwnd, RESOURCETYPE_DISK); 00661 if (ret == NO_ERROR) 00662 refresh_drives(); 00663 else if (ret != (DWORD)-1) { 00664 if (ret == ERROR_EXTENDED_ERROR) 00665 display_network_error(hwnd); 00666 else 00667 display_error(hwnd, ret); 00668 } 00669 break;} 00670 00671 case ID_FORMAT_DISK: { 00672 UINT sem_org = SetErrorMode(0); /* Get the current Error Mode settings. */ 00673 SetErrorMode(sem_org & ~SEM_FAILCRITICALERRORS); /* Force O/S to handle */ 00674 SHFormatDrive(hwnd, 0 /* A: */, SHFMT_ID_DEFAULT, 0); 00675 SetErrorMode(sem_org); /* Put it back the way it was. */ 00676 break;} 00677 00678 case ID_HELP: 00679 WinHelp(hwnd, RS(b1,IDS_WINEFILE), HELP_INDEX, 0); 00680 break; 00681 00682 #ifndef _NO_EXTENSIONS 00683 case ID_VIEW_FULLSCREEN: 00684 CheckMenuItem(Globals.hMenuOptions, cmd, toggle_fullscreen(hwnd)?MF_CHECKED:0); 00685 break; 00686 00687 #ifdef __WINE__ 00688 case ID_DRIVE_UNIX_FS: { 00689 TCHAR path[MAX_PATH]; 00690 #ifdef UNICODE 00691 char cpath[MAX_PATH]; 00692 #endif 00693 ChildWnd* child; 00694 00695 if (activate_fs_window(RS(b1,IDS_UNIXFS))) 00696 break; 00697 00698 00699 #ifdef UNICODE 00700 getcwd(cpath, MAX_PATH); 00701 MultiByteToWideChar(CP_UNIXCP, 0, cpath, -1, path, MAX_PATH); 00702 #else 00703 getcwd(path, MAX_PATH); 00704 #endif 00705 child = alloc_child_window(path, NULL, hwnd); 00706 00707 if (!create_child_window(child)) 00708 heap_free(child); 00709 break;} 00710 #endif 00711 00712 #ifdef _SHELL_FOLDERS 00713 case ID_DRIVE_SHELL_NS: { 00714 TCHAR path[MAX_PATH]; 00715 ChildWnd* child; 00716 00717 if (activate_fs_window(RS(b1,IDS_SHELL))) 00718 break; 00719 00720 GetCurrentDirectory(MAX_PATH, path); 00721 child = alloc_child_window(path, get_path_pidl(path,hwnd), hwnd); 00722 00723 if (!create_child_window(child)) 00724 heap_free(child); 00725 break;} 00726 #endif 00727 #endif 00728 00729 /*TODO: There are even more menu items! */ 00730 00731 case ID_ABOUT: 00732 ShellAbout(hwnd, RS(b1,IDS_WINEFILE), NULL, 00733 LoadImage(Globals.hInstance, MAKEINTRESOURCE(IDI_WINEFILE), 00734 IMAGE_ICON, 48, 48, LR_SHARED)); 00735 break; 00736 00737 default: 00738 /*TODO: if (wParam >= PM_FIRST_LANGUAGE && wParam <= PM_LAST_LANGUAGE) 00739 STRING_SelectLanguageByNumber(wParam - PM_FIRST_LANGUAGE); 00740 else */if ((cmd<IDW_FIRST_CHILD || cmd>=IDW_FIRST_CHILD+0x100) && 00741 (cmd<SC_SIZE || cmd>SC_RESTORE)) 00742 MessageBox(hwnd, RS(b2,IDS_NO_IMPL), RS(b1,IDS_WINEFILE), MB_OK); 00743 00744 return DefFrameProc(hwnd, Globals.hmdiclient, nmsg, wparam, lparam); 00745 } 00746 break;} 00747 00748 case WM_SIZE: 00749 resize_frame(hwnd, LOWORD(lparam), HIWORD(lparam)); 00750 break; /* do not pass message to DefFrameProc */ 00751 00752 case WM_DEVICECHANGE: 00753 SendMessage(hwnd, WM_COMMAND, MAKELONG(ID_REFRESH,0), 0); 00754 break; 00755 00756 #ifndef _NO_EXTENSIONS 00757 case WM_GETMINMAXINFO: { 00758 LPMINMAXINFO lpmmi = (LPMINMAXINFO)lparam; 00759 00760 lpmmi->ptMaxTrackSize.x <<= 1;/*2*GetSystemMetrics(SM_CXSCREEN) / SM_CXVIRTUALSCREEN */ 00761 lpmmi->ptMaxTrackSize.y <<= 1;/*2*GetSystemMetrics(SM_CYSCREEN) / SM_CYVIRTUALSCREEN */ 00762 break;} 00763 00764 case FRM_CALC_CLIENT: 00765 frame_get_clientspace(hwnd, (PRECT)lparam); 00766 return TRUE; 00767 #endif /* _NO_EXTENSIONS */ 00768 00769 default: 00770 return DefFrameProc(hwnd, Globals.hmdiclient, nmsg, wparam, lparam); 00771 } 00772 00773 return 0; 00774 } 00775 00776 00777 /* array of item attribute names, filled from ressource strings */ 00778 static TCHAR g_pos_names[COLUMNS][20] = { 00779 {'\0'} /* symbol */ 00780 }; 00781 00782 /* array of item attribute flags */ 00783 static const int g_pos_align[] = { 00784 0, 00785 HDF_LEFT, /* Name */ 00786 HDF_RIGHT, /* Size */ 00787 HDF_LEFT, /* CDate */ 00788 #ifndef _NO_EXTENSIONS 00789 HDF_LEFT, /* ADate */ 00790 HDF_LEFT, /* MDate */ 00791 HDF_LEFT, /* Index */ 00792 HDF_CENTER, /* Links */ 00793 #endif 00794 HDF_CENTER, /* Attributes */ 00795 #ifndef _NO_EXTENSIONS 00796 HDF_LEFT /* Security */ 00797 #endif 00798 }; 00799 00800 /* resize child window descendants */ 00801 static void resize_tree(ChildWnd* child, int cx, int cy) 00802 { 00803 HDWP hdwp = BeginDeferWindowPos(4); 00804 RECT rt; 00805 00806 rt.left = 0; 00807 rt.top = 0; 00808 rt.right = cx; 00809 rt.bottom = cy; 00810 00811 cx = child->split_pos + SPLIT_WIDTH/2; 00812 00813 #ifndef _NO_EXTENSIONS 00814 { 00815 WINDOWPOS wp; 00816 HD_LAYOUT hdl; 00817 00818 hdl.prc = &rt; 00819 hdl.pwpos = ℘ 00820 00821 (void)Header_Layout(child->left.hwndHeader, &hdl); 00822 00823 DeferWindowPos(hdwp, child->left.hwndHeader, wp.hwndInsertAfter, 00824 wp.x-1, wp.y, child->split_pos-SPLIT_WIDTH/2+1, wp.cy, wp.flags); 00825 DeferWindowPos(hdwp, child->right.hwndHeader, wp.hwndInsertAfter, 00826 rt.left+cx+1, wp.y, wp.cx-cx+2, wp.cy, wp.flags); 00827 } 00828 #endif /* _NO_EXTENSIONS */ 00829 00830 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); 00831 DeferWindowPos(hdwp, child->right.hwnd, 0, rt.left+cx+1, rt.top, rt.right-cx, rt.bottom-rt.top, SWP_NOZORDER|SWP_NOACTIVATE); 00832 00833 EndDeferWindowPos(hdwp); 00834 } 00835 00836 00837 #ifndef _NO_EXTENSIONS 00838 00839 /* create the header control for the given pane */ 00840 static HWND create_header(HWND parent, Pane* pane, UINT id) 00841 { 00842 HD_ITEM hdi; 00843 int idx; 00844 00845 HWND hwnd = CreateWindow(WC_HEADER, 0, WS_CHILD|WS_VISIBLE|HDS_HORZ|HDS_FULLDRAG/*TODO: |HDS_BUTTONS + sort orders*/, 00846 0, 0, 0, 0, parent, (HMENU)ULongToHandle(id), Globals.hInstance, 0); 00847 if (!hwnd) 00848 return 0; 00849 00850 SetWindowFont(hwnd, GetStockObject(DEFAULT_GUI_FONT), FALSE); 00851 00852 hdi.mask = HDI_TEXT|HDI_WIDTH|HDI_FORMAT; 00853 00854 for(idx=0; idx<COLUMNS; idx++) { 00855 hdi.pszText = g_pos_names[idx]; 00856 hdi.fmt = HDF_STRING | g_pos_align[idx]; 00857 hdi.cxy = pane->widths[idx]; 00858 (void)Header_InsertItem(hwnd, idx, &hdi); 00859 } 00860 00861 return hwnd; 00862 } 00863 00864 #endif /* _NO_EXTENSIONS */ 00865 00866 00867 /* initialise global variables for text output */ 00868 00869 static void init_output(HWND hwnd) 00870 { 00871 static const TCHAR s1000[] = {'1','0','0','0','\0'}; 00872 00873 TCHAR b[16]; 00874 HFONT old_font; 00875 HDC hdc = GetDC(hwnd); 00876 00877 if (GetNumberFormat(LOCALE_USER_DEFAULT, 0, s1000, 0, b, 16) > 4) 00878 Globals.num_sep = b[1]; 00879 else 00880 Globals.num_sep = '.'; 00881 00882 old_font = SelectFont(hdc, Globals.hfont); 00883 GetTextExtentPoint32(hdc, sSpace, 1, &Globals.spaceSize); 00884 (void)SelectFont(hdc, old_font); 00885 ReleaseDC(hwnd, hdc); 00886 } 00887 00888 static void draw_item(Pane* pane, LPDRAWITEMSTRUCT dis, Entry* entry, int calcWidthCol); 00889 00890 00891 /* calculate preferred width for all visible columns */ 00892 00893 static BOOL calc_widths(Pane* pane, BOOL anyway) 00894 { 00895 int col, x, cx, spc=3*Globals.spaceSize.cx; 00896 int entries = ListBox_GetCount(pane->hwnd); 00897 int orgWidths[COLUMNS]; 00898 int orgPositions[COLUMNS+1]; 00899 HFONT hfontOld; 00900 HDC hdc; 00901 int cnt; 00902 00903 if (!anyway) { 00904 memcpy(orgWidths, pane->widths, sizeof(orgWidths)); 00905 memcpy(orgPositions, pane->positions, sizeof(orgPositions)); 00906 } 00907 00908 for(col=0; col<COLUMNS; col++) 00909 pane->widths[col] = 0; 00910 00911 hdc = GetDC(pane->hwnd); 00912 hfontOld = SelectFont(hdc, Globals.hfont); 00913 00914 for(cnt=0; cnt<entries; cnt++) { 00915 Entry* entry = (Entry*) ListBox_GetItemData(pane->hwnd, cnt); 00916 00917 DRAWITEMSTRUCT dis; 00918 00919 dis.CtlType = 0; 00920 dis.CtlID = 0; 00921 dis.itemID = 0; 00922 dis.itemAction = 0; 00923 dis.itemState = 0; 00924 dis.hwndItem = pane->hwnd; 00925 dis.hDC = hdc; 00926 dis.rcItem.left = 0; 00927 dis.rcItem.top = 0; 00928 dis.rcItem.right = 0; 00929 dis.rcItem.bottom = 0; 00930 /*dis.itemData = 0; */ 00931 00932 draw_item(pane, &dis, entry, COLUMNS); 00933 } 00934 00935 SelectObject(hdc, hfontOld); 00936 ReleaseDC(pane->hwnd, hdc); 00937 00938 x = 0; 00939 for(col=0; col<COLUMNS; col++) { 00940 pane->positions[col] = x; 00941 cx = pane->widths[col]; 00942 00943 if (cx) { 00944 cx += spc; 00945 00946 if (cx < IMAGE_WIDTH) 00947 cx = IMAGE_WIDTH; 00948 00949 pane->widths[col] = cx; 00950 } 00951 00952 x += cx; 00953 } 00954 00955 pane->positions[COLUMNS] = x; 00956 00957 ListBox_SetHorizontalExtent(pane->hwnd, x); 00958 00959 /* no change? */ 00960 if (!memcmp(orgWidths, pane->widths, sizeof(orgWidths))) 00961 return FALSE; 00962 00963 /* don't move, if only collapsing an entry */ 00964 if (!anyway && pane->widths[0]<orgWidths[0] && 00965 !memcmp(orgWidths+1, pane->widths+1, sizeof(orgWidths)-sizeof(int))) { 00966 pane->widths[0] = orgWidths[0]; 00967 memcpy(pane->positions, orgPositions, sizeof(orgPositions)); 00968 00969 return FALSE; 00970 } 00971 00972 InvalidateRect(pane->hwnd, 0, TRUE); 00973 00974 return TRUE; 00975 } 00976 00977 00978 /* calculate one preferred column width */ 00979 00980 static void calc_single_width(Pane* pane, int col) 00981 { 00982 HFONT hfontOld; 00983 int x, cx; 00984 int entries = ListBox_GetCount(pane->hwnd); 00985 int cnt; 00986 HDC hdc; 00987 00988 pane->widths[col] = 0; 00989 00990 hdc = GetDC(pane->hwnd); 00991 hfontOld = SelectFont(hdc, Globals.hfont); 00992 00993 for(cnt=0; cnt<entries; cnt++) { 00994 Entry* entry = (Entry*) ListBox_GetItemData(pane->hwnd, cnt); 00995 DRAWITEMSTRUCT dis; 00996 00997 dis.CtlType = 0; 00998 dis.CtlID = 0; 00999 dis.itemID = 0; 01000 dis.itemAction = 0; 01001 dis.itemState = 0; 01002 dis.hwndItem = pane->hwnd; 01003 dis.hDC = hdc; 01004 dis.rcItem.left = 0; 01005 dis.rcItem.top = 0; 01006 dis.rcItem.right = 0; 01007 dis.rcItem.bottom = 0; 01008 /*dis.itemData = 0; */ 01009 01010 draw_item(pane, &dis, entry, col); 01011 } 01012 01013 SelectObject(hdc, hfontOld); 01014 ReleaseDC(pane->hwnd, hdc); 01015 01016 cx = pane->widths[col]; 01017 01018 if (cx) { 01019 cx += 3*Globals.spaceSize.cx; 01020 01021 if (cx < IMAGE_WIDTH) 01022 cx = IMAGE_WIDTH; 01023 } 01024 01025 pane->widths[col] = cx; 01026 01027 x = pane->positions[col] + cx; 01028 01029 for(; col<COLUMNS; ) { 01030 pane->positions[++col] = x; 01031 x += pane->widths[col]; 01032 } 01033 01034 ListBox_SetHorizontalExtent(pane->hwnd, x); 01035 } 01036 01037 01038 /* check for file name matches, taking case into account */ 01039 01040 static BOOL pattern_match(LPCTSTR str, LPCTSTR pattern) 01041 { 01042 for( ; *str&&*pattern; str++,pattern++) { 01043 if (*pattern == '*') { 01044 do pattern++; 01045 while(*pattern == '*'); 01046 01047 if (!*pattern) 01048 return TRUE; 01049 01050 for(; *str; str++) 01051 if (*str==*pattern && pattern_match(str, pattern)) 01052 return TRUE; 01053 01054 return FALSE; 01055 } 01056 else if (*str!=*pattern && *pattern!='?') 01057 return FALSE; 01058 } 01059 01060 if (*str || *pattern) 01061 if (*pattern!='*' || pattern[1]!='\0') 01062 return FALSE; 01063 01064 return TRUE; 01065 } 01066 01067 01068 /* case independent file name matching algorithm */ 01069 01070 static BOOL pattern_imatch(LPCTSTR str, LPCTSTR pattern) 01071 { 01072 TCHAR b1[BUFFER_LEN], b2[BUFFER_LEN]; 01073 01074 lstrcpy(b1, str); 01075 lstrcpy(b2, pattern); 01076 CharUpper(b1); 01077 CharUpper(b2); 01078 01079 return pattern_match(b1, b2); 01080 } 01081 01082 01083 /* file type constants */ 01084 enum FILE_TYPE { 01085 FT_OTHER = 0, 01086 FT_EXECUTABLE = 1, 01087 FT_DOCUMENT = 2 01088 }; 01089 01090 static enum FILE_TYPE get_file_type(LPCTSTR filename); 01091 01092 01093 /* insert listbox entries after index idx */ 01094 01095 static int insert_entries(Pane* pane, Entry* dir, LPCTSTR pattern, int filter_flags, int idx) 01096 { 01097 Entry* entry = dir; 01098 01099 if (!entry) 01100 return idx; 01101 01102 ShowWindow(pane->hwnd, SW_HIDE); 01103 01104 for(; entry; entry=entry->next) { 01105 #ifndef _LEFT_FILES 01106 if (pane->treePane && !(entry->data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)) 01107 continue; 01108 #endif 01109 01110 if (entry->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { 01111 /* don't display entries "." and ".." in the left pane */ 01112 if (pane->treePane && entry->data.cFileName[0]=='.') 01113 if ( 01114 #ifndef _NO_EXTENSIONS 01115 entry->data.cFileName[1]=='\0' || 01116 #endif 01117 (entry->data.cFileName[1]=='.' && entry->data.cFileName[2]=='\0')) 01118 continue; 01119 01120 /* filter directories in right pane */ 01121 if (!pane->treePane && !(filter_flags&TF_DIRECTORIES)) 01122 continue; 01123 } 01124 01125 /* filter using the file name pattern */ 01126 if (pattern) 01127 if (!pattern_imatch(entry->data.cFileName, pattern)) 01128 continue; 01129 01130 /* filter system and hidden files */ 01131 if (!(filter_flags&TF_HIDDEN) && (entry->data.dwFileAttributes&(FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM))) 01132 continue; 01133 01134 /* filter looking at the file type */ 01135 if ((filter_flags&(TF_PROGRAMS|TF_DOCUMENTS|TF_OTHERS)) != (TF_PROGRAMS|TF_DOCUMENTS|TF_OTHERS)) 01136 switch(get_file_type(entry->data.cFileName)) { 01137 case FT_EXECUTABLE: 01138 if (!(filter_flags & TF_PROGRAMS)) 01139 continue; 01140 break; 01141 01142 case FT_DOCUMENT: 01143 if (!(filter_flags & TF_DOCUMENTS)) 01144 continue; 01145 break; 01146 01147 default: /* TF_OTHERS */ 01148 if (!(filter_flags & TF_OTHERS)) 01149 continue; 01150 } 01151 01152 if (idx != -1) 01153 idx++; 01154 01155 (void)ListBox_InsertItemData(pane->hwnd, idx, entry); 01156 01157 if (pane->treePane && entry->expanded) 01158 idx = insert_entries(pane, entry->down, pattern, filter_flags, idx); 01159 } 01160 01161 ShowWindow(pane->hwnd, SW_SHOW); 01162 01163 return idx; 01164 } 01165 01166 01167 /* print a file size as textual representation into the given character buffer */ 01168 static void format_bytes(LPTSTR buffer, LONGLONG bytes) 01169 { 01170 static const TCHAR sFmtGB[] = {'%', '.', '1', 'f', ' ', 'G', 'B', '\0'}; 01171 static const TCHAR sFmtMB[] = {'%', '.', '1', 'f', ' ', 'M', 'B', '\0'}; 01172 static const TCHAR sFmtkB[] = {'%', '.', '1', 'f', ' ', 'k', 'B', '\0'}; 01173 01174 float fBytes = (float)bytes; 01175 01176 if (bytes >= 1073741824) /* 1 GB */ 01177 _stprintf(buffer, sFmtGB, fBytes/1073741824.f+.5f); 01178 else if (bytes >= 1048576) /* 1 MB */ 01179 _stprintf(buffer, sFmtMB, fBytes/1048576.f+.5f); 01180 else if (bytes >= 1024) /* 1 kB */ 01181 _stprintf(buffer, sFmtkB, fBytes/1024.f+.5f); 01182 else 01183 _stprintf(buffer, sLongNumFmt, bytes); 01184 } 01185 01186 /* display free space of the current drive in the status bar */ 01187 static void set_space_status(void) 01188 { 01189 ULARGE_INTEGER ulFreeBytesToCaller, ulTotalBytes, ulFreeBytes; 01190 TCHAR fmt[64], b1[64], b2[64], buffer[BUFFER_LEN]; 01191 01192 if (GetDiskFreeSpaceEx(NULL, &ulFreeBytesToCaller, &ulTotalBytes, &ulFreeBytes)) { 01193 format_bytes(b1, ulFreeBytesToCaller.QuadPart); 01194 format_bytes(b2, ulTotalBytes.QuadPart); 01195 wsprintf(buffer, RS(fmt,IDS_FREE_SPACE_FMT), b1, b2); 01196 } else 01197 lstrcpy(buffer, sQMarks); 01198 01199 SendMessage(Globals.hstatusbar, SB_SETTEXT, 0, (LPARAM)buffer); 01200 } 01201 01202 01203 #ifndef _NO_EXTENSIONS 01204 01205 /* initialise the header control for a Winefile pane */ 01206 static void set_header(Pane* pane) 01207 { 01208 HD_ITEM item; 01209 int scroll_pos = GetScrollPos(pane->hwnd, SB_HORZ); 01210 int i=0, x=0; 01211 01212 item.mask = HDI_WIDTH; 01213 item.cxy = 0; 01214 01215 for(; x+pane->widths[i]<scroll_pos && i<COLUMNS; i++) { 01216 x += pane->widths[i]; 01217 (void)Header_SetItem(pane->hwndHeader, i, &item); 01218 } 01219 01220 if (i < COLUMNS) { 01221 x += pane->widths[i]; 01222 item.cxy = x - scroll_pos; 01223 (void)Header_SetItem(pane->hwndHeader, i++, &item); 01224 01225 for(; i<COLUMNS; i++) { 01226 item.cxy = pane->widths[i]; 01227 x += pane->widths[i]; 01228 (void)Header_SetItem(pane->hwndHeader, i, &item); 01229 } 01230 } 01231 } 01232 01233 /* handle WM_NOTIFY messages for Winefile panes */ 01234 static LRESULT pane_notify(Pane* pane, NMHDR* pnmh) 01235 { 01236 switch(pnmh->code) { 01237 case HDN_ITEMCHANGED: { 01238 HD_NOTIFY* phdn = (HD_NOTIFY*) pnmh; 01239 int idx = phdn->iItem; 01240 int dx = phdn->pitem->cxy - pane->widths[idx]; 01241 int i; 01242 01243 RECT clnt; 01244 GetClientRect(pane->hwnd, &clnt); 01245 01246 pane->widths[idx] += dx; 01247 01248 for(i=idx; ++i<=COLUMNS; ) 01249 pane->positions[i] += dx; 01250 01251 { 01252 int scroll_pos = GetScrollPos(pane->hwnd, SB_HORZ); 01253 RECT rt_scr; 01254 RECT rt_clip; 01255 01256 rt_scr.left = pane->positions[idx+1]-scroll_pos; 01257 rt_scr.top = 0; 01258 rt_scr.right = clnt.right; 01259 rt_scr.bottom = clnt.bottom; 01260 01261 rt_clip.left = pane->positions[idx]-scroll_pos; 01262 rt_clip.top = 0; 01263 rt_clip.right = clnt.right; 01264 rt_clip.bottom = clnt.bottom; 01265 01266 if (rt_scr.left < 0) rt_scr.left = 0; 01267 if (rt_clip.left < 0) rt_clip.left = 0; 01268 01269 ScrollWindowEx(pane->hwnd, dx, 0, &rt_scr, &rt_clip, 0, 0, SW_INVALIDATE); 01270 01271 rt_clip.right = pane->positions[idx+1]; 01272 RedrawWindow(pane->hwnd, &rt_clip, 0, RDW_INVALIDATE|RDW_UPDATENOW); 01273 01274 if (pnmh->code == HDN_ENDTRACK) { 01275 ListBox_SetHorizontalExtent(pane->hwnd, pane->positions[COLUMNS]); 01276 01277 if (GetScrollPos(pane->hwnd, SB_HORZ) != scroll_pos) 01278 set_header(pane); 01279 } 01280 } 01281 01282 return FALSE; 01283 } 01284 01285 case HDN_DIVIDERDBLCLICK: { 01286 HD_NOTIFY* phdn = (HD_NOTIFY*) pnmh; 01287 HD_ITEM item; 01288 01289 calc_single_width(pane, phdn->iItem); 01290 item.mask = HDI_WIDTH; 01291 item.cxy = pane->widths[phdn->iItem]; 01292 01293 (void)Header_SetItem(pane->hwndHeader, phdn->iItem, &item); 01294 InvalidateRect(pane->hwnd, 0, TRUE); 01295 break;} 01296 } 01297 01298 return 0; 01299 } 01300 01301 #endif /* _NO_EXTENSIONS */ 01302 01303 01304 /* original tree window message handler */ 01305 static WNDPROC g_orgTreeWndProc; 01306 01307 /* tree window message handler */ 01308 static LRESULT CALLBACK TreeWndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam) 01309 { 01310 ChildWnd* child = (ChildWnd*) GetWindowLongPtr(GetParent(hwnd), GWLP_USERDATA); 01311 Pane* pane = (Pane*) GetWindowLongPtr(hwnd, GWLP_USERDATA); 01312 ASSERT(child); 01313 01314 switch(nmsg) { 01315 #ifndef _NO_EXTENSIONS 01316 case WM_HSCROLL: 01317 set_header(pane); 01318 break; 01319 #endif 01320 01321 case WM_SETFOCUS: 01322 child->focus_pane = pane==&child->right? 1: 0; 01323 (void)ListBox_SetSel(hwnd, TRUE, 1); 01324 /*TODO: check menu items */ 01325 break; 01326 01327 case WM_KEYDOWN: 01328 if (wparam == VK_TAB) { 01329 /*TODO: SetFocus(Globals.hdrivebar) */ 01330 SetFocus(child->focus_pane? child->left.hwnd: child->right.hwnd); 01331 } 01332 } 01333 01334 return CallWindowProc(g_orgTreeWndProc, hwnd, nmsg, wparam, lparam); 01335 } 01336 01337 01338 /* create a new tree window to be used as Winefile pane */ 01339 01340 static void create_tree_window(HWND parent, Pane* pane, UINT id, UINT id_header, LPCTSTR pattern, int filter_flags) 01341 { 01342 static const TCHAR sListBox[] = {'L','i','s','t','B','o','x','\0'}; 01343 01344 static int s_init = 0; 01345 Entry* entry = pane->root; 01346 01347 pane->hwnd = CreateWindow(sListBox, sEmpty, WS_CHILD|WS_VISIBLE|WS_HSCROLL|WS_VSCROLL| 01348 LBS_DISABLENOSCROLL|LBS_NOINTEGRALHEIGHT|LBS_OWNERDRAWFIXED|LBS_NOTIFY, 01349 0, 0, 0, 0, parent, (HMENU)ULongToHandle(id), Globals.hInstance, 0); 01350 01351 SetWindowLongPtr(pane->hwnd, GWLP_USERDATA, (LPARAM)pane); 01352 g_orgTreeWndProc = SubclassWindow(pane->hwnd, TreeWndProc); 01353 01354 SetWindowFont(pane->hwnd, Globals.hfont, FALSE); 01355 01356 /* insert entries into listbox */ 01357 if (entry) 01358 insert_entries(pane, entry, pattern, filter_flags, -1); 01359 01360 /* calculate column widths */ 01361 if (!s_init) { 01362 s_init = 1; 01363 init_output(pane->hwnd); 01364 } 01365 01366 calc_widths(pane, TRUE); 01367 01368 #ifndef _NO_EXTENSIONS 01369 pane->hwndHeader = create_header(parent, pane, id_header); 01370 #endif 01371 } 01372 01373 01374 /* initialise child window data */ 01375 01376 static void InitChildWindow(ChildWnd* child) 01377 { 01378 create_tree_window(child->hwnd, &child->left, IDW_TREE_LEFT, IDW_HEADER_LEFT, NULL, TF_ALL); 01379 create_tree_window(child->hwnd, &child->right, IDW_TREE_RIGHT, IDW_HEADER_RIGHT, child->filter_pattern, child->filter_flags); 01380 } 01381 01382 01383 /* print a FILETIME as textual representation */ 01384 01385 void format_date(const FILETIME* ft, TCHAR* buffer, int visible_cols) 01386 { 01387 SYSTEMTIME systime; 01388 FILETIME lft; 01389 int len = 0; 01390 01391 *buffer = '\0'; 01392 01393 if (!ft->dwLowDateTime && !ft->dwHighDateTime) 01394 return; 01395 01396 if (!FileTimeToLocalFileTime(ft, &lft)) 01397 {err: lstrcpy(buffer,sQMarks); return;} 01398 01399 if (!FileTimeToSystemTime(&lft, &systime)) 01400 goto err; 01401 01402 if (visible_cols & COL_DATE) { 01403 len = GetDateFormat(LOCALE_USER_DEFAULT, 0, &systime, 0, buffer, BUFFER_LEN); 01404 if (!len) 01405 goto err; 01406 } 01407 01408 if (visible_cols & COL_TIME) { 01409 if (len) 01410 buffer[len-1] = ' '; 01411 01412 buffer[len++] = ' '; 01413 01414 if (!GetTimeFormat(LOCALE_USER_DEFAULT, 0, &systime, 0, buffer+len, BUFFER_LEN-len)) 01415 buffer[len] = '\0'; 01416 } 01417 } 01418 01419 01420 /* accumulate the maximum pane width for the given text */ 01421 static void calc_width(Pane* pane, LPDRAWITEMSTRUCT dis, int col, LPCTSTR str) 01422 { 01423 RECT rt = {0, 0, 0, 0}; 01424 01425 DrawText(dis->hDC, (LPTSTR)str, -1, &rt, DT_CALCRECT|DT_SINGLELINE|DT_NOPREFIX); 01426 01427 if (rt.right > pane->widths[col]) 01428 pane->widths[col] = rt.right; 01429 } 01430 01431 /* accumulate the maximum oane width for the given text, taking tabs into account */ 01432 static void calc_tabbed_width(Pane* pane, LPDRAWITEMSTRUCT dis, int col, LPCTSTR str) 01433 { 01434 RECT rt = {0, 0, 0, 0}; 01435 01436 /* DRAWTEXTPARAMS dtp = {sizeof(DRAWTEXTPARAMS), 2}; 01437 DrawTextEx(dis->hDC, (LPTSTR)str, -1, &rt, DT_CALCRECT|DT_SINGLELINE|DT_NOPREFIX|DT_EXPANDTABS|DT_TABSTOP, &dtp);*/ 01438 01439 DrawText(dis->hDC, (LPTSTR)str, -1, &rt, DT_CALCRECT|DT_SINGLELINE|DT_EXPANDTABS|DT_TABSTOP|(2<<8)); 01440 /*FIXME rt (0,0) ??? */ 01441 01442 if (rt.right > pane->widths[col]) 01443 pane->widths[col] = rt.right; 01444 } 01445 01446 01447 /* display text in a Winefile pane */ 01448 static void output_text(Pane* pane, LPDRAWITEMSTRUCT dis, int col, LPCTSTR str, DWORD flags) 01449 { 01450 int x = dis->rcItem.left; 01451 RECT rt; 01452 01453 rt.left = x+pane->positions[col]+Globals.spaceSize.cx; 01454 rt.top = dis->rcItem.top; 01455 rt.right = x+pane->positions[col+1]-Globals.spaceSize.cx; 01456 rt.bottom = dis->rcItem.bottom; 01457 01458 DrawText(dis->hDC, (LPTSTR)str, -1, &rt, DT_SINGLELINE|DT_NOPREFIX|flags); 01459 } 01460 01461 /* display text in a Winefile pane, formated by tabulator characters */ 01462 static void output_tabbed_text(Pane* pane, LPDRAWITEMSTRUCT dis, int col, LPCTSTR str) 01463 { 01464 int x = dis->rcItem.left; 01465 RECT rt; 01466 01467 rt.left = x+pane->positions[col]+Globals.spaceSize.cx; 01468 rt.top = dis->rcItem.top; 01469 rt.right = x+pane->positions[col+1]-Globals.spaceSize.cx; 01470 rt.bottom = dis->rcItem.bottom; 01471 01472 /* DRAWTEXTPARAMS dtp = {sizeof(DRAWTEXTPARAMS), 2}; 01473 DrawTextEx(dis->hDC, (LPTSTR)str, -1, &rt, DT_SINGLELINE|DT_NOPREFIX|DT_EXPANDTABS|DT_TABSTOP, &dtp);*/ 01474 01475 DrawText(dis->hDC, (LPTSTR)str, -1, &rt, DT_SINGLELINE|DT_EXPANDTABS|DT_TABSTOP|(2<<8)); 01476 } 01477 01478 /* display numbers in a Winefile pane */ 01479 static void output_number(Pane* pane, LPDRAWITEMSTRUCT dis, int col, LPCTSTR str) 01480 { 01481 int x = dis->rcItem.left; 01482 RECT rt; 01483 LPCTSTR s = str; 01484 TCHAR b[128]; 01485 LPTSTR d = b; 01486 int pos; 01487 01488 rt.left = x+pane->positions[col]+Globals.spaceSize.cx; 01489 rt.top = dis->rcItem.top; 01490 rt.right = x+pane->positions[col+1]-Globals.spaceSize.cx; 01491 rt.bottom = dis->rcItem.bottom; 01492 01493 if (*s) 01494 *d++ = *s++; 01495 01496 /* insert number separator characters */ 01497 pos = lstrlen(s) % 3; 01498 01499 while(*s) 01500 if (pos--) 01501 *d++ = *s++; 01502 else { 01503 *d++ = Globals.num_sep; 01504 pos = 3; 01505 } 01506 01507 DrawText(dis->hDC, b, d-b, &rt, DT_RIGHT|DT_SINGLELINE|DT_NOPREFIX|DT_END_ELLIPSIS); 01508 } 01509 01510 01511 /* check for executable filename extensions */ 01512 static BOOL is_exe_file(LPCTSTR ext) 01513 { 01514 static const TCHAR executable_extensions[][4] = { 01515 {'C','O','M','\0'}, 01516 {'E','X','E','\0'}, 01517 {'B','A','T','\0'}, 01518 {'C','M','D','\0'}, 01519 #ifndef _NO_EXTENSIONS 01520 {'C','M','M','\0'}, 01521 {'B','T','M','\0'}, 01522 {'A','W','K','\0'}, 01523 #endif /* _NO_EXTENSIONS */ 01524 {'\0'} 01525 }; 01526 01527 TCHAR ext_buffer[_MAX_EXT]; 01528 const TCHAR (*p)[4]; 01529 LPCTSTR s; 01530 LPTSTR d; 01531 01532 for(s=ext+1,d=ext_buffer; (*d=tolower(*s)); s++) 01533 d++; 01534 01535 for(p=executable_extensions; (*p)[0]; p++) 01536 if (!lstrcmpi(ext_buffer, *p)) 01537 return TRUE; 01538 01539 return FALSE; 01540 } 01541 01542 /* check is the given file name extension is present in the Registry */ 01543 static BOOL is_registered_type(LPCTSTR ext) 01544 { 01545 /* check if there exists a classname for this file extension in the registry */ 01546 if (!RegQueryValue(HKEY_CLASSES_ROOT, ext, NULL, NULL)) 01547 return TRUE; 01548 01549 return FALSE; 01550 } 01551 01552 /* determine file type from filename */ 01553 static enum FILE_TYPE get_file_type(LPCTSTR filename) 01554 { 01555 LPCTSTR ext = _tcsrchr(filename, '.'); 01556 if (!ext) 01557 ext = sEmpty; 01558 01559 if (is_exe_file(ext)) 01560 return FT_EXECUTABLE; 01561 else if (is_registered_type(ext)) 01562 return FT_DOCUMENT; 01563 else 01564 return FT_OTHER; 01565 } 01566 01567 01568 /* display a entry in a Winefile pane */ 01569 01570 //@@ TODO refactor into smaller functions 01571 static void draw_item(Pane* pane, LPDRAWITEMSTRUCT dis, Entry* entry, int calcWidthCol) 01572 { 01573 TCHAR buffer[BUFFER_LEN]; 01574 DWORD attrs; 01575 int visible_cols = pane->visible_cols; 01576 COLORREF bkcolor, textcolor; 01577 RECT focusRect = dis->rcItem; 01578 HBRUSH hbrush; 01579 enum IMAGE img; 01580 int img_pos, cx; 01581 int col = 0; 01582 01583 if (entry) { 01584 attrs = entry->data.dwFileAttributes; 01585 01586 if (attrs & FILE_ATTRIBUTE_DIRECTORY) { 01587 if (entry->data.cFileName[0]=='.' && entry->data.cFileName[1]=='.' 01588 && entry->data.cFileName[2]=='\0') 01589 img = IMG_FOLDER_UP; 01590 #ifndef _NO_EXTENSIONS 01591 else if (entry->data.cFileName[0]=='.' && entry->data.cFileName[1]=='\0') 01592 img = IMG_FOLDER_CUR; 01593 #endif 01594 else if ( 01595 #ifdef _NO_EXTENSIONS 01596 entry->expanded || 01597 #endif 01598 (pane->treePane && (dis->itemState&ODS_FOCUS))) 01599 img = IMG_OPEN_FOLDER; 01600 else 01601 img = IMG_FOLDER; 01602 } else { 01603 switch(get_file_type(entry->data.cFileName)) { 01604 case FT_EXECUTABLE: img = IMG_EXECUTABLE; break; 01605 case FT_DOCUMENT: img = IMG_DOCUMENT; break; 01606 default: img = IMG_FILE; 01607 } 01608 } 01609 } else { 01610 attrs = 0; 01611 img = IMG_NONE; 01612 } 01613 01614 if (pane->treePane) { 01615 if (entry) { 01616 img_pos = dis->rcItem.left + entry->level*(IMAGE_WIDTH+TREE_LINE_DX); 01617 01618 if (calcWidthCol == -1) { 01619 int x; 01620 int y = dis->rcItem.top + IMAGE_HEIGHT/2; 01621 Entry* up; 01622 RECT rt_clip; 01623 HRGN hrgn_org = CreateRectRgn(0, 0, 0, 0); 01624 HRGN hrgn; 01625 01626 rt_clip.left = dis->rcItem.left; 01627 rt_clip.top = dis->rcItem.top; 01628 rt_clip.right = dis->rcItem.left+pane->widths[col]; 01629 rt_clip.bottom = dis->rcItem.bottom; 01630 01631 hrgn = CreateRectRgnIndirect(&rt_clip); 01632 01633 if (!GetClipRgn(dis->hDC, hrgn_org)) { 01634 DeleteObject(hrgn_org); 01635 hrgn_org = 0; 01636 } 01637 01638 /* HGDIOBJ holdPen = SelectObject(dis->hDC, GetStockObject(BLACK_PEN)); */ 01639 ExtSelectClipRgn(dis->hDC, hrgn, RGN_AND); 01640 DeleteObject(hrgn); 01641 01642 if ((up=entry->up) != NULL) { 01643 MoveToEx(dis->hDC, img_pos-IMAGE_WIDTH/2, y, 0); 01644 LineTo(dis->hDC, img_pos-2, y); 01645 01646 x = img_pos - IMAGE_WIDTH/2; 01647 01648 do { 01649 x -= IMAGE_WIDTH+TREE_LINE_DX; 01650 01651 if (up->next 01652 #ifndef _LEFT_FILES 01653 && (up->next->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 01654 #endif 01655 ) { 01656 MoveToEx(dis->hDC, x, dis->rcItem.top, 0); 01657 LineTo(dis->hDC, x, dis->rcItem.bottom); 01658 } 01659 } while((up=up->up) != NULL); 01660 } 01661 01662 x = img_pos - IMAGE_WIDTH/2; 01663 01664 MoveToEx(dis->hDC, x, dis->rcItem.top, 0); 01665 LineTo(dis->hDC, x, y); 01666 01667 if (entry->next 01668 #ifndef _LEFT_FILES 01669 && (entry->next->data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) 01670 #endif 01671 ) 01672 LineTo(dis->hDC, x, dis->rcItem.bottom); 01673 01674 SelectClipRgn(dis->hDC, hrgn_org); 01675 if (hrgn_org) DeleteObject(hrgn_org); 01676 /* SelectObject(dis->hDC, holdPen); */ 01677 } else if (calcWidthCol==col || calcWidthCol==COLUMNS) { 01678 int right = img_pos + IMAGE_WIDTH - TREE_LINE_DX; 01679 01680 if (right > pane->widths[col]) 01681 pane->widths[col] = right; 01682 } 01683 } else { 01684 img_pos = dis->rcItem.left; 01685 } 01686 } else { 01687 img_pos = dis->rcItem.left; 01688 01689 if (calcWidthCol==col || calcWidthCol==COLUMNS) 01690 pane->widths[col] = IMAGE_WIDTH; 01691 } 01692 01693 if (calcWidthCol == -1) { 01694 focusRect.left = img_pos - 2; 01695 01696 #ifdef _NO_EXTENSIONS 01697 if (pane->treePane && entry) { 01698 RECT rt = {0}; 01699 01700 DrawText(dis->hDC, entry->data.cFileName, -1, &rt, DT_CALCRECT|DT_SINGLELINE|DT_NOPREFIX); 01701 01702 focusRect.right = dis->rcItem.left+pane->positions[col+1]+TREE_LINE_DX + rt.right +2; 01703 } 01704 #else 01705 01706 if (attrs & FILE_ATTRIBUTE_COMPRESSED) 01707 textcolor = COLOR_COMPRESSED; 01708 else 01709 #endif /* _NO_EXTENSIONS */ 01710 textcolor = RGB(0,0,0); 01711 01712 if (dis->itemState & ODS_FOCUS) { 01713 textcolor = COLOR_SELECTION_TXT; 01714 bkcolor = COLOR_SELECTION; 01715 } else { 01716 bkcolor = GetSysColor(COLOR_WINDOW); 01717 } 01718 01719 hbrush = CreateSolidBrush(bkcolor); 01720 FillRect(dis->hDC, &focusRect, hbrush); 01721 DeleteObject(hbrush); 01722 01723 SetBkMode(dis->hDC, TRANSPARENT); 01724 SetTextColor(dis->hDC, textcolor); 01725 01726 cx = pane->widths[col]; 01727 01728 if (cx && img!=IMG_NONE) { 01729 if (cx > IMAGE_WIDTH) 01730 cx = IMAGE_WIDTH; 01731 01732 #ifdef _SHELL_FOLDERS 01733 if (entry->hicon && entry->hicon!=(HICON)-1) 01734 DrawIconEx(dis->hDC, img_pos, dis->rcItem.top, entry->hicon, cx, GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL); 01735 else 01736 #endif 01737 ImageList_DrawEx(Globals.himl, img, dis->hDC, 01738 img_pos, dis->rcItem.top, cx, 01739 IMAGE_HEIGHT, bkcolor, CLR_DEFAULT, ILD_NORMAL); 01740 } 01741 } 01742 01743 if (!entry) 01744 return; 01745 01746 #ifdef _NO_EXTENSIONS 01747 if (img >= IMG_FOLDER_UP) 01748 return; 01749 #endif 01750 01751 col++; 01752 01753 /* ouput file name */ 01754 if (calcWidthCol == -1) 01755 output_text(pane, dis, col, entry->data.cFileName, 0); 01756 else if (calcWidthCol==col || calcWidthCol==COLUMNS) 01757 calc_width(pane, dis, col, entry->data.cFileName); 01758 01759 col++; 01760 01761 #ifdef _NO_EXTENSIONS 01762 if (!pane->treePane) { 01763 #endif 01764 01765 /* display file size */ 01766 if (visible_cols & COL_SIZE) { 01767 #ifdef _NO_EXTENSIONS 01768 if (!(attrs&FILE_ATTRIBUTE_DIRECTORY)) 01769 #endif 01770 { 01771 ULONGLONG size; 01772 01773 size = ((ULONGLONG)entry->data.nFileSizeHigh << 32) | entry->data.nFileSizeLow; 01774 01775 _stprintf(buffer, sLongNumFmt, size); 01776 01777 if (calcWidthCol == -1) 01778 output_number(pane, dis, col, buffer); 01779 else if (calcWidthCol==col || calcWidthCol==COLUMNS) 01780 calc_width(pane, dis, col, buffer);/*TODO: not in every case time enough */ 01781 } 01782 01783 col++; 01784 } 01785 01786 /* display file date */ 01787 if (visible_cols & (COL_DATE|COL_TIME)) { 01788 #ifndef _NO_EXTENSIONS 01789 format_date(&entry->data.ftCreationTime, buffer, visible_cols); 01790 if (calcWidthCol == -1) 01791 output_text(pane, dis, col, buffer, 0); 01792 else if (calcWidthCol==col || calcWidthCol==COLUMNS) 01793 calc_width(pane, dis, col, buffer); 01794 col++; 01795 01796 format_date(&entry->data.ftLastAccessTime, buffer, visible_cols); 01797 if (calcWidthCol == -1) 01798 output_text(pane, dis, col, buffer, 0); 01799 else if (calcWidthCol==col || calcWidthCol==COLUMNS) 01800 calc_width(pane, dis, col, buffer); 01801 col++; 01802 #endif /* _NO_EXTENSIONS */ 01803 01804 format_date(&entry->data.ftLastWriteTime, buffer, visible_cols); 01805 if (calcWidthCol == -1) 01806 output_text(pane, dis, col, buffer, 0); 01807 else if (calcWidthCol==col || calcWidthCol==COLUMNS) 01808 calc_width(pane, dis, col, buffer); 01809 col++; 01810 } 01811 01812 #ifndef _NO_EXTENSIONS 01813 if (entry->bhfi_valid) { 01814 ULONGLONG index = ((ULONGLONG)entry->bhfi.nFileIndexHigh << 32) | entry->bhfi.nFileIndexLow; 01815 01816 if (visible_cols & COL_INDEX) { 01817 _stprintf(buffer, sLongHexFmt, index); 01818 01819 if (calcWidthCol == -1) 01820 output_text(pane, dis, col, buffer, DT_RIGHT); 01821 else if (calcWidthCol==col || calcWidthCol==COLUMNS) 01822 calc_width(pane, dis, col, buffer); 01823 01824 col++; 01825 } 01826 01827 if (visible_cols & COL_LINKS) { 01828 wsprintf(buffer, sNumFmt, entry->bhfi.nNumberOfLinks); 01829 01830 if (calcWidthCol == -1) 01831 output_text(pane, dis, col, buffer, DT_CENTER); 01832 else if (calcWidthCol==col || calcWidthCol==COLUMNS) 01833 calc_width(pane, dis, col, buffer); 01834 01835 col++; 01836 } 01837 } else 01838 col += 2; 01839 #endif /* _NO_EXTENSIONS */ 01840 01841 /* show file attributes */ 01842 if (visible_cols & COL_ATTRIBUTES) { 01843 #ifdef _NO_EXTENSIONS 01844 static const TCHAR s4Tabs[] = {' ','\t',' ','\t',' ','\t',' ','\t',' ','\0'}; 01845 lstrcpy(buffer, s4Tabs); 01846 #else 01847 static const TCHAR s11Tabs[] = {' ','\t',' ','\t',' ','\t',' ','\t',' ','\t',' ','\t',' ','\t',' ','\t',' ','\t',' ','\t',' ','\t',' ','\0'}; 01848 lstrcpy(buffer, s11Tabs); 01849 #endif 01850 01851 if (attrs & FILE_ATTRIBUTE_NORMAL) buffer[ 0] = 'N'; 01852 else { 01853 if (attrs & FILE_ATTRIBUTE_READONLY) buffer[ 2] = 'R'; 01854 if (attrs & FILE_ATTRIBUTE_HIDDEN) buffer[ 4] = 'H'; 01855 if (attrs & FILE_ATTRIBUTE_SYSTEM) buffer[ 6] = 'S'; 01856 if (attrs & FILE_ATTRIBUTE_ARCHIVE) buffer[ 8] = 'A'; 01857 if (attrs & FILE_ATTRIBUTE_COMPRESSED) buffer[10] = 'C'; 01858 #ifndef _NO_EXTENSIONS 01859 if (attrs & FILE_ATTRIBUTE_DIRECTORY) buffer[12] = 'D'; 01860 if (attrs & FILE_ATTRIBUTE_ENCRYPTED) buffer[14] = 'E'; 01861 if (attrs & FILE_ATTRIBUTE_TEMPORARY) buffer[16] = 'T'; 01862 if (attrs & FILE_ATTRIBUTE_SPARSE_FILE) buffer[18] = 'P'; 01863 if (attrs & FILE_ATTRIBUTE_REPARSE_POINT) buffer[20] = 'Q'; 01864 if (attrs & FILE_ATTRIBUTE_OFFLINE) buffer[22] = 'O'; 01865 if (attrs & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED) buffer[24] = 'X'; 01866 #endif /* _NO_EXTENSIONS */ 01867 } 01868 01869 if (calcWidthCol == -1) 01870 output_tabbed_text(pane, dis, col, buffer); 01871 else if (calcWidthCol==col || calcWidthCol==COLUMNS) 01872 calc_tabbed_width(pane, dis, col, buffer); 01873 01874 col++; 01875 } 01876 01877 /*TODO 01878 if (flags.security) { 01879 static const TCHAR sSecTabs[] = { 01880 ' ','\t',' ','\t',' ','\t',' ', 01881 ' ','\t',' ', 01882 ' ','\t',' ','\t',' ','\t',' ', 01883 ' ','\t',' ', 01884 ' ','\t',' ','\t',' ','\t',' ', 01885 '\0' 01886 }; 01887 01888 DWORD rights = get_access_mask(); 01889 01890 lstrcpy(buffer, sSecTabs); 01891 01892 if (rights & FILE_READ_DATA) buffer[ 0] = 'R'; 01893 if (rights & FILE_WRITE_DATA) buffer[ 2] = 'W'; 01894 if (rights & FILE_APPEND_DATA) buffer[ 4] = 'A'; 01895 if (rights & FILE_READ_EA) {buffer[6] = 'entry'; buffer[ 7] = 'R';} 01896 if (rights & FILE_WRITE_EA) {buffer[9] = 'entry'; buffer[10] = 'W';} 01897 if (rights & FILE_EXECUTE) buffer[12] = 'X'; 01898 if (rights & FILE_DELETE_CHILD) buffer[14] = 'D'; 01899 if (rights & FILE_READ_ATTRIBUTES) {buffer[16] = 'a'; buffer[17] = 'R';} 01900 if (rights & FILE_WRITE_ATTRIBUTES) {buffer[19] = 'a'; buffer[20] = 'W';} 01901 if (rights & WRITE_DAC) buffer[22] = 'C'; 01902 if (rights & WRITE_OWNER) buffer[24] = 'O'; 01903 if (rights & SYNCHRONIZE) buffer[26] = 'S'; 01904 01905 output_text(dis, col++, buffer, DT_LEFT, 3, psize); 01906 } 01907 01908 if (flags.description) { 01909 get_description(buffer); 01910 output_text(dis, col++, buffer, 0, psize); 01911 } 01912 */ 01913 01914 #ifdef _NO_EXTENSIONS 01915 } 01916 01917 /* draw focus frame */ 01918 if ((dis->itemState&ODS_FOCUS) && calcWidthCol==-1) { 01919 /* Currently [04/2000] Wine neither behaves exactly the same */ 01920 /* way as WIN 95 nor like Windows NT... */ 01921 HGDIOBJ lastBrush; 01922 HPEN lastPen; 01923 HPEN hpen; 01924 01925 if (!(GetVersion() & 0x80000000)) { /* Is the OS already Windows NT compatible? */ 01926 LOGBRUSH lb = {PS_SOLID, RGB(255,255,255)}; 01927 hpen = ExtCreatePen(PS_COSMETIC|PS_ALTERNATE, 1, &lb, 0, 0); 01928 } else 01929 hpen = CreatePen(PS_DOT, 0, RGB(255,255,255)); 01930 01931 lastPen = SelectPen(dis->hDC, hpen); 01932 lastBrush = SelectObject(dis->hDC, GetStockObject(HOLLOW_BRUSH)); 01933 SetROP2(dis->hDC, R2_XORPEN); 01934 Rectangle(dis->hDC, focusRect.left, focusRect.top, focusRect.right, focusRect.bottom); 01935 SelectObject(dis->hDC, lastBrush); 01936 SelectObject(dis->hDC, lastPen); 01937 DeleteObject(hpen); 01938 } 01939 #endif /* _NO_EXTENSIONS */ 01940 } 01941 01942 01943 #ifdef _NO_EXTENSIONS 01944 01945 /* draw the window split bar when not providing extensions over the original Winfile user interface */ 01946 01947 static void draw_splitbar(HWND hwnd, int x) 01948 { 01949 RECT rt; 01950 HDC hdc = GetDC(hwnd); 01951 01952 GetClientRect(hwnd, &rt); 01953 01954 rt.left = x - SPLIT_WIDTH/2; 01955 rt.right = x + SPLIT_WIDTH/2+1; 01956 01957 InvertRect(hdc, &rt); 01958 01959 ReleaseDC(hwnd, hdc); 01960 } 01961 01962 #endif /* _NO_EXTENSIONS */ 01963 01964 01965 /* scan the content of the given entry node */ 01966 01967 static void scan_entry(ChildWnd* child, Entry* entry, int idx, HWND hwnd) 01968 { 01969 TCHAR path[MAX_PATH]; 01970 HCURSOR old_cursor = SetCursor(LoadCursor(0, IDC_WAIT)); 01971 01972 /* delete sub entries in left pane */ 01973 for(;;) { 01974 LRESULT res = ListBox_GetItemData(child->left.hwnd, idx+1); 01975 Entry* sub = (Entry*) res; 01976 01977 if (res==LB_ERR || !sub || sub->level<=entry->level) 01978 break; 01979 01980 (void)ListBox_DeleteString(child->left.hwnd, idx+1); 01981 } 01982 01983 /* empty right pane */ 01984 (void)ListBox_ResetContent(child->right.hwnd); 01985 01986 /* release memory */ 01987 free_entries(entry); 01988 01989 /* read contents from disk */ 01990 #ifdef _SHELL_FOLDERS 01991 if (entry->etype == ET_SHELL) 01992 { 01993 read_directory(entry, NULL, child->sortOrder, hwnd); 01994 } 01995 else 01996 #endif 01997 { 01998 get_path(entry, path); 01999 read_directory(entry, path, child->sortOrder, hwnd); 02000 } 02001 02002 /* insert found entries in right pane */ 02003 insert_entries(&child->right, entry->down, child->filter_pattern, child->filter_flags, -1); 02004 calc_widths(&child->right, FALSE); 02005 #ifndef _NO_EXTENSIONS 02006 set_header(&child->right); 02007 #endif 02008 02009 child->header_wdths_ok = FALSE; 02010 02011 SetCursor(old_cursor); 02012 } 02013 02014 02015 /* expand a directory entry */ 02016 02017 static BOOL expand_entry(ChildWnd* child, Entry* dir) 02018 { 02019 int idx; 02020 Entry* p; 02021 02022 if (!dir || dir->expanded || !dir->down) 02023 return FALSE; 02024 02025 p = dir->down; 02026 02027 if (p->data.cFileName[0]=='.' && p->data.cFileName[1]=='\0' && p->next) { 02028 p = p->next; 02029 02030 if (p->data.cFileName[0]=='.' && p->data.cFileName[1]=='.' && 02031 p->data.cFileName[2]=='\0' && p->next) 02032 p = p->next; 02033 } 02034 02035 /* no subdirectories ? */ 02036 if (!(p->data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)) 02037 return FALSE; 02038 02039 idx = ListBox_FindItemData(child->left.hwnd, 0, dir); 02040 02041 dir->expanded = TRUE; 02042 02043 /* insert entries in left pane */ 02044 insert_entries(&child->left, p, NULL, TF_ALL, idx); 02045 02046 if (!child->header_wdths_ok) { 02047 if (calc_widths(&child->left, FALSE)) { 02048 #ifndef _NO_EXTENSIONS 02049 set_header(&child->left); 02050 #endif 02051 02052 child->header_wdths_ok = TRUE; 02053 } 02054 } 02055 02056 return TRUE; 02057 } 02058 02059 02060 /* close child nodes of the given entry */ 02061 02062 static void collapse_entry(Pane* pane, Entry* dir) 02063 { 02064 int idx = ListBox_FindItemData(pane->hwnd, 0, dir); 02065 02066 ShowWindow(pane->hwnd, SW_HIDE); 02067 02068 /* hide sub entries */ 02069 for(;;) { 02070 LRESULT res = ListBox_GetItemData(pane->hwnd, idx+1); 02071 Entry* sub = (Entry*) res; 02072 02073 if (res==LB_ERR || !sub || sub->level<=dir->level) 02074 break; 02075 02076 (void)ListBox_DeleteString(pane->hwnd, idx+1); 02077 } 02078 02079 dir->expanded = FALSE; 02080 02081 ShowWindow(pane->hwnd, SW_SHOW); 02082 } 02083 02084 02085 /* refresh the right pane of a Winefile child window */ 02086 02087 static void refresh_right_pane(ChildWnd* child) 02088 { 02089 (void)ListBox_ResetContent(child->right.hwnd); 02090 insert_entries(&child->right, child->right.root, child->filter_pattern, child->filter_flags, -1); 02091 calc_widths(&child->right, FALSE); 02092 02093 #ifndef _NO_EXTENSIONS 02094 set_header(&child->right); 02095 #endif 02096 } 02097 02098 02099 /* change the current directory of a child window according to the given entry pointer */ 02100 02101 static void set_curdir(ChildWnd* child, Entry* entry, int idx, HWND hwnd) 02102 { 02103 TCHAR path[MAX_PATH]; 02104 02105 if (!entry) 02106 return; 02107 02108 path[0] = '\0'; 02109 02110 child->left.cur = entry; 02111 02112 child->right.root = entry->down? entry->down: entry; 02113 child->right.cur = entry; 02114 02115 if (!entry->scanned) 02116 scan_entry(child, entry, idx, hwnd); 02117 else 02118 refresh_right_pane(child); 02119 02120 get_path(entry, path); 02121 lstrcpy(child->path, path); 02122 02123 if (child->hwnd) /* only change window title, if the window already exists */ 02124 SetWindowText(child->hwnd, path); 02125 02126 if (path[0]) 02127 if (SetCurrentDirectory(path)) 02128 set_space_status(); 02129 } 02130 02131 02132 /* refresh the child window content */ 02133 02134 static void refresh_child(ChildWnd* child) 02135 { 02136 TCHAR path[MAX_PATH], drv[_MAX_DRIVE+1]; 02137 Entry* entry; 02138 int idx; 02139 02140 get_path(child->left.cur, path); 02141 _tsplitpath(path, drv, NULL, NULL, NULL); 02142 02143 child->right.root = NULL; 02144 02145 scan_entry(child, &child->root.entry, 0, child->hwnd); 02146 02147 #ifdef _SHELL_FOLDERS 02148 if (child->root.entry.etype == ET_SHELL) 02149 entry = read_tree(&child->root, NULL, get_path_pidl(path,child->hwnd), drv, child->sortOrder, child->hwnd); 02150 else 02151 #endif 02152 entry = read_tree(&child->root, path, NULL, drv, child->sortOrder, child->hwnd); 02153 02154 if (!entry) 02155 entry = &child->root.entry; 02156 02157 insert_entries(&child->left, child->root.entry.down, NULL, TF_ALL, 0); 02158 02159 set_curdir(child, entry, 0, child->hwnd); 02160 02161 idx = ListBox_FindItemData(child->left.hwnd, 0, child->left.cur); 02162 (void)ListBox_SetCurSel(child->left.hwnd, idx); 02163 } 02164 02165 02166 /* create the drive toolbar */ 02167 02168 static void create_drive_bar(void) 02169 { 02170 TBBUTTON drivebarBtn = {0, 0, TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0}; 02171 #ifndef _NO_EXTENSIONS 02172 TCHAR b1[BUFFER_LEN]; 02173 #endif 02174 int btn = 1; 02175 PTSTR p; 02176 02177 GetLogicalDriveStrings(BUFFER_LEN, Globals.drives); 02178 02179 Globals.hdrivebar = CreateToolbarEx(Globals.hMainWnd, WS_CHILD|WS_VISIBLE|CCS_NOMOVEY|TBSTYLE_LIST, 02180 IDW_DRIVEBAR, 2, Globals.hInstance, IDB_DRIVEBAR, &drivebarBtn, 02181 0, 16, 13, 16, 13, sizeof(TBBUTTON)); 02182 02183 #ifndef _NO_EXTENSIONS 02184 #ifdef __WINE__ 02185 /* insert unix file system button */ 02186 b1[0] = '/'; 02187 b1[1] = '\0'; 02188 b1[2] = '\0'; 02189 SendMessage(Globals.hdrivebar, TB_ADDSTRING, 0, (LPARAM)b1); 02190 02191 drivebarBtn.idCommand = ID_DRIVE_UNIX_FS; 02192 SendMessage(Globals.hdrivebar, TB_INSERTBUTTON, btn++, (LPARAM)&drivebarBtn); 02193 drivebarBtn.iString++; 02194 #endif 02195 #ifdef _SHELL_FOLDERS 02196 /* insert shell namespace button */ 02197 load_string(b1, IDS_SHELL); 02198 b1[lstrlen(b1)+1] = '\0'; 02199 SendMessage(Globals.hdrivebar, TB_ADDSTRING, 0, (LPARAM)b1); 02200 02201 drivebarBtn.idCommand = ID_DRIVE_SHELL_NS; 02202 SendMessage(Globals.hdrivebar, TB_INSERTBUTTON, btn++, (LPARAM)&drivebarBtn); 02203 drivebarBtn.iString++; 02204 #endif 02205 02206 /* register windows drive root strings */ 02207 SendMessage(Globals.hdrivebar, TB_ADDSTRING, 0, (LPARAM)Globals.drives); 02208 #endif 02209 02210 drivebarBtn.idCommand = ID_DRIVE_FIRST; 02211 02212 for(p=Globals.drives; *p; ) { 02213 #ifdef _NO_EXTENSIONS 02214 /* insert drive letter */ 02215 TCHAR b[3] = {tolower(*p)}; 02216 SendMessage(Globals.hdrivebar, TB_ADDSTRING, 0, (LPARAM)b); 02217 #endif 02218 switch(GetDriveType(p)) { 02219 case DRIVE_REMOVABLE: drivebarBtn.iBitmap = 1; break; 02220 case DRIVE_CDROM: drivebarBtn.iBitmap = 3; break; 02221 case DRIVE_REMOTE: drivebarBtn.iBitmap = 4; break; 02222 case DRIVE_RAMDISK: drivebarBtn.iBitmap = 5; break; 02223 default:/*DRIVE_FIXED*/ drivebarBtn.iBitmap = 2; 02224 } 02225 02226 SendMessage(Globals.hdrivebar, TB_INSERTBUTTON, btn++, (LPARAM)&drivebarBtn); 02227 drivebarBtn.idCommand++; 02228 drivebarBtn.iString++; 02229 02230 while(*p++); 02231 } 02232 } 02233 02234 02235 /* refresh the drive toolbar */ 02236 02237 static void refresh_drives(void) 02238 { 02239 RECT rect; 02240 02241 /* destroy drive bar */ 02242 DestroyWindow(Globals.hdrivebar); 02243 Globals.hdrivebar = 0; 02244 02245 /* re-create drive bar */ 02246 create_drive_bar(); 02247 02248 /* update window layout */ 02249 GetClientRect(Globals.hMainWnd, &rect); 02250 SendMessage(Globals.hMainWnd, WM_SIZE, 0, MAKELONG(rect.right, rect.bottom)); 02251 } 02252 02253 02254 /* launch a executable or document */ 02255 02256 static BOOL launch_file(HWND hwnd, LPCTSTR cmd, UINT nCmdShow) 02257 { 02258 HINSTANCE hinst = ShellExecute(hwnd, NULL/*operation*/, cmd, NULL/*parameters*/, NULL/*dir*/, nCmdShow); 02259 02260 if (PtrToUlong(hinst) <= 32) { 02261 display_error(hwnd, GetLastError()); 02262 return FALSE; 02263 } 02264 02265 return TRUE; 02266 } 02267 02268 02269 /* launch the file associated with a Winefile entry */ 02270 02271 static BOOL launch_entry(Entry* entry, HWND hwnd, UINT nCmdShow) 02272 { 02273 TCHAR cmd[MAX_PATH]; 02274 02275 #ifdef _SHELL_FOLDERS 02276 if (entry->etype == ET_SHELL) { 02277 BOOL ret = TRUE; 02278 02279 SHELLEXECUTEINFO shexinfo; 02280 02281 shexinfo.cbSize = sizeof(SHELLEXECUTEINFO); 02282 shexinfo.fMask = SEE_MASK_IDLIST; 02283 shexinfo.hwnd = hwnd; 02284 shexinfo.lpVerb = NULL; 02285 shexinfo.lpFile = NULL; 02286 shexinfo.lpParameters = NULL; 02287 shexinfo.lpDirectory = NULL; 02288 shexinfo.nShow = nCmdShow; 02289 shexinfo.lpIDList = get_to_absolute_pidl(entry, hwnd); 02290 02291 if (!ShellExecuteEx(&shexinfo)) { 02292 display_error(hwnd, GetLastError()); 02293 ret = FALSE; 02294 } 02295 02296 if (shexinfo.lpIDList != entry->pidl) 02297 IMalloc_Free(Globals.iMalloc, shexinfo.lpIDList); 02298 02299 return ret; 02300 } 02301 #endif 02302 02303 get_path(entry, cmd); 02304 02305 /* start program, open document... */ 02306 return launch_file(hwnd, cmd, nCmdShow); 02307 } 02308 02309 02310 /* activate a Winefile entry (on double click or ENTER) */ 02311 02312 static void activate_entry(ChildWnd* child, Pane* pane, HWND hwnd) 02313 { 02314 Entry* entry = pane->cur; 02315 02316 if (!entry) 02317 return; 02318 02319 if (entry->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { 02320 int scanned_old = entry->scanned; 02321 02322 if (!scanned_old) 02323 scan_entry(child, entry, ListBox_GetCurSel(child->left.hwnd), hwnd); 02324 02325 #ifndef _NO_EXTENSIONS 02326 if (entry->data.cFileName[0]=='.' && entry->data.cFileName[1]=='\0') 02327 return; 02328 #endif 02329 02330 if (entry->data.cFileName[0]=='.' && entry->data.cFileName[1]=='.' && entry->data.cFileName[2]=='\0') { 02331 entry = child->left.cur->up; 02332 collapse_entry(&child->left, entry); 02333 goto focus_entry; 02334 } else if (entry->expanded) 02335 collapse_entry(pane, child->left.cur); 02336 else { 02337 expand_entry(child, child->left.cur); 02338 02339 if (!pane->treePane) focus_entry: { 02340 int idx = ListBox_FindItemData(child->left.hwnd, ListBox_GetCurSel(child->left.hwnd), entry); 02341 (void)ListBox_SetCurSel(child->left.hwnd, idx); 02342 set_curdir(child, entry, idx, hwnd); 02343 } 02344 } 02345 02346 if (!scanned_old) { 02347 calc_widths(pane, FALSE); 02348 02349 #ifndef _NO_EXTENSIONS 02350 set_header(pane); 02351 #endif 02352 } 02353 } else { 02354 if (GetKeyState(VK_MENU) < 0) 02355 show_properties_dlg(entry, child->hwnd); 02356 else 02357 launch_entry(entry, child->hwnd, SW_SHOWNORMAL); 02358 } 02359 } 02360 02361 02362 /* command handler for Winefile panes */ 02363 02364 static BOOL pane_command(Pane* pane, UINT cmd) 02365 { 02366 switch(cmd) { 02367 case ID_VIEW_NAME: 02368 if (pane->visible_cols) { 02369 pane->visible_cols = 0; 02370 calc_widths(pane, TRUE); 02371 #ifndef _NO_EXTENSIONS 02372 set_header(pane); 02373 #endif 02374 InvalidateRect(pane->hwnd, 0, TRUE); 02375 CheckMenuItem(Globals.hMenuView, ID_VIEW_NAME, MF_BYCOMMAND|MF_CHECKED); 02376 CheckMenuItem(Globals.hMenuView, ID_VIEW_ALL_ATTRIBUTES, MF_BYCOMMAND); 02377 CheckMenuItem(Globals.hMenuView, ID_VIEW_SELECTED_ATTRIBUTES, MF_BYCOMMAND); 02378 } 02379 break; 02380 02381 case ID_VIEW_ALL_ATTRIBUTES: 02382 if (pane->visible_cols != COL_ALL) { 02383 pane->visible_cols = COL_ALL; 02384 calc_widths(pane, TRUE); 02385 #ifndef _NO_EXTENSIONS 02386 set_header(pane); 02387 #endif 02388 InvalidateRect(pane->hwnd, 0, TRUE); 02389 CheckMenuItem(Globals.hMenuView, ID_VIEW_NAME, MF_BYCOMMAND); 02390 CheckMenuItem(Globals.hMenuView, ID_VIEW_ALL_ATTRIBUTES, MF_BYCOMMAND|MF_CHECKED); 02391 CheckMenuItem(Globals.hMenuView, ID_VIEW_SELECTED_ATTRIBUTES, MF_BYCOMMAND); 02392 } 02393 break; 02394 02395 #ifndef _NO_EXTENSIONS 02396 case ID_PREFERRED_SIZES: { 02397 calc_widths(pane, TRUE); 02398 set_header(pane); 02399 InvalidateRect(pane->hwnd, 0, TRUE); 02400 break;} 02401 #endif 02402 02403 /* TODO: more command ids... */ 02404 02405 default: 02406 return FALSE; 02407 } 02408 02409 return TRUE; 02410 } 02411 02412 02413 /* set the sort order of a child window */ 02414 02415 static void set_sort_order(ChildWnd* child, enum SORT_ORDER sortOrder) 02416 { 02417 if (child->sortOrder != sortOrder) { 02418 child->sortOrder = sortOrder; 02419 refresh_child(child); 02420 } 02421 } 02422 02423 02424 /* update the check state of the view menu items */ 02425 02426 static void update_view_menu(ChildWnd* child) 02427 { 02428 CheckMenuItem(Globals.hMenuView, ID_VIEW_SORT_NAME, child->sortOrder==SORT_NAME? MF_CHECKED: MF_UNCHECKED); 02429 CheckMenuItem(Globals.hMenuView, ID_VIEW_SORT_TYPE, child->sortOrder==SORT_EXT? MF_CHECKED: MF_UNCHECKED); 02430 CheckMenuItem(Globals.hMenuView, ID_VIEW_SORT_SIZE, child->sortOrder==SORT_SIZE? MF_CHECKED: MF_UNCHECKED); 02431 CheckMenuItem(Globals.hMenuView, ID_VIEW_SORT_DATE, child->sortOrder==SORT_DATE? MF_CHECKED: MF_UNCHECKED); 02432 } 02433 02434 02435 /* utility function to check for directories at the given path */ 02436 02437 static BOOL is_directory(LPCTSTR target) 02438 { 02439 /*TODO correctly handle UNIX paths */ 02440 DWORD target_attr = GetFileAttributes(target); 02441 02442 if (target_attr == INVALID_FILE_ATTRIBUTES) 02443 return FALSE; 02444 02445 return target_attr&FILE_ATTRIBUTE_DIRECTORY? TRUE: FALSE; 02446 } 02447 02448 02449 /* display a dialog to ask the user for a target path */ 02450 02451 static BOOL prompt_target(Pane* pane, LPTSTR source, LPTSTR target) 02452 { 02453 TCHAR path[MAX_PATH]; 02454 int len; 02455 02456 get_path(pane->cur, path); 02457 02458 if (DialogBoxParam(Globals.hInstance, MAKEINTRESOURCE(IDD_SELECT_DESTINATION), pane->hwnd, DestinationDlgProc, (LPARAM)path) != IDOK) 02459 return FALSE; 02460 02461 get_path(pane->cur, source); 02462 02463 /* convert relative targets to absolute paths */ 02464 if (path[0]!='/' && path[1]!=':') { 02465 get_path(pane->cur->up, target); 02466 len = lstrlen(target); 02467 02468 if (target[len-1]!='\\' && target[len-1]!='/') 02469 target[len++] = '/'; 02470 02471 lstrcpy(target+len, path); 02472 } else 02473 lstrcpy(target, path); 02474 02475 /* If the target already exists as directory, create a new target below this. */ 02476 if (is_directory(path)) { 02477 TCHAR fname[_MAX_FNAME], ext[_MAX_EXT]; 02478 static const TCHAR sAppend[] = {'%','s','/','%','s','%','s','\0'}; 02479 02480 _tsplitpath(source, NULL, NULL, fname, ext); 02481 02482 wsprintf(target, sAppend, path, fname, ext); 02483 } 02484 02485 return TRUE; 02486 } 02487 02488 02489 /* message handler funtion for the Winefile child windows */ 02490 02491 static LRESULT CALLBACK ChildWndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam) 02492 { 02493 ChildWnd* child = (ChildWnd*) GetWindowLongPtr(hwnd, GWLP_USERDATA); 02494 ASSERT(child); 02495 02496 switch(nmsg) { 02497 case WM_DRAWITEM: { 02498 LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT)lparam; 02499 Entry* entry = (Entry*) dis->itemData; 02500 02501 if (dis->CtlID == IDW_TREE_LEFT) 02502 draw_item(&child->left, dis, entry, -1); 02503 else if (dis->CtlID == IDW_TREE_RIGHT) 02504 draw_item(&child->right, dis, entry, -1); 02505 else 02506 goto draw_menu_item; 02507 02508 return TRUE;} 02509 02510 case WM_CREATE: 02511 InitChildWindow(child); 02512 break; 02513 02514 case WM_NCDESTROY: 02515 free_child_window(child); 02516 SetWindowLongPtr(hwnd, GWLP_USERDATA, 0); 02517 break; 02518 02519 case WM_PAINT: { 02520 PAINTSTRUCT ps; 02521 HBRUSH lastBrush; 02522 RECT rt; 02523 GetClientRect(hwnd, &rt); 02524 BeginPaint(hwnd, &ps); 02525 rt.left = child->split_pos-SPLIT_WIDTH/2; 02526 rt.right = child->split_pos+SPLIT_WIDTH/2+1; 02527 lastBrush = SelectBrush(ps.hdc, (HBRUSH)GetStockObject(COLOR_SPLITBAR)); 02528 Rectangle(ps.hdc, rt.left, rt.top-1, rt.right, rt.bottom+1); 02529 SelectObject(ps.hdc, lastBrush); 02530 #ifdef _NO_EXTENSIONS 02531 rt.top = rt.bottom - GetSystemMetrics(SM_CYHSCROLL); 02532 FillRect(ps.hdc, &rt, GetStockObject(BLACK_BRUSH)); 02533 #endif 02534 EndPaint(hwnd, &ps); 02535 break;} 02536 02537 case WM_SETCURSOR: 02538 if (LOWORD(lparam) == HTCLIENT) { 02539 POINT pt; 02540 GetCursorPos(&pt); 02541 ScreenToClient(hwnd, &pt); 02542 02543 if (pt.x>=child->split_pos-SPLIT_WIDTH/2 && pt.x<child->split_pos+SPLIT_WIDTH/2+1) { 02544 SetCursor(LoadCursor(0, IDC_SIZEWE)); 02545 return TRUE; 02546 } 02547 } 02548 goto def; 02549 02550 case WM_LBUTTONDOWN: { 02551 RECT rt; 02552 int x = GET_X_LPARAM(lparam); 02553 02554 GetClientRect(hwnd, &rt); 02555 02556 if (x>=child->split_pos-SPLIT_WIDTH/2 && x<child->split_pos+SPLIT_WIDTH/2+1) { 02557 last_split = child->split_pos; 02558 #ifdef _NO_EXTENSIONS 02559 draw_splitbar(hwnd, last_split); 02560 #endif 02561 SetCapture(hwnd); 02562 } 02563 02564 break;} 02565 02566 case WM_LBUTTONUP: 02567 if (GetCapture() == hwnd) { 02568 #ifdef _NO_EXTENSIONS 02569 RECT rt; 02570 int x = LOWORD(lparam); 02571 draw_splitbar(hwnd, last_split); 02572 last_split = -1; 02573 GetClientRect(hwnd, &rt); 02574 child->split_pos = x; 02575 resize_tree(child, rt.right, rt.bottom); 02576 #endif 02577 ReleaseCapture(); 02578 } 02579 break; 02580 02581 #ifdef _NO_EXTENSIONS 02582 case WM_CAPTURECHANGED: 02583 if (GetCapture()==hwnd && last_split>=0) 02584 draw_splitbar(hwnd, last_split); 02585 break; 02586 #endif 02587 02588 case WM_KEYDOWN: 02589 if (wparam == VK_ESCAPE) 02590 if (GetCapture() == hwnd) { 02591 RECT rt; 02592 #ifdef _NO_EXTENSIONS 02593 draw_splitbar(hwnd, last_split); 02594 #else 02595 child->split_pos = last_split; 02596 #endif 02597 GetClientRect(hwnd, &rt); 02598 resize_tree(child, rt.right, rt.bottom); 02599 last_split = -1; 02600 ReleaseCapture(); 02601 SetCursor(LoadCursor(0, IDC_ARROW)); 02602 } 02603 break; 02604 02605 case WM_MOUSEMOVE: 02606 if (GetCapture() == hwnd) { 02607 RECT rt; 02608 int x = LOWORD(lparam); 02609 02610 #ifdef _NO_EXTENSIONS 02611 HDC hdc = GetDC(hwnd); 02612 GetClientRect(hwnd, &rt); 02613 02614 rt.left = last_split-SPLIT_WIDTH/2; 02615 rt.right = last_split+SPLIT_WIDTH/2+1; 02616 InvertRect(hdc, &rt); 02617 02618 last_split = x; 02619 rt.left = x-SPLIT_WIDTH/2; 02620 rt.right = x+SPLIT_WIDTH/2+1; 02621 InvertRect(hdc, &rt); 02622 02623 ReleaseDC(hwnd, hdc); 02624 #else 02625 GetClientRect(hwnd, &rt); 02626 02627 if (x>=0 && x<rt.right) { 02628 child->split_pos = x; 02629 resize_tree(child, rt.right, rt.bottom); 02630 rt.left = x-SPLIT_WIDTH/2; 02631 rt.right = x+SPLIT_WIDTH/2+1; 02632 InvalidateRect(hwnd, &rt, FALSE); 02633 UpdateWindow(child->left.hwnd); 02634 UpdateWindow(hwnd); 02635 UpdateWindow(child->right.hwnd); 02636 } 02637 #endif 02638 } 02639 break; 02640 02641 #ifndef _NO_EXTENSIONS 02642 case WM_GETMINMAXINFO: 02643 DefMDIChildProc(hwnd, nmsg, wparam, lparam); 02644 02645 {LPMINMAXINFO lpmmi = (LPMINMAXINFO)lparam; 02646 02647 lpmmi->ptMaxTrackSize.x <<= 1;/*2*GetSystemMetrics(SM_CXSCREEN) / SM_CXVIRTUALSCREEN */ 02648 lpmmi->ptMaxTrackSize.y <<= 1;/*2*GetSystemMetrics(SM_CYSCREEN) / SM_CYVIRTUALSCREEN */ 02649 break;} 02650 #endif /* _NO_EXTENSIONS */ 02651 02652 case WM_SETFOCUS: 02653 if (SetCurrentDirectory(child->path)) 02654 set_space_status(); 02655 SetFocus(child->focus_pane? child->right.hwnd: child->left.hwnd); 02656 break; 02657 02658 case WM_DISPATCH_COMMAND: { 02659 Pane* pane = GetFocus()==child->left.hwnd? &child->left: &child->right; 02660 02661 switch(LOWORD(wparam)) { 02662 case ID_WINDOW_NEW: { 02663 ChildWnd* new_child = alloc_child_window(child->path, NULL, hwnd); 02664 02665 if (!create_child_window(new_child)) 02666 heap_free(new_child); 02667 02668 break;} 02669 02670 case ID_REFRESH: 02671 refresh_drives(); 02672 refresh_child(child); 02673 break; 02674 02675 case ID_ACTIVATE: 02676 activate_entry(child, pane, hwnd); 02677 break; 02678 02679 case ID_FILE_MOVE: { 02680 TCHAR source[BUFFER_LEN], target[BUFFER_LEN]; 02681 02682 if (prompt_target(pane, source, target)) { 02683 SHFILEOPSTRUCT shfo = {hwnd, FO_MOVE, source, target}; 02684 02685 source[lstrlen(source)+1] = '\0'; 02686 target[lstrlen(target)+1] = '\0'; 02687 02688 if (!SHFileOperation(&shfo)) 02689 refresh_child(child); 02690 } 02691 break;} 02692 02693 case ID_FILE_COPY: { 02694 TCHAR source[BUFFER_LEN], target[BUFFER_LEN]; 02695 02696 if (prompt_target(pane, source, target)) { 02697 SHFILEOPSTRUCT shfo = {hwnd, FO_COPY, source, target}; 02698 02699 source[lstrlen(source)+1] = '\0'; 02700 target[lstrlen(target)+1] = '\0'; 02701 02702 if (!SHFileOperation(&shfo)) 02703 refresh_child(child); 02704 } 02705 break;} 02706 02707 case ID_FILE_DELETE: { 02708 TCHAR path[BUFFER_LEN]; 02709 SHFILEOPSTRUCT shfo = {hwnd, FO_DELETE, path, NULL, FOF_ALLOWUNDO}; 02710 02711 get_path(pane->cur, path); 02712 02713 path[lstrlen(path)+1] = '\0'; 02714 02715 if (!SHFileOperation(&shfo)) 02716 refresh_child(child); 02717 break;} 02718 02719 case ID_VIEW_SORT_NAME: 02720 set_sort_order(child, SORT_NAME); 02721 break; 02722 02723 case ID_VIEW_SORT_TYPE: 02724 set_sort_order(child, SORT_EXT); 02725 break; 02726 02727 case ID_VIEW_SORT_SIZE: 02728 set_sort_order(child, SORT_SIZE); 02729 break; 02730 02731 case ID_VIEW_SORT_DATE: 02732 set_sort_order(child, SORT_DATE); 02733 break; 02734 02735 case ID_VIEW_FILTER: { 02736 struct FilterDialog dlg; 02737 02738 memset(&dlg, 0, sizeof(struct FilterDialog)); 02739 lstrcpy(dlg.pattern, child->filter_pattern); 02740 dlg.flags = child->filter_flags; 02741 02742 if (DialogBoxParam(Globals.hInstance, MAKEINTRESOURCE(IDD_DIALOG_VIEW_TYPE), hwnd, FilterDialogDlgProc, (LPARAM)&dlg) == IDOK) { 02743 lstrcpy(child->filter_pattern, dlg.pattern); 02744 child->filter_flags = dlg.flags; 02745 refresh_right_pane(child); 02746 } 02747 break;} 02748 02749 case ID_VIEW_SPLIT: { 02750 last_split = child->split_pos; 02751 #ifdef _NO_EXTENSIONS 02752 draw_splitbar(hwnd, last_split); 02753 #endif 02754 SetCapture(hwnd); 02755 break;} 02756 02757 case ID_EDIT_PROPERTIES: 02758 show_properties_dlg(pane->cur, child->hwnd); 02759 break; 02760 02761 default: 02762 return pane_command(pane, LOWORD(wparam)); 02763 } 02764 02765 return TRUE;} 02766 02767 case WM_COMMAND: { 02768 Pane* pane = GetFocus()==child->left.hwnd? &child->left: &child->right; 02769 02770 switch(HIWORD(wparam)) { 02771 case LBN_SELCHANGE: { 02772 int idx = ListBox_GetCurSel(pane->hwnd); 02773 Entry* entry = (Entry*) ListBox_GetItemData(pane->hwnd, idx); 02774 02775 if (pane == &child->left) 02776 set_curdir(child, entry, idx, hwnd); 02777 else 02778 pane->cur = entry; 02779 break;} 02780 02781 case LBN_DBLCLK: 02782 activate_entry(child, pane, hwnd); 02783 break; 02784 } 02785 break;} 02786 02787 #ifndef _NO_EXTENSIONS 02788 case WM_NOTIFY: { 02789 NMHDR* pnmh = (NMHDR*) lparam; 02790 return pane_notify(pnmh->idFrom==IDW_HEADER_LEFT? &child->left: &child->right, pnmh);} 02791 #endif 02792 02793 #ifdef _SHELL_FOLDERS 02794 case WM_CONTEXTMENU: { 02795 POINT pt, pt_clnt; 02796 Pane* pane; 02797 int idx; 02798 02799 /* first select the current item in the listbox */ 02800 HWND hpanel = (HWND) wparam; 02801 pt_clnt.x = pt.x = (short)LOWORD(lparam); 02802 pt_clnt.y = pt.y = (short)HIWORD(lparam); 02803 ScreenToClient(hpanel, &pt_clnt); 02804 SendMessage(hpanel, WM_LBUTTONDOWN, 0, MAKELONG(pt_clnt.x, pt_clnt.y)); 02805 SendMessage(hpanel, WM_LBUTTONUP, 0, MAKELONG(pt_clnt.x, pt_clnt.y)); 02806 02807 /* now create the popup menu using shell namespace and IContextMenu */ 02808 pane = GetFocus()==child->left.hwnd? &child->left: &child->right; 02809 idx = ListBox_GetCurSel(pane->hwnd); 02810 02811 if (idx != -1) { 02812 Entry* entry = (Entry*) ListBox_GetItemData(pane->hwnd, idx); 02813 02814 LPITEMIDLIST pidl_abs = get_to_absolute_pidl(entry, hwnd); 02815 02816 if (pidl_abs) { 02817 IShellFolder* parentFolder; 02818 LPCITEMIDLIST pidlLast; 02819 02820 /* get and use the parent folder to display correct context menu in all cases */ 02821 if (SUCCEEDED(SHBindToParent(pidl_abs, &IID_IShellFolder, (LPVOID*)&parentFolder, &pidlLast))) { 02822 if (ShellFolderContextMenu(parentFolder, hwnd, 1, &pidlLast, pt.x, pt.y) == S_OK) 02823 refresh_child(child); 02824 02825 IShellFolder_Release(parentFolder); 02826 } 02827 02828 IMalloc_Free(Globals.iMalloc, pidl_abs); 02829 } 02830 } 02831 break;} 02832 #endif 02833 02834 case WM_MEASUREITEM: 02835 draw_menu_item: 02836 if (!wparam) /* Is the message menu-related? */ 02837 if (CtxMenu_HandleMenuMsg(nmsg, wparam, lparam)) 02838 return TRUE; 02839 02840 break; 02841 02842 case WM_INITMENUPOPUP: 02843 if (CtxMenu_HandleMenuMsg(nmsg, wparam, lparam)) 02844 return 0; 02845 02846 update_view_menu(child); 02847 break; 02848 02849 case WM_MENUCHAR: /* only supported by IContextMenu3 */ 02850 if (s_pctxmenu3) { 02851 LRESULT lResult = 0; 02852 02853 (*s_pctxmenu3->lpVtbl->HandleMenuMsg2)(s_pctxmenu3, nmsg, wparam, lparam, &lResult); 02854 02855 return lResult; 02856 } 02857 02858 break; 02859 02860 case WM_SIZE: 02861 if (wparam != SIZE_MINIMIZED) 02862 resize_tree(child, LOWORD(lparam), HIWORD(lparam)); 02863 /* fall through */ 02864 02865 default: def: 02866 return DefMDIChildProc(hwnd, nmsg, wparam, lparam); 02867 } 02868 02869 return 0; 02870 } 02871 02872 02873 /* program initialisation */ 02874 02875 static void InitInstance(HINSTANCE hinstance) 02876 { 02877 static const TCHAR sFont[] = {'M','i','c','r','o','s','o','f','t',' ','S','a','n','s',' ','S','e','r','i','f','\0'}; 02878 02879 WNDCLASSEX wcFrame; 02880 WNDCLASS wcChild; 02881 ATOM hChildClass; 02882 int col; 02883 02884 INITCOMMONCONTROLSEX icc = { 02885 sizeof(INITCOMMONCONTROLSEX), 02886 ICC_BAR_CLASSES 02887 }; 02888 02889 HDC hdc = GetDC(0); 02890 02891 setlocale(LC_COLLATE, ""); /* set collating rules to local settings for compareName */ 02892 02893 InitCommonControlsEx(&icc); 02894 02895 02896 /* register frame window class */ 02897 02898 wcFrame.cbSize = sizeof(WNDCLASSEX); 02899 wcFrame.style = 0; 02900 wcFrame.lpfnWndProc = FrameWndProc; 02901 wcFrame.cbClsExtra = 0; 02902 wcFrame.cbWndExtra = 0; 02903 wcFrame.hInstance = hinstance; 02904 wcFrame.hIcon = LoadIcon(hinstance, MAKEINTRESOURCE(IDI_WINEFILE)); 02905 wcFrame.hCursor = LoadCursor(0, IDC_ARROW); 02906 wcFrame.hbrBackground = 0; 02907 wcFrame.lpszMenuName = 0; 02908 wcFrame.lpszClassName = sWINEFILEFRAME; 02909 wcFrame.hIconSm = (HICON)LoadImage(hinstance, 02910 MAKEINTRESOURCE(IDI_WINEFILE), 02911 IMAGE_ICON, 02912 GetSystemMetrics(SM_CXSMICON), 02913 GetSystemMetrics(SM_CYSMICON), 02914 LR_SHARED); 02915 02916 Globals.hframeClass = RegisterClassEx(&wcFrame); 02917 02918 02919 /* register tree windows class */ 02920 02921 wcChild.style = CS_CLASSDC|CS_DBLCLKS|CS_VREDRAW; 02922 wcChild.lpfnWndProc = ChildWndProc; 02923 wcChild.cbClsExtra = 0; 02924 wcChild.cbWndExtra = 0; 02925 wcChild.hInstance = hinstance; 02926 wcChild.hIcon = 0; 02927 wcChild.hCursor = LoadCursor(0, IDC_ARROW); 02928 wcChild.hbrBackground = 0; 02929 wcChild.lpszMenuName = 0; 02930 wcChild.lpszClassName = sWINEFILETREE; 02931 02932 hChildClass = RegisterClass(&wcChild); 02933 02934 02935 Globals.haccel = LoadAccelerators(hinstance, MAKEINTRESOURCE(IDA_WINEFILE)); 02936 02937 Globals.hfont = CreateFont(-MulDiv(8,GetDeviceCaps(hdc,LOGPIXELSY),72), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, sFont); 02938 02939 ReleaseDC(0, hdc); 02940 02941 Globals.hInstance = hinstance; 02942 02943 #ifdef _SHELL_FOLDERS 02944 CoInitialize(NULL); 02945 CoGetMalloc(MEMCTX_TASK, &Globals.iMalloc); 02946 SHGetDesktopFolder(&Globals.iDesktop); 02947 #ifdef __WINE__ 02948 Globals.cfStrFName = RegisterClipboardFormatA(CFSTR_FILENAME); 02949 #else 02950 Globals.cfStrFName = RegisterClipboardFormat(CFSTR_FILENAME); 02951 #endif 02952 #endif 02953 02954 /* load column strings */ 02955 col = 1; 02956 02957 load_string(g_pos_names[col++], IDS_COL_NAME); 02958 load_string(g_pos_names[col++], IDS_COL_SIZE); 02959 load_string(g_pos_names[col++], IDS_COL_CDATE); 02960 #ifndef _NO_EXTENSIONS 02961 load_string(g_pos_names[col++], IDS_COL_ADATE); 02962 load_string(g_pos_names[col++], IDS_COL_MDATE); 02963 load_string(g_pos_names[col++], IDS_COL_IDX); 02964 load_string(g_pos_names[col++], IDS_COL_LINKS); 02965 #endif 02966 load_string(g_pos_names[col++], IDS_COL_ATTR); 02967 #ifndef _NO_EXTENSIONS 02968 load_string(g_pos_names[col++], IDS_COL_SEC); 02969 #endif 02970 } 02971 02972 02973 /* display main frame window */ 02974 02975 static void show_frame(HWND hwndParent, int cmdshow, LPCTSTR path) 02976 { 02977 static const TCHAR sMDICLIENT[] = {'M','D','I','C','L','I','E','N','T','\0'}; 02978 02979 TCHAR buffer[MAX_PATH], b1[BUFFER_LEN]; 02980 HMENU hMenuFrame, hMenuWindow; 02981 ChildWnd* child; 02982 struct WINDOW_OPTIONS opts; 02983 02984 CLIENTCREATESTRUCT ccs; 02985 02986 if (Globals.hMainWnd) 02987 return; 02988 02989 load_registry_settings(&opts); 02990 hMenuFrame = LoadMenu(Globals.hInstance, MAKEINTRESOURCE(IDM_WINEFILE)); 02991 hMenuWindow = GetSubMenu(hMenuFrame, GetMenuItemCount(hMenuFrame)-2); 02992 02993 Globals.hMenuFrame = hMenuFrame; 02994 Globals.hMenuView = GetSubMenu(hMenuFrame, 3); 02995 Globals.hMenuOptions = GetSubMenu(hMenuFrame, 4); 02996 02997 ccs.hWindowMenu = hMenuWindow; 02998 ccs.idFirstChild = IDW_FIRST_CHILD; 02999 03000 03001 /* create main window */ 03002 Globals.hMainWnd = CreateWindowEx(0, MAKEINTRESOURCE(Globals.hframeClass), RS(b1,IDS_WINE_FILE), WS_OVERLAPPEDWINDOW, 03003 opts.start_x, opts.start_y, opts.width, opts.height, 03004 hwndParent, Globals.hMenuFrame, Globals.hInstance, 0/*lpParam*/); 03005 03006 03007 Globals.hmdiclient = CreateWindowEx(0, sMDICLIENT, NULL, 03008 WS_CHILD|WS_CLIPCHILDREN|WS_VSCROLL|WS_HSCROLL|WS_VISIBLE|WS_BORDER, 03009 0, 0, 0, 0, 03010 Globals.hMainWnd, 0, Globals.hInstance, &ccs); 03011 03012 03013 CheckMenuItem(Globals.hMenuOptions, ID_VIEW_DRIVE_BAR, MF_BYCOMMAND|MF_CHECKED); 03014 CheckMenuItem(Globals.hMenuOptions, ID_VIEW_SAVESETTINGS, MF_BYCOMMAND); 03015 03016 create_drive_bar(); 03017 03018 { 03019 TBBUTTON toolbarBtns[] = { 03020 {0, 0, 0, BTNS_SEP, {0, 0}, 0, 0}, 03021 {0, ID_WINDOW_NEW, TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0}, 03022 {1, ID_WINDOW_CASCADE, TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0}, 03023 {2, ID_WINDOW_TILE_HORZ, TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0}, 03024 {3, ID_WINDOW_TILE_VERT, TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0}, 03025 /*TODO 03026 {4, ID_... , TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0}, 03027 {5, ID_... , TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0}, 03028 */ }; 03029 03030 Globals.htoolbar = CreateToolbarEx(Globals.hMainWnd, WS_CHILD|WS_VISIBLE, 03031 IDW_TOOLBAR, 2, Globals.hInstance, IDB_TOOLBAR, toolbarBtns, 03032 sizeof(toolbarBtns)/sizeof(TBBUTTON), 16, 15, 16, 15, sizeof(TBBUTTON)); 03033 CheckMenuItem(Globals.hMenuOptions, ID_VIEW_TOOL_BAR, MF_BYCOMMAND|MF_CHECKED); 03034 } 03035 03036 Globals.hstatusbar = CreateStatusWindow(WS_CHILD|WS_VISIBLE, 0, Globals.hMainWnd, IDW_STATUSBAR); 03037 CheckMenuItem(Globals.hMenuOptions, ID_VIEW_STATUSBAR, MF_BYCOMMAND|MF_CHECKED); 03038 03039 /* CreateStatusWindow does not accept WS_BORDER 03040 Globals.hstatusbar = CreateWindowEx(WS_EX_NOPARENTNOTIFY, STATUSCLASSNAME, 0, 03041 WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS|WS_BORDER|CCS_NODIVIDER, 0,0,0,0, 03042 Globals.hMainWnd, (HMENU)IDW_STATUSBAR, hinstance, 0);*/ 03043 03044 /*TODO: read paths from registry */ 03045 03046 if (!path || !*path) { 03047 GetCurrentDirectory(MAX_PATH, buffer); 03048 path = buffer; 03049 } 03050 03051 ShowWindow(Globals.hMainWnd, cmdshow); 03052 03053 #if defined(_SHELL_FOLDERS) && 0 /* Display drive view as default. */ 03054 /* display Shell Namespace */ 03055 child = alloc_child_window(path, get_path_pidl(path,Globals.hMainWnd), Globals.hMainWnd); 03056 #else 03057 child = alloc_child_window(path, NULL, Globals.hMainWnd); 03058 #endif 03059 03060 child->pos.showCmd = SW_SHOWMAXIMIZED; 03061 child->pos.rcNormalPosition.left = 0; 03062 child->pos.rcNormalPosition.top = 0; 03063 child->pos.rcNormalPosition.right = 320; 03064 child->pos.rcNormalPosition.bottom = 280; 03065 03066 if (!create_child_window(child)) 03067 heap_free(child); 03068 03069 SetWindowPlacement(child->hwnd, &child->pos); 03070 03071 Globals.himl = ImageList_LoadBitmap(Globals.hInstance, MAKEINTRESOURCE(IDB_IMAGES), 16, 0, RGB(0,255,0)); 03072 03073 Globals.prescan_node = FALSE; 03074 03075 UpdateWindow(Globals.hMainWnd); 03076 03077 if (path && path[0]) 03078 { 03079 int index,count; 03080 TCHAR drv[_MAX_DRIVE+1], dir[_MAX_DIR], name[_MAX_FNAME], ext[_MAX_EXT]; 03081 TCHAR fullname[_MAX_FNAME+_MAX_EXT+1]; 03082 03083 memset(name,0,sizeof(name)); 03084 memset(name,0,sizeof(ext)); 03085 _tsplitpath(path, drv, dir, name, ext); 03086 if (name[0]) 03087 { 03088 count = ListBox_GetCount(child->right.hwnd); 03089 lstrcpy(fullname,name); 03090 lstrcat(fullname,ext); 03091 03092 for (index = 0; index < count; index ++) 03093 { 03094 Entry* entry = (Entry*) ListBox_GetItemData(child->right.hwnd, index); 03095 if (lstrcmp(entry->data.cFileName,fullname)==0 || 03096 lstrcmp(entry->data.cAlternateFileName,fullname)==0) 03097 { 03098 (void)ListBox_SetCurSel(child->right.hwnd, index); 03099 SetFocus(child->right.hwnd); 03100 break; 03101 } 03102 } 03103 } 03104 } 03105 } 03106 03107 03108 /* release memory on program termination */ 03109 03110 static void ExitInstance(void) 03111 { 03112 #ifdef _SHELL_FOLDERS 03113 IShellFolder_Release(Globals.iDesktop); 03114 IMalloc_Release(Globals.iMalloc); 03115 CoUninitialize(); 03116 #endif 03117 03118 DeleteObject(Globals.hfont); 03119 ImageList_Destroy(Globals.himl); 03120 } 03121 03122 03123 #ifdef _NO_EXTENSIONS 03124 03125 /* search for already running win[e]file instances */ 03126 03127 static int g_foundPrevInstance = 0; 03128 03129 /* callback fucntion to enumerate Win[e]file frame windows */ 03130 static BOOL CALLBACK EnumWndProc(HWND hwnd, LPARAM lparam) 03131 { 03132 TCHAR cls[128]; 03133 03134 GetClassName(hwnd, cls, 128); 03135 03136 if (!lstrcmp(cls, (LPCTSTR)lparam)) { 03137 g_foundPrevInstance++; 03138 return FALSE; 03139 } 03140 03141 return TRUE; 03142 } 03143 03144 /* search for window of given class name to allow only one running instance */ 03145 static int find_window_class(LPCTSTR classname) 03146 { 03147 EnumWindows(EnumWndProc, (LPARAM)classname); 03148 03149 if (g_foundPrevInstance) 03150 return 1; 03151 03152 return 0; 03153 } 03154 03155 #endif 03156 03157 03158 /* main function */ 03159 03160 static int winefile_main(HINSTANCE hinstance, int cmdshow, LPCTSTR path) 03161 { 03162 MSG msg; 03163 03164 InitInstance(hinstance); 03165 03166 show_frame(0, cmdshow, path); 03167 03168 while(GetMessage(&msg, 0, 0, 0)) { 03169 if (Globals.hmdiclient && TranslateMDISysAccel(Globals.hmdiclient, &msg)) 03170 continue; 03171 03172 if (Globals.hMainWnd && TranslateAccelerator(Globals.hMainWnd, Globals.haccel, &msg)) 03173 continue; 03174 03175 TranslateMessage(&msg); 03176 DispatchMessage(&msg); 03177 } 03178 03179 ExitInstance(); 03180 03181 return msg.wParam; 03182 } 03183 03184 03185 /* program entry function */ 03186 03187 #if defined(UNICODE) && defined(_MSC_VER) 03188 int APIENTRY wWinMain(HINSTANCE hinstance, HINSTANCE previnstance, LPWSTR cmdline, int cmdshow) 03189 #else 03190 int APIENTRY WinMain(HINSTANCE hinstance, HINSTANCE previnstance, LPSTR cmdline, int cmdshow) 03191 #endif 03192 { 03193 #ifdef _NO_EXTENSIONS 03194 if (find_window_class(sWINEFILEFRAME)) 03195 return 1; 03196 #endif 03197 03198 #if defined(UNICODE) && !defined(_MSC_VER) 03199 { /* convert ANSI cmdline into WCS path string */ 03200 TCHAR buffer[MAX_PATH]; 03201 MultiByteToWideChar(CP_ACP, 0, cmdline, -1, buffer, MAX_PATH); 03202 winefile_main(hinstance, cmdshow, buffer); 03203 } 03204 #else 03205 winefile_main(hinstance, cmdshow, cmdline); 03206 #endif 03207 03208 return 0; 03209 }
Winefile Source Code Documentation
generated on 15.09.2008 by |