/* * ReactOS winfile * * utils.c * * Copyright (C) 2002 Robert Dickenson * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers #include #include #include #include #include #include #include #include #include #include #include "main.h" #include "listview.h" #include "utils.h" #include "sort.h" #define FRM_CALC_CLIENT 0xBF83 #define Frame_CalcFrameClient(hWnd, prt) ((BOOL)SNDMSG(hWnd, FRM_CALC_CLIENT, 0, (LPARAM)(PRECT)prt)) void display_error(HWND hWnd, DWORD error) { PTSTR msg; if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, 0, error, MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), (PTSTR)&msg, 0, NULL)) MessageBox(hWnd, msg, _T("Winefile"), MB_OK); else MessageBox(hWnd, _T("Error"), _T("Winefile"), MB_OK); LocalFree(msg); } static void read_directory_win(Entry* parent, LPCTSTR path) { Entry* entry = (Entry*) malloc(sizeof(Entry)); int level = parent->level + 1; Entry* last = 0; HANDLE hFind; //#ifndef _NO_EXTENSIONS HANDLE hFile; //#endif TCHAR buffer[MAX_PATH], *p; for(p=buffer; *path; ) *p++ = *path++; lstrcpy(p, _T("\\*")); memset(entry, 0, sizeof(Entry)); hFind = FindFirstFile(buffer, &entry->data); if (hFind != INVALID_HANDLE_VALUE) { parent->down = entry; do { entry->down = 0; entry->up = parent; entry->expanded = FALSE; entry->scanned = FALSE; entry->level = level; //#ifdef _NO_EXTENSIONS #if 0 // hide directory entry "." if (entry->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { LPCTSTR name = entry->data.cFileName; if (name[0]=='.' && name[1]=='\0') continue; } #else entry->unix_dir = FALSE; entry->bhfi_valid = FALSE; lstrcpy(p+1, entry->data.cFileName); hFile = CreateFile(buffer, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0); if (hFile != INVALID_HANDLE_VALUE) { if (GetFileInformationByHandle(hFile, &entry->bhfi)) entry->bhfi_valid = TRUE; CloseHandle(hFile); } #endif last = entry; entry = (Entry*) malloc(sizeof(Entry)); memset(entry, 0, sizeof(Entry)); if (last) last->next = entry; } while(FindNextFile(hFind, &entry->data)); last->next = 0; FindClose(hFind); } else parent->down = 0; free(entry); parent->scanned = TRUE; } void read_directory(Entry* parent, LPCTSTR path, int sortOrder) { TCHAR buffer[MAX_PATH]; Entry* entry; LPCTSTR s; PTSTR d; #if !defined(_NO_EXTENSIONS) && defined(__linux__) if (parent->unix_dir) { read_directory_unix(parent, path); if (Globals.prescan_node) { s = path; d = buffer; while(*s) *d++ = *s++; *d++ = _T('/'); for(entry=parent->down; entry; entry=entry->next) if (entry->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { lstrcpy(d, entry->data.cFileName); read_directory_unix(entry, buffer); SortDirectory(entry, sortOrder); } } } else #endif { read_directory_win(parent, path); if (Globals.prescan_node) { s = path; d = buffer; while(*s) *d++ = *s++; *d++ = _T('\\'); for(entry=parent->down; entry; entry=entry->next) if (entry->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { lstrcpy(d, entry->data.cFileName); read_directory_win(entry, buffer); SortDirectory(entry, sortOrder); } } } SortDirectory(parent, sortOrder); } // get full path of specified directory entry void get_path(Entry* dir, PTSTR path) { Entry* entry; int len = 0; int level = 0; for(entry=dir; entry; level++) { LPCTSTR name = entry->data.cFileName; LPCTSTR s = name; int l; for(l=0; *s && *s!=_T('/') && *s!=_T('\\'); s++) l++; if (entry->up) { memmove(path+l+1, path, len*sizeof(TCHAR)); memcpy(path+1, name, l*sizeof(TCHAR)); len += l+1; #ifndef _NO_EXTENSIONS if (entry->unix_dir) path[0] = _T('/'); else #endif path[0] = _T('\\'); entry = entry->up; } else { memmove(path+l, path, len*sizeof(TCHAR)); memcpy(path, name, l*sizeof(TCHAR)); len += l; break; } } if (!level) { #ifndef _NO_EXTENSIONS if (entry->unix_dir) path[len++] = _T('/'); else #endif path[len++] = _T('\\'); } path[len] = _T('\0'); } #ifndef _NO_EXTENSIONS void frame_get_clientspace(HWND hWnd, PRECT prect) { RECT rt; if (!IsIconic(hWnd)) GetClientRect(hWnd, prect); else { WINDOWPLACEMENT wp; GetWindowPlacement(hWnd, &wp); prect->left = prect->top = 0; prect->right = wp.rcNormalPosition.right-wp.rcNormalPosition.left- 2*(GetSystemMetrics(SM_CXSIZEFRAME)+GetSystemMetrics(SM_CXEDGE)); prect->bottom = wp.rcNormalPosition.bottom-wp.rcNormalPosition.top- 2*(GetSystemMetrics(SM_CYSIZEFRAME)+GetSystemMetrics(SM_CYEDGE))- GetSystemMetrics(SM_CYCAPTION)-GetSystemMetrics(SM_CYMENUSIZE); } if (IsWindowVisible(Globals.hToolBar)) { GetClientRect(Globals.hToolBar, &rt); prect->top += rt.bottom+2; } if (IsWindowVisible(Globals.hDriveBar)) { GetClientRect(Globals.hDriveBar, &rt); prect->top += rt.bottom+2; } if (IsWindowVisible(Globals.hStatusBar)) { GetClientRect(Globals.hStatusBar, &rt); prect->bottom -= rt.bottom; } } #endif int is_exe_file(LPCTSTR ext) { const static LPCTSTR executable_extensions[] = { _T("COM"), _T("EXE"), _T("BAT"), _T("CMD"), #ifndef _NO_EXTENSIONS _T("CMM"), _T("BTM"), _T("AWK"), #endif 0 }; TCHAR ext_buffer[_MAX_EXT]; const LPCTSTR* p; LPCTSTR s; LPTSTR d; for (s = ext + 1, d = ext_buffer; (*d = tolower(*s)); s++) d++; for (p = executable_extensions; *p; p++) if (!_tcscmp(ext_buffer, *p)) return 1; return 0; } int is_registered_type(LPCTSTR ext) { //TODO return 1; } void set_curdir(ChildWnd* child, Entry* entry) { TCHAR path[MAX_PATH]; // child->left.cur = entry; // child->right.root = entry; // child->right.cur = entry; if (!entry->scanned) scan_entry(child, entry); else { // ListBox_ResetContent(child->hListWnd); // insert_entries(&child->right, entry->down, -1); // RefreshList(child->hListWnd, entry); // calc_widths(&child->right, FALSE); //#ifndef _NO_EXTENSIONS // set_header(&child->right); //#endif } RefreshList(child->hListWnd, entry->down); get_path(entry, path); lstrcpy(child->szPath, path); SetWindowText(child->hWnd, path); SetCurrentDirectory(path); } // calculate prefered width for all visible columns BOOL calc_widths(Pane* pane, BOOL anyway) { int col, x, cx, spc=3*Globals.spaceSize.cx; int entries = ListBox_GetCount(pane->hWnd); int orgWidths[COLUMNS]; int orgPositions[COLUMNS+1]; HFONT hfontOld; HDC hdc; int cnt; if (!anyway) { memcpy(orgWidths, pane->widths, sizeof(orgWidths)); memcpy(orgPositions, pane->positions, sizeof(orgPositions)); } for (col = 0; col < COLUMNS; col++) pane->widths[col] = 0; hdc = GetDC(pane->hWnd); hfontOld = SelectFont(hdc, Globals.hFont); for (cnt = 0; cnt < entries; cnt++) { #if 0 Entry* entry = (Entry*) ListBox_GetItemData(pane->hWnd, cnt); DRAWITEMSTRUCT dis = {0/*CtlType*/, 0/*CtlID*/, 0/*itemID*/, 0/*itemAction*/, 0/*itemState*/, pane->hWnd/*hwndItem*/, hdc}; draw_item(pane, &dis, entry, COLUMNS); #endif } SelectObject(hdc, hfontOld); ReleaseDC(pane->hWnd, hdc); x = 0; for ( col = 0; col < COLUMNS; col++) { pane->positions[col] = x; cx = pane->widths[col]; if (cx) { cx += spc; if (cx < IMAGE_WIDTH) cx = IMAGE_WIDTH; pane->widths[col] = cx; } x += cx; } pane->positions[COLUMNS] = x; ListBox_SetHorizontalExtent(pane->hWnd, x); // no change? if (!memcmp(orgWidths, pane->widths, sizeof(orgWidths))) return FALSE; // don't move, if only collapsing an entry if (!anyway && pane->widths[0]widths+1, sizeof(orgWidths)-sizeof(int))) { pane->widths[0] = orgWidths[0]; memcpy(pane->positions, orgPositions, sizeof(orgPositions)); return FALSE; } InvalidateRect(pane->hWnd, 0, TRUE); return TRUE; } // calculate one prefered column width void calc_single_width(Pane* pane, int col) { HFONT hfontOld; int x, cx; int entries = ListBox_GetCount(pane->hWnd); int cnt; HDC hdc; pane->widths[col] = 0; hdc = GetDC(pane->hWnd); hfontOld = SelectFont(hdc, Globals.hFont); for (cnt = 0; cnt < entries; cnt++) { #if 0 Entry* entry = (Entry*) ListBox_GetItemData(pane->hWnd, cnt); DRAWITEMSTRUCT dis = {0, 0, 0, 0, 0, pane->hWnd, hdc}; draw_item(pane, &dis, entry, col); #endif } SelectObject(hdc, hfontOld); ReleaseDC(pane->hWnd, hdc); cx = pane->widths[col]; if (cx) { cx += 3*Globals.spaceSize.cx; if (cx < IMAGE_WIDTH) cx = IMAGE_WIDTH; } pane->widths[col] = cx; x = pane->positions[col] + cx; for(; colpositions[++col] = x; x += pane->widths[col]; } ListBox_SetHorizontalExtent(pane->hWnd, x); } #ifndef _NO_EXTENSIONS static struct FullScreenParameters { BOOL mode; RECT orgPos; BOOL wasZoomed; } g_fullscreen = { FALSE // mode }; BOOL toggle_fullscreen(HWND hWnd) { RECT rt; if ((g_fullscreen.mode=!g_fullscreen.mode)) { GetWindowRect(hWnd, &g_fullscreen.orgPos); g_fullscreen.wasZoomed = IsZoomed(hWnd); Frame_CalcFrameClient(hWnd, &rt); ClientToScreen(hWnd, (LPPOINT)&rt.left); ClientToScreen(hWnd, (LPPOINT)&rt.right); rt.left = g_fullscreen.orgPos.left-rt.left; rt.top = g_fullscreen.orgPos.top-rt.top; rt.right = GetSystemMetrics(SM_CXSCREEN)+g_fullscreen.orgPos.right-rt.right; rt.bottom = GetSystemMetrics(SM_CYSCREEN)+g_fullscreen.orgPos.bottom-rt.bottom; MoveWindow(hWnd, rt.left, rt.top, rt.right-rt.left, rt.bottom-rt.top, TRUE); } else { MoveWindow(hWnd, g_fullscreen.orgPos.left, g_fullscreen.orgPos.top, g_fullscreen.orgPos.right-g_fullscreen.orgPos.left, g_fullscreen.orgPos.bottom-g_fullscreen.orgPos.top, TRUE); if (g_fullscreen.wasZoomed) ShowWindow(hWnd, WS_MAXIMIZE); } return g_fullscreen.mode; } void fullscreen_move(HWND hWnd) { RECT rt, pos; GetWindowRect(hWnd, &pos); Frame_CalcFrameClient(hWnd, &rt); ClientToScreen(hWnd, (LPPOINT)&rt.left); ClientToScreen(hWnd, (LPPOINT)&rt.right); rt.left = pos.left-rt.left; rt.top = pos.top-rt.top; rt.right = GetSystemMetrics(SM_CXSCREEN)+pos.right-rt.right; rt.bottom = GetSystemMetrics(SM_CYSCREEN)+pos.bottom-rt.bottom; MoveWindow(hWnd, rt.left, rt.top, rt.right-rt.left, rt.bottom-rt.top, TRUE); } #endif