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
;
50 BOOL
ReadText(HANDLE hFile
, LPWSTR
*ppszText
, DWORD
*pdwTextLen
, int *piEncoding
, int *piEoln
)
55 LPWSTR pszAllocText
= NULL
;
58 BOOL bSuccess
= FALSE
;
60 int iEncoding
= ENCODING_ANSI
;
62 WCHAR szCrlf
[2] = { '\r', '\n' };
63 DWORD adwEolnCount
[3] = { 0, 0, 0 };
68 dwSize
= GetFileSize(hFile
, NULL
);
69 if (dwSize
== INVALID_FILE_SIZE
)
72 pBytes
= HeapAlloc(GetProcessHeap(), 0, dwSize
+ 2);
76 if (!ReadFile(hFile
, pBytes
, dwSize
, &dwSize
, NULL
))
80 /* Make sure that there is a NUL character at the end, in any encoding */
81 pBytes
[dwSize
+ 0] = '\0';
82 pBytes
[dwSize
+ 1] = '\0';
84 /* Look for Byte Order Marks */
85 if ((dwSize
>= 2) && (pBytes
[0] == 0xFF) && (pBytes
[1] == 0xFE))
87 iEncoding
= ENCODING_UNICODE
;
90 else if ((dwSize
>= 2) && (pBytes
[0] == 0xFE) && (pBytes
[1] == 0xFF))
92 iEncoding
= ENCODING_UNICODE_BE
;
95 else if ((dwSize
>= 3) && (pBytes
[0] == 0xEF) && (pBytes
[1] == 0xBB) && (pBytes
[2] == 0xBF))
97 iEncoding
= ENCODING_UTF8
;
103 case ENCODING_UNICODE_BE
:
104 for (i
= dwPos
; i
< dwSize
-1; i
+= 2)
107 pBytes
[i
+0] = pBytes
[i
+1];
112 case ENCODING_UNICODE
:
113 pszText
= (LPWSTR
) &pBytes
[dwPos
];
114 dwCharCount
= (dwSize
- dwPos
) / sizeof(WCHAR
);
119 if (iEncoding
== ENCODING_ANSI
)
121 else if (iEncoding
== ENCODING_UTF8
)
124 if ((dwSize
- dwPos
) > 0)
126 dwCharCount
= MultiByteToWideChar(iCodePage
, 0, (LPCSTR
)&pBytes
[dwPos
], dwSize
- dwPos
, NULL
, 0);
127 if (dwCharCount
== 0)
132 /* special case for files with no characters (other than BOMs) */
136 pszAllocText
= (LPWSTR
) HeapAlloc(GetProcessHeap(), 0, (dwCharCount
+ 1) * sizeof(WCHAR
));
140 if ((dwSize
- dwPos
) > 0)
142 if (!MultiByteToWideChar(iCodePage
, 0, (LPCSTR
)&pBytes
[dwPos
], dwSize
- dwPos
, pszAllocText
, dwCharCount
))
146 pszAllocText
[dwCharCount
] = '\0';
147 pszText
= pszAllocText
;
152 for (i
= 0; i
< dwCharCount
; i
++)
157 if ((i
< dwCharCount
-1) && (pszText
[i
+1] == '\n'))
160 adwEolnCount
[EOLN_CRLF
]++;
166 if (!Append(ppszText
, pdwTextLen
, &pszText
[dwPos
], i
- dwPos
))
168 if (!Append(ppszText
, pdwTextLen
, szCrlf
, sizeof(szCrlf
) / sizeof(szCrlf
[0])))
172 if (pszText
[i
] == '\r')
173 adwEolnCount
[EOLN_CR
]++;
175 adwEolnCount
[EOLN_LF
]++;
184 if (!*ppszText
&& (pszText
== pszAllocText
))
186 /* special case; don't need to reallocate */
187 *ppszText
= pszAllocText
;
188 *pdwTextLen
= dwCharCount
;
193 /* append last remaining text */
194 if (!Append(ppszText
, pdwTextLen
, &pszText
[dwPos
], i
- dwPos
+ 1))
198 /* chose which eoln to use */
200 if (adwEolnCount
[EOLN_LF
] > adwEolnCount
[*piEoln
])
202 if (adwEolnCount
[EOLN_CR
] > adwEolnCount
[*piEoln
])
204 *piEncoding
= iEncoding
;
210 HeapFree(GetProcessHeap(), 0, pBytes
);
212 HeapFree(GetProcessHeap(), 0, pszAllocText
);
214 if (!bSuccess
&& *ppszText
)
216 HeapFree(GetProcessHeap(), 0, *ppszText
);
223 static BOOL
WriteEncodedText(HANDLE hFile
, LPCWSTR pszText
, DWORD dwTextLen
, int iEncoding
)
225 LPBYTE pBytes
= NULL
;
226 LPBYTE pAllocBuffer
= NULL
;
232 BOOL bSuccess
= FALSE
;
233 int iBufferSize
, iRequiredBytes
;
236 while(dwPos
< dwTextLen
)
240 case ENCODING_UNICODE
:
241 pBytes
= (LPBYTE
) &pszText
[dwPos
];
242 dwByteCount
= (dwTextLen
- dwPos
) * sizeof(WCHAR
);
246 case ENCODING_UNICODE_BE
:
247 dwByteCount
= (dwTextLen
- dwPos
) * sizeof(WCHAR
);
248 if (dwByteCount
> sizeof(buffer
))
249 dwByteCount
= sizeof(buffer
);
251 memcpy(buffer
, &pszText
[dwPos
], dwByteCount
);
252 for (i
= 0; i
< dwByteCount
; i
+= 2)
255 buffer
[i
+0] = buffer
[i
+1];
258 pBytes
= (LPBYTE
) &buffer
[dwPos
];
259 dwPos
+= dwByteCount
/ sizeof(WCHAR
);
264 if (iEncoding
== ENCODING_ANSI
)
266 else if (iEncoding
== ENCODING_UTF8
)
269 iRequiredBytes
= WideCharToMultiByte(iCodePage
, 0, &pszText
[dwPos
], dwTextLen
- dwPos
, NULL
, 0, NULL
, NULL
);
270 if (iRequiredBytes
<= 0)
274 else if (iRequiredBytes
< sizeof(buffer
))
277 iBufferSize
= sizeof(buffer
);
281 pAllocBuffer
= (LPBYTE
) HeapAlloc(GetProcessHeap(), 0, iRequiredBytes
);
284 pBytes
= pAllocBuffer
;
285 iBufferSize
= iRequiredBytes
;
288 dwByteCount
= WideCharToMultiByte(iCodePage
, 0, &pszText
[dwPos
], dwTextLen
- dwPos
, (LPSTR
) pBytes
, iBufferSize
, NULL
, NULL
);
299 if (!WriteFile(hFile
, pBytes
, dwByteCount
, &dwDummy
, NULL
))
302 /* free the buffer, if we have allocated one */
305 HeapFree(GetProcessHeap(), 0, pAllocBuffer
);
313 HeapFree(GetProcessHeap(), 0, pAllocBuffer
);
317 BOOL
WriteText(HANDLE hFile
, LPCWSTR pszText
, DWORD dwTextLen
, int iEncoding
, int iEoln
)
320 LPCWSTR pszLF
= L
"\n";
323 /* Write the proper byte order marks if not ANSI */
324 if (iEncoding
!= ENCODING_ANSI
)
327 if (!WriteEncodedText(hFile
, &wcBom
, 1, iEncoding
))
333 /* pszText eoln are always \r\n */
337 /* Find the next eoln */
339 while(dwNext
< dwTextLen
)
341 if (pszText
[dwNext
] == '\r' && pszText
[dwNext
+ 1] == '\n')
346 if (dwNext
!= dwTextLen
)
351 /* Write text (without eoln) */
352 if (!WriteEncodedText(hFile
, &pszText
[dwPos
], dwNext
- dwPos
, iEncoding
))
355 if (!WriteEncodedText(hFile
, pszLF
, 1, iEncoding
))
359 /* Write text (including \r as eoln) */
360 if (!WriteEncodedText(hFile
, &pszText
[dwPos
], dwNext
- dwPos
+ 1, iEncoding
))
364 /* Write text (including \r\n as eoln) */
365 if (!WriteEncodedText(hFile
, &pszText
[dwPos
], dwNext
- dwPos
+ 2, iEncoding
))
374 /* Write text (without eoln, since this is the end of the file) */
375 if (!WriteEncodedText(hFile
, &pszText
[dwPos
], dwNext
- dwPos
, iEncoding
))
382 while (dwPos
< dwTextLen
);