43d1c6ad2f13f8cb373870940f447eba9dade205
4 * Copyright 1998,99 Marcel Baur <mbaur@g26.ethz.ch>
5 * Copyright 2002 Sylvain Petreolle <spetreolle@yahoo.fr>
6 * Copyright 2002 Andriy Palamarchuk
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32 static BOOL
Append(LPWSTR
*ppszText
, DWORD
*pdwTextLen
, LPCWSTR pszAppendText
, DWORD dwAppendLen
)
40 pszNewText
= (LPWSTR
) HeapReAlloc(GetProcessHeap(), 0, *ppszText
, (*pdwTextLen
+ dwAppendLen
) * sizeof(WCHAR
));
44 pszNewText
= (LPWSTR
) HeapAlloc(GetProcessHeap(), 0, dwAppendLen
* sizeof(WCHAR
));
50 memcpy(pszNewText
+ *pdwTextLen
, pszAppendText
, dwAppendLen
* sizeof(WCHAR
));
51 *ppszText
= pszNewText
;
52 *pdwTextLen
+= dwAppendLen
;
57 BOOL
ReadText(HANDLE hFile
, LPWSTR
*ppszText
, DWORD
*pdwTextLen
, int *piEncoding
, int *piEoln
)
62 LPWSTR pszAllocText
= NULL
;
65 BOOL bSuccess
= FALSE
;
67 int iEncoding
= ENCODING_ANSI
;
69 WCHAR szCrlf
[2] = { '\r', '\n' };
70 DWORD adwEolnCount
[3] = { 0, 0, 0 };
75 dwSize
= GetFileSize(hFile
, NULL
);
76 if (dwSize
== INVALID_FILE_SIZE
)
79 pBytes
= HeapAlloc(GetProcessHeap(), 0, dwSize
+ 2);
83 if (!ReadFile(hFile
, pBytes
, dwSize
, &dwSize
, NULL
))
87 /* Make sure that there is a NUL character at the end, in any encoding */
88 pBytes
[dwSize
+ 0] = '\0';
89 pBytes
[dwSize
+ 1] = '\0';
91 /* Look for Byte Order Marks */
92 if ((dwSize
>= 2) && (pBytes
[0] == 0xFF) && (pBytes
[1] == 0xFE))
94 iEncoding
= ENCODING_UNICODE
;
97 else if ((dwSize
>= 2) && (pBytes
[0] == 0xFE) && (pBytes
[1] == 0xFF))
99 iEncoding
= ENCODING_UNICODE_BE
;
102 else if ((dwSize
>= 3) && (pBytes
[0] == 0xEF) && (pBytes
[1] == 0xBB) && (pBytes
[2] == 0xBF))
104 iEncoding
= ENCODING_UTF8
;
110 case ENCODING_UNICODE_BE
:
111 for (i
= dwPos
; i
< dwSize
-1; i
+= 2)
114 pBytes
[i
+0] = pBytes
[i
+1];
119 case ENCODING_UNICODE
:
120 pszText
= (LPCWSTR
) &pBytes
[dwPos
];
121 dwCharCount
= (dwSize
- dwPos
) / sizeof(WCHAR
);
126 if (iEncoding
== ENCODING_ANSI
)
128 else if (iEncoding
== ENCODING_UTF8
)
133 if ((dwSize
- dwPos
) > 0)
135 dwCharCount
= MultiByteToWideChar(iCodePage
, 0, (LPCSTR
)&pBytes
[dwPos
], dwSize
- dwPos
, NULL
, 0);
136 if (dwCharCount
== 0)
141 /* special case for files with no characters (other than BOMs) */
145 pszAllocText
= (LPWSTR
) HeapAlloc(GetProcessHeap(), 0, (dwCharCount
+ 1) * sizeof(WCHAR
));
149 if ((dwSize
- dwPos
) > 0)
151 if (!MultiByteToWideChar(iCodePage
, 0, (LPCSTR
)&pBytes
[dwPos
], dwSize
- dwPos
, pszAllocText
, dwCharCount
))
155 pszAllocText
[dwCharCount
] = '\0';
156 pszText
= pszAllocText
;
161 for (i
= 0; i
< dwCharCount
; i
++)
166 if ((i
< dwCharCount
-1) && (pszText
[i
+1] == '\n'))
169 adwEolnCount
[EOLN_CRLF
]++;
175 if (!Append(ppszText
, pdwTextLen
, &pszText
[dwPos
], i
- dwPos
))
177 if (!Append(ppszText
, pdwTextLen
, szCrlf
, sizeof(szCrlf
) / sizeof(szCrlf
[0])))
181 if (pszText
[i
] == '\r')
182 adwEolnCount
[EOLN_CR
]++;
184 adwEolnCount
[EOLN_LF
]++;
189 if (!*ppszText
&& (pszText
== pszAllocText
))
191 /* special case; don't need to reallocate */
192 *ppszText
= pszAllocText
;
193 *pdwTextLen
= dwCharCount
;
198 /* append last remaining text */
199 if (!Append(ppszText
, pdwTextLen
, &pszText
[dwPos
], i
- dwPos
+ 1))
203 /* chose which eoln to use */
205 if (adwEolnCount
[EOLN_LF
] > adwEolnCount
[*piEoln
])
207 if (adwEolnCount
[EOLN_CR
] > adwEolnCount
[*piEoln
])
209 *piEncoding
= iEncoding
;
215 HeapFree(GetProcessHeap(), 0, pBytes
);
217 HeapFree(GetProcessHeap(), 0, pszAllocText
);
219 if (!bSuccess
&& *ppszText
)
221 HeapFree(GetProcessHeap(), 0, *ppszText
);
228 static BOOL
WriteEncodedText(HANDLE hFile
, LPCWSTR pszText
, DWORD dwTextLen
, int iEncoding
)
230 LPBYTE pBytes
= NULL
;
231 LPBYTE pAllocBuffer
= NULL
;
237 BOOL bSuccess
= FALSE
;
238 int iBufferSize
, iRequiredBytes
;
241 while(dwPos
< dwTextLen
)
245 case ENCODING_UNICODE
:
246 pBytes
= (LPBYTE
) &pszText
[dwPos
];
247 dwByteCount
= (dwTextLen
- dwPos
) * sizeof(WCHAR
);
251 case ENCODING_UNICODE_BE
:
252 dwByteCount
= (dwTextLen
- dwPos
) * sizeof(WCHAR
);
253 if (dwByteCount
> sizeof(buffer
))
254 dwByteCount
= sizeof(buffer
);
256 memcpy(buffer
, &pszText
[dwPos
], dwByteCount
);
257 for (i
= 0; i
< dwByteCount
; i
+= 2)
260 buffer
[i
+0] = buffer
[i
+1];
263 dwPos
+= dwByteCount
/ sizeof(WCHAR
);
268 if (iEncoding
== ENCODING_ANSI
)
270 else if (iEncoding
== ENCODING_UTF8
)
275 iRequiredBytes
= WideCharToMultiByte(iCodePage
, 0, &pszText
[dwPos
], dwTextLen
- dwPos
, NULL
, 0, NULL
, NULL
);
276 if (iRequiredBytes
<= 0)
280 else if (iRequiredBytes
< sizeof(buffer
))
283 iBufferSize
= sizeof(buffer
);
287 pAllocBuffer
= (LPBYTE
) HeapAlloc(GetProcessHeap(), 0, iRequiredBytes
);
290 pBytes
= pAllocBuffer
;
291 iBufferSize
= iRequiredBytes
;
294 dwByteCount
= WideCharToMultiByte(iCodePage
, 0, &pszText
[dwPos
], dwTextLen
- dwPos
, (LPSTR
) pBytes
, iBufferSize
, NULL
, NULL
);
305 if (!WriteFile(hFile
, pBytes
, dwByteCount
, &dwDummy
, NULL
))
308 /* free the buffer, if we have allocated one */
311 HeapFree(GetProcessHeap(), 0, pAllocBuffer
);
319 HeapFree(GetProcessHeap(), 0, pAllocBuffer
);
323 BOOL
WriteText(HANDLE hFile
, LPCWSTR pszText
, DWORD dwTextLen
, int iEncoding
, int iEoln
)
328 LPBYTE pbEoln
= NULL
;
329 DWORD dwDummy
, dwPos
, dwNext
, dwEolnSize
= 0;
331 /* Write the proper byte order marks if not ANSI */
332 if (iEncoding
!= ENCODING_ANSI
)
335 if (!WriteEncodedText(hFile
, &wcBom
, 1, iEncoding
))
339 /* Identify the proper eoln to use */
345 dwEolnSize
= sizeof(bEoln
);
350 dwEolnSize
= sizeof(bEoln
);
354 /* If we have an eoln, make sure it is of the proper encoding */
355 if (pbEoln
&& ((iEncoding
== ENCODING_UNICODE
) || (iEncoding
== ENCODING_UNICODE_BE
)))
358 pbEoln
= (LPBYTE
) &wcEoln
;
359 dwEolnSize
= sizeof(wcEoln
);
364 while(dwPos
< dwTextLen
)
368 /* Find the next eoln */
370 while(dwNext
< dwTextLen
-1)
372 if ((pszText
[dwNext
] == '\r') && (pszText
[dwNext
+1] == '\n'))
379 /* No eoln conversion is necessary */
383 if (!WriteEncodedText(hFile
, &pszText
[dwPos
], dwNext
- dwPos
, iEncoding
))
387 /* are we at an eoln? */
388 while ((dwPos
< dwTextLen
-1) &&
389 ((pszText
[dwPos
] == '\r') && (pszText
[dwPos
+1] == '\n')))
391 if (!WriteFile(hFile
, pbEoln
, dwEolnSize
, &dwDummy
, NULL
))
396 while(dwPos
< dwTextLen
);