Modified: trunk/reactos/subsys/system/notepad/En.rc
Modified: trunk/reactos/subsys/system/notepad/dialog.c
Modified: trunk/reactos/subsys/system/notepad/main.c
Modified: trunk/reactos/subsys/system/notepad/main.h
Modified: trunk/reactos/subsys/system/notepad/notepad.xml
Modified: trunk/reactos/subsys/system/notepad/notepad_res.h
Added: trunk/reactos/subsys/system/notepad/text.c
--- trunk/reactos/subsys/system/notepad/En.rc 2005-09-24 20:37:53 UTC (rev 18036)
+++ trunk/reactos/subsys/system/notepad/En.rc 2005-09-24 23:45:05 UTC (rev 18037)
@@ -95,7 +95,7 @@
}
/* Dialog `Encoding' */
-DIALOG_ENCODING DIALOG 0, 0, 256, 26
+DIALOG_ENCODING DIALOG 0, 0, 256, 44
STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS |
WS_CAPTION | WS_SYSMENU
FONT 8, "MS Shell Dlg"
@@ -103,6 +103,8 @@
{
COMBOBOX ID_ENCODING,54,0,156,80,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
LTEXT "Encoding:",0x155,5,2,41,12
+COMBOBOX ID_EOLN,54,18,156,80,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+LTEXT "Endlines:",0x156,5,20,41,12
}
STRINGTABLE DISCARDABLE
@@ -140,4 +142,7 @@
STRING_UNICODE, "Unicode"
STRING_UNICODE_BE, "Unicode (big endian)"
STRING_UTF8, "UTF-8"
+STRING_CRLF, "Windows"
+STRING_LF, "Unix"
+STRING_CR, "Mac"
}
--- trunk/reactos/subsys/system/notepad/dialog.c 2005-09-24 20:37:53 UTC (rev 18036)
+++ trunk/reactos/subsys/system/notepad/dialog.c 2005-09-24 23:45:05 UTC (rev 18037)
@@ -93,7 +93,7 @@
wsprintf(szMessage, szResource, szFileName);
/* Load szCaption */
- LoadString(Globals.hInstance, STRING_ERROR, szResource, SIZEOF(szResource));
+ LoadString(Globals.hInstance, STRING_NOTEPAD, szResource, SIZEOF(szResource));
/* Display Modal Dialog */
MessageBox(Globals.hMainWnd, szMessage, szResource, MB_ICONEXCLAMATION);
@@ -112,7 +112,7 @@
wsprintf(szMessage, szResource, szFileName[0] ? szFileName : szUntitled);
/* Load Caption */
- LoadString(Globals.hInstance, STRING_ERROR, szResource, SIZEOF(szResource));
+ LoadString(Globals.hInstance, STRING_NOTEPAD, szResource, SIZEOF(szResource));
/* Display modal */
return MessageBox(Globals.hMainWnd, szMessage, szResource, MB_ICONEXCLAMATION|MB_YESNOCANCEL);
@@ -138,15 +138,8 @@
static VOID DoSaveFile(VOID)
{
HANDLE hFile;
- DWORD dwNumWrite;
LPWSTR pTemp;
- LPVOID pConverted = NULL;
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);
@@ -166,72 +159,13 @@
}
size = GetWindowTextW(Globals.hEdit, pTemp, size);
- 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))
+ if (!WriteText(hFile, pTemp, size, Globals.iEncoding, Globals.iEoln))
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);
}
/**
@@ -273,15 +207,9 @@
{
static const WCHAR dotlog[] = { '.','L','O','G',0 };
HANDLE hFile;
- LPSTR pTemp;
- LPWSTR pTemp2 = NULL;
- DWORD size;
- DWORD dwNumRead;
+ LPWSTR pszText;
+ DWORD dwTextLen;
WCHAR log[5];
- LPWSTR p;
- LPBYTE p2;
- int iCodePage;
- int iNewSize;
/* Close any files and prompt to save changes */
if (!DoCloseFile())
@@ -289,91 +217,20 @@
hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
- if(hFile == INVALID_HANDLE_VALUE)
+ if (hFile == INVALID_HANDLE_VALUE)
{
ShowLastError();
- return;
+ goto done;
}
- size = GetFileSize(hFile, NULL);
- if (size == INVALID_FILE_SIZE)
+ if (!ReadText(hFile, &pszText, &dwTextLen, &Globals.iEncoding, &Globals.iEoln))
{
- CloseHandle(hFile);
ShowLastError();
- return;
+ goto done;
}
- pTemp = HeapAlloc(GetProcessHeap(), 0, size + sizeof(WCHAR));
- if (!pTemp)
- {
- CloseHandle(hFile);
- ShowLastError();
- return;
- }
+ SetWindowTextW(Globals.hEdit, pszText);
- if (!ReadFile(hFile, pTemp, size, &dwNumRead, NULL))
- {
- CloseHandle(hFile);
- HeapFree(GetProcessHeap(), 0, pTemp);
- ShowLastError();
- return;
- }
-
- CloseHandle(hFile);
- pTemp[dwNumRead] = 0;
-
- if (IsTextUnicode(pTemp, dwNumRead, NULL))
- {
- 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
- {
- p2 = (LPBYTE)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, (LPCSTR)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, (LPCSTR)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);
SetFocus(Globals.hEdit);
@@ -392,6 +249,12 @@
SetFileName(szFileName);
UpdateWindowCaption();
+
+done:
+ if (hFile != INVALID_HANDLE_VALUE)
+ CloseHandle(hFile);
+ if (pszText)
+ HeapFree(GetProcessHeap(), 0, pszText);
}
VOID DIALOG_FileNew(VOID)
@@ -475,14 +338,33 @@
SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM) szText);
SendMessage(hCombo, CB_SETCURSEL, Globals.iEncoding, 0);
+
+ hCombo = GetDlgItem(hDlg, ID_EOLN);
+
+ LoadString(Globals.hInstance, STRING_CRLF, szText, SIZEOF(szText));
+ SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM) szText);
+
+ LoadString(Globals.hInstance, STRING_LF, szText, SIZEOF(szText));
+ SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM) szText);
+
+ LoadString(Globals.hInstance, STRING_CR, szText, SIZEOF(szText));
+ SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM) szText);
+
+ SendMessage(hCombo, CB_SETCURSEL, Globals.iEoln, 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);
+ if (hCombo)
+ Globals.iEncoding = SendMessage(hCombo, CB_GETCURSEL, 0, 0);
+
+ hCombo = GetDlgItem(hDlg, ID_EOLN);
+ if (hCombo)
+ Globals.iEoln = SendMessage(hCombo, CB_GETCURSEL, 0, 0);
}
break;
}
@@ -736,7 +618,7 @@
{
static const WCHAR editW[] = { 'e','d','i','t',0 };
DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_BORDER | WS_VSCROLL |
- ES_AUTOVSCROLL | ES_MULTILINE;
+ ES_AUTOVSCROLL | ES_MULTILINE | ES_NOHIDESEL;
RECT rc;
DWORD size;
LPWSTR pTemp;
--- trunk/reactos/subsys/system/notepad/main.c 2005-09-24 20:37:53 UTC (rev 18036)
+++ trunk/reactos/subsys/system/notepad/main.c 2005-09-24 23:45:05 UTC (rev 18037)
@@ -23,9 +23,11 @@
*/
#define UNICODE
+#define _UNICODE
#include <windows.h>
#include <stdio.h>
+#include <tchar.h>
#include "main.h"
#include "dialog.h"
@@ -94,6 +96,78 @@
}
/***********************************************************************
+ *
+ * NOTEPAD_FindNext
+ */
+
+static VOID NOTEPAD_FindNext(FINDREPLACE *pFindReplace)
+{
+ int iTextLength, iTargetLength;
+ LPTSTR pszText = NULL;
+ DWORD dwPosition, dwDummy;
+ BOOL bMatches = FALSE;
+
+ iTargetLength = _tcslen(pFindReplace->lpstrFindWhat);
+
+ iTextLength = GetWindowTextLength(Globals.hEdit);
+
+ if (iTextLength > 0)
+ {
+ pszText = (LPTSTR) HeapAlloc(GetProcessHeap(), 0, (iTextLength + 1) * sizeof(TCHAR));
+ if (!pszText)
+ return;
+
+ GetWindowText(Globals.hEdit, pszText, iTextLength + 1);
+ }
+
+ SendMessage(Globals.hEdit, EM_GETSEL, (WPARAM) &dwDummy, (LPARAM) &dwPosition);
+
+ while(dwPosition < iTextLength)
+ {
+ /* Make proper comparison */
+ if (pFindReplace->Flags & FR_MATCHCASE)
+ bMatches = !_tcsncmp(&pszText[dwPosition], pFindReplace->lpstrFindWhat, iTargetLength);
+ else
+ bMatches = !_tcsnicmp(&pszText[dwPosition], pFindReplace->lpstrFindWhat, iTargetLength);
+
+ if (bMatches && pFindReplace->Flags & FR_WHOLEWORD)
+ {
+ if ((dwPosition > 0) && !_istspace(pszText[dwPosition-1]))
+ bMatches = FALSE;
+ if ((dwPosition < iTextLength - 1) && !_istspace(pszText[dwPosition+1]))
+ bMatches = FALSE;
+ }
+
+ if (bMatches)
+ break;
+
+ if (pFindReplace->Flags & FR_DOWN)
+ dwPosition++;
+ else
+ dwPosition--;
+ }
+
+ if (bMatches)
+ {
+ SendMessage(Globals.hEdit, EM_SETSEL, dwPosition, dwPosition + iTargetLength);
+ SendMessage(Globals.hEdit, EM_SCROLLCARET, 0, 0);
+ }
+
+ if (pszText)
+ HeapFree(GetProcessHeap(), 0, pszText);
+}
+
+/***********************************************************************
+ *
+ * NOTEPAD_FindTerm
+ */
+
+static VOID NOTEPAD_FindTerm(VOID)
+{
+ Globals.hFindReplaceDlg = NULL;
+}
+
+/***********************************************************************
* Data Initialization
*/
static VOID NOTEPAD_InitData(VOID)
@@ -150,7 +224,7 @@
GetClientRect(hWnd, &rc);
Globals.hEdit = CreateWindowEx(WS_EX_CLIENTEDGE, editW, NULL,
WS_CHILD | WS_VISIBLE | WS_BORDER | WS_VSCROLL | WS_HSCROLL |
- ES_AUTOVSCROLL | ES_MULTILINE,
+ ES_AUTOVSCROLL | ES_MULTILINE | ES_NOHIDESEL,
0, 0, rc.right, rc.bottom, hWnd,
NULL, Globals.hInstance, NULL);
break;
@@ -205,6 +279,17 @@
break;
default:
+ if (msg == aFINDMSGSTRING)
+ {
+ FINDREPLACE *pFindReplace = (FINDREPLACE *) lParam;
+
+ if (pFindReplace->Flags & FR_FINDNEXT)
+ NOTEPAD_FindNext(pFindReplace);
+ else if (pFindReplace->Flags & FR_DIALOGTERM)
+ NOTEPAD_FindTerm();
+ break;
+ }
+
return DefWindowProc(hWnd, msg, wParam, lParam);
}
return 0;
@@ -219,7 +304,7 @@
LoadString(Globals.hInstance, STRING_DOESNOTEXIST, szResource, SIZEOF(szResource));
wsprintf(szMessage, szResource, szFileName);
- LoadString(Globals.hInstance, STRING_ERROR, szResource, SIZEOF(szResource));
+ LoadString(Globals.hInstance, STRING_NOTEPAD, szResource, SIZEOF(szResource));
nResult = MessageBox(Globals.hMainWnd, szMessage, szResource,
MB_ICONEXCLAMATION | MB_YESNO);
--- trunk/reactos/subsys/system/notepad/main.h 2005-09-24 20:37:53 UTC (rev 18036)
+++ trunk/reactos/subsys/system/notepad/main.h 2005-09-24 23:45:05 UTC (rev 18037)
@@ -30,6 +30,10 @@
#define ENCODING_UNICODE_BE 2
#define ENCODING_UTF8 3
+#define EOLN_CRLF 0
+#define EOLN_LF 1
+#define EOLN_CR 2
+
typedef struct
{
HANDLE hInstance;
@@ -50,6 +54,7 @@
WCHAR szHeader[MAX_PATH];
WCHAR szFooter[MAX_PATH];
int iEncoding;
+ int iEoln;
FINDREPLACE find;
} NOTEPAD_GLOBALS;
@@ -57,3 +62,9 @@
extern NOTEPAD_GLOBALS Globals;
VOID SetFileName(LPCWSTR szFileName);
+
+/* from text.c */
+BOOL ReadText(HANDLE hFile, LPWSTR *ppszText, DWORD *pdwTextLen, int *piEncoding, int *piEoln);
+BOOL WriteText(HANDLE hFile, LPCWSTR pszText, DWORD dwTextLen, int iEncoding, int iEoln);
+
+
--- trunk/reactos/subsys/system/notepad/notepad.xml 2005-09-24 20:37:53 UTC (rev 18036)
+++ trunk/reactos/subsys/system/notepad/notepad.xml 2005-09-24 23:45:05 UTC (rev 18037)
@@ -10,5 +10,6 @@
<file>dialog.c</file>
<file>license.c</file>
<file>main.c</file>
+ <file>text.c</file>
<file>rsrc.rc</file>
</module>
--- trunk/reactos/subsys/system/notepad/notepad_res.h 2005-09-24 20:37:53 UTC (rev 18036)
+++ trunk/reactos/subsys/system/notepad/notepad_res.h 2005-09-24 23:45:05 UTC (rev 18037)
@@ -24,6 +24,7 @@
#define ID_ACCEL 0x203
#define DIALOG_ENCODING 0x204
#define ID_ENCODING 0x205
+#define ID_EOLN 0x206
/* Commands */
#define CMD_NEW 0x100
@@ -84,3 +85,6 @@
#define STRING_UNICODE_BE 0x17F
#define STRING_UTF8 0x180
+#define STRING_CRLF 0x181
+#define STRING_LF 0x182
+#define STRING_CR 0x183
--- trunk/reactos/subsys/system/notepad/text.c 2005-09-24 20:37:53 UTC (rev 18036)
+++ trunk/reactos/subsys/system/notepad/text.c 2005-09-24 23:45:05 UTC (rev 18037)
@@ -0,0 +1,389 @@
+/*
+ * Notepad (text.c)
+ *
+ * Copyright 1998,99 Marcel Baur <mbaur@g26.ethz.ch>
+ * Copyright 2002 Sylvain Petreolle <spetreolle@yahoo.fr>
+ * Copyright 2002 Andriy Palamarchuk
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define UNICODE
+
+#include <assert.h>
+#include <stdio.h>
+#include <windows.h>
+#include <commdlg.h>
+
+#include "main.h"
+
+static BOOL Append(LPWSTR *ppszText, DWORD *pdwTextLen, LPCWSTR pszAppendText, DWORD dwAppendLen)
+{
+ LPWSTR pszNewText;
+
+ if (dwAppendLen > 0)
+ {
+ if (*ppszText)
+ {
+ pszNewText = (LPWSTR) HeapReAlloc(GetProcessHeap(), 0, *ppszText, (*pdwTextLen + dwAppendLen) * sizeof(WCHAR));
+ }
+ else
+ {
+ pszNewText = (LPWSTR) HeapAlloc(GetProcessHeap(), 0, dwAppendLen * sizeof(WCHAR));
+ }
+
+ if (!pszNewText)
+ return FALSE;
+
+ memcpy(pszNewText + *pdwTextLen, pszAppendText, dwAppendLen * sizeof(WCHAR));
+ *ppszText = pszNewText;
+ *pdwTextLen += dwAppendLen;
+ }
+ return TRUE;
+}
+
+BOOL ReadText(HANDLE hFile, LPWSTR *ppszText, DWORD *pdwTextLen, int *piEncoding, int *piEoln)
+{
+ DWORD dwSize;
+ LPBYTE pBytes = NULL;
+ LPCWSTR pszText;
+ LPWSTR pszAllocText = NULL;
+ DWORD dwPos, i;
+ DWORD dwCharCount;
+ BOOL bSuccess = FALSE;
+ BYTE b;
+ int iEncoding = ENCODING_ANSI;
+ int iCodePage;
+ WCHAR szCrlf[2] = { '\r', '\n' };
+ DWORD adwEolnCount[3] = { 0, 0, 0 };
+
+ *ppszText = NULL;
+ *pdwTextLen = 0;
+
+ dwSize = GetFileSize(hFile, NULL);
+ if (dwSize == INVALID_FILE_SIZE)
+ goto done;
+
+ pBytes = HeapAlloc(GetProcessHeap(), 0, dwSize + 2);
+ if (!pBytes)
+ goto done;
+
+ if (!ReadFile(hFile, pBytes, dwSize, &dwSize, NULL))
+ goto done;
+ dwPos = 0;
+
+ /* Make sure that there is a NUL character at the end, in any encoding */
+ pBytes[dwSize + 0] = '\0';
+ pBytes[dwSize + 1] = '\0';
+
+ /* Look for Byte Order Marks */
+ if ((dwSize >= 2) && (pBytes[0] == 0xFF) && (pBytes[1] == 0xFE))
+ {
+ iEncoding = ENCODING_UNICODE;
+ dwPos += 2;
+ }
+ else if ((dwSize >= 2) && (pBytes[0] == 0xFE) && (pBytes[1] == 0xFF))
+ {
+ iEncoding = ENCODING_UNICODE_BE;
+ dwPos += 2;
+ }
+ else if ((dwSize >= 3) && (pBytes[0] == 0xEF) && (pBytes[1] == 0xBB) && (pBytes[2] == 0xBF))
+ {
+ iEncoding = ENCODING_UTF8;
+ dwPos += 3;
+ }
+
+ switch(iEncoding)
+ {
+ case ENCODING_UNICODE_BE:
+ for (i = dwPos; i < dwSize-1; i += 2)
+ {
+ b = pBytes[i+0];
+ pBytes[i+0] = pBytes[i+1];
+ pBytes[i+1] = b;
+ }
+ /* fall through */
+
+ case ENCODING_UNICODE:
+ pszText = (LPCWSTR) &pBytes[dwPos];
+ dwCharCount = (dwSize - dwPos) / sizeof(WCHAR);
+ break;
+
+ case ENCODING_ANSI:
+ case ENCODING_UTF8:
+ if (iEncoding == ENCODING_ANSI)
+ iCodePage = CP_ACP;
+ else if (iEncoding == ENCODING_UTF8)
+ iCodePage = CP_UTF8;
+ else
+ goto done;
+
+ dwCharCount = MultiByteToWideChar(iCodePage, 0, &pBytes[dwPos], dwSize - dwPos, NULL, 0);
+ if (dwCharCount == 0)
+ goto done;
+
+ pszAllocText = (LPWSTR) HeapAlloc(GetProcessHeap(), 0, (dwCharCount + 1) * sizeof(WCHAR));
+ if (!pszAllocText)
+ goto done;
+
+ if (!MultiByteToWideChar(iCodePage, 0, &pBytes[dwPos], dwSize - dwPos, pszAllocText, dwCharCount))
+ goto done;
+
+ pszAllocText[dwCharCount] = '\0';
+ pszText = pszAllocText;
+ break;
+ }
+
+ dwPos = 0;
+ for (i = 0; i < dwCharCount; i++)
+ {
+ switch(pszText[i])
+ {
+ case '\r':
+ if ((i < dwCharCount-1) && (pszText[i+1] == '\n'))
+ {
+ i++;
+ adwEolnCount[EOLN_CRLF]++;
+ break;
+ }
+ /* fall through */
+
+ case '\n':
+ if (!Append(ppszText, pdwTextLen, &pszText[dwPos], i - dwPos))
+ return FALSE;
+ if (!Append(ppszText, pdwTextLen, szCrlf, sizeof(szCrlf) / sizeof(szCrlf[0])))
+ return FALSE;
+ dwPos = i + 1;
+
+ if (pszText[i] == '\r')
+ adwEolnCount[EOLN_CR]++;
+ else
+ adwEolnCount[EOLN_LF]++;
+ break;
+ }
+ }
+
+ if (!*ppszText && (pszText == pszAllocText))
+ {
+ /* special case; don't need to reallocate */
+ *ppszText = pszAllocText;
+ *pdwTextLen = dwCharCount;
+ pszAllocText = NULL;
+ }
+ else
+ {
+ /* append last remaining text */
+ if (!Append(ppszText, pdwTextLen, &pszText[dwPos], i - dwPos + 1))
+ return FALSE;
+ }
+
+ /* chose which eoln to use */
+ *piEoln = EOLN_CRLF;
+ if (adwEolnCount[EOLN_LF] > adwEolnCount[*piEoln])
+ *piEoln = EOLN_LF;
+ if (adwEolnCount[EOLN_CR] > adwEolnCount[*piEoln])
+ *piEoln = EOLN_CR;
+ *piEncoding = iEncoding;
+
+ bSuccess = TRUE;
+
+done:
+ if (pBytes)
+ HeapFree(GetProcessHeap(), 0, pBytes);
+ if (pszAllocText)
+ HeapFree(GetProcessHeap(), 0, pszAllocText);
+
+ if (!bSuccess && *ppszText)
+ {
+ HeapFree(GetProcessHeap(), 0, *ppszText);
+ *ppszText = NULL;
+ *pdwTextLen = 0;
+ }
+ return bSuccess;
+}
+
+static BOOL WriteEncodedText(HANDLE hFile, LPCWSTR pszText, DWORD dwTextLen, int iEncoding)
+{
+ LPBYTE pBytes;
+ LPBYTE pAllocBuffer = NULL;
+ DWORD dwPos = 0;
+ DWORD dwByteCount;
+ BYTE buffer[1024];
+ UINT iCodePage;
+ DWORD dwDummy, i;
+ BOOL bSuccess;
+ int iBufferSize, iRequiredBytes;
+ BYTE b;
+
+ while(dwPos < dwTextLen)
+ {
+ switch(iEncoding)
+ {
+ case ENCODING_UNICODE:
+ pBytes = (LPBYTE) &pszText[dwPos];
+ dwByteCount = (dwTextLen - dwPos) * sizeof(WCHAR);
+ dwPos = dwTextLen;
+ break;
+
+ case ENCODING_UNICODE_BE:
+ dwByteCount = (dwTextLen - dwPos) * sizeof(WCHAR);
+ if (dwByteCount > sizeof(buffer))
+ dwByteCount = sizeof(buffer);
+
+ memcpy(buffer, &pszText[dwPos], dwByteCount);
+ for (i = 0; i < dwByteCount; i += 2)
+ {
+ b = buffer[i+0];
+ buffer[i+0] = buffer[i+1];
+ buffer[i+1] = b;
+ }
+ dwPos += dwByteCount / sizeof(WCHAR);
+ break;
+
+ case ENCODING_ANSI:
+ case ENCODING_UTF8:
+ if (iEncoding == ENCODING_ANSI)
+ iCodePage = CP_ACP;
+ else if (iEncoding == ENCODING_UTF8)
+ iCodePage = CP_UTF8;
+ else
+ goto done;
+
+ iRequiredBytes = WideCharToMultiByte(iCodePage, 0, &pszText[dwPos], dwTextLen - dwPos, NULL, 0, NULL, NULL);
+ if (iRequiredBytes <= 0)
+ {
+ goto done;
+ }
+ else if (iRequiredBytes < sizeof(buffer))
+ {
+ pBytes = buffer;
+ iBufferSize = sizeof(buffer);
+ }
+ else
+ {
+ pAllocBuffer = (LPBYTE) HeapAlloc(GetProcessHeap(), 0, iRequiredBytes);
+ if (!pAllocBuffer)
+ return FALSE;
+ pBytes = pAllocBuffer;
+ iBufferSize = iRequiredBytes;
+ }
+
+ dwByteCount = WideCharToMultiByte(iCodePage, 0, &pszText[dwPos], dwTextLen - dwPos, (LPSTR) pBytes, iBufferSize, NULL, NULL);
+ if (!dwByteCount)
+ goto done;
+
+ dwPos = dwTextLen;
+ break;
+
+ default:
+ goto done;
+ }
+
+ if (!WriteFile(hFile, pBytes, dwByteCount, &dwDummy, NULL))
+ goto done;
+
+ /* free the buffer, if we have allocated one */
+ if (pAllocBuffer)
+ {
+ HeapFree(GetProcessHeap(), 0, pAllocBuffer);
+ pAllocBuffer = NULL;
+ }
+ }
+ bSuccess = TRUE;
+
+done:
+ if (pAllocBuffer)
+ HeapFree(GetProcessHeap(), 0, pAllocBuffer);
+ return bSuccess;
+}
+
+BOOL WriteText(HANDLE hFile, LPCWSTR pszText, DWORD dwTextLen, int iEncoding, int iEoln)
+{
+ WCHAR wcBom;
+ WCHAR wcEoln;
+ BYTE bEoln;
+ LPBYTE pbEoln = NULL;
+ DWORD dwDummy, dwPos, dwNext, dwEolnSize = 0;
+
+ /* Write the proper byte order marks if not ANSI */
+ if (iEncoding != ENCODING_ANSI)
+ {
+ wcBom = 0xFEFF;
+ if (!WriteEncodedText(hFile, &wcBom, 1, iEncoding))
+ return FALSE;
+ }
+
+ /* Identify the proper eoln to use */
+ switch(iEoln)
+ {
+ case EOLN_LF:
+ bEoln = '\n';
+ pbEoln = &bEoln;
+ dwEolnSize = sizeof(bEoln);
+ break;
+ case EOLN_CR:
+ bEoln = '\r';
+ pbEoln = &bEoln;
+ dwEolnSize = sizeof(bEoln);
+ break;
+ }
+
+ /* If we have an eoln, make sure it is of the proper encoding */
+ if (pbEoln && ((iEncoding == ENCODING_UNICODE) || (iEncoding == ENCODING_UNICODE_BE)))
+ {
+ wcEoln = bEoln;
+ pbEoln = (LPBYTE) &wcEoln;
+ dwEolnSize = sizeof(wcEoln);
+ }
+
+ dwPos = 0;
+
+ while(dwPos < dwTextLen)
+ {
+ if (pbEoln)
+ {
+ /* Find the next eoln */
+ dwNext = dwPos;
+ while(dwNext < dwTextLen-1)
+ {
+ if ((pszText[dwNext] == '\r') && (pszText[dwNext+1] == '\n'))
+ break;
+ dwNext++;
+ }
+ }
+ else
+ {
+ /* No eoln conversion is necessary */
+ dwNext = dwTextLen;
+ }
+
+ if (!WriteEncodedText(hFile, &pszText[dwPos], dwNext - dwPos, iEncoding))
+ return FALSE;
+ dwPos = dwNext;
+
+ /* are we at an eoln? */
+ while ((dwPos < dwTextLen-1) &&
+ ((pszText[dwPos] == '\r') && (pszText[dwPos+1] == '\n')))
+ {
+ if (!WriteFile(hFile, pbEoln, dwEolnSize, &dwDummy, NULL))
+ return FALSE;
+ dwPos += 2;
+ }
+ }
+ while(dwPos < dwTextLen);
+
+ return TRUE;
+}
+