VOID DIALOG_FileOpen(VOID) { OPENFILENAME openfilename; TCHAR szDir[MAX_PATH]; TCHAR szPath[MAX_PATH]; ZeroMemory(&openfilename, sizeof(openfilename)); GetCurrentDirectory(SIZEOF(szDir), szDir); if (Globals.szFileName[0] == 0) _tcscpy(szPath, txt_files); else _tcscpy(szPath, Globals.szFileName); openfilename.lStructSize = sizeof(openfilename); openfilename.hwndOwner = Globals.hMainWnd; openfilename.hInstance = Globals.hInstance; openfilename.lpstrFilter = Globals.szFilter; openfilename.lpstrFile = szPath; openfilename.nMaxFile = SIZEOF(szPath); openfilename.lpstrInitialDir = szDir; openfilename.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY; openfilename.lpstrDefExt = szDefaultExt; if (GetOpenFileName(&openfilename)) { if (FileExists(openfilename.lpstrFile)) DoOpenFile(openfilename.lpstrFile); else AlertFileNotFound(openfilename.lpstrFile); } }
void DoOpenFile(LPCWSTR szFileName, ENCODING enc) { static const WCHAR dotlog[] = { '.','L','O','G',0 }; HANDLE hFile; LPSTR pTemp; DWORD size; DWORD dwNumRead; int lenW; WCHAR* textW; int i; WCHAR log[5]; /* Close any files and prompt to save changes */ if (!DoCloseFile()) return; hFile = CreateFileW(szFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if(hFile == INVALID_HANDLE_VALUE) { AlertFileNotFound(szFileName); return; } size = GetFileSize(hFile, NULL); if (size == INVALID_FILE_SIZE) { CloseHandle(hFile); ShowLastError(); return; } /* Extra memory for (WCHAR)'\0'-termination. */ pTemp = HeapAlloc(GetProcessHeap(), 0, size+2); if (!pTemp) { CloseHandle(hFile); ShowLastError(); return; } if (!ReadFile(hFile, pTemp, size, &dwNumRead, NULL)) { CloseHandle(hFile); HeapFree(GetProcessHeap(), 0, pTemp); ShowLastError(); return; } CloseHandle(hFile); size = dwNumRead; if (enc == ENCODING_AUTO) enc = detect_encoding_of_buffer(pTemp, size); else if (size >= 2 && (enc==ENCODING_UTF16LE || enc==ENCODING_UTF16BE)) { /* If UTF-16 (BE or LE) is selected, and there is a UTF-16 BOM, * override the selection (like native Notepad). */ if ((BYTE)pTemp[0] == 0xff && (BYTE)pTemp[1] == 0xfe) enc = ENCODING_UTF16LE; else if ((BYTE)pTemp[0] == 0xfe && (BYTE)pTemp[1] == 0xff) enc = ENCODING_UTF16BE; } switch (enc) { case ENCODING_UTF16BE: byteswap_wide_string((WCHAR*) pTemp, size/sizeof(WCHAR)); /* Forget whether the file is BE or LE, like native Notepad. */ enc = ENCODING_UTF16LE; /* fall through */ case ENCODING_UTF16LE: textW = (LPWSTR)pTemp; lenW = size/sizeof(WCHAR); break; default: { int cp = (enc==ENCODING_UTF8) ? CP_UTF8 : CP_ACP; lenW = MultiByteToWideChar(cp, 0, pTemp, size, NULL, 0); textW = HeapAlloc(GetProcessHeap(), 0, (lenW+1) * sizeof(WCHAR)); if (!textW) { ShowLastError(); HeapFree(GetProcessHeap(), 0, pTemp); return; } MultiByteToWideChar(cp, 0, pTemp, size, textW, lenW); HeapFree(GetProcessHeap(), 0, pTemp); break; } } /* Replace '\0's with spaces. Other than creating a custom control that * can deal with '\0' characters, it's the best that can be done. */ for (i = 0; i < lenW; i++) if (textW[i] == '\0') textW[i] = ' '; textW[lenW] = '\0'; if (lenW >= 1 && textW[0] == 0xfeff) SetWindowTextW(Globals.hEdit, textW+1); else SetWindowTextW(Globals.hEdit, textW); HeapFree(GetProcessHeap(), 0, textW); SendMessageW(Globals.hEdit, EM_SETMODIFY, FALSE, 0); SendMessageW(Globals.hEdit, EM_EMPTYUNDOBUFFER, 0, 0); SetFocus(Globals.hEdit); /* If the file starts with .LOG, add a time/date at the end and set cursor after */ if (GetWindowTextW(Globals.hEdit, log, ARRAY_SIZE(log)) && !lstrcmpW(log, dotlog)) { static const WCHAR lfW[] = { '\r','\n',0 }; SendMessageW(Globals.hEdit, EM_SETSEL, GetWindowTextLengthW(Globals.hEdit), -1); SendMessageW(Globals.hEdit, EM_REPLACESEL, TRUE, (LPARAM)lfW); DIALOG_EditTimeDate(); SendMessageW(Globals.hEdit, EM_REPLACESEL, TRUE, (LPARAM)lfW); } SetFileNameAndEncoding(szFileName, enc); UpdateWindowCaption(); }