[3/4] notepad: Allow user to choose which encoding to open and save files in.
Alexander Scott-Johns
alexander.scott.johns at googlemail.com
Mon Jun 29 19:25:14 CDT 2009
---
programs/notepad/En.rc | 10 +++
programs/notepad/dialog.c | 147 ++++++++++++++++++++++++++++++++++++++--
programs/notepad/main.h | 16 +++--
programs/notepad/notepad_res.h | 7 ++
4 files changed, 169 insertions(+), 11 deletions(-)
-------------- next part --------------
From 0926abcf200c96d89cd1e80e0bbbd1fcb638450b Mon Sep 17 00:00:00 2001
From: Alexander Scott-Johns <alexander.scott.johns at googlemail.com>
Date: Mon, 29 Jun 2009 23:50:39 +0100
Subject: notepad: Allow user to choose which encoding to open and save files in.
---
programs/notepad/En.rc | 10 +++
programs/notepad/dialog.c | 147 ++++++++++++++++++++++++++++++++++++++--
programs/notepad/main.h | 16 +++--
programs/notepad/notepad_res.h | 7 ++
4 files changed, 169 insertions(+), 11 deletions(-)
diff --git a/programs/notepad/En.rc b/programs/notepad/En.rc
index c4a4baf..8a2ceb8 100644
--- a/programs/notepad/En.rc
+++ b/programs/notepad/En.rc
@@ -91,6 +91,14 @@ PUSHBUTTON "Cancel", IDCANCEL, 180, 21, 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
{
STRING_PAGESETUP_HEADERVALUE, "&f"
@@ -119,4 +127,6 @@ STRING_OUT_OF_MEMORY, "Not enough memory to complete this \
task.\nClose one or more applications to increase the amount of\nfree \
memory."
+STRING_UNICODE_LE, "Unicode (UTF-16)"
+STRING_UNICODE_BE, "Unicode (UTF-16 big-endian)"
}
diff --git a/programs/notepad/dialog.c b/programs/notepad/dialog.c
index 10d4ddd..51ad695 100644
--- a/programs/notepad/dialog.c
+++ b/programs/notepad/dialog.c
@@ -45,6 +45,28 @@ static inline void byteswap_wide_string(LPWSTR str, UINT num)
str[i] = (WCHAR) MAKEWORD(HIBYTE((WORD) str[i]), LOBYTE((WORD) 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)
{
DWORD error = GetLastError();
@@ -340,6 +362,16 @@ void DoOpenFile(LPCWSTR szFileName, ENCODING enc)
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
* check if they succeed.
@@ -412,6 +444,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)
{
OPENFILENAMEW openfilename;
@@ -432,13 +555,18 @@ VOID DIALOG_FileOpen(VOID)
openfilename.lpstrFile = szPath;
openfilename.nMaxFile = ARRAY_SIZE(szPath);
openfilename.lpstrInitialDir = szDir;
- openfilename.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST |
- OFN_HIDEREADONLY | OFN_ENABLESIZING;
+ openfilename.Flags = OFN_ENABLETEMPLATE | OFN_ENABLEHOOK | OFN_EXPLORER |
+ OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST |
+ OFN_HIDEREADONLY | OFN_ENABLESIZING;
+ openfilename.lpfnHook = OfnHookProc;
+ openfilename.lpTemplateName = MAKEINTRESOURCEW(IDD_OFN_TEMPLATE);
openfilename.lpstrDefExt = szDefaultExt;
+ Globals.encOfnCombo = ENCODING_ANSI;
+ Globals.bOfnIsOpenDialog = TRUE;
if (GetOpenFileNameW(&openfilename))
- DoOpenFile(openfilename.lpstrFile, ENCODING_AUTO);
+ DoOpenFile(openfilename.lpstrFile, Globals.encOfnCombo);
}
@@ -471,12 +599,19 @@ BOOL DIALOG_FileSaveAs(VOID)
saveas.lpstrFile = szPath;
saveas.nMaxFile = ARRAY_SIZE(szPath);
saveas.lpstrInitialDir = szDir;
- saveas.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT |
- OFN_HIDEREADONLY | OFN_ENABLESIZING;
+ saveas.Flags = OFN_ENABLETEMPLATE | OFN_ENABLEHOOK | OFN_EXPLORER |
+ OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT |
+ OFN_HIDEREADONLY | OFN_ENABLESIZING;
+ saveas.lpfnHook = OfnHookProc;
+ saveas.lpTemplateName = MAKEINTRESOURCEW(IDD_OFN_TEMPLATE);
saveas.lpstrDefExt = szDefaultExt;
+ /* Preset encoding to what file was opened/saved last with. */
+ Globals.encOfnCombo = Globals.encFile;
+ Globals.bOfnIsOpenDialog = FALSE;
+
if (GetSaveFileNameW(&saveas)) {
- SetFileNameAndEncoding(szPath, Globals.encFile);
+ SetFileNameAndEncoding(szPath, Globals.encOfnCombo);
UpdateWindowCaption();
DoSaveFile(szPath, Globals.encFile);
return TRUE;
diff --git a/programs/notepad/main.h b/programs/notepad/main.h
index e5662ff..b672be6 100644
--- a/programs/notepad/main.h
+++ b/programs/notepad/main.h
@@ -25,15 +25,19 @@
#define MAX_STRING_LEN 255
+/* Values are indexes of the items in the Encoding combobox. */
typedef enum
{
- ENCODING_AUTO,
- ENCODING_ANSI,
- ENCODING_UTF16LE,
- ENCODING_UTF16BE,
- ENCODING_UTF8
+ ENCODING_AUTO = -1,
+ ENCODING_ANSI = 0,
+ ENCODING_UTF16LE = 1,
+ ENCODING_UTF16BE = 2,
+ ENCODING_UTF8 = 3
} ENCODING;
+#define MIN_ENCODING 0
+#define MAX_ENCODING 3
+
typedef struct
{
HANDLE hInstance;
@@ -49,6 +53,8 @@ typedef struct
WCHAR szFileTitle[MAX_PATH];
ENCODING encFile;
WCHAR szFilter[2 * MAX_STRING_LEN + 100];
+ ENCODING encOfnCombo; /* Encoding selected in IDC_OFN_ENCCOMBO */
+ BOOL bOfnIsOpenDialog;
INT iMarginTop;
INT iMarginBottom;
INT iMarginLeft;
diff --git a/programs/notepad/notepad_res.h b/programs/notepad/notepad_res.h
index 8176b85..3122d98 100644
--- a/programs/notepad/notepad_res.h
+++ b/programs/notepad/notepad_res.h
@@ -81,3 +81,10 @@
#define STRING_NOTFOUND 0x17B
#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
--
1.5.6.3
More information about the wine-patches
mailing list