| /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
| /* ***** BEGIN LICENSE BLOCK ***** |
| * Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
| * |
| * The contents of this file are subject to the Mozilla Public License Version |
| * 1.1 (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * http://www.mozilla.org/MPL/ |
| * |
| * Software distributed under the License is distributed on an "AS IS" basis, |
| * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
| * for the specific language governing rights and limitations under the |
| * License. |
| * |
| * The Original Code is mozilla.org code. |
| * |
| * The Initial Developer of the Original Code is |
| * Netscape Communications Corporation. |
| * Portions created by the Initial Developer are Copyright (C) 1998 |
| * the Initial Developer. All Rights Reserved. |
| * |
| * Contributor(s): |
| * |
| * Alternatively, the contents of this file may be used under the terms of |
| * either the GNU General Public License Version 2 or later (the "GPL"), or |
| * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), |
| * in which case the provisions of the GPL or the LGPL are applicable instead |
| * of those above. If you wish to allow use of your version of this file only |
| * under the terms of either the GPL or the LGPL, and not to allow others to |
| * use your version of this file under the terms of the MPL, indicate your |
| * decision by deleting the provisions above and replace them with the notice |
| * and other provisions required by the GPL or the LGPL. If you do not delete |
| * the provisions above, a recipient may use your version of this file under |
| * the terms of any one of the MPL, the GPL or the LGPL. |
| * |
| * ***** END LICENSE BLOCK ***** */ |
| #define _CRT_SECURE_NO_DEPRECATE |
| |
| #include <windows.h> |
| #include <windowsx.h> |
| #include <direct.h> |
| #include <stdio.h> |
| |
| #include "resource.h" |
| |
| extern HINSTANCE hInst; |
| |
| #define ITEM_BITMAPWIDTH 16 |
| #define ITEM_BITMAPHEIGHT 16 |
| #define ITEM_LEFTMARGIN 4 |
| #define ITEM_GAP 4 |
| |
| static HWND hWndDirPicker; |
| static HICON hIconDrives[5]; |
| static HICON hIconFolders[3]; |
| static LPSTR lpszStringToReturn; |
| static char szUNCRoot[256] = ""; |
| |
| UINT DriveType(UINT iType); |
| |
| static void fillComboBox(HWND hWnd) |
| { |
| HWND hWndCB = GetDlgItem(hWnd, ID_COMBO_DIR); |
| HWND hWndTempLB = GetDlgItem(hWnd, ID_LISTTEMP_DIR); |
| if(hWndCB == NULL) |
| return; |
| ComboBox_ResetContent(hWndCB); |
| ListBox_ResetContent(hWndTempLB); |
| ListBox_Dir(hWndTempLB, DDL_DRIVES|DDL_EXCLUSIVE, (LPSTR)"*"); |
| |
| int iDriveCount = ListBox_GetCount(hWndTempLB); |
| int iCurDrive=_getdrive() - 1; |
| |
| char szDrive[16]; |
| char szItem[80]; |
| |
| for (int i = 0; i < iDriveCount; i++) |
| { |
| ListBox_GetText(hWndTempLB, i, szDrive); |
| CharLower(szDrive); |
| int iDrive = szDrive[2] - 'a'; |
| char szRoot[16]; |
| sprintf(szRoot, "%c:\\", szDrive[2]); |
| |
| int iType = DriveType(iDrive); |
| |
| if(iType < 2) |
| continue; |
| |
| //Start the item string with the drive letter, colon, and two spaces |
| sprintf(szItem, "%c%s", szDrive[2], ": "); |
| |
| if((iType == DRIVE_FIXED) || (iType == DRIVE_RAMDISK)) |
| { // get volume ID |
| char szVolumeID[80]; |
| DWORD dwMaxLength; |
| DWORD dwSysFlags; |
| GetVolumeInformation(szRoot, // address of root directory of the file system |
| szVolumeID, // address of name of the volume |
| sizeof(szVolumeID), // length of lpVolumeNameBuffer |
| NULL, // address of volume serial number |
| &dwMaxLength, // address of system's maximum filename length |
| &dwSysFlags, // address of file system flags |
| NULL, // address of name of file system |
| NULL); // length of lpFileSystemNameBuffer |
| |
| CharLower(szVolumeID); |
| lstrcat(szItem, szVolumeID); |
| } |
| |
| //For network drives, go grab the \\server\share for it. |
| if(DRIVE_REMOTE == iType) |
| { |
| char szNet[64]; |
| szNet[0] = '\0'; |
| DWORD dwSizeOfszNet = sizeof(szNet); |
| |
| sprintf(szDrive, "%c:", szDrive[2]); |
| CharUpper(szDrive); |
| WNetGetConnection(szDrive, szNet, &dwSizeOfszNet); |
| CharLower(szNet); |
| lstrcat(szItem, szNet); |
| } |
| |
| int index = ComboBox_AddString(hWndCB, szItem); |
| ComboBox_SetItemData(hWndCB, index, MAKELONG(iDrive, iType)); |
| if(iDrive == iCurDrive) |
| ComboBox_SetCurSel(hWndCB, index); |
| if(szUNCRoot[0] != '\0') |
| ComboBox_SetCurSel(hWndCB, -1); |
| } |
| } |
| |
| static void fillTempLBWithDirs(HWND hWndTempLB, LPSTR lpszDir) |
| { |
| BOOL bDone = FALSE; |
| WIN32_FIND_DATA ffdataStruct; |
| |
| char szPath[_MAX_PATH]; |
| char szFileName[_MAX_PATH]; |
| lstrcpy(szPath, lpszDir); |
| if(szPath[lstrlen(szPath) - 1] == '\\') |
| szPath[lstrlen(szPath) - 1] = '\0'; |
| lstrcpy(szFileName, szPath); |
| lstrcat(szFileName, "\\*"); |
| HANDLE handle = FindFirstFile(szFileName, &ffdataStruct); |
| if(handle == INVALID_HANDLE_VALUE) |
| { |
| FindClose(handle); |
| return; |
| } |
| while(!bDone) |
| { |
| lstrcpy(szFileName, szPath); |
| lstrcat(szFileName, "\\"); |
| lstrcat(szFileName, ffdataStruct.cFileName); |
| if(ffdataStruct. dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) |
| { |
| char szStringToAdd[_MAX_PATH + 2]; |
| lstrcpy(szStringToAdd, "["); |
| lstrcat(szStringToAdd, ffdataStruct.cFileName); |
| lstrcat(szStringToAdd, "]"); |
| CharLower(szStringToAdd); |
| ListBox_AddString(hWndTempLB, szStringToAdd); |
| } |
| bDone = !FindNextFile(handle, &ffdataStruct); |
| } |
| FindClose(handle); |
| } |
| |
| static void fillListBox(HWND hWnd, LPSTR lpszDir) |
| { |
| HWND hWndLB = GetDlgItem(hWnd, ID_LIST_DIR); |
| HWND hWndTempLB = GetDlgItem(hWnd, ID_LISTTEMP_DIR); |
| HWND hWndEdit = GetDlgItem(hWnd, ID_EDIT_DIR); |
| if((hWndLB == NULL) || (lpszDir == NULL)) |
| return; |
| |
| int iLastChar = lstrlen(lpszDir); |
| if(lpszDir[iLastChar - 1] == '\\') |
| lpszDir[iLastChar - 1] = '\0'; |
| |
| SetWindowRedraw(hWndLB, FALSE); |
| ListBox_ResetContent(hWndLB); |
| ListBox_ResetContent(hWndTempLB); |
| |
| LPSTR lpszLast; |
| lpszLast = CharLower(lpszDir); |
| |
| SetWindowText(hWndLB, lpszDir); |
| |
| char szDir[_MAX_DIR]; |
| char szFullDir[_MAX_DIR]; |
| sprintf(szFullDir, "%s", lpszDir); |
| sprintf(szDir, "%s\\*.*", lpszDir); |
| |
| BOOL bFirst = TRUE; |
| char ch; |
| int index; |
| while (TRUE) |
| { |
| LPSTR lpsz; |
| if((lpszDir[0] == '\\') && (lpszDir[1] == '\\') && bFirst) |
| lpsz = strchr(lpszLast + lstrlen(szUNCRoot), '\\'); |
| else |
| lpsz = strchr(lpszLast, '\\'); |
| if(lpsz != NULL) { |
| if (bFirst) |
| ch = *(++lpsz); |
| else |
| ch = *lpsz; |
| *lpsz = 0; |
| } |
| else |
| { |
| //If we're looking at a drive only, then append a backslash |
| if (lpszLast == lpszDir && bFirst) |
| lstrcat(lpszLast, "\\"); |
| } |
| //Add the drive string--includes the last one where lpsz == NULL |
| index = ListBox_AddString(hWndLB, lpszLast); |
| |
| UINT i = (NULL != lpsz) ? ID_ICON_FOLDEROPEN : ID_ICON_OPENSELECT; |
| ListBox_SetItemData(hWndLB, index, MAKELONG(index, i)); |
| |
| if(NULL == lpsz) |
| break; |
| |
| //Restore last character. |
| *lpsz = ch; |
| lpsz += (bFirst) ? 0 : 1; |
| |
| bFirst=FALSE; |
| lpszLast = lpsz; |
| } |
| int indent = index + 1; |
| |
| //Get available directories |
| fillTempLBWithDirs(hWndTempLB, lpszDir); |
| |
| int itemCount = ListBox_GetCount(hWndTempLB); |
| |
| int i=0; |
| for (i = 0; i < itemCount; i++) { |
| index = ListBox_GetText(hWndTempLB, i, lpszDir); |
| //Skip directories beginning with . (skipping . and ..) |
| if(lpszDir[1] == '.') |
| continue; |
| //Remove the ending ']' |
| iLastChar = lstrlen(lpszDir); |
| lpszDir[iLastChar - 1] = '\0'; |
| //Add the string to the real directory list. |
| index = ListBox_AddString(hWndLB, lpszDir + 1); |
| ListBox_SetItemData(hWndLB, index, MAKELONG(indent, ID_ICON_FOLDERCLOSED)); |
| } |
| //Force a listbox repaint. |
| SetWindowRedraw(hWndLB, TRUE); |
| InvalidateRect(hWndLB, NULL, TRUE); |
| |
| if(szFullDir[lstrlen(szFullDir) - 1] == ':') |
| lstrcat(szFullDir, "\\"); |
| Edit_SetText(hWndEdit, szFullDir); |
| |
| GetScrollRange(hWndLB, SB_VERT, (LPINT)&i, (LPINT)&index); |
| |
| if(!(i == 0 && index == 0)) |
| ListBox_SetTopIndex(hWndLB, max((int)(index - 2), 0)); |
| |
| ListBox_SetCurSel(hWndLB, indent - 1); |
| } |
| |
| static void onDrawItem(LPDRAWITEMSTRUCT lpdis, BOOL bDrive) |
| { |
| if((int)lpdis->itemID < 0) |
| return; |
| |
| char szItem[_MAX_DIR]; |
| DWORD dwItemData; |
| |
| if(bDrive) |
| { |
| dwItemData = ComboBox_GetItemData(lpdis->hwndItem, lpdis->itemID); |
| ComboBox_GetLBText(lpdis->hwndItem, lpdis->itemID, szItem); |
| } |
| else |
| { |
| dwItemData = ListBox_GetItemData(lpdis->hwndItem, lpdis->itemID); |
| ListBox_GetText(lpdis->hwndItem, lpdis->itemID, szItem); |
| } |
| |
| if(lpdis->itemAction & (ODA_DRAWENTIRE | ODA_SELECT)) |
| { |
| COLORREF colorText; |
| COLORREF colorBack; |
| if(lpdis->itemState & ODS_SELECTED) |
| { |
| colorText = SetTextColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT)); |
| colorBack = SetBkColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT)); |
| } |
| HICON hIcon; |
| int indent = 0; |
| if(bDrive) |
| { |
| int iType=(int)HIWORD(dwItemData); |
| switch (iType) |
| { |
| case DRIVE_REMOVABLE: |
| hIcon = hIconDrives[0]; |
| break; |
| case DRIVE_FIXED: |
| hIcon = hIconDrives[1]; |
| break; |
| case DRIVE_REMOTE: |
| hIcon = hIconDrives[2]; |
| break; |
| case DRIVE_CDROM: |
| hIcon = hIconDrives[3]; |
| break; |
| case DRIVE_RAMDISK: |
| hIcon = hIconDrives[4]; |
| break; |
| } |
| |
| } |
| else |
| { |
| int iconID = (int)HIWORD(lpdis->itemData); |
| switch (iconID) |
| { |
| case ID_ICON_FOLDERCLOSED: |
| hIcon = hIconFolders[0]; |
| break; |
| case ID_ICON_FOLDEROPEN: |
| hIcon = hIconFolders[1]; |
| break; |
| case ID_ICON_OPENSELECT: |
| hIcon = hIconFolders[2]; |
| break; |
| } |
| indent = 4 * (1 + LOWORD(lpdis->itemData)); |
| } |
| |
| ExtTextOut(lpdis->hDC, |
| lpdis->rcItem.left + ITEM_LEFTMARGIN + ITEM_BITMAPWIDTH + ITEM_GAP + indent, |
| lpdis->rcItem.top, |
| ETO_OPAQUE | ETO_CLIPPED, |
| &lpdis->rcItem, |
| szItem, |
| lstrlen(szItem), |
| NULL); |
| |
| BOOL res = DrawIcon(lpdis->hDC, |
| lpdis->rcItem.left + ITEM_LEFTMARGIN + indent, |
| lpdis->rcItem.top, |
| hIcon); |
| |
| if(lpdis->itemState & ODS_SELECTED) |
| { |
| SetTextColor(lpdis->hDC, colorText); |
| SetBkColor(lpdis->hDC, colorBack); |
| } |
| } |
| if((lpdis->itemAction & ODA_FOCUS) || (lpdis->itemState & ODS_FOCUS)) |
| DrawFocusRect(lpdis->hDC, &lpdis->rcItem); |
| } |
| |
| static void fillUNCRootArray(LPSTR lpsz) |
| { |
| char szCurDir[_MAX_PATH]; |
| _getcwd(szCurDir, sizeof(szCurDir)); |
| lstrcpy(szUNCRoot, lpsz); |
| if(szUNCRoot[lstrlen(szUNCRoot) - 1] == '\\') |
| szUNCRoot[lstrlen(szUNCRoot) - 1] = '\0'; |
| for(;;) |
| { |
| LPSTR lptemp = strrchr(szUNCRoot, '\\'); |
| if(lptemp == NULL) |
| break; |
| *lptemp = '\0'; |
| if(_chdir(szUNCRoot) == -1) |
| { |
| *lptemp = '\\'; |
| break; |
| } |
| } |
| _chdir(szCurDir); |
| } |
| |
| static void onInitDialog(HWND hWnd, LPSTR lpsz) |
| { |
| hWndDirPicker = hWnd; |
| lpszStringToReturn = lpsz; |
| |
| hIconDrives[0] = LoadIcon(hInst, MAKEINTRESOURCE(ID_ICON_DRIVEFLOPPY)); |
| hIconDrives[1] = LoadIcon(hInst, MAKEINTRESOURCE(ID_ICON_DRIVEHARD)); |
| hIconDrives[2] = LoadIcon(hInst, MAKEINTRESOURCE(ID_ICON_DRIVENETWORK)); |
| hIconDrives[3] = LoadIcon(hInst, MAKEINTRESOURCE(ID_ICON_DRIVECDROM)); |
| hIconDrives[4] = LoadIcon(hInst, MAKEINTRESOURCE(ID_ICON_DRIVERAM)); |
| |
| hIconFolders[0] = LoadIcon(hInst, MAKEINTRESOURCE(ID_ICON_FOLDERCLOSED)); |
| hIconFolders[1] = LoadIcon(hInst, MAKEINTRESOURCE(ID_ICON_FOLDEROPEN)); |
| hIconFolders[2] = LoadIcon(hInst, MAKEINTRESOURCE(ID_ICON_OPENSELECT)); |
| |
| if(lpsz[0] == '\0') |
| _getcwd(lpsz, _MAX_PATH); |
| else if(lpsz[lstrlen(lpsz) - 1] == ':') |
| lstrcat(lpsz, "\\"); |
| |
| int ret = _chdir(lpsz); |
| if(ret == -1) |
| { |
| char szText[_MAX_PATH + 80]; |
| sprintf(szText, "The specified directory %s\ncannot be found", lpsz); |
| MessageBox(GetParent(hWnd), szText, "Choose Directory", MB_ICONEXCLAMATION|MB_OK); |
| _getcwd(lpsz, _MAX_PATH); |
| } |
| if((lpsz[0] == '\\') && (lpsz[1] == '\\')) |
| fillUNCRootArray(lpsz); |
| fillListBox(hWnd, lpsz); |
| fillComboBox(hWnd); |
| } |
| |
| static void shutDialog(HWND hWnd) |
| { |
| szUNCRoot[0] = '\0'; |
| } |
| |
| static void onCommand(HWND hWnd, int id, HWND hWndCtl, UINT codeNotify) |
| { |
| char szCurDir[_MAX_PATH]; |
| switch(id) |
| { |
| case ID_LIST_DIR: |
| if(codeNotify == LBN_DBLCLK) |
| { |
| int index = ListBox_GetCurSel(hWndCtl); |
| DWORD dwItemData = ListBox_GetItemData(hWndCtl, index); |
| |
| if(HIWORD(dwItemData) == ID_ICON_OPENSELECT) |
| { |
| shutDialog(hWnd); |
| char szString[_MAX_PATH]; |
| Edit_GetText(GetDlgItem(hWndDirPicker, ID_EDIT_DIR), szString, sizeof(szString)); |
| lstrcpy(lpszStringToReturn, szString); |
| EndDialog(hWnd, IDOK); |
| break; |
| } |
| |
| ListBox_GetText(hWndCtl, index, szCurDir); |
| |
| char szDir[_MAX_DIR]; |
| LPSTR lpsz; |
| if((HIWORD(dwItemData) == ID_ICON_FOLDEROPEN) && (index != 0)) |
| { |
| GetWindowText(hWndCtl, szDir, sizeof(szDir)); |
| lpsz=_fstrstr(szDir, szCurDir); |
| *(lpsz + lstrlen(szCurDir)) = '\0'; |
| lstrcpy(szCurDir, szDir); |
| } |
| if (_chdir(szCurDir) == 0) |
| { |
| _getcwd(szCurDir, _MAX_PATH); |
| fillListBox(hWndDirPicker, szCurDir); |
| } |
| } |
| break; |
| case ID_COMBO_DIR: |
| if(codeNotify == CBN_SELCHANGE) |
| { |
| char szDrive[80]; |
| int index = ComboBox_GetCurSel(hWndCtl); |
| if(index == CB_ERR) |
| break; |
| ComboBox_GetLBText(hWndCtl, index, szDrive); |
| |
| int iCurDrive = _getdrive(); |
| Retry: |
| HCURSOR hCursorOld = SetCursor(LoadCursor(NULL, IDC_WAIT)); |
| SetCapture(hWndDirPicker); |
| if((0 == _chdrive((int)(szDrive[0] - 'a' + 1))) && (NULL != _getcwd(szCurDir, _MAX_PATH))) |
| { |
| fillListBox(hWndDirPicker, szCurDir); |
| ListBox_SetTopIndex(GetDlgItem(hWndDirPicker, ID_LIST_DIR), 0); |
| SetCursor(hCursorOld); |
| ReleaseCapture(); |
| break; |
| } |
| SetCursor(hCursorOld); |
| ReleaseCapture(); |
| |
| char szText[80]; |
| sprintf(szText, "Cannot read drive %c:", szDrive[0]); |
| if(IDRETRY == MessageBox(hWndDirPicker, szText, "Choose Directory", MB_ICONEXCLAMATION|MB_RETRYCANCEL)) |
| goto Retry; |
| |
| //Changing drives failed so restore drive and selection |
| _chdrive(iCurDrive); |
| |
| sprintf(szDrive, "%c:", (char)(iCurDrive + 'a' - 1)); |
| index = ComboBox_SelectString(hWndCtl, -1, szDrive); |
| } |
| break; |
| case IDOK: |
| shutDialog(hWnd); |
| char szString[_MAX_PATH]; |
| Edit_GetText(GetDlgItem(hWndDirPicker, ID_EDIT_DIR), szString, sizeof(szString)); |
| lstrcpy(lpszStringToReturn, szString); |
| EndDialog(hWnd, IDOK); |
| break; |
| case IDCANCEL: |
| shutDialog(hWnd); |
| lpszStringToReturn[0] = '\0'; |
| EndDialog(hWnd, IDCANCEL); |
| break; |
| default: |
| break; |
| } |
| } |
| |
| static BOOL CALLBACK DirPickDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) |
| { |
| switch(msg) { |
| case WM_INITDIALOG: |
| onInitDialog(hWnd, (LPSTR)lParam); |
| break; |
| case WM_COMMAND: |
| HANDLE_WM_COMMAND(hWnd, wParam, lParam, onCommand); |
| break; |
| case WM_MEASUREITEM: |
| { |
| static int cyItem = -1; //Height of a listbox item |
| LPMEASUREITEMSTRUCT lpmis = (LPMEASUREITEMSTRUCT)lParam; |
| if(cyItem == -1) |
| { |
| HFONT hFont = (HFONT)SendMessage(hWnd, WM_GETFONT, 0, 0L); |
| if(hFont == NULL) |
| hFont = GetStockFont(SYSTEM_FONT); |
| HDC hDC = GetDC(hWnd); |
| HFONT hFontOld = SelectFont(hDC, hFont); |
| TEXTMETRIC tm; |
| GetTextMetrics(hDC, &tm); |
| cyItem = max(ITEM_BITMAPHEIGHT, tm.tmHeight); |
| SelectFont(hDC, hFontOld); |
| ReleaseDC(hWnd, hDC); |
| } |
| |
| lpmis->itemHeight = cyItem; |
| } |
| break; |
| case WM_DRAWITEM: |
| onDrawItem((LPDRAWITEMSTRUCT)lParam, ((UINT)wParam == ID_COMBO_DIR)); |
| return TRUE; // to prevent default action in listbox (drawing focus) |
| default: |
| return FALSE; |
| } |
| return TRUE; |
| } |
| |
| /* |
| * DriveType |
| * |
| * Purpose: |
| * Augments the Windows API GetDriveType with a call to the CD-ROM |
| * extensions to determine if a drive is a floppy, hard disk, CD-ROM, |
| * RAM-drive, or networked drive. |
| * |
| * Parameters: |
| * iDrive UINT containing the zero-based drive index |
| * |
| * Return Value: |
| * UINT One of the following values describing the drive: |
| * DRIVE_FLOPPY, DRIVE_HARD, DRIVE_CDROM, DRIVE_RAMDISK, |
| * DRIVE_NETWORK. |
| * |
| * Copyright (c)1992 Kraig Brockschmidt, All Right Reserved |
| * Compuserve: 70750,2344 |
| * Internet : kraigb@microsoft.com |
| * |
| */ |
| UINT DriveType(UINT iDrive) |
| { |
| //Validate possible drive indices |
| if((0 > iDrive) || (25 < iDrive)) |
| return (UINT)-1; |
| |
| static char path[] = "d:\\"; |
| path[0] = 'a' + iDrive; |
| int iType = GetDriveType(path); |
| |
| /* |
| * Under Windows NT, GetDriveType returns complete information |
| * not provided under Windows 3.x which we now get through other |
| * means. |
| */ |
| |
| return iType; |
| } |
| |
| BOOL PickupDirectory(HWND hWndOwner, LPSTR lpszString) |
| { |
| if(hWndOwner == NULL) |
| hWndOwner = GetDesktopWindow(); |
| int ret = DialogBoxParam(hInst, MAKEINTRESOURCE(ID_DIALOG_CHOOSEDIR), hWndOwner, DirPickDlgProc, (LPARAM)lpszString); |
| return (ret == IDOK); |
| } |