notepad: Allow user to choose which encoding to open and save files in.
This commit is contained in:
parent
080cc90992
commit
67766392bf
|
@ -93,6 +93,14 @@ PUSHBUTTON "Cancel", IDCANCEL, 180, 21, 40, 15, WS_TABSTOP
|
||||||
PUSHBUTTON "&Help", IDHELP, 180, 39, 40, 15, WS_TABSTOP
|
PUSHBUTTON "&Help", IDHELP, 180, 39, 40, 15, WS_TABSTOP
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IDD_OFN_TEMPLATE DIALOG DISCARDABLE 50,50,300,15
|
||||||
|
STYLE DS_3DLOOK | DS_CONTROL | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_BORDER
|
||||||
|
FONT 8, "MS Shell Dlg"
|
||||||
|
BEGIN
|
||||||
|
LTEXT "Encoding:", -1, 5,0, 50,12
|
||||||
|
COMBOBOX IDC_OFN_ENCCOMBO, 53,0, 156,48, WS_CHILD | WS_VSCROLL | CBS_DROPDOWNLIST
|
||||||
|
END
|
||||||
|
|
||||||
STRINGTABLE DISCARDABLE
|
STRINGTABLE DISCARDABLE
|
||||||
{
|
{
|
||||||
STRING_PAGESETUP_HEADERVALUE, "&f"
|
STRING_PAGESETUP_HEADERVALUE, "&f"
|
||||||
|
@ -121,4 +129,6 @@ STRING_OUT_OF_MEMORY, "Not enough memory to complete this \
|
||||||
task.\nClose one or more applications to increase the amount of\nfree \
|
task.\nClose one or more applications to increase the amount of\nfree \
|
||||||
memory."
|
memory."
|
||||||
|
|
||||||
|
STRING_UNICODE_LE, "Unicode (UTF-16)"
|
||||||
|
STRING_UNICODE_BE, "Unicode (UTF-16 big-endian)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,6 +45,28 @@ static inline void byteswap_wide_string(LPWSTR str, UINT num)
|
||||||
for (i = 0; i < num; i++) str[i] = RtlUshortByteSwap(str[i]);
|
for (i = 0; i < num; i++) str[i] = RtlUshortByteSwap(str[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void load_encoding_name(ENCODING enc, WCHAR* buffer, int length)
|
||||||
|
{
|
||||||
|
switch (enc)
|
||||||
|
{
|
||||||
|
case ENCODING_UTF16LE:
|
||||||
|
LoadStringW(Globals.hInstance, STRING_UNICODE_LE, buffer, length);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ENCODING_UTF16BE:
|
||||||
|
LoadStringW(Globals.hInstance, STRING_UNICODE_BE, buffer, length);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
CPINFOEXW cpi;
|
||||||
|
GetCPInfoExW((enc==ENCODING_UTF8) ? CP_UTF8 : CP_ACP, 0, &cpi);
|
||||||
|
lstrcpynW(buffer, cpi.CodePageName, length);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
VOID ShowLastError(void)
|
VOID ShowLastError(void)
|
||||||
{
|
{
|
||||||
DWORD error = GetLastError();
|
DWORD error = GetLastError();
|
||||||
|
@ -286,14 +308,13 @@ static BOOL SetWindowTextUtf8(HWND hwnd, LPCSTR lpTextInUtf8)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DoOpenFile(LPCWSTR szFileName)
|
void DoOpenFile(LPCWSTR szFileName, ENCODING enc)
|
||||||
{
|
{
|
||||||
static const WCHAR dotlog[] = { '.','L','O','G',0 };
|
static const WCHAR dotlog[] = { '.','L','O','G',0 };
|
||||||
HANDLE hFile;
|
HANDLE hFile;
|
||||||
LPSTR pTemp;
|
LPSTR pTemp;
|
||||||
DWORD size;
|
DWORD size;
|
||||||
DWORD dwNumRead;
|
DWORD dwNumRead;
|
||||||
ENCODING enc;
|
|
||||||
BOOL succeeded;
|
BOOL succeeded;
|
||||||
WCHAR log[5];
|
WCHAR log[5];
|
||||||
|
|
||||||
|
@ -340,7 +361,18 @@ void DoOpenFile(LPCWSTR szFileName)
|
||||||
pTemp[size] = 0; /* make sure it's (char)'\0'-terminated */
|
pTemp[size] = 0; /* make sure it's (char)'\0'-terminated */
|
||||||
pTemp[size+1] = 0; /* make sure it's (WCHAR)'\0'-terminated */
|
pTemp[size+1] = 0; /* make sure it's (WCHAR)'\0'-terminated */
|
||||||
|
|
||||||
enc = detect_encoding_of_buffer(pTemp, size);
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
/* SetWindowTextUtf8 and SetWindowTextA try to allocate memory, so we
|
/* SetWindowTextUtf8 and SetWindowTextA try to allocate memory, so we
|
||||||
* check if they succeed.
|
* check if they succeed.
|
||||||
|
@ -413,6 +445,97 @@ VOID DIALOG_FileNew(VOID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Used to detect encoding of files selected in Open dialog.
|
||||||
|
* Returns ENCODING_AUTO if file can't be read, etc.
|
||||||
|
*/
|
||||||
|
static ENCODING detect_encoding_of_file(LPCWSTR szFileName)
|
||||||
|
{
|
||||||
|
DWORD size;
|
||||||
|
HANDLE hFile = CreateFileW(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
|
||||||
|
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
if (hFile == INVALID_HANDLE_VALUE)
|
||||||
|
return ENCODING_AUTO;
|
||||||
|
size = GetFileSize(hFile, NULL);
|
||||||
|
if (size == INVALID_FILE_SIZE)
|
||||||
|
{
|
||||||
|
CloseHandle(hFile);
|
||||||
|
return ENCODING_AUTO;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DWORD dwNumRead;
|
||||||
|
BYTE buffer[MAX_STRING_LEN];
|
||||||
|
if (!ReadFile(hFile, buffer, min(size, sizeof(buffer)), &dwNumRead, NULL))
|
||||||
|
{
|
||||||
|
CloseHandle(hFile);
|
||||||
|
return ENCODING_AUTO;
|
||||||
|
}
|
||||||
|
CloseHandle(hFile);
|
||||||
|
return detect_encoding_of_buffer(buffer, dwNumRead);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static UINT_PTR CALLBACK OfnHookProc(HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
static HWND hEncCombo;
|
||||||
|
|
||||||
|
switch (uMsg)
|
||||||
|
{
|
||||||
|
case WM_INITDIALOG:
|
||||||
|
{
|
||||||
|
ENCODING enc;
|
||||||
|
hEncCombo = GetDlgItem(hdlg, IDC_OFN_ENCCOMBO);
|
||||||
|
for (enc = MIN_ENCODING; enc <= MAX_ENCODING; enc++)
|
||||||
|
{
|
||||||
|
WCHAR szEnc[MAX_STRING_LEN];
|
||||||
|
load_encoding_name(enc, szEnc, ARRAY_SIZE(szEnc));
|
||||||
|
SendMessageW(hEncCombo, CB_ADDSTRING, 0, (LPARAM)szEnc);
|
||||||
|
}
|
||||||
|
SendMessageW(hEncCombo, CB_SETCURSEL, (WPARAM)Globals.encOfnCombo, 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_COMMAND:
|
||||||
|
if (LOWORD(wParam) == IDC_OFN_ENCCOMBO &&
|
||||||
|
HIWORD(wParam) == CBN_SELCHANGE)
|
||||||
|
{
|
||||||
|
int index = SendMessageW(hEncCombo, CB_GETCURSEL, 0, 0);
|
||||||
|
Globals.encOfnCombo = index==CB_ERR ? ENCODING_ANSI : (ENCODING)index;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_NOTIFY:
|
||||||
|
switch (((OFNOTIFYW*)lParam)->hdr.code)
|
||||||
|
{
|
||||||
|
case CDN_SELCHANGE:
|
||||||
|
if (Globals.bOfnIsOpenDialog)
|
||||||
|
{
|
||||||
|
/* Check the start of the selected file for a BOM. */
|
||||||
|
ENCODING enc;
|
||||||
|
WCHAR szFileName[MAX_PATH];
|
||||||
|
SendMessageW(GetParent(hdlg), CDM_GETFILEPATH,
|
||||||
|
ARRAY_SIZE(szFileName), (LPARAM)szFileName);
|
||||||
|
enc = detect_encoding_of_file(szFileName);
|
||||||
|
if (enc != ENCODING_AUTO)
|
||||||
|
{
|
||||||
|
Globals.encOfnCombo = enc;
|
||||||
|
SendMessageW(hEncCombo, CB_SETCURSEL, (WPARAM)enc, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
VOID DIALOG_FileOpen(VOID)
|
VOID DIALOG_FileOpen(VOID)
|
||||||
{
|
{
|
||||||
OPENFILENAMEW openfilename;
|
OPENFILENAMEW openfilename;
|
||||||
|
@ -433,13 +556,18 @@ VOID DIALOG_FileOpen(VOID)
|
||||||
openfilename.lpstrFile = szPath;
|
openfilename.lpstrFile = szPath;
|
||||||
openfilename.nMaxFile = ARRAY_SIZE(szPath);
|
openfilename.nMaxFile = ARRAY_SIZE(szPath);
|
||||||
openfilename.lpstrInitialDir = szDir;
|
openfilename.lpstrInitialDir = szDir;
|
||||||
openfilename.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST |
|
openfilename.Flags = OFN_ENABLETEMPLATE | OFN_ENABLEHOOK | OFN_EXPLORER |
|
||||||
OFN_HIDEREADONLY | OFN_ENABLESIZING;
|
OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST |
|
||||||
|
OFN_HIDEREADONLY | OFN_ENABLESIZING;
|
||||||
|
openfilename.lpfnHook = OfnHookProc;
|
||||||
|
openfilename.lpTemplateName = MAKEINTRESOURCEW(IDD_OFN_TEMPLATE);
|
||||||
openfilename.lpstrDefExt = szDefaultExt;
|
openfilename.lpstrDefExt = szDefaultExt;
|
||||||
|
|
||||||
|
Globals.encOfnCombo = ENCODING_ANSI;
|
||||||
|
Globals.bOfnIsOpenDialog = TRUE;
|
||||||
|
|
||||||
if (GetOpenFileNameW(&openfilename))
|
if (GetOpenFileNameW(&openfilename))
|
||||||
DoOpenFile(openfilename.lpstrFile);
|
DoOpenFile(openfilename.lpstrFile, Globals.encOfnCombo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -472,12 +600,19 @@ BOOL DIALOG_FileSaveAs(VOID)
|
||||||
saveas.lpstrFile = szPath;
|
saveas.lpstrFile = szPath;
|
||||||
saveas.nMaxFile = ARRAY_SIZE(szPath);
|
saveas.nMaxFile = ARRAY_SIZE(szPath);
|
||||||
saveas.lpstrInitialDir = szDir;
|
saveas.lpstrInitialDir = szDir;
|
||||||
saveas.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT |
|
saveas.Flags = OFN_ENABLETEMPLATE | OFN_ENABLEHOOK | OFN_EXPLORER |
|
||||||
OFN_HIDEREADONLY | OFN_ENABLESIZING;
|
OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT |
|
||||||
|
OFN_HIDEREADONLY | OFN_ENABLESIZING;
|
||||||
|
saveas.lpfnHook = OfnHookProc;
|
||||||
|
saveas.lpTemplateName = MAKEINTRESOURCEW(IDD_OFN_TEMPLATE);
|
||||||
saveas.lpstrDefExt = szDefaultExt;
|
saveas.lpstrDefExt = szDefaultExt;
|
||||||
|
|
||||||
|
/* Preset encoding to what file was opened/saved last with. */
|
||||||
|
Globals.encOfnCombo = Globals.encFile;
|
||||||
|
Globals.bOfnIsOpenDialog = FALSE;
|
||||||
|
|
||||||
if (GetSaveFileNameW(&saveas)) {
|
if (GetSaveFileNameW(&saveas)) {
|
||||||
SetFileNameAndEncoding(szPath, Globals.encFile);
|
SetFileNameAndEncoding(szPath, Globals.encOfnCombo);
|
||||||
UpdateWindowCaption();
|
UpdateWindowCaption();
|
||||||
DoSaveFile();
|
DoSaveFile();
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
|
@ -55,4 +55,4 @@ VOID ShowLastError(void);
|
||||||
void UpdateWindowCaption(void);
|
void UpdateWindowCaption(void);
|
||||||
BOOL FileExists(LPCWSTR szFilename);
|
BOOL FileExists(LPCWSTR szFilename);
|
||||||
BOOL DoCloseFile(void);
|
BOOL DoCloseFile(void);
|
||||||
void DoOpenFile(LPCWSTR szFileName);
|
void DoOpenFile(LPCWSTR szFileName, ENCODING enc);
|
||||||
|
|
|
@ -581,7 +581,7 @@ static LRESULT WINAPI NOTEPAD_WndProc(HWND hWnd, UINT msg, WPARAM wParam,
|
||||||
|
|
||||||
DragQueryFileW(hDrop, 0, szFileName, ARRAY_SIZE(szFileName));
|
DragQueryFileW(hDrop, 0, szFileName, ARRAY_SIZE(szFileName));
|
||||||
DragFinish(hDrop);
|
DragFinish(hDrop);
|
||||||
DoOpenFile(szFileName);
|
DoOpenFile(szFileName, ENCODING_AUTO);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -692,7 +692,7 @@ static void HandleCommandLine(LPWSTR cmdline)
|
||||||
|
|
||||||
if (file_exists)
|
if (file_exists)
|
||||||
{
|
{
|
||||||
DoOpenFile(file_name);
|
DoOpenFile(file_name, ENCODING_AUTO);
|
||||||
InvalidateRect(Globals.hMainWnd, NULL, FALSE);
|
InvalidateRect(Globals.hMainWnd, NULL, FALSE);
|
||||||
if (opt_print)
|
if (opt_print)
|
||||||
DIALOG_FilePrint();
|
DIALOG_FilePrint();
|
||||||
|
|
|
@ -25,14 +25,19 @@
|
||||||
|
|
||||||
#define MAX_STRING_LEN 255
|
#define MAX_STRING_LEN 255
|
||||||
|
|
||||||
|
/* Values are indexes of the items in the Encoding combobox. */
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
ENCODING_ANSI,
|
ENCODING_AUTO = -1,
|
||||||
ENCODING_UTF16LE,
|
ENCODING_ANSI = 0,
|
||||||
ENCODING_UTF16BE,
|
ENCODING_UTF16LE = 1,
|
||||||
ENCODING_UTF8
|
ENCODING_UTF16BE = 2,
|
||||||
|
ENCODING_UTF8 = 3
|
||||||
} ENCODING;
|
} ENCODING;
|
||||||
|
|
||||||
|
#define MIN_ENCODING 0
|
||||||
|
#define MAX_ENCODING 3
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
HANDLE hInstance;
|
HANDLE hInstance;
|
||||||
|
@ -48,6 +53,8 @@ typedef struct
|
||||||
WCHAR szFileTitle[MAX_PATH];
|
WCHAR szFileTitle[MAX_PATH];
|
||||||
ENCODING encFile;
|
ENCODING encFile;
|
||||||
WCHAR szFilter[2 * MAX_STRING_LEN + 100];
|
WCHAR szFilter[2 * MAX_STRING_LEN + 100];
|
||||||
|
ENCODING encOfnCombo; /* Encoding selected in IDC_OFN_ENCCOMBO */
|
||||||
|
BOOL bOfnIsOpenDialog;
|
||||||
INT iMarginTop;
|
INT iMarginTop;
|
||||||
INT iMarginBottom;
|
INT iMarginBottom;
|
||||||
INT iMarginLeft;
|
INT iMarginLeft;
|
||||||
|
|
|
@ -84,3 +84,10 @@
|
||||||
|
|
||||||
#define STRING_NOTFOUND 0x17B
|
#define STRING_NOTFOUND 0x17B
|
||||||
#define STRING_OUT_OF_MEMORY 0x17C
|
#define STRING_OUT_OF_MEMORY 0x17C
|
||||||
|
|
||||||
|
#define STRING_UNICODE_LE 0x180
|
||||||
|
#define STRING_UNICODE_BE 0x181
|
||||||
|
|
||||||
|
/* Open/Save As dialog template */
|
||||||
|
#define IDD_OFN_TEMPLATE 0x190
|
||||||
|
#define IDC_OFN_ENCCOMBO 0x191
|
||||||
|
|
Loading…
Reference in New Issue