2c6ee8cd070026507d07a66e8a99b7d6f3a5356a
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 static BOOL
Append(LPWSTR
*ppszText
, DWORD
*pdwTextLen
, LPCWSTR pszAppendText
, DWORD dwAppendLen
)
33 pszNewText
= (LPWSTR
) HeapReAlloc(GetProcessHeap(), 0, *ppszText
, (*pdwTextLen
+ dwAppendLen
) * sizeof(WCHAR
));
37 pszNewText
= (LPWSTR
) HeapAlloc(GetProcessHeap(), 0, dwAppendLen
* sizeof(WCHAR
));
43 memcpy(pszNewText
+ *pdwTextLen
, pszAppendText
, dwAppendLen
* sizeof(WCHAR
));
44 *ppszText
= pszNewText
;
45 *pdwTextLen
+= dwAppendLen
;
51 ReadText(HANDLE hFile
, LPWSTR
*ppszText
, DWORD
*pdwTextLen
, ENCODING
*pencFile
, int *piEoln
)
56 LPWSTR pszAllocText
= NULL
;
59 BOOL bSuccess
= FALSE
;
61 ENCODING encFile
= ENCODING_ANSI
;
63 WCHAR szCrlf
[2] = {'\r', '\n'};
64 DWORD adwEolnCount
[3] = {0, 0, 0};
69 dwSize
= GetFileSize(hFile
, NULL
);
70 if (dwSize
== INVALID_FILE_SIZE
)
73 pBytes
= HeapAlloc(GetProcessHeap(), 0, dwSize
+ 2);
77 if (!ReadFile(hFile
, pBytes
, dwSize
, &dwSize
, NULL
))
81 /* Make sure that there is a NUL character at the end, in any encoding */
82 pBytes
[dwSize
+ 0] = '\0';
83 pBytes
[dwSize
+ 1] = '\0';
85 /* Look for Byte Order Marks */
86 if ((dwSize
>= 2) && (pBytes
[0] == 0xFF) && (pBytes
[1] == 0xFE))
88 encFile
= ENCODING_UNICODE
;
91 else if ((dwSize
>= 2) && (pBytes
[0] == 0xFE) && (pBytes
[1] == 0xFF))
93 encFile
= ENCODING_UNICODE_BE
;
96 else if ((dwSize
>= 3) && (pBytes
[0] == 0xEF) && (pBytes
[1] == 0xBB) && (pBytes
[2] == 0xBF))
98 encFile
= ENCODING_UTF8
;
104 case ENCODING_UNICODE_BE
:
105 for (i
= dwPos
; i
< dwSize
-1; i
+= 2)
108 pBytes
[i
+0] = pBytes
[i
+1];
113 case ENCODING_UNICODE
:
114 pszText
= (LPWSTR
) &pBytes
[dwPos
];
115 dwCharCount
= (dwSize
- dwPos
) / sizeof(WCHAR
);
120 if (encFile
== ENCODING_ANSI
)
122 else if (encFile
== ENCODING_UTF8
)
125 if ((dwSize
- dwPos
) > 0)
127 dwCharCount
= MultiByteToWideChar(iCodePage
, 0, (LPCSTR
)&pBytes
[dwPos
], dwSize
- dwPos
, NULL
, 0);
128 if (dwCharCount
== 0)
133 /* special case for files with no characters (other than BOMs) */
137 pszAllocText
= (LPWSTR
) HeapAlloc(GetProcessHeap(), 0, (dwCharCount
+ 1) * sizeof(WCHAR
));
141 if ((dwSize
- dwPos
) > 0)
143 if (!MultiByteToWideChar(iCodePage
, 0, (LPCSTR
)&pBytes
[dwPos
], dwSize
- dwPos
, pszAllocText
, dwCharCount
))
147 pszAllocText
[dwCharCount
] = '\0';
148 pszText
= pszAllocText
;
154 for (i
= 0; i
< dwCharCount
; i
++)
159 if ((i
< dwCharCount
-1) && (pszText
[i
+1] == '\n'))
162 adwEolnCount
[EOLN_CRLF
]++;
168 if (!Append(ppszText
, pdwTextLen
, &pszText
[dwPos
], i
- dwPos
))
170 if (!Append(ppszText
, pdwTextLen
, szCrlf
, ARRAY_SIZE(szCrlf
)))
174 if (pszText
[i
] == '\r')
175 adwEolnCount
[EOLN_CR
]++;
177 adwEolnCount
[EOLN_LF
]++;
186 if (!*ppszText
&& (pszText
== pszAllocText
))
188 /* special case; don't need to reallocate */
189 *ppszText
= pszAllocText
;
190 *pdwTextLen
= dwCharCount
;
195 /* append last remaining text */
196 if (!Append(ppszText
, pdwTextLen
, &pszText
[dwPos
], i
- dwPos
+ 1))
200 /* chose which eoln to use */
202 if (adwEolnCount
[EOLN_LF
] > adwEolnCount
[*piEoln
])
204 if (adwEolnCount
[EOLN_CR
] > adwEolnCount
[*piEoln
])
212 HeapFree(GetProcessHeap(), 0, pBytes
);
214 HeapFree(GetProcessHeap(), 0, pszAllocText
);
216 if (!bSuccess
&& *ppszText
)
218 HeapFree(GetProcessHeap(), 0, *ppszText
);
225 static BOOL
WriteEncodedText(HANDLE hFile
, LPCWSTR pszText
, DWORD dwTextLen
, ENCODING encFile
)
227 LPBYTE pBytes
= NULL
;
228 LPBYTE pAllocBuffer
= NULL
;
234 BOOL bSuccess
= FALSE
;
235 int iBufferSize
, iRequiredBytes
;
238 while(dwPos
< dwTextLen
)
242 case ENCODING_UNICODE
:
243 pBytes
= (LPBYTE
) &pszText
[dwPos
];
244 dwByteCount
= (dwTextLen
- dwPos
) * sizeof(WCHAR
);
248 case ENCODING_UNICODE_BE
:
249 dwByteCount
= (dwTextLen
- dwPos
) * sizeof(WCHAR
);
250 if (dwByteCount
> sizeof(buffer
))
251 dwByteCount
= sizeof(buffer
);
253 memcpy(buffer
, &pszText
[dwPos
], dwByteCount
);
254 for (i
= 0; i
< dwByteCount
; i
+= 2)
257 buffer
[i
+0] = buffer
[i
+1];
260 pBytes
= (LPBYTE
) &buffer
[dwPos
];
261 dwPos
+= dwByteCount
/ sizeof(WCHAR
);
266 if (encFile
== ENCODING_ANSI
)
268 else if (encFile
== ENCODING_UTF8
)
271 iRequiredBytes
= WideCharToMultiByte(iCodePage
, 0, &pszText
[dwPos
], dwTextLen
- dwPos
, NULL
, 0, NULL
, NULL
);
272 if (iRequiredBytes
<= 0)
276 else if (iRequiredBytes
< sizeof(buffer
))
279 iBufferSize
= sizeof(buffer
);
283 pAllocBuffer
= (LPBYTE
) HeapAlloc(GetProcessHeap(), 0, iRequiredBytes
);
286 pBytes
= pAllocBuffer
;
287 iBufferSize
= iRequiredBytes
;
290 dwByteCount
= WideCharToMultiByte(iCodePage
, 0, &pszText
[dwPos
], dwTextLen
- dwPos
, (LPSTR
) pBytes
, iBufferSize
, NULL
, NULL
);
301 if (!WriteFile(hFile
, pBytes
, dwByteCount
, &dwDummy
, NULL
))
304 /* free the buffer, if we have allocated one */
307 HeapFree(GetProcessHeap(), 0, pAllocBuffer
);
315 HeapFree(GetProcessHeap(), 0, pAllocBuffer
);
319 BOOL
WriteText(HANDLE hFile
, LPCWSTR pszText
, DWORD dwTextLen
, ENCODING encFile
, int iEoln
)
322 LPCWSTR pszLF
= L
"\n";
325 /* Write the proper byte order marks if not ANSI */
326 if (encFile
!= ENCODING_ANSI
)
329 if (!WriteEncodedText(hFile
, &wcBom
, 1, encFile
))
335 /* pszText eoln are always \r\n */
339 /* Find the next eoln */
341 while(dwNext
< dwTextLen
)
343 if (pszText
[dwNext
] == '\r' && pszText
[dwNext
+ 1] == '\n')
348 if (dwNext
!= dwTextLen
)
353 /* Write text (without eoln) */
354 if (!WriteEncodedText(hFile
, &pszText
[dwPos
], dwNext
- dwPos
, encFile
))
357 if (!WriteEncodedText(hFile
, pszLF
, 1, encFile
))
361 /* Write text (including \r as eoln) */
362 if (!WriteEncodedText(hFile
, &pszText
[dwPos
], dwNext
- dwPos
+ 1, encFile
))
366 /* Write text (including \r\n as eoln) */
367 if (!WriteEncodedText(hFile
, &pszText
[dwPos
], dwNext
- dwPos
+ 2, encFile
))
376 /* Write text (without eoln, since this is the end of the file) */
377 if (!WriteEncodedText(hFile
, &pszText
[dwPos
], dwNext
- dwPos
, encFile
))
384 while (dwPos
< dwTextLen
);