Bletch npwoods@mess.org - Implements the Encoding field when you save, allowing the user to save as ANSI, Unicode or UTF-8 - Invoking 'Save As' after saving or loading a file will default to the earlier filename (minor changes by GvG, so mistakes are mine). Modified: trunk/reactos/subsys/system/notepad/En.rc Modified: trunk/reactos/subsys/system/notepad/dialog.c Modified: trunk/reactos/subsys/system/notepad/main.h Modified: trunk/reactos/subsys/system/notepad/notepad_res.h _____
Modified: trunk/reactos/subsys/system/notepad/En.rc --- trunk/reactos/subsys/system/notepad/En.rc 2005-09-12 16:06:53 UTC (rev 17819) +++ trunk/reactos/subsys/system/notepad/En.rc 2005-09-12 17:10:00 UTC (rev 17820) @@ -94,6 +94,17 @@
PUSHBUTTON "&Help", 0x153, 180, 39, 40, 15, WS_TABSTOP }
+/* Dialog `Encoding' */ +DIALOG_ENCODING DIALOG 0, 0, 256, 26 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS | + WS_CAPTION | WS_SYSMENU +FONT 8, "MS Shell Dlg" +CAPTION "Encoding" +{ +COMBOBOX ID_ENCODING,54,0,156,80,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP +LTEXT "Encoding:",0x155,5,2,41,12 +} + STRINGTABLE DISCARDABLE { STRING_PAGESETUP_HEADERVALUE, "&n" /* FIXME */ @@ -125,5 +136,8 @@ STRING_OUT_OF_MEMORY, "Not enough memory to complete this \ task. \nClose one or more applications to increase the amount of \nfree \ memory." - +STRING_ANSI, "ANSI" +STRING_UNICODE, "Unicode" +STRING_UNICODE_BE, "Unicode (big endian)" +STRING_UTF8, "UTF-8" } _____
Modified: trunk/reactos/subsys/system/notepad/dialog.c --- trunk/reactos/subsys/system/notepad/dialog.c 2005-09-12 16:06:53 UTC (rev 17819) +++ trunk/reactos/subsys/system/notepad/dialog.c 2005-09-12 17:10:00 UTC (rev 17820) @@ -139,8 +139,14 @@
{ HANDLE hFile; DWORD dwNumWrite; - LPSTR pTemp; + LPWSTR pTemp; + LPVOID pConverted; DWORD size; + BYTE bom[3]; + int iBomSize = 0; + int iCodePage = -1; + int iNewSize; + int i;
hFile = CreateFile(Globals.szFileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); @@ -150,23 +156,82 @@ return; }
- size = GetWindowTextLengthA(Globals.hEdit) + 1; - pTemp = HeapAlloc(GetProcessHeap(), 0, size); + size = GetWindowTextLengthW(Globals.hEdit) + 1; + pTemp = HeapAlloc(GetProcessHeap(), 0, size * sizeof(*pTemp)); if (!pTemp) { - CloseHandle(hFile); + CloseHandle(hFile); ShowLastError(); return; } - size = GetWindowTextA(Globals.hEdit, pTemp, size); + size = GetWindowTextW(Globals.hEdit, pTemp, size);
- if (!WriteFile(hFile, pTemp, size, &dwNumWrite, NULL)) + switch(Globals.iEncoding) + { + case ENCODING_ANSI: + iCodePage = CP_ACP; + break; + + case ENCODING_UNICODE: + pConverted = pTemp; + iBomSize = 2; + bom[0] = 0xFF; + bom[1] = 0xFE; + break; + + case ENCODING_UNICODE_BE: + pConverted = pTemp; + iBomSize = 2; + bom[0] = 0xFE; + bom[1] = 0xFF; + + /* flip the endianness */ + for (i = 0; i < size; i++) + { + pTemp[i] = ((pTemp[i] & 0x00FF) << 8) + | ((pTemp[i] & 0xFF00) >> 8); + } + break; + + case ENCODING_UTF8: + iCodePage = CP_UTF8; + iBomSize = 3; + bom[0] = 0xEF; + bom[1] = 0xBB; + bom[2] = 0xBF; + break; + } + + if (iCodePage >= 0) + { + iNewSize = WideCharToMultiByte(iCodePage, 0, pTemp, size, NULL, 0, NULL, NULL); + pConverted = HeapAlloc(GetProcessHeap(), 0, iNewSize); + if (!pConverted) + { + HeapFree(GetProcessHeap(), 0, pTemp); + CloseHandle(hFile); + ShowLastError(); + return; + } + WideCharToMultiByte(iCodePage, 0, pTemp, size, pConverted, iNewSize, NULL, NULL); + } + else + { + iNewSize = size * sizeof(WCHAR); + } + + if ((iBomSize > 0) && !WriteFile(hFile, bom, iBomSize, &dwNumWrite, NULL)) ShowLastError(); + else if (!WriteFile(hFile, pConverted, iNewSize, &dwNumWrite, NULL)) + ShowLastError(); else SendMessage(Globals.hEdit, EM_SETMODIFY, FALSE, 0);
CloseHandle(hFile); HeapFree(GetProcessHeap(), 0, pTemp); + + if (iCodePage >= 0) + HeapFree(GetProcessHeap(), 0, pConverted); }
/** @@ -208,44 +273,48 @@ { HANDLE hFile; LPSTR pTemp; + LPWSTR pTemp2 = NULL; DWORD size; DWORD dwNumRead; + LPWSTR p; + LPBYTE p2; + int iCodePage; + int iNewSize;
/* Close any files and prompt to save changes */ if (!DoCloseFile()) - return; + return;
hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, - OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if(hFile == INVALID_HANDLE_VALUE) { - ShowLastError(); - return; + ShowLastError(); + return; }
size = GetFileSize(hFile, NULL); if (size == INVALID_FILE_SIZE) { - CloseHandle(hFile); - ShowLastError(); - return; + CloseHandle(hFile); + ShowLastError(); + return; } - size++;
- pTemp = HeapAlloc(GetProcessHeap(), 0, size); + pTemp = HeapAlloc(GetProcessHeap(), 0, size + sizeof(WCHAR)); if (!pTemp) { - CloseHandle(hFile); - ShowLastError(); - return; + CloseHandle(hFile); + ShowLastError(); + return; }
if (!ReadFile(hFile, pTemp, size, &dwNumRead, NULL)) { - CloseHandle(hFile); - HeapFree(GetProcessHeap(), 0, pTemp); - ShowLastError(); - return; + CloseHandle(hFile); + HeapFree(GetProcessHeap(), 0, pTemp); + ShowLastError(); + return; }
CloseHandle(hFile); @@ -253,15 +322,55 @@
if (IsTextUnicode(pTemp, dwNumRead, NULL)) { - LPWSTR p = (LPWSTR)pTemp; - /* We need to strip BOM Unicode character, SetWindowTextW won't do it for us. */ - if (*p == 0xFEFF || *p == 0xFFFE) p++; - SetWindowTextW(Globals.hEdit, p); + p = (LPWSTR)pTemp; + p[dwNumRead / 2] = 0; + + /* We need to strip BOM Unicode character, SetWindowTextW won't do it for us. */ + if (*p == 0xFEFF) + { + Globals.iEncoding = ENCODING_UNICODE_BE; + p++; + } + else if (*p == 0xFFFE) + { + Globals.iEncoding = ENCODING_UNICODE; + p++; + } } else - SetWindowTextA(Globals.hEdit, pTemp); + { + p2 = pTemp; + if ((p2[0] == 0xEF) && (p2[1] == 0xBB) && (p2[2] == 0xBF)) + { + iCodePage = CP_UTF8; + Globals.iEncoding = ENCODING_UTF8; + p2 += 3; + dwNumRead -= 3; + } + else + { + iCodePage = CP_ACP; + Globals.iEncoding = ENCODING_ANSI; + }
+ iNewSize = MultiByteToWideChar(iCodePage, 0, p2, dwNumRead, NULL, 0); + pTemp2 = HeapAlloc(GetProcessHeap(), 0, (iNewSize + 1) * sizeof(*pTemp2)); + if (!pTemp2) + { + CloseHandle(hFile); + HeapFree(GetProcessHeap(), 0, pTemp); + ShowLastError(); + return; + } + MultiByteToWideChar(iCodePage, 0, p2, dwNumRead, pTemp2, iNewSize); + pTemp2[iNewSize] = 0; + p = pTemp2; + } + SetWindowTextW(Globals.hEdit, p); + HeapFree(GetProcessHeap(), 0, pTemp); + if (pTemp2) + HeapFree(GetProcessHeap(), 0, pTemp2);
SendMessage(Globals.hEdit, EM_SETMODIFY, FALSE, 0); SendMessage(Globals.hEdit, EM_EMPTYUNDOBUFFER, 0, 0); @@ -286,15 +395,18 @@ VOID DIALOG_FileOpen(VOID) { OPENFILENAME openfilename; + WCHAR szDir[MAX_PATH]; WCHAR szPath[MAX_PATH]; - WCHAR szDir[MAX_PATH]; static const WCHAR szDefaultExt[] = { 't','x','t',0 }; static const WCHAR txt_files[] = { '*','.','t','x','t',0 };
ZeroMemory(&openfilename, sizeof(openfilename));
GetCurrentDirectory(SIZEOF(szDir), szDir); - lstrcpy(szPath, txt_files); + if (Globals.szFileName[0] == 0) + lstrcpy(szPath, txt_files); + else + lstrcpy(szPath, Globals.szFileName);
openfilename.lStructSize = sizeof(openfilename); openfilename.hwndOwner = Globals.hMainWnd; @@ -325,18 +437,59 @@ DoSaveFile(); }
+static UINT_PTR CALLBACK DIALOG_FileSaveAs_Hook(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + WCHAR szText[128]; + HWND hCombo; + OFNOTIFY *pNotify; + + switch(msg) + { + case WM_INITDIALOG: + hCombo = GetDlgItem(hDlg, ID_ENCODING); + + LoadString(Globals.hInstance, STRING_ANSI, szText, SIZEOF(szText)); + SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM) szText); + + LoadString(Globals.hInstance, STRING_UNICODE, szText, SIZEOF(szText)); + SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM) szText); + + LoadString(Globals.hInstance, STRING_UNICODE_BE, szText, SIZEOF(szText)); + SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM) szText); + + LoadString(Globals.hInstance, STRING_UTF8, szText, SIZEOF(szText)); + SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM) szText); + + SendMessage(hCombo, CB_SETCURSEL, Globals.iEncoding, 0); + break; + + case WM_NOTIFY: + if (((NMHDR *) lParam)->code == CDN_FILEOK) + { + pNotify = (OFNOTIFY *) lParam; + hCombo = GetDlgItem(hDlg, ID_ENCODING); + Globals.iEncoding = SendMessage(hCombo, CB_GETCURSEL, 0, 0); + } + break; + } + return 0; +} + VOID DIALOG_FileSaveAs(VOID) { OPENFILENAME saveas; + WCHAR szDir[MAX_PATH]; WCHAR szPath[MAX_PATH]; - WCHAR szDir[MAX_PATH]; static const WCHAR szDefaultExt[] = { 't','x','t',0 }; static const WCHAR txt_files[] = { '*','.','t','x','t',0 };
ZeroMemory(&saveas, sizeof(saveas));
GetCurrentDirectory(SIZEOF(szDir), szDir); - lstrcpy(szPath, txt_files); + if (Globals.szFileName[0] == 0) + lstrcpy(szPath, txt_files); + else + lstrcpy(szPath, Globals.szFileName);
saveas.lStructSize = sizeof(OPENFILENAME); saveas.hwndOwner = Globals.hMainWnd; @@ -346,8 +499,10 @@ saveas.nMaxFile = SIZEOF(szPath); saveas.lpstrInitialDir = szDir; saveas.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT | - OFN_HIDEREADONLY; + OFN_HIDEREADONLY | OFN_EXPLORER | OFN_ENABLETEMPLATE | OFN_ENABLEHOOK; saveas.lpstrDefExt = szDefaultExt; + saveas.lpTemplateName = MAKEINTRESOURCE(DIALOG_ENCODING); + saveas.lpfnHook = DIALOG_FileSaveAs_Hook;
if (GetSaveFileName(&saveas)) { SetFileName(szPath); @@ -423,14 +578,14 @@ cHeightPels = GetDeviceCaps(printer.hDC, VERTRES);
/* Get the file text */ - size = GetWindowTextLength(Globals.hEdit) + 1; + size = GetWindowTextLengthW(Globals.hEdit) + 1; pTemp = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR)); if (!pTemp) { ShowLastError(); return; } - size = GetWindowText(Globals.hEdit, pTemp, size); + size = GetWindowTextW(Globals.hEdit, pTemp, size);
border = 150; for (copycount=1; copycount <= printer.nCopies; copycount++) { @@ -700,8 +855,8 @@ return TRUE; }
- default: - break; + default: + break; } break;
_____
Modified: trunk/reactos/subsys/system/notepad/main.h --- trunk/reactos/subsys/system/notepad/main.h 2005-09-12 16:06:53 UTC (rev 17819) +++ trunk/reactos/subsys/system/notepad/main.h 2005-09-12 17:10:00 UTC (rev 17820) @@ -25,6 +25,11 @@
#define MAX_STRING_LEN 255
+#define ENCODING_ANSI 0 +#define ENCODING_UNICODE 1 +#define ENCODING_UNICODE_BE 2 +#define ENCODING_UTF8 3 + typedef struct { HANDLE hInstance; @@ -44,6 +49,7 @@ WCHAR szMarginRight[MAX_PATH]; WCHAR szHeader[MAX_PATH]; WCHAR szFooter[MAX_PATH]; + int iEncoding;
FINDREPLACE find; } NOTEPAD_GLOBALS; _____
Modified: trunk/reactos/subsys/system/notepad/notepad_res.h --- trunk/reactos/subsys/system/notepad/notepad_res.h 2005-09-12 16:06:53 UTC (rev 17819) +++ trunk/reactos/subsys/system/notepad/notepad_res.h 2005-09-12 17:10:00 UTC (rev 17820) @@ -22,6 +22,8 @@
#define MAIN_MENU 0x201 #define DIALOG_PAGESETUP 0x202 #define ID_ACCEL 0x203 +#define DIALOG_ENCODING 0x204 +#define ID_ENCODING 0x205
/* Commands */ #define CMD_NEW 0x100 @@ -76,3 +78,9 @@
#define STRING_NOTFOUND 0x17B #define STRING_OUT_OF_MEMORY 0x17C + +#define STRING_ANSI 0x17D +#define STRING_UNICODE 0x17E +#define STRING_UNICODE_BE 0x17F +#define STRING_UTF8 0x180 +